Make Your Kubernetes Deployments Lightning Fast: Only Update What’s Changed!

Ahmed RazaAhmed Raza
4 min read

Deploying an entire application for every update can be time-consuming and inefficient. Kubernetes, with its declarative model and modular architecture, allows for partial updates, where only the changed components are deployed. This approach not only saves resources but also reduces downtime and risk.

In this article, we will explore strategies to achieve partial deployments in Kubernetes, with practical examples and configuration files to illustrate the concepts.


Why Deploy Only Changed Parts?

Key Benefits

  1. Efficiency: Updates are faster and require fewer resources.

  2. Reduced Risk: Limiting the scope of changes minimizes potential issues.

  3. Improved Developer Productivity: Teams can focus on specific components without worrying about the entire system.

Common Use Cases

  • Microservices-based architectures where individual services are updated independently.

  • Large-scale applications with modular deployments.

  • Continuous Integration/Continuous Deployment (CI/CD) pipelines.


Strategies for Partial Deployments

1. Leveraging Kubernetes Deployments

Kubernetes deployments inherently support partial updates. By updating only the relevant deployment resource, Kubernetes handles the rolling updates for that specific component.

2. Managing Configurations with ConfigMaps and Secrets

Configuration changes can be decoupled from application code, allowing for updates without restarting pods unnecessarily.

3. Using Canary or Blue-Green Deployments

For more complex scenarios, strategies like canary deployments or blue-green deployments can target updates to specific portions of the environment.


Practical Example: Partial Deployment of a Multi-Service Application

Scenario

Consider an application with three microservices:

  1. frontend: A React-based web application.

  2. backend: A Node.js REST API.

  3. database: A MySQL database.

We need to update the backend service without affecting the frontend or database services.


Step 1: Initial Setup

Cluster Configuration

Ensure you have a Kubernetes cluster running. Use Minikube, Kind, or a cloud provider for setup. Install kubectl and configure access to your cluster.

Application Architecture

Define the application components using the following YAML files:

frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: myapp
    tier: frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      tier: frontend
  template:
    metadata:
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: frontend
        image: myregistry/frontend:v1
        ports:
        - containerPort: 3000
backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  labels:
    app: myapp
    tier: backend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      tier: backend
  template:
    metadata:
      labels:
        app: myapp
        tier: backend
    spec:
      containers:
      - name: backend
        image: myregistry/backend:v1
        ports:
        - containerPort: 8080
database-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: database
  labels:
    app: myapp
    tier: database
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      tier: database
  template:
    metadata:
      labels:
        app: myapp
        tier: database
    spec:
      containers:
      - name: database
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "rootpassword"

Apply these configurations to deploy the application:

kubectl apply -f frontend-deployment.yaml
kubectl apply -f backend-deployment.yaml
kubectl apply -f database-deployment.yaml

Step 2: Updating the Backend

Make Code Changes

Suppose the backend now includes a new API endpoint. Build and push the updated image:

docker build -t myregistry/backend:v2 .
docker push myregistry/backend:v2

Update Deployment Configuration

Modify only the backend-deployment.yaml file to use the new image:

spec:
  containers:
  - name: backend
    image: myregistry/backend:v2

Apply the updated configuration:

kubectl apply -f backend-deployment.yaml

Step 3: Verifying the Update

  1. Check Pods: Ensure only the backend pods are restarted:

     kubectl get pods
    
  2. Monitor Rollout: Kubernetes performs a rolling update by default:

     kubectl rollout status deployment/backend
    
  3. Validate the Changes: Test the new API endpoint to verify functionality.


Step 4: Rollback (if needed)

If issues arise, rollback to the previous version:

kubectl rollout undo deployment/backend

Handling Configuration Changes

For changes to configurations without modifying code, use ConfigMaps.

  1. Create a ConfigMap:

     kubectl create configmap backend-config --from-literal=ENV=production
    
  2. Mount the ConfigMap in the deployment:

     spec:
       containers:
       - name: backend
         image: myregistry/backend:v2
         env:
         - name: ENV
           valueFrom:
             configMapKeyRef:
               name: backend-config
               key: ENV
    
  3. Update the ConfigMap without redeploying:

     kubectl edit configmap backend-config
    
  4. Restart pods to apply the changes:

     kubectl rollout restart deployment/backend
    

Advanced Techniques

1. Canary Deployments

Deploy the new version alongside the current one to a subset of users for testing:

kubectl set image deployment/backend backend=myregistry/backend:v2

2. Blue-Green Deployments

Maintain two separate environments (blue and green) and switch traffic between them.


Conclusion

By updating only the changed parts of your application, Kubernetes enables efficient and scalable workflows. This approach aligns with modern DevOps practices, reducing downtime and resource usage. Leveraging deployments, ConfigMaps, and advanced strategies like canary deployments, you can achieve seamless updates tailored to your application needs.

For complex systems, integrating these techniques into a CI/CD pipeline ensures automated, reliable, and consistent partial deployments.

0
Subscribe to my newsletter

Read articles from Ahmed Raza directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ahmed Raza
Ahmed Raza

Ahmed Raza is a versatile full-stack developer with extensive experience in building APIs through both REST and GraphQL. Skilled in Golang, he uses gqlgen to create optimized GraphQL APIs, alongside Redis for effective caching and data management. Ahmed is proficient in a wide range of technologies, including YAML, SQL, and MongoDB for data handling, as well as JavaScript, HTML, and CSS for front-end development. His technical toolkit also includes Node.js, React, Java, C, and C++, enabling him to develop comprehensive, scalable applications. Ahmed's well-rounded expertise allows him to craft high-performance solutions that address diverse and complex application needs.