Capstone: Deliver
Kubernetes and CI/CD.
Step five. A container on a laptop is a demo. In production, it runs on Kubernetes, with several copies, health checks, and updates without downtime, and the whole path, from a code change to a running service, is automated. We describe both, in files, which is exactly the point. Everything is code.

- Describe the deployment as code
- Automate the whole path
- Everything is reviewable
The deployment files
Here are the deployment files, which you can read, thanks to the Kubernetes course. A deployment with three replicas of our container image, tagged with a version. A readiness probe on the health endpoint, so traffic only reaches pods that have loaded the model. Requests, and limits for processor and memory. And a service, which gives the pods one stable address. To release a new model, only the image tag changes, and Kubernetes performs a rolling update, with no downtime.
apiVersion: apps/v1
kind: Deployment
metadata:
name: churn-api
spec:
replicas: 3
selector:
matchLabels:
app: churn-api
template:
metadata:
labels:
app: churn-api
spec:
containers:
- name: api
image: registry.example.com/churn-api:1
ports:
- containerPort: 8000
readinessProbe:
httpGet:
path: /health
port: 8000
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
memory: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: churn-api
spec:
selector:
app: churn-api
ports:
- port: 80
targetPort: 8000The delivery pipeline
And here is the pipeline that ties it together. The first job, trains, tests, and gates. It pulls the versioned data, reproduces the pipeline, runs the tests, and runs the promotion script, which only promotes a model that beats the champion. The second job ships, and needs the first to pass. It pulls the champion model, builds the image, tagged with the commit, pushes it, and updates the image tag in the manifests, which a Git ops tool delivers to the cluster. A person only reviews the pull request. Everything else is automatic, and traceable.
name: capstone
on:
push:
branches: [main]
jobs:
train-test-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements-dev.txt
- run: dvc pull
- run: dvc repro
- run: pytest -q
- run: python src/promote.py
ship:
needs: train-test-gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: dvc pull models/model.joblib
- run: docker build -t registry.example.com/churn-api:${{ github.sha }} .
- run: docker push registry.example.com/churn-api:${{ github.sha }}
- run: ./scripts/set-image.sh ${{ github.sha }}Summary
Wonderful. The deployment, and the pipeline, are described as files, reviewed like code. A merge triggers training, testing, the gate, and the build, and Git ops rolls out the new image. Finally, step six, operating the system, and closing the loop.
Key takeaways- Deployment and service as YAML
- Pipeline: train, test, gate, ship
- A merge is the release