# 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
# Dockerfile for payment-gateway v1
FROM node:14
WORKDIR /app
COPY ./v1/ .
RUN npm install
CMD ["npm", "start"]
```

#### Dockerfile for v2

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

Build and push the images:

```bash
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.

```yaml
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**:

```yaml
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:

```bash
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**:

```yaml
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:

```bash
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)

```yaml
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:

```bash
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**:

```yaml
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

```yaml
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:

```yaml
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:

```yaml
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:

```bash
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:

```bash
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](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
    
2. [Canary Deployments with Istio](https://istio.io/latest/docs/tasks/traffic-management/canary/)
    
3. [Blue-Green Deployments in Kubernetes](https://docs.cloudfoundry.org/devguide/deploy-apps/blue-green.html)
    
4. [Kubernetes API Versioning](https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning)
    
5. [NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/)
    
6. [Rollback Kubernetes Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment)
    
7. [Traffic Shifting with Istio](https://istio.io/latest/docs/tasks/traffic-management/traffic-shifting/)
    

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**](https://blogs.subhanshumg.com/newsletter) and follow me on [**LinkedIn**](https://www.linkedin.com/in/subhanshu-mohan-gupta-039559123/)
