DevOps & Automation

CI/CD Pipeline Design

Shipping code largely, safely, and quickly: Anatomy of a Pipeline, Deployment Strategies (Blue/Green, Canary), and Immutable Infrastructure.

The Release Pipeline

A pipeline transforms code into a running service. It must be Idempotent and Immutable.

Code
(Git Push)
Build
(Docker Build)
Test
(Unit/Integration)
Release
(Push to Registry)
Deploy
(K8s Apply)

The Testing Pyramid

Don't just run E2E tests. They are slow and flaky. Balance your suite.

E2E (UI)
10% (Slow)
Integration (API)
20% (Medium)
Unit (Code)
70% (Fast)

Deployment Strategies

How do you update a running application without downtime?

Strategy Description Pros Cons
Rolling Update Replace N instances at a time (e.g., k8s default). Zero downtime. No extra infrastructure cost. Slow rollback. Hard to verify mid-flight.
Blue/Green Spin up a full parallel environment (Green). Switch load balancer. Instant rollback (Switch back to Blue). Safe. Double infrastructure cost (2x resources).
Canary Route 1% of traffic to new version. Gradually increase. Real user testing. Lowest risk of widespread outage. Complex routing (requires Service Mesh/LB).

Immutable Infrastructure

🚫 Mutable (Bad)

SSH into servers to run `git pull` or `apt-get install`. Leads to "Configuration Drift" and "Snowflake Servers".

✅ Immutable (Good)

Bake a new Docker Image or AMI for every change. Never patch running servers. If a server is sick, shoot it and spawn a new one.

Example: GitHub Actions Workflow
name: Production Build
on:
  push:
    tags: ["v*"]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build Docker Image
        run: docker build -t myapp:${{ github.ref_name }} .
      - name: Push to Registry
        run: docker push myregistry.com/myapp:${{ github.ref_name }}
      - name: Deploy to K8s
        run: |
          # GitOps Pattern: Update the manifest repo, don't kubectl apply directly
          git clone [email protected]:org/ops-repo.git
          cd ops-repo
          yq -i '.spec.template.spec.containers[0].image = "myapp:${{ github.ref_name }}"' deployment.yaml
          git commit -am "Deploy v${{ github.ref_name }}"
          git push

Summary

  • Automate Everything: Humans should not touch production servers.
  • Fail Fast: Run unit tests first. If they fail, stop the pipeline immediately.
  • GitOps: The state of your cluster should mirror the state of your Git repository.