Tweaking Kubernetes Deployments for Enhanced Backward Compatibility

Welcome to Part II of my Kubernetes series, where we explore how to Master Kubernetes Deployments for Seamless Backward Compatibility. Managing Kubernetes upgrades can be tricky, especially when you need to ensure existing services and configurations remain unaffected. In this article, we will dive deep into techniques such as Canary Deployments, Blue-Green Deployments, and API Versioning — methods that help you maintain backward compatibility during updates, reduce downtime, and allow smooth transitions between different service versions.

Why Backward Compatibility Matters?

In a microservices-driven Kubernetes environment, backward compatibility ensures that when new features or updates are rolled out, existing services, APIs, or clients can still operate as expected without disruption. Updates can break compatibility without proper planning, resulting in service downtime or forcing all clients to adapt to the new version immediately. This is why incorporating backward compatibility is essential to a successful deployment strategy.

Key Strategies for Ensuring Backward Compatibility in Kubernetes

Before diving into the detailed steps, here’s a quick overview of the techniques we’ll cover:

  1. Canary Deployments: Gradually roll out a new version to a subset of users, monitor the performance, and slowly shift more traffic.

  2. Blue-Green Deployments: Maintain two production environments, one with the current version (Blue) and one with the new version (Green), allowing for testing before switching all traffic.

  3. API Versioning: Keep multiple versions of your API running concurrently, so older clients or services can continue to use the older version while others transition to the newer version.

Step-by-Step Implementation Guide

Now, let’s go through a precise and technical guide on how to implement these strategies in Kubernetes. In this example, we’ll manage a fictional payment gateway service with two versions — v1 (current stable version) and v2 (new release).

Step 1: Build and Push Docker Images

We first need to create and push the Docker images for both the old and new versions of the service.

Dockerfile for v1

# Dockerfile for payment-gateway v1
FROM node:14
WORKDIR /app
COPY ./v1/ .
RUN npm install
CMD ["npm", "start"]

Dockerfile for v2

# Dockerfile for payment-gateway v2
FROM node:14
WORKDIR /app
COPY ./v2/ .
RUN npm install
CMD ["npm", "start"]

Build and push the images:

docker build -t my-registry/payment-gateway:v1 -f Dockerfile.v1 .
docker build -t my-registry/payment-gateway:v2 -f Dockerfile.v2 .
docker push my-registry/payment-gateway:v1
docker push my-registry/payment-gateway:v2

Step 2: Canary Deployment

In a Canary Deployment, we introduce v2 to a small percentage of users to test stability and compatibility, while the majority continue using v1.

Step 2.1: Create Canary Deployment YAML

Deploy the current stable version v1 first.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-gateway-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-gateway
      version: v1
  template:
    metadata:
      labels:
        app: payment-gateway
        version: v1
    spec:
      containers:
      - name: payment-gateway
        image: my-registry/payment-gateway:v1
        ports:
        - containerPort: 8080

Deploy the Canary version of v2:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-gateway-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: payment-gateway
      version: canary
  template:
    metadata:
      labels:
        app: payment-gateway
        version: canary
    spec:
      containers:
      - name: payment-gateway
        image: my-registry/payment-gateway:v2
        ports:
        - containerPort: 8080

Apply these YAMLs:

kubectl apply -f payment-gateway-deployment-v1.yaml
kubectl apply -f payment-gateway-canary.yaml

Step 2.2: Gradual Traffic Shift

Use Istio or Linkerd for traffic shifting. For example, with Istio, split traffic between v1 and v2:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: payment-gateway
spec:
  hosts:
  - "*"
  http:
  - route:
    - destination:
        host: payment-gateway-service
        subset: v1
      weight: 90
    - destination:
        host: payment-gateway-service
        subset: canary
      weight: 10

Monitor performance, and if v2 is stable, scale it up:

kubectl scale --replicas=3 deployment/payment-gateway-canary
kubectl delete deployment payment-gateway-v1  # Optionally decommission v1

Step 3: Blue-Green Deployment

In a Blue-Green Deployment, both v1 (Blue) and v2 (Green) are running concurrently. After testing v2, traffic is switched to v2 without affecting the existing environment.

Step 3.1: Deploy Green (v2)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-gateway-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-gateway
      version: green
  template:
    metadata:
      labels:
        app: payment-gateway
        version: green
    spec:
      containers:
      - name: payment-gateway
        image: my-registry/payment-gateway:v2
        ports:
        - containerPort: 8080

Apply the Green deployment:

kubectl apply -f payment-gateway-green.yaml

Step 3.2: Testing and Switching Traffic

Once all tests pass in v2 (Green), update the service to point to v2:

apiVersion: v1
kind: Service
metadata:
  name: payment-gateway-service
spec:
  selector:
    app: payment-gateway
    version: green
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer

Step 4: API Versioning

Versioning APIs allows older clients to continue using v1 while new clients can migrate to v2. This minimizes disruptions for different users and services.

Step 4.1: Deploy APIs for v1 and v2

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-gateway-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-gateway
      version: v1
  template:
    metadata:
      labels:
        app: payment-gateway
        version: v1
    spec:
      containers:
      - name: payment-gateway
        image: my-registry/payment-gateway:v1
        ports:
        - containerPort: 8080

For v2:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-gateway-v2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-gateway
      version: v2
  template:
    metadata:
      labels:
        app: payment-gateway
        version: v2
    spec:
      containers:
      - name: payment-gateway
        image: my-registry/payment-gateway:v2
        ports:
        - containerPort: 8080

Step 4.2: API Gateway for Versioning

Configure NGINX or an API Gateway to route traffic based on the API version:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: payment-gateway-ingress
spec:
  rules:
  - host: payment.example.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: payment-gateway-v1
            port:
              number: 8080
      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: payment-gateway-v2
            port:
              number: 8080

Apply this Ingress:

kubectl apply -f payment-gateway-ingress.yaml

Step 5: Testing and Monitoring

  • Run end-to-end tests using Postman or Selenium.

  • Use Prometheus and Grafana for monitoring and setting alerts.

Step 6: Rollback (If Needed)

If any issues arise, you can rollback the deployment:

kubectl rollout undo deployment/payment-gateway-v2

Conclusion

In this article, we've explored how to tweak Kubernetes deployments for enhanced backward compatibility using Canary Deployments, Blue-Green Deployments, and API Versioning. These strategies ensure that you can seamlessly upgrade services while maintaining compatibility with existing clients and services.

Implementing these strategies equips your infrastructure with the flexibility to adapt to ever-changing demands, ensuring smooth & future-proof Kubernetes deployments.

Additional Resources

  1. Kubernetes - Deployments

  2. Canary Deployments with Istio

  3. Blue-Green Deployments in Kubernetes

  4. Kubernetes API Versioning

  5. NGINX Ingress Controller

  6. Rollback Kubernetes Deployments

  7. Traffic Shifting with Istio

Stay tuned for Part III, where we’ll dive into Cost Estimation for Cloud Architectures & Kubernetes Workloads to help you optimize cloud infrastructure costs effectively.


Feel free to subscribe to my newsletter and follow me on LinkedIn

11
Subscribe to my newsletter

Read articles from Subhanshu Mohan Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Subhanshu Mohan Gupta
Subhanshu Mohan Gupta

A passionate AI DevOps Engineer specialized in creating secure, scalable, and efficient systems that bridge development and operations. My expertise lies in automating complex processes, integrating AI-driven solutions, and ensuring seamless, secure delivery pipelines. With a deep understanding of cloud infrastructure, CI/CD, and cybersecurity, I thrive on solving challenges at the intersection of innovation and security, driving continuous improvement in both technology and team dynamics.