Stage 7 · Master
CI/CD Pipeline
Continuous Deployment to Kubernetes: the First Safe Design
How a deployment pipeline should promote one immutable service image at a time, wait for rollout health, and stay honest about what Meridian has not implemented yet.
What CD Must Guarantee
A deployment pipeline exists to move an exact artifact into a known environment and then prove that the system is healthy afterward. A good pipeline therefore answers three questions precisely: what binary or image is being deployed, where is it being deployed, and how is success measured? If any of those answers is fuzzy, rollback becomes guesswork and incident debugging becomes archaeology.
For a Kubernetes-based Go backend, the minimum safe guarantees are straightforward. Build one immutable image per service. Tag it with the commit identity and preferably record the digest. Update only the target Deployment. Wait for rollout status to complete. Refuse to call the deploy successful merely because kubectl apply returned exit code 0.
Why This Is Still a Design Spec
The reference meridian repository does not yet contain Dockerfiles, Kubernetes manifests, GitHub Actions workflows, or a migration system. This chapter therefore specifies the first credible deployment design rather than pretending an automated production path already exists. That honesty matters: the educational goal is to teach how such a pipeline should be built from the current repository state, not to describe infrastructure that has not been written yet.
Push-Based vs GitOps
| Model | Why teams choose it | Recommended use for Meridian now |
|---|---|---|
| Push-based CD from CI | Fast to implement; the pipeline already knows the exact artifact it built | Best first step for Meridian's scaffolding phase because the repository still lacks deployment controllers and manifest overlays. |
| Full GitOps reconciler | Excellent drift detection and environment history | A good later evolution, but additional control-plane complexity is unnecessary before the first manifests and image builds exist. |
| Manual kubectl from laptops | Feels simple at first | Should be avoided for anything beyond experiments because artifact identity and auditability become weak immediately. |
Planned Deploy Assets
.github/workflows/deploy.ymlcreateResponsibility: Builds and pushes one service image, updates the matching Kubernetes Deployment, and waits for rollout success.
Why now: Each service is already an independent module and should become an independent deployment unit.
deploy/k8s/overlays/staging/kustomization.yamlcreateResponsibility: Pins staging-specific image references and operational values on top of the shared base manifests.
Why now: Environment differences should be declarative and reviewable instead of hidden inside shell commands.
deploy/k8s/overlays/production/kustomization.yamlcreateResponsibility: Defines the production overlay with higher replica counts and production secret references.
Why now: Production will differ in scale and credentials, but not in basic service topology.
Reference Workflow
name: deploy\n\non:\n workflow_dispatch:\n inputs:\n service:\n type: choice\n required: true\n options: [gateway, identity-service, community-service, billing-service]\n environment:\n type: choice\n required: true\n options: [staging, production]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n environment: ${{ inputs.environment }}\n steps:\n - uses: actions/checkout@v4\n - uses: docker/login-action@v3\n with:\n registry: ghcr.io\n username: ${{ github.actor }}\n password: ${{ secrets.GITHUB_TOKEN }}\n - name: Build and push image\n uses: docker/build-push-action@v6\n with:\n context: .\n file: ./apps/${{ inputs.service }}/Dockerfile\n push: true\n tags: ghcr.io/thesyscoder/meridian/${{ inputs.service }}:${{ github.sha }}\n - uses: azure/setup-kubectl@v4\n - name: Apply overlay and wait for rollout\n run: |\n kubectl apply -k deploy/k8s/overlays/${{ inputs.environment }}\n kubectl -n meridian rollout status deployment/${{ inputs.service }} --timeout=180sThis first design deliberately deploys one service at a time. That matches the repository's independent module boundaries and keeps rollback scope small.
Rollback and Safety Gates
Because Meridian has not yet implemented schema migrations, this initial CD design intentionally omits a migration step rather than inventing one. The correct forward plan is to reserve a pre-rollout hook for migrations once a real migrator and backward-compatible schema policy exist. Until then, the pipeline's core safety gates are CI success, protected deployment environments, rollout-status verification, and a practiced rollback path.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.