Kubernetes Fundamentals: Container Orchestration at Scale
Kubernetes (K8s) automates the deployment, scaling, and management of containerized applications. This guide covers the essential objects and commands you need to run workloads in a cluster.
kubectl Basics
kubectl is the primary CLI for interacting with a Kubernetes cluster:
# View cluster info
kubectl cluster-info
# List all resources in the default namespace
kubectl get all
# Get detailed information about a resource
kubectl describe pod my-app-7d4f8b6c9-x2k5j
# View logs
kubectl logs -f deployment/my-app
# Execute a command in a running pod
kubectl exec -it my-app-7d4f8b6c9-x2k5j -- /bin/bash
# Apply a manifest
kubectl apply -f deployment.yaml
# Delete a resource
kubectl delete -f deployment.yaml
Pod Specification
A Pod is the smallest deployable unit. While you rarely create pods directly, understanding the spec is essential:
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
labels:
app: debug
spec:
containers:
- name: main
image: alpine:3.19
command: ["sleep", "3600"]
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Liveness probes restart the container if it becomes unresponsive. Readiness probes remove the pod from service endpoints until it is ready to accept traffic.
Deployments
Deployments manage ReplicaSets and provide declarative updates:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: myregistry/my-app:v1.2.3
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: my-app-config
- secretRef:
name: my-app-secrets
The RollingUpdate strategy replaces pods one at a time, ensuring zero
downtime.
Services
Services provide stable networking for a set of pods:
# ClusterIP -- reachable only within the cluster
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
type: ClusterIP
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
# NodePort -- accessible on every node at a static port
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30080
# LoadBalancer -- provisions an external LB (cloud providers)
spec:
type: LoadBalancer
ports:
- port: 443
targetPort: 8080
Ingress
Ingress routes external HTTP/HTTPS traffic to services:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
ConfigMaps and Secrets
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
data:
APP_ENV: production
LOG_LEVEL: info
---
apiVersion: v1
kind: Secret
metadata:
name: my-app-secrets
type: Opaque
data:
DB_PASSWORD: c3VwZXJzZWNyZXQ= # base64-encoded
Namespaces and Resource Limits
Namespaces isolate workloads. Combine them with ResourceQuotas:
kubectl create namespace staging
kubectl get pods -n staging
apiVersion: v1
kind: ResourceQuota
metadata:
name: staging-quota
namespace: staging
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
Return to the DevOps hub or continue to Docker Guide and Terraform Guide.