CI/CD for Microservices

A microservices system can have 50 or more services, each updated by a different team several times per week. Manually testing and deploying each update is impractical. CI/CD — Continuous Integration and Continuous Delivery — automates the process from code change to production deployment.

What CI/CD Means

Continuous Integration (CI)

Every time a developer commits code, an automated system builds the service, runs all tests, and reports whether the code is healthy. Problems get caught within minutes of being written — not days later during a manual review.

Continuous Delivery (CD)

After CI confirms the code is healthy, CD automatically packages the service, pushes it to a registry, and deploys it to a target environment (staging or production). Deployment becomes a routine, repeatable process rather than a stressful manual event.

The CI/CD Pipeline

A pipeline is a series of automated stages, each building on the previous one.

CI/CD PIPELINE FOR ORDER SERVICE
==================================

Developer commits code to Git
          |
          v
[Stage 1: Build]
  Compile code
  Build Docker image
  Tag with commit ID (e.g., order-service:a3f9c21)
          |
          v
[Stage 2: Test]
  Run unit tests (do individual functions work?)
  Run integration tests (do services work together?)
  Run security scan (any known vulnerabilities in dependencies?)
  If any test fails: pipeline stops, developer is notified
          |
          v
[Stage 3: Publish]
  Push Docker image to container registry
  Available for deployment
          |
          v
[Stage 4: Deploy to Staging]
  Deploy image to staging environment
  Run smoke tests (is the service responding?)
  Run end-to-end tests (does the user flow work?)
          |
          v
[Stage 5: Deploy to Production]
  Rolling update in Kubernetes
  Monitor for errors in the first 5 minutes
  Auto-rollback if error rate exceeds threshold

Independent Pipelines per Service

Each microservice has its own independent CI/CD pipeline. The Payment Service team deploys without waiting for the Order Service team. Changes to the Inventory Service do not trigger rebuilds of unrelated services.

SEPARATE PIPELINES
===================
[Order Service Repo]    --> [Order Service Pipeline]  --> Production
[Payment Service Repo]  --> [Payment Service Pipeline] --> Production
[User Service Repo]     --> [User Service Pipeline]    --> Production

Teams release independently. No coordination needed.

Feature Flags

Feature flags let teams deploy code to production without making it visible to users. A flag controls whether a feature is active. Teams turn the flag on for a small percentage of users first, monitor for problems, then gradually roll out to everyone.

CODE EXAMPLE (conceptual)
==========================
if (featureFlag.isEnabled("new-checkout-flow", userId)) {
  showNewCheckout()  // 10% of users see new flow
} else {
  showOldCheckout()  // 90% still see old flow
}

If new checkout has a bug:
  Turn flag OFF
  All users back to old checkout immediately
  No deployment needed. No rollback needed.

Environment Strategy

ENVIRONMENT PIPELINE
=====================
[Development]  --> [Staging]  --> [Production]

Development:  Developer's local machine or shared dev cluster
              Fast iteration, no strict quality gates

Staging:      Mirror of production environment
              Full integration tests, performance tests
              Real data shapes (not real user data)

Production:   Live system serving real users
              Reached only after passing all gates

Testing in a Microservices Pipeline

Unit Tests

Test individual functions or classes in isolation. They run in milliseconds. A pipeline runs thousands of unit tests in under a minute.

Contract Tests

Contract tests verify that a service honors its API contract. The Order Service contract test checks that the Payment Service API still accepts requests in the expected format. A contract test catches breaking changes before deployment.

CONTRACT TEST EXAMPLE
======================
Payment Service contract says:
  POST /charge accepts { order_id, amount, card_token }
  Returns { status, transaction_id }

Contract test sends a sample request.
Verifies response matches the documented contract.
If Payment Service team changes the response format:
  Contract test fails
  Team is alerted before the change reaches production
  Order Service team is not surprised by a broken integration

End-to-End Tests

End-to-end tests simulate a real user flow across multiple services. They confirm that placing an order goes all the way through to payment confirmation. These tests run in staging, not on every commit, because they take longer.

Popular CI/CD Tools

  • GitHub Actions — built into GitHub, YAML-based pipelines, widely used.
  • GitLab CI/CD — built into GitLab, powerful and fully integrated.
  • Jenkins — mature, self-hosted, highly customizable.
  • ArgoCD — Kubernetes-native CD tool, uses Git as the source of truth for deployments.
  • Tekton — Kubernetes-native CI/CD pipelines.

GitOps: Deployments via Git

GitOps is a deployment approach where the desired state of the production environment is stored in a Git repository. ArgoCD watches the repository. When the repository changes (a new image tag is committed), ArgoCD applies the change to the Kubernetes cluster automatically.

GITOPS FLOW
============
Developer merges PR
  --> CI builds and pushes image: order-service:1.5
  --> CI commits updated image tag to config repo (gitops-configs)

ArgoCD watches config repo
  --> Detects change: order-service image updated to 1.5
  --> Applies to Kubernetes cluster
  --> Rolling update begins automatically
  --> Production now runs order-service:1.5

No human ran "kubectl apply". Git is the single source of truth.

GitOps provides a full audit trail — every production change corresponds to a Git commit with an author, timestamp, and reason for the change.

Leave a Comment

Your email address will not be published. Required fields are marked *