In this Kubernetes guide, we will dive deep into how to use Kubernetes for microservices, microservices architecture, when to use & when not to use K8s for Kubernetes with examples.

kubernetes microservices banner, kubernetes microservices, microservices kubernetes

In the world of Kubernetes, containers and microservices are the building blocks of modern, scalable applications. 

Let's divide this foundation understanding into more bits.

Containers in Kubernetes

Containers are lightweight, portable, and consistent environments that encapsulate your microservices. 

Kubernetes leverages containerization technology (like Docker) to ensure that each microservice runs reliably across different environments. 

Assuming you are an intermediate/advanced Kubernetes user, you're no stranger to creating and managing containers, so let's skip the basics and jump right into some advanced container concepts.

A. Container Definition (Dockerfile Example)

# Use a minimal base image
FROM alpine:3.14
# Set environment variables
ENV APP_NAME=my-microservice
# Install dependencies and configure your app
RUN apk add --no-cache nodejs npm
COPY . .
RUN npm install
# Expose ports and define startup command
CMD ["node", "index.js"]

B. Container Build and Push to Registry

# Build the Docker image
docker build -t my-microservice:1.0.0 .
# Push the image to a container registry
docker push my-container-registry/my-microservice:1.0.0

Also Read: Microservices Monitoring & Testing Tools

Microservices in Kubernetes

Kubernetes excels at orchestrating microservices, enabling you to manage a complex network of independently deployable services. 

With that in mind, here's a brief overview of some microservices-related Kubernetes concepts.

A. Pod Anti-Affinity

Pods of the same microservice are distributed across different nodes to enhance fault tolerance and availability. 

Here's an example of defining anti-affinity rules in a Deployment:

      - labelSelector:
            - key: app
              operator: In
                - my-microservice

B. Horizontal Pod Autoscaler (HPA)

Automatically adjust the number of replicas based on resource utilization or custom metrics. 

Here’s how to set up a Horizontal Pod Autoscaler (HPA) for your microservice:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
  name: my-microservice-hpa
    apiVersion: apps/v1
    kind: Deployment
    name: my-microservice-deployment
  minReplicas: 2
  maxReplicas: 10
    - type: Resource
        name: cpu
          type: Utilization
          averageUtilization: 70

C. Advanced Service Discovery

Implement advanced service discovery mechanisms like Consul, Istio, or Linkerd to manage traffic between microservices, apply security policies, and gain deep observability into the communication patterns.

Kubernetes Microservices Architecture Explained

Kubernetes microservices architecture is the backbone of any advanced microservices deployment. 

Let's dive deeper into its key components and how they work together.


Pods are the fundamental units in Kubernetes. They can contain one or more containers that share the same network namespace and storage volumes. 

This makes it possible to co-locate tightly coupled microservices within a pod while keeping loosely coupled ones separate.

Here's an example of creating a pod with two containers.

apiVersion: v1
kind: Pod
  name: multi-container-pod
  - name: nginx-container
    image: nginx:latest
  - name: busybox-container
    image: busybox:latest

Also Read: Kubernetes Pods vs Nodes


Services enable network communication between microservices. They provide a stable IP address and DNS name for accessing pods, even as they scale up or down. 

Services can be of type ClusterIP, NodePort, or LoadBalancer depending on your networking needs.

Here's how to create a ClusterIP service.

apiVersion: v1
kind: Service
  name: my-service
    app: my-app
    - protocol: TCP
      port: 80
      targetPort: 8080

Also Read: How to Use Just One Load Balancer for Multiple Apps?

Deployments and StatefulSets

Deployments and StatefulSets are controllers that manage the lifecycle of pods. 

Deployments are suitable for stateless microservices, while StatefulSets are designed for stateful ones. They handle scaling, updates, and rollbacks with ease.

Let's look at an example of a Deployment.

apiVersion: apps/v1
kind: Deployment
  name: nginx-deployment
  replicas: 3
      app: nginx
        app: nginx
        - name: nginx-container
          image: nginx:latest

Ingress Controllers

Ingress controllers manage external access to the services within your cluster. They act as reverse proxies and handle routing, SSL termination, etc. Popular choices include Nginx Ingress and Traefik.

Here's how to install Nginx Ingress Controller using Helm.

helm repo add ingress-nginx
helm install my-ingress ingress-nginx/ingress-nginx

Also Read: Top NGNIX Ingress Configuration Options

ConfigMaps and Secrets

ConfigMaps store configuration data as key-value pairs, on the other hand, Secrets securely store sensitive information like API keys and passwords. 

Microservices can access these resources to configure themselves dynamically.

Here's how to create a ConfigMap.

kubectl create configmap my-config

Also Read: How to Create & Use Kubeconfig File?

Why Use Kubernetes for Deploying Microservices?

Kubernetes really shines when it comes to deploying microservices in complex scenarios. Here's a deeper look into why you should opt for Kubernetes:


Kubernetes offers two types of scaling:

A. Horizontal Scaling

This allows you to scale your microservices by adding or removing pods based on resource usage or custom metrics. 

To scale a deployment named `my-microservice` to 5 replicas, you can use the `kubectl` command.

kubectl scale deployment my-microservice --replicas=5

Also Read: Vertical vs Horizontal Scaling

B. Vertical Scaling

For applications that require more resources within a pod, Kubernetes supports vertical scaling using the Vertical Pod Autoscaler (VPA). You can define resource requests and limits in your pod specs to ensure efficient resource utilization.

    memory: "64Mi"
    cpu: "250m"
    memory: "128Mi"
    cpu: "500m"

High Availability

Kubernetes takes care of high availability automatically by distributing pods across nodes and ensuring that they are rescheduled in case of node failures. 

Services provide load balancing, for continuous availability of your application to clients.

Also Read: Kubectl Commands Cheat Sheet

Resource Efficiency

Resource efficiency is crucial, especially in microservices environments. 

Kubernetes optimizes resource usage by packing multiple pods onto nodes and applying standard algorithms to make sure the load is equally shared. 

This efficiency translates into cost savings, particularly in cloud environments.

Rolling Updates

Kubernetes simplifies the process of updating your microservices without disrupting service. You can perform rolling updates by changing the image in a deployment spec:

kubectl set image deployment/my-microservice my-microservice=my-new-image:tag

Kubernetes will gradually replace old pods with new ones, maintaining service availability during the update.

Also Read: Blue Green vs Canary Deployment

Creating and Deploying a Microservice on Kubernetes Cluster

Let's get into the nitty-gritty of deploying a Node.js microservice on your Kubernetes cluster

You're already familiar with Kubernetes, so let's skip the basics and jump right into the action.

Create a Deployment

First, define a Kubernetes Deployment YAML file. In this example, we'll create a Node.js microservice with three replicas for high availability. 

Replace `your-nodejs-image:tag` with your actual Node.js Docker image and version.

apiVersion: apps/v1
kind: Deployment
  name: nodejs-microservice
  replicas: 3
      app: nodejs-microservice
        app: nodejs-microservice
        - name: nodejs-microservice
          image: your-nodejs-image:tag
            - containerPort: 3000

Apply this deployment to your cluster using the `kubectl apply` command:

kubectl apply -f your-deployment.yaml

Create a Service

Next, create a Kubernetes Service to expose your Node.js microservice within the cluster. Why? 

This service will enable other parts of your application to communicate with it. 

apiVersion: v1
kind: Service
  name: nodejs-microservice
    app: nodejs-microservice
    - protocol: TCP
      port: 80
      targetPort: 3000

Apply the service definition to your cluster:

kubectl apply -f your-service.yaml

Your Node.js microservice is now deployed and accessible within your Kubernetes cluster.

Scaling the Microservice

To scale your Node.js microservice up or down, simply use the `kubectl scale` command. For example, to scale up to 5 replicas:

kubectl scale deployment nodejs-microservice --replicas=5

Also Read: A Complete Guide to Replicasets

Updating the Microservice

To update your microservice with a new Docker image, modify the image tag in your Deployment YAML file to point to the new version.

Then, apply the updated configuration:

kubectl apply -f your-updated-deployment.yaml

Kubernetes will perform a rolling update, ensuring minimal downtime during the process.

Rolling Back an Update

In the unlikely event that an update causes issues, you can roll back to a previous version using the `kubectl rollout` commands. 

For example, to roll back to the previous revision:

kubectl rollout undo deployment/nodejs-microservice

Also Read: How to Use Kubectl Rollout Restart?

12-Factor App Method & Kubernetes Microservices

The 12-Factor App methodology is a set of best practices for building modern, scalable, and maintainable web applications. 

When it comes to deploying microservices on Kubernetes, these principles align seamlessly, contributing to a smoother and more efficient deployment process. 

Let's explore this alignment further.

1. Codebase in Version Control

Ensure your microservices codebase is stored in version control. Popular platforms like GitHub, GitLab, or Bitbucket work well with Kubernetes. 

Here's a brief guide on how to set up your repository:

# Initialize a Git repository
git init

# Add your code
git add .

# Commit changes
git commit -m "Initial commit"

# Create a remote repository on your preferred platform and link it
git remote add origin <repository_url>

# Push your code to the remote repository
git push -u origin master

2. Dependencies Declared Explicitly

Kubernetes encourages the explicit declaration of dependencies through resource definitions. You can define dependencies between microservices using Kubernetes Services. 

Here's an example:

apiVersion: v1
kind: Service
  name: backend
    app: backend
    - protocol: TCP
      port: 80
      targetPort: 8080

3. Configurations Stored in Environment Variables

12-Factor Apps suggest storing configurations in environment variables. Kubernetes supports this practice by allowing you to inject environment variables into your containers. 

For instance, you can create a ConfigMap:

kubectl create configmap my-config --from-literal=DATABASE_URL=your_db_url

And then reference it in your Pod definition:

apiVersion: v1
kind: Pod
  name: my-pod
    - name: my-container
      image: my-image
        - name: DATABASE_URL
              name: my-config
              key: DATABASE_URL

4. Stateless Services

Kubernetes pods are designed to be stateless, which aligns with the 12-Factor App's stateless service principle. 

Pods can be easily scaled horizontally to handle increased traffic without worrying about managing state.

5. Port Binding

Kubernetes Services handles port binding for you, allowing microservices to communicate with each other over a network. You don't need to manage port conflicts manually.

Also Read: A Guide to Kubernetes Port Forwarding

6. Concurrency

Kubernetes enables fine-grained control over microservice scaling using Horizontal Pod Autoscaling. You can define custom metrics to trigger scaling based on your application's specific needs.

7. Disposability

Kubernetes makes it easy to manage the lifecycle of your microservices. Use Deployments or StatefulSets to ensure your microservices are disposable and can be replaced or scaled up/down without downtime.

8. Dev/Prod Parity

Kubernetes supports creating separate environments for development, staging, and production, ensuring parity between them. 

Utilize Namespaces to isolate your microservices environments.

9. Logs as Event Streams

Kubernetes abstracts log management, allowing you to centralize logs using tools like Fluentd or Prometheus. This aligns with the concept of treating logs as event streams.

Also Read: A Complete Guide to Kubernetes Log

10. Admin Processes

Kubernetes provides Jobs and CronJobs for running admin processes, such as database migrations or periodic tasks, in your microservices architecture.

11. Port Exporting

Use Kubernetes Services to expose specific ports of your microservices to the external world securely. Control access with Network Policies to align with the 12-Factor App's port exporting principle.

12. Concurrency Scaling

Kubernetes Horizontal Pod Autoscaling allows you to automatically scale the number of replicas based on resource utilization, ensuring efficient concurrency scaling.

When to Use Kubernetes for Microservices?

Let's look at a few ideal scenarios where you should use Kubernetes for microservices.

Complex Microservices Architecture

When your microservices architecture becomes intricate, involving multiple services with interdependencies, Kubernetes shines. It offers a unified platform for managing these complexities. 

For instance, consider a scenario where you have a front-end service, several microservices handling various back-end functions, and a database. 

Kubernetes simplifies the orchestration and scaling of these services.

High Scalability, Availability, and Resilience

Kubernetes excels in scenarios where high scalability, availability, and resilience are non-negotiable. 

It automatically handles load balancing and service scaling, ensuring your microservices can handle unpredictable traffic spikes. 

To deploy a highly available microservice, you might create a Deployment with replicas:

apiVersion: apps/v1
kind: Deployment
  name: high-availability-microservice
  replicas: 3

Automated Deployment and Scaling

Kubernetes offers robust automation capabilities. You can leverage tools like Helm for packaging and deploying applications. 

For instance, to deploy an application using Helm, use the following commands:

helm create my-app
helm install my-app ./my-app

When Not to Use Kubernetes for Microservices?

Let's look at a few ideal scenarios where using Kubernetes for microservices might not be the best way.

Simple Microservices Applications

For smaller, straightforward microservices applications that don't involve intricate orchestration or scaling, Kubernetes may introduce unnecessary complexity. 

Consider a simple microservice written in Go that performs a single function. 

In such cases, deploying it as a standalone container without Kubernetes might be more efficient:

docker run -d -p 8080:8080 your-golang-microservice

Learning Curve vs. Benefits

Kubernetes comes with a learning curve. If your project is small and you and your team are not well-versed in Kubernetes, the time spent learning it might not justify the benefits. 

In such cases, consider simpler container orchestration solutions or serverless platforms.

Budget Constraints

Kubernetes can be cost-effective for large, high-traffic applications, but it can also be resource-intensive. 

If you have tight budget constraints, evaluate the cost of setting up and maintaining a Kubernetes cluster against the benefits it provides. 

You might find that serverless platforms or managed Kubernetes services from cloud providers offer a more budget-friendly option.

humalect developer platform, kubernetes microservices

TL;DR - Kubernetes Microservices

In a nutshell, Kubernetes is a powerful tool for managing microservices in complex, large-scale environments. 

It excels in orchestrating containers, providing automatic scaling, ensuring high availability, and streamlining updates. 

However, before you commit to Kubernetes, let's dive into some critical considerations.

1. Infrastructure Costs

Kubernetes infrastructure costs can escalate rapidly, especially for smaller projects. Consider whether your budget allows for the required resources.

# Estimate Kubernetes infrastructure costs using cloud providers

gcloud compute instances create my-cluster-node --machine-type=n1-standard-2 --image-family=ubuntu-2004-lts --image-project=ubuntu-os-cloud

2. Complexity

Kubernetes is a complex beast. While it's incredibly flexible, it also has a steep learning curve. Ensure your team is prepared to invest time in learning and managing Kubernetes.

3. Project Scale

Consider the scale of your microservices project. Kubernetes shines when you have numerous microservices that need to be orchestrated and scaled. 

For smaller projects, the overhead might not be justified.

4. Alternative Solutions

Don't forget that Kubernetes isn't the only solution. 

For simpler projects, serverless platforms like AWS Lambda or Azure Functions might be more cost-effective and easier to manage.

# Deploy a serverless function

aws lambda create-function --function-name my-function --runtime nodejs14.x --handler index.handler --zip-file fileb://

5. Ecosystem Compatibility

Ensure that the rest of your technology stack is compatible with Kubernetes. Some legacy systems or specialized tools might not integrate seamlessly.

6. Monitoring and Maintenance

Kubernetes requires robust monitoring and maintenance. Implement monitoring solutions like Prometheus and Grafana to keep a close eye on your microservices.

# Install Prometheus and Grafana

kubectl apply -f

In conclusion, Kubernetes is a phenomenal tool, but it's not a one-size-fits-all solution. Assess your project's size, complexity, and budget carefully before jumping in. 

While Kubernetes is a game-changer for managing microservices, it's essential to make an informed decision based on your specific needs.