Application Design and Build (20%)¶
This domain covers designing and building cloud native applications for Kubernetes.
Container Images¶
Building Container Images¶
# Example Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
USER 1000
CMD ["python", "app.py"]
Multi-stage Builds¶
# Build stage
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o myapp
# Runtime stage
FROM alpine:3.18
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]
Image Best Practices¶
- Use specific image tags, not
latest - Use minimal base images (alpine, distroless)
- Run as non-root user
- Use multi-stage builds to reduce image size
- Scan images for vulnerabilities
Jobs and CronJobs¶
Job¶
A Job creates one or more Pods and ensures they complete successfully.
apiVersion: batch/v1
kind: Job
metadata:
name: pi-job
spec:
completions: 3
parallelism: 2
backoffLimit: 4
activeDeadlineSeconds: 100
template:
spec:
containers:
- name: pi
image: perl:5.34
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Key Fields:
| Field | Description |
|---|---|
completions | Number of successful completions required |
parallelism | Number of pods running in parallel |
backoffLimit | Number of retries before marking as failed |
activeDeadlineSeconds | Maximum time for the job |
restartPolicy | Must be Never or OnFailure |
CronJob¶
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-cronjob
spec:
schedule: "0 2 * * *" # Daily at 2 AM
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:v1
command: ["/bin/sh", "-c", "backup.sh"]
restartPolicy: OnFailure
Cron Schedule Format:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6)
│ │ │ │ │
* * * * *
Concurrency Policies:
| Policy | Description |
|---|---|
Allow | Allow concurrent jobs (default) |
Forbid | Skip new job if previous is still running |
Replace | Replace currently running job with new one |
Multi-Container Pods¶
Sidecar Pattern¶
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-shipper
image: fluentd:v1
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}
Init Containers¶
Init containers run before app containers start:
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: init-db
image: busybox:1.36
command: ['sh', '-c', 'until nc -z db-service 5432; do sleep 2; done']
- name: init-config
image: busybox:1.36
command: ['sh', '-c', 'wget -O /config/app.conf http://config-server/app.conf']
volumeMounts:
- name: config
mountPath: /config
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
emptyDir: {}
Ambassador Pattern¶
apiVersion: v1
kind: Pod
metadata:
name: app-with-ambassador
spec:
containers:
- name: app
image: myapp:v1
env:
- name: DB_HOST
value: "localhost"
- name: DB_PORT
value: "5432"
- name: ambassador
image: ambassador-proxy:v1
ports:
- containerPort: 5432
Adapter Pattern¶
apiVersion: v1
kind: Pod
metadata:
name: app-with-adapter
spec:
containers:
- name: app
image: legacy-app:v1
volumeMounts:
- name: logs
mountPath: /var/log
- name: adapter
image: log-adapter:v1
volumeMounts:
- name: logs
mountPath: /var/log
Volumes¶
emptyDir¶
Temporary storage that exists for the Pod's lifetime:
hostPath¶
Mount a file or directory from the host node:
PersistentVolumeClaim¶
Kubectl Imperative Commands¶
Create Resources Quickly¶
# Create a pod
kubectl run nginx --image=nginx --port=80
# Create a deployment
kubectl create deployment nginx --image=nginx --replicas=3
# Create a job
kubectl create job pi --image=perl -- perl -Mbignum=bpi -wle 'print bpi(2000)'
# Create a cronjob
kubectl create cronjob backup --image=backup --schedule="0 2 * * *" -- /bin/sh -c 'backup.sh'
# Generate YAML
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
Key Concepts to Remember¶
- Jobs - Run to completion, use
restartPolicy: NeverorOnFailure - CronJobs - Scheduled jobs using cron syntax
- Init containers - Run before main containers, must complete successfully
- Sidecar pattern - Helper container alongside main app
- Multi-stage builds - Reduce image size
Practice Questions¶
- How do you create a Job that runs 5 completions with 2 parallel pods?
- What is the difference between init containers and sidecar containers?
- How do you generate YAML for a pod without creating it?
- What cron schedule runs every Monday at 3 AM?
- What happens if a CronJob's concurrencyPolicy is set to Forbid?