feat(ci): add the deploy job and the kubernetes manifests #8
@@ -93,6 +93,7 @@ jobs:
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
git.aridgwayweb.com/armistace/beer-data:latest
|
||||
git.aridgwayweb.com/armistace/beer-data:${{ github.sha }}
|
||||
|
||||
# The deploy job is separate from the build job on purpose. The
|
||||
# `KUBEC_CONFIG_BUILDX` secret is cluster-admin-equivalent, and a build
|
||||
@@ -117,6 +118,11 @@ jobs:
|
||||
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
# Skip the whole apt dance if the runner already has a kubectl.
|
||||
if command -v kubectl >/dev/null 2>&1; then
|
||||
kubectl version --client
|
||||
exit 0
|
||||
fi
|
||||
apt-get update
|
||||
apt-get install -y apt-transport-https ca-certificates curl gnupg
|
||||
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
@@ -131,14 +137,21 @@ jobs:
|
||||
# (beer-db, beer-app) are hand-provisioned and are NOT in the repo,
|
||||
# so they are deliberately not in the apply set.
|
||||
kubectl apply -f kube/beer_namespace.yaml
|
||||
kubectl apply -f kube/beer-deployment.yaml
|
||||
kubectl apply -f kube/beer-service.yaml
|
||||
# The deployment manifest carries a sentinel image tag; the real
|
||||
# SHA-pinned image is set immediately below. Applying it here
|
||||
# keeps the rest of the spec (probes, resources, security context)
|
||||
# in the repo and under review.
|
||||
kubectl apply -f kube/beer-deployment.yaml
|
||||
|
||||
# The image tag is `:latest`, which is immutable in the manifest, so
|
||||
# `kubectl apply` alone does NOT roll the pods. Without the restart
|
||||
# the deployment reports success while the old pods keep serving
|
||||
# the old image.
|
||||
kubectl -n beer rollout restart deployment/beer-deployment
|
||||
# The image is pinned to the commit SHA rather than `:latest`.
|
||||
# `kubectl set image` writes the SHA into the pod template, which
|
||||
# makes the change a real manifest change - the Deployment rolls
|
||||
# because its pod template changed, not because it was told to.
|
||||
# That also makes `kubectl rollout undo` meaningful: it can go back
|
||||
# to the previous SHA.
|
||||
kubectl -n beer set image deployment/beer-deployment \
|
||||
beer-data=git.aridgwayweb.com/armistace/beer-data:${{ github.sha }}
|
||||
kubectl -n beer rollout status deployment/beer-deployment --timeout=180s
|
||||
|
||||
- name: Verify the new image is actually running
|
||||
@@ -160,8 +173,10 @@ jobs:
|
||||
|
||||
- name: Smoke test the deployed app
|
||||
run: |
|
||||
# The pods are behind a NodePort. Hit the service directly from
|
||||
# inside the cluster.
|
||||
# Check the app's own port from inside the pod, AND the Service in
|
||||
# front of it. The pod check alone would pass even if the Service
|
||||
# selector or the port mapping were wrong, which is exactly the
|
||||
# kind of breakage a deploy can introduce silently.
|
||||
for i in $(seq 1 12); do
|
||||
if kubectl -n beer exec deploy/beer-deployment -- \
|
||||
python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:5000/healthz').status==200 else 1)"; then
|
||||
@@ -173,3 +188,7 @@ jobs:
|
||||
done
|
||||
kubectl -n beer exec deploy/beer-deployment -- \
|
||||
python -c "import urllib.request,sys; r=urllib.request.urlopen('http://127.0.0.1:5000/readyz'); print('readyz:', r.read().decode()); sys.exit(0 if r.status==200 else 1)"
|
||||
|
||||
# Through the Service - the path a real client takes.
|
||||
kubectl -n beer run smoke --rm -i --restart=Never --image=python:3.14-slim -- \
|
||||
python -c "import urllib.request,sys; r=urllib.request.urlopen('http://beer-service.beer.svc.cluster.local/healthz'); print('service healthz:', r.read().decode()); sys.exit(0 if r.status==200 else 1)"
|
||||
|
||||
@@ -22,7 +22,13 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: beer-data
|
||||
image: git.aridgwayweb.com/armistace/beer-data:latest
|
||||
# The image tag is pinned to the commit SHA by CI (`kubectl set
|
||||
# image`). The value here is a sentinel: applying the manifest
|
||||
# as-is would leave the deployment on that sentinel, so CI always
|
||||
# replaces it before rolling. It is deliberately NOT `:latest` —
|
||||
# a mutable tag makes the rollout a no-op (the pod template does not
|
||||
# change) and makes `rollout undo` meaningless.
|
||||
image: git.aridgwayweb.com/armistace/beer-data:SET_BY_CI
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
@@ -56,7 +62,10 @@ spec:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
# The app reads its own source and talks to Mongo over the
|
||||
# network. It writes no files, so the root filesystem can be
|
||||
# read-only. /tmp is still writable via the emptyDir below.
|
||||
readOnlyRootFilesystem: true
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
|
||||
Reference in New Issue
Block a user