Compare commits
2
Commits
c0c6b4c1fc
...
b73df93f20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b73df93f20 | ||
|
|
55c5de9d61 |
@@ -93,3 +93,83 @@ jobs:
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
git.aridgwayweb.com/armistace/beer-data:latest
|
||||
|
||||
# The deploy job is separate from the build job on purpose. The
|
||||
# `KUBEC_CONFIG_BUILDX` secret is cluster-admin-equivalent, and a build
|
||||
# step that never talks to the cluster should not be able to read it - a
|
||||
# compromised dependency in the build would otherwise have a direct path to
|
||||
# the cluster.
|
||||
deploy:
|
||||
name: Deploy to the cluster
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: gitea.ref == 'refs/heads/master'
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create Kubeconfig
|
||||
run: |
|
||||
mkdir -p $HOME/.kube
|
||||
echo "${{ secrets.KUBEC_CONFIG_BUILDX }}" > $HOME/.kube/config
|
||||
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
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
|
||||
chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
||||
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list
|
||||
apt-get update
|
||||
apt-get install -y kubectl
|
||||
|
||||
- name: Deploy
|
||||
run: |
|
||||
# Apply the namespace and the non-secret manifests. The Secrets
|
||||
# (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 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
|
||||
kubectl -n beer rollout status deployment/beer-deployment --timeout=180s
|
||||
|
||||
- name: Verify the new image is actually running
|
||||
run: |
|
||||
# CI green and pods Ready do NOT prove the new code is live. Compare
|
||||
# the running digest against the registry's :latest.
|
||||
RUNNING=$(kubectl -n beer get pod -l app=beer-data \
|
||||
-o jsonpath='{.items[0].status.containerStatuses[0].imageID}')
|
||||
REGISTRY=$(curl -s -u "armistace:${{ secrets.REG_PASSWORD }}" -I \
|
||||
"https://git.aridgwayweb.com/v2/armistace/beer-data/manifests/latest" \
|
||||
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
|
||||
| grep -i docker-content-digest | awk '{print $2}' | tr -d '\r')
|
||||
echo "running: $RUNNING"
|
||||
echo "registry: $REGISTRY"
|
||||
if [ "$RUNNING" != "$REGISTRY" ]; then
|
||||
echo "ERROR: the running pod is not the image that was just pushed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Smoke test the deployed app
|
||||
run: |
|
||||
# The pods are behind a NodePort. Hit the service directly from
|
||||
# inside the cluster.
|
||||
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
|
||||
echo "healthz OK"
|
||||
break
|
||||
fi
|
||||
echo "waiting for the app to come up ($i/12)"
|
||||
sleep 5
|
||||
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)"
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: beer-deployment
|
||||
namespace: beer
|
||||
labels:
|
||||
app: beer-data
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: beer-data
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: beer-data
|
||||
spec:
|
||||
containers:
|
||||
- name: beer-data
|
||||
image: git.aridgwayweb.com/armistace/beer-data:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 5000
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: MONGO_HOST
|
||||
value: "192.168.178.229"
|
||||
- name: MONGO_USER
|
||||
value: "root"
|
||||
# MONGO_PASS and SECRET_KEY come from the live Secret - they are
|
||||
# deliberately NOT in this file. See RUNBOOK.md.
|
||||
- name: MONGO_PASS
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: beer-db
|
||||
key: mongo_pass
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: beer-app
|
||||
key: secret_key
|
||||
resources:
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 5000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: 5000
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
# The image creates a named user "beer". kubelet cannot verify that a
|
||||
# *named* user is non-root (it can only check a numeric UID), so the
|
||||
# UID is set explicitly here. It must match the UID in the image.
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
fsGroup: 999
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: archlinux-k3s-3
|
||||
imagePullSecrets:
|
||||
- name: beercred
|
||||
terminationGracePeriodSeconds: 30
|
||||
restartPolicy: Always
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: beer-service
|
||||
namespace: beer
|
||||
labels:
|
||||
app: beer-data
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: beer-data
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 5000
|
||||
nodePort: 30015
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: beer
|
||||
labels:
|
||||
app: beer-data
|
||||
Reference in New Issue
Block a user