A Pod is Kubernetes' atomic unit — one or more containers sharing a network namespace and storage. You almost never deploy a bare Pod in production (Deployments and StatefulSets do that for you), but understanding Pods directly is the foundation.
Prerequisites
- A running cluster — k3s, kind, minikube, or full kubeadm. See Install k3s for the easy path.
kubectlconfigured (kubectl get nodesworks).
Step 1: Imperative first — get something running
kubectl run nginx --image=nginx:1.27-alpine --restart=Never
kubectl get pods
kubectl get pod nginx -o wide
--restart=Never makes it a bare Pod. Without that flag, kubectl run would create a Deployment.
Watch it come up:
kubectl wait --for=condition=Ready pod/nginx --timeout=60s
kubectl describe pod nginx | tail -30
Step 2: Declarative — write the YAML
pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
Apply and inspect:
kubectl apply -f pod.yaml
kubectl get pods -o wide
kubectl describe pod web | tail -20
Step 3: Reach the pod
# port-forward from your workstation
kubectl port-forward pod/web 8080:80 &
curl http://localhost:8080/
# exec a shell inside
kubectl exec -it web -- sh
# tail logs
kubectl logs web -f
Step 4: Init containers and sidecars
For pods that need setup before the main container runs:
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ['sh', '-c', 'until nc -z db 5432; do sleep 2; done']
containers:
- name: app
image: skyline/api:1.0
- name: log-shipper # sidecar
image: skyline/log-shipper:1.0
The init container must exit 0 before the main containers start.
Step 5: Pod lifecycle and restart policy
Three restartPolicy values:
Always— default for DeploymentsOnFailure— for Job-like workloadsNever— for one-shot diagnostic pods
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: skyline/db-backup:1.0
Watch state transitions:
kubectl get pods -w
States you will see: Pending → ContainerCreating → Running → Succeeded/Failed/CrashLoopBackOff.
Step 6: Delete and clean up
kubectl delete pod web
kubectl delete -f pod.yaml
Pods do not respawn — they are gone forever. Use Deployments in production. A bare Pod is only for one-off diagnostics or learning.
Verify
kubectl get pods
kubectl get events --sort-by=.lastTimestamp | tail -20
kubectl top pod # if metrics-server is installed
Conclusion
A Pod is the smallest unit you deploy. Knowing how to write one (and read one's events / logs / describe output) is the foundation for understanding Deployments, StatefulSets, DaemonSets, and Jobs — which all just template Pods.
Next steps
- Expose this pod to the network via Kubernetes service with NodePort.
- Set up a cluster first if you skipped ahead — k3s lightweight Kubernetes.
- For container basics see Docker + Compose on Ubuntu.
Comments
0 total · 0 threads