Skip to main content

Kubernetes Fundamentals

Volume 5 — Platform Engineering

A note before diving in: Traxs infrastructure currently runs on Azure App Service, not Kubernetes — nothing in this chapter reflects a planned migration. It's included because Kubernetes concepts and vocabulary show up constantly in the broader industry, in job postings, in vendor documentation, and in architecture discussions, and understanding them well enough to evaluate whether they'd ever apply is worth having independent of current usage.

1. What Problem Kubernetes Solves

Docker Compose (Volume 3) orchestrates containers on a single machine. Kubernetes does the same job — running, networking, and scaling containers — across a cluster of many machines, with automatic handling of failures, scaling, and rolling updates that Compose simply doesn't address.

2. Core Concepts

ConceptWhat it is
PodThe smallest deployable unit — one or more tightly-coupled containers that share networking and storage, scheduled together on the same node
DeploymentDeclares "run N replicas of this pod" and manages rolling updates, restarts, and scaling to maintain that desired state
ServiceA stable network identity/DNS name in front of a set of pods — pods are ephemeral and get replaced constantly, a Service gives callers something consistent to reach regardless of which specific pods are currently running
IngressRoutes external HTTP(S) traffic into the cluster, to the right Service, based on hostname/path — the Kubernetes-world equivalent of the reverse proxy concepts from Volume 2
NamespaceA way to logically partition a cluster — separate environments (dev/staging/prod) or teams within the same physical cluster
ConfigMap / SecretExternalized configuration and sensitive values injected into pods — conceptually similar to App Service application settings and Key Vault references, respectively

3. A Minimal Deployment and Service

apiVersion: apps/v1
kind: Deployment
metadata:
name: roundtrip-api
spec:
replicas: 3
selector:
matchLabels:
app: roundtrip-api
template:
metadata:
labels:
app: roundtrip-api
spec:
containers:
- name: roundtrip-api
image: traxsregistry.azurecr.io/roundtrip-api:latest
ports:
- containerPort: 8080
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
---
apiVersion: v1
kind: Service
metadata:
name: roundtrip-api-service
spec:
selector:
app: roundtrip-api
ports:
- port: 80
targetPort: 8080

The selector/labels pairing is how a Service finds its pods — not by name, but by matching labels, which is also how a Deployment knows which pods it owns when replacing or scaling them.

4. kubectl — the CLI

kubectl get pods # list pods in the current namespace
kubectl get pods -n production # list pods in a specific namespace
kubectl describe pod roundtrip-api-xyz # detailed info, including recent events — the first stop when a pod isn't behaving
kubectl logs roundtrip-api-xyz # a pod's logs
kubectl logs roundtrip-api-xyz -f # follow live
kubectl exec -it roundtrip-api-xyz -- bash # shell into a running pod, same idea as docker exec
kubectl apply -f deployment.yaml # create/update resources from a YAML file
kubectl scale deployment roundtrip-api --replicas=5 # manually scale
kubectl rollout status deployment roundtrip-api # watch a rolling update's progress
kubectl rollout undo deployment roundtrip-api # roll back to the previous version

5. Health Probes

Kubernetes uses the same health-probe concept from the Load Balancers & Reverse Proxies chapter (Volume 3), but with two distinct probe types serving different purposes:

ProbeQuestion it answersConsequence of failure
Liveness probe"Is this container still working, or should it be restarted?"Kubernetes kills and restarts the container
Readiness probe"Is this container ready to receive traffic right now?"The pod is temporarily removed from the Service's routing, without being restarted
livenessProbe:
httpGet:
path: /health/live
port: 8080
periodSeconds: 10

readinessProbe:
httpGet:
path: /health/ready
port: 8080
periodSeconds: 5

Conflating these two is a common mistake: a pod that's simply busy (still starting up, or momentarily overloaded but otherwise fine) should fail its readiness probe temporarily, not its liveness probe — restarting a container that was just working hard, not actually broken, only makes the underlying load problem worse.

6. Autoscaling

A Horizontal Pod Autoscaler adjusts replica count automatically based on observed load:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: roundtrip-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: roundtrip-api
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

Conceptually the same idea as App Service's own autoscale rules — Kubernetes just makes the scaling target (a specific Deployment) and the trigger metric explicit as its own resource, rather than a setting on the hosting platform.

7. Kubernetes vs. App Service: When Each Makes Sense

Azure App Service (current Traxs approach)Kubernetes
Operational overheadLow — Azure manages the underlying infrastructure entirelyHigh — someone owns cluster upgrades, node management, networking configuration
FlexibilityOpinionated, covers the common web-app hosting case wellExtremely flexible — arbitrary workloads, custom networking, complex multi-service topologies
Team size fitWell suited to a small team without dedicated platform/infrastructure engineersGenerally justified once there's a dedicated team (or at least a dedicated role) managing the platform itself
Traxs current fitMatches the current single-region, moderate-scale, .NET web application architecture wellWould add meaningful operational burden without a corresponding current need

The honest assessment: for the current Traxs architecture and team size, App Service is doing the job Kubernetes would do, with meaningfully less operational overhead. Kubernetes becomes worth genuinely evaluating if requirements shift toward things App Service doesn't handle well — highly customized networking topologies, workloads that aren't a good fit for App Service's model, or a scale where the flexibility starts to outweigh the added operational cost. That's a future architectural decision, not a current gap.

8. Troubleshooting Playbook

(Included for completeness and future reference — not reflecting current Traxs infrastructure.)

SymptomLikely causeWhat to check
Pod stuck in PendingCluster doesn't have available resources (CPU/memory) matching the pod's requestskubectl describe pod — the Events section usually states the scheduling failure reason directly
Pod in CrashLoopBackOffContainer repeatedly failing its liveness probe or exiting on startupkubectl logs <pod> --previous to see the log from the crashed instance, not the fresh restart
Service returns no response, pods look healthyLabel selector mismatch between Service and podskubectl get pods --show-labels compared against the Service's selector
Readiness probe failing right after a fresh deployProbe configured with too short an initial delay for the app's actual startup timeAdd/increase initialDelaySeconds on the readiness probe
Rolling update stuck partwayNew pods failing their readiness probe, so Kubernetes won't proceed with replacing the restkubectl rollout status and kubectl describe pod on the new replica set's pods

9. Quick Reference

CategoryItemDetail
ConceptPodSmallest deployable unit, one or more containers
ConceptDeploymentManages desired replica count and rolling updates
ConceptServiceStable network identity in front of ephemeral pods
ConceptIngressExternal HTTP(S) routing into the cluster
ProbeLivenessFailure → container restarted
ProbeReadinessFailure → pod temporarily removed from routing, not restarted
Commandkubectl get podsList pods
Commandkubectl describe podDetailed status and recent events
Commandkubectl logs -fFollow a pod's logs
Commandkubectl rollout undoRoll back a deployment

Part of the Traxs Engineering Handbook — Volume 5: Platform Engineering. Companion chapters in this volume: Linux Fundamentals, Linux Administration, CI/CD, Observability, Secrets Management.