Skill 92 · K8S Manifest Generator
Subchapter 92.1
references/deployment-spec.mdMarkdown17 KBView on GitHub
Comprehensive reference for Kubernetes Deployment resources, covering all key fields, best practices, and common patterns.
A Deployment provides declarative updates for Pods and ReplicaSets. It manages the desired state of your application, handling rollouts, rollbacks, and scaling operations.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
labels:
app.kubernetes.io/name: my-app
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: backend
app.kubernetes.io/part-of: my-system
annotations:
description: "Main application deployment"
contact:
apiVersion: apps/v1 (current stable version)kind: Deploymentmetadata.name: Unique name within namespacemetadata.namespace: Target namespace (defaults to default)metadata.labels: Key-value pairs for organizationmetadata.annotations: Non-identifying metadatareplicas (integer, default: 1)
revisionHistoryLimit (integer, default: 10)
strategy.type (string)
RollingUpdate (default): Gradual pod replacementRecreate: Delete all pods before creating new onesstrategy.rollingUpdate.maxSurge (int or percent, default: 25%)
strategy.rollingUpdate.maxUnavailable (int or percent, default: 25%)
Best practices:
# Zero-downtime deployment
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# Fast deployment (can have brief downtime)
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
# Complete replacement
strategy:
type: Recreatetemplate.metadata.labels
spec.selector.matchLabelstemplate.spec.containers (required)
Image Management:
containers:
- name: app
image: registry.example.com/myapp:1.0.0
imagePullPolicy: IfNotPresent # or Always, NeverImage pull policies:
IfNotPresent: Pull if not cached (default for tagged images)Always: Always pull (default for :latest)Never: Never pull, fail if not cachedPort Declarations:
ports:
- name: http # Named for referencing in Service
containerPort: 8080
protocol: TCP # TCP (default), UDP, or SCTP
hostPort: 8080 # Optional: Bind to host port (rarely used)Requests vs Limits:
resources:
requests:
memory: "256Mi" # Guaranteed resources
cpu: "250m" # 0.25 CPU cores
limits:
memory: "512Mi" # Maximum allowed
cpu: "500m" # 0.5 CPU coresQoS Classes (determined automatically):
Guaranteed: requests = limits for all containers
Burstable: requests < limits or only requests set
BestEffort: No requests or limits set
Best practices:
Probe Types:
startupProbe - For slow-starting applications
startupProbe:
httpGet:
path: /health/startup
port: 8080
initialDelaySeconds: 0
periodSeconds: 10
failureThreshold: 30 # 5 minutes to start (10s * 30)livenessProbe - Restarts unhealthy containers
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3 # Restart after 3 failuresreadinessProbe - Controls traffic routing
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3 # Remove from service after 3 failuresProbe Mechanisms:
# HTTP GET
httpGet:
path: /health
port: 8080
httpHeaders:
- name: Authorization
value: Bearer token
# TCP Socket
tcpSocket:
port: 3306
# Command execution
exec:
command:
- cat
- /tmp/healthy
# gRPC (Kubernetes 1.24+)
grpc:
port: 9090
service: my.service.health.v1.HealthProbe Timing Parameters:
initialDelaySeconds: Wait before first probeperiodSeconds: How often to probetimeoutSeconds: Probe timeoutsuccessThreshold: Successes needed to mark healthy (1 for liveness/startup)failureThreshold: Failures before taking actionPod-level security context:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefaultContainer-level security context:
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE # Only if neededSecurity best practices:
runAsNonRoot: true)Volume Types:
volumes:
# PersistentVolumeClaim
- name: data
persistentVolumeClaim:
claimName: app-data
# ConfigMap
- name: config
configMap:
name: app-config
items:
- key: app.properties
path: application.properties
# Secret
- name: secrets
secret:
secretName: app-secrets
defaultMode: 0400
# EmptyDir (ephemeral)
- name: cache
emptyDir:
sizeLimit: 1Gi
# HostPath (avoid in production)
- name: host-data
hostPath:
path: /data
type: DirectoryOrCreateNode Selection:
# Simple node selector
nodeSelector:
disktype: ssd
zone: us-west-1a
# Node affinity (more expressive)
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
- arm64Pod Affinity/Anti-Affinity:
# Spread pods across nodes
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: my-app
topologyKey: kubernetes.io/hostname
# Co-locate with database
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: database
topologyKey: kubernetes.io/hostnameTolerations:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 30
- key: "dedicated"
operator: "Equal"
value: "database"
effect: "NoSchedule"spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: my-app
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: my-appspec:
template:
spec:
containers:
- name: app
image: myapp:1.0.0
volumeMounts:
- name: shared-logs
mountPath: /var/log
- name: log-forwarder
image: fluent-bit:2.0
volumeMounts:
- name: shared-logs
mountPath: /var/log
readOnly: true
volumes:
- name: shared-logs
emptyDir: {}spec:
template:
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command:
- sh
- -c
- |
until nc -z database-service 5432; do
echo "Waiting for database..."
sleep 2
done
- name: run-migrations
image: myapp:1.0.0
command: ["./migrate", "up"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
containers:
- name: app
image: myapp:1.0.0Fast startup:
spec:
minReadySeconds: 5
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 1Zero-downtime updates:
spec:
minReadySeconds: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0Graceful shutdown:
spec:
template:
spec:
terminationGracePeriodSeconds: 60
containers:
- name: app
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15 && kill -SIGTERM 1"]Pods not starting:
kubectl describe deployment <name>
kubectl get pods -l app=<app-name>
kubectl describe pod <pod-name>
kubectl logs <pod-name>ImagePullBackOff:
CrashLoopBackOff:
Deployment stuck in progress: