04 β Kubernetes Manifests
What Kubernetes is: the system that runs your containerised app in production. It restarts your app if it crashes, runs multiple copies for reliability, and rolls out new versions without downtime. What a manifest is: a YAML file that tells Kubernetes what to run and how.
4.1 Deployment β kubernetes/deployment.yaml
Keeps 2+ copies of your app running at all times.
Rules
replicas: 2minimum- CPU and memory requests and limits defined
- livenessProbe β detects a frozen process so Kubernetes can restart it. Point it at
/healthz, which must not depend on the database (see guide 08 β a DB outage must not restart-loop your app). - readinessProbe β tells Kubernetes when the pod may receive traffic. Point it at
/readyz, which should include the DB connectivity check. - All secrets referenced via
secretKeyRefβ never plain-text values securityContextenforcing non-root (defence in depth on top of the DockerfileUSER)- The container port, Service
targetPort, probe ports, and the app'sAPP_PORTmust all agree.
Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 2 # Always run 2 copies for high availability
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
securityContext:
runAsNonRoot: true # Refuse to start if the image tries to run as root
# (requires a NUMERIC `USER` in the Dockerfile β see guide 03)
containers:
- name: my-app
# β The pipeline replaces this with the correct ECR image URI on deploy
image: <AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/my-app:latest
ports:
- containerPort: 3000 # Must match EXPOSE in the Dockerfile and APP_PORT
resources:
requests:
cpu: "100m" # 0.1 core minimum
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
env:
- name: APP_PORT
valueFrom:
configMapKeyRef:
name: my-app-config
key: app-port
- name: APP_ENV
valueFrom:
configMapKeyRef:
name: my-app-config
key: app-env
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: my-app-config
key: log-level
- name: DB_HOST
valueFrom:
secretKeyRef:
name: my-app-secrets # Created by the DevOps team
key: db-host
- name: DB_PORT
valueFrom:
secretKeyRef:
name: my-app-secrets
key: db-port
- name: DB_NAME
valueFrom:
secretKeyRef:
name: my-app-secrets
key: db-name
- name: DB_USER
valueFrom:
secretKeyRef:
name: my-app-secrets
key: db-user
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secrets
key: db-password
livenessProbe:
httpGet:
path: /healthz # Process-alive only β no DB dependency
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz # Ready to serve β may include DB check
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
(If your app only implements a single /healthz, you may point both probes at it β but then /healthz must NOT fail when the database is down, or Kubernetes will restart healthy pods in a loop during a DB outage.)
4.2 Service β kubernetes/service.yaml
Gives your app a stable internal address and load-balances across replicas.
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app # Must match the Deployment's pod labels
ports:
- protocol: TCP
port: 80 # Port other services use inside the cluster
targetPort: 3000 # Must match containerPort in the Deployment
type: ClusterIP # Internal only β DevOps handles external access via Ingress
4.3 ConfigMap β kubernetes/configmap.yaml (only if needed)
Non-sensitive config only. Never put a secret in a ConfigMap β they are not encrypted.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
data:
app-port: "3000"
app-env: "production"
log-level: "info"
Naming convention
Use your app's name consistently: Deployment metadata.name, container name, Secret <app>-secrets, ConfigMap <app>-config, Service <app>-svc. The pipeline's DEPLOYMENT_NAME and CONTAINER_NAME variables must match.
Prompt tip
"Write Kubernetes manifests at
kubernetes/deployment.yaml,kubernetes/service.yaml, andkubernetes/configmap.yaml. Deployment: 2 replicas, CPU/memory requests and limits,runAsNonRoot, liveness probe on/healthz(no DB dependency), readiness probe on/readyz, all secrets viasecretKeyReffrom a Secret named<app>-secrets, non-sensitive config viaconfigMapKeyReffrom<app>-config."