Skip to content
Latchkey

Deploying to Kubernetes from CI/CD

A Kubernetes deploy is a new image, an updated manifest, and a watched rollout.

This module starts with the fundamental Kubernetes deploy loop from a pipeline: build an image, push it, point the deployment at the new tag, and wait for the rollout. Later lessons add Helm, GitOps, and progressive delivery on top of this base.

The deploy loop

  • Build and push a uniquely tagged image (use the commit SHA).
  • Authenticate the pipeline to the cluster.
  • Update the deployment to reference the new image tag.
  • Wait for the rollout and verify pods are healthy.

Tag images immutably

Never deploy :latest. Tag images with the commit SHA so each deploy references an exact, reproducible build. This makes rollbacks deterministic and avoids the cluster pulling a different image than you tested under a moving tag.

A basic deploy job

Set the image on the deployment, then wait for the rollout to complete:

.github/workflows/deploy-k8s.yml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          IMAGE=registry.example.com/app:${{ github.sha }}
          docker build -t $IMAGE . && docker push $IMAGE
          kubectl set image deployment/app app=$IMAGE
          kubectl rollout status deployment/app --timeout=120s

Verify the rollout

The kubectl rollout status command blocks until new pods are ready or the timeout hits, failing the job if the rollout stalls. This catches crash-looping pods or failed readiness checks instead of reporting a broken deploy as success.

Key takeaways

  • The Kubernetes deploy loop is push image, update deployment, watch rollout.
  • Tag images by commit SHA for reproducible, rollback-friendly deploys.
  • Use kubectl rollout status so a stalled rollout fails the job.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →