28Kubernetes for Testers
What you will master here
- The mental model: cluster, node, pod, deployment, service
- kubectl essentials
- Running tests in a Job / CronJob
- Ingress, ConfigMap, Secret
- Helm charts (5-minute intro)
- Where tests get observability (kubectl logs, events)
28.1 Mental model
- Cluster = control plane + worker nodes
- Node = VM/host running pods
- Pod = one or more containers sharing network + storage. Smallest deployable unit.
- Deployment = manages a set of identical pods (replicas) and rolling updates
- Service = stable network endpoint pointing at pods (load balancer)
- Ingress = HTTP router exposing services externally
- ConfigMap / Secret = injected config (env vars or files)
- Namespace = logical partition for grouping/quota/access
28.2 kubectl essentials
kubectl config use-context staging kubectl get nodes kubectl get pods -A # all namespaces kubectl get pods -n my-app -w # watch kubectl describe pod my-pod kubectl logs my-pod -f # follow kubectl logs my-pod -c container-name --previous kubectl exec -it my-pod -- /bin/sh kubectl port-forward svc/web 8080:80 # local 8080 → cluster service kubectl apply -f deploy.yaml kubectl delete -f deploy.yaml kubectl rollout restart deployment web kubectl rollout undo deployment web kubectl top pod # CPU/RAM
28.3 A test Job
apiVersion: batch/v1
kind: Job
metadata:
name: e2e-tests-pr-123
spec:
backoffLimit: 1
template:
spec:
restartPolicy: Never
containers:
- name: pw
image: mcr.microsoft.com/playwright:v1.50.0-jammy
env:
- name: BASE_URL
value: https://staging.acme.com
- name: ADMIN_PASS
valueFrom: { secretKeyRef: { name: e2e-secrets, key: admin-pass } }
command: ["npx","playwright","test","--shard=1/4"]
kubectl apply -f e2e-job.yaml kubectl logs -f job/e2e-tests-pr-123 kubectl wait --for=condition=complete --timeout=600s job/e2e-tests-pr-123
28.4 Deployment + Service + Ingress (mini stack)
apiVersion: apps/v1
kind: Deployment
metadata: { name: web }
spec:
replicas: 3
selector: { matchLabels: { app: web } }
template:
metadata: { labels: { app: web } }
spec:
containers:
- name: web
image: acme/web:1.2.0
ports: [{ containerPort: 3000 }]
readinessProbe:
httpGet: { path: /health, port: 3000 }
env:
- name: DATABASE_URL
valueFrom: { configMapKeyRef: { name: app-config, key: db-url } }
---
apiVersion: v1
kind: Service
metadata: { name: web }
spec:
selector: { app: web }
ports: [{ port: 80, targetPort: 3000 }]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: web }
spec:
rules:
- host: app.acme.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: web, port: { number: 80 } }
28.5 ConfigMap & Secret
kubectl create configmap app-config --from-literal=db-url=postgres://...
kubectl create secret generic e2e-secrets --from-literal=admin-pass=hunter2
kubectl get secret e2e-secrets -o jsonpath='{.data.admin-pass}' | base64 -d
28.6 Helm — package manager
helm repo add bitnami https://charts.bitnami.com/bitnami helm install pg bitnami/postgresql --namespace test --create-namespace helm upgrade --install web ./charts/web --values prod-values.yaml helm uninstall pg helm template ./charts/web # render YAML without applying
A Helm chart templatises YAML. values.yaml holds defaults; values-prod.yaml overrides for prod. Common for the SDET's test stack (DB + app + mocks).
28.7 Observability for tests
kubectl logs --tail=100 -f pod— live logskubectl get events --sort-by=.metadata.creationTimestamp— recent cluster events- Datadog / New Relic / Grafana — production-grade observability
- Lens / k9s — TUI alternatives to kubectl
28.8 Common SDET use cases
- Per-PR test environments — spin a namespace per PR, deploy app + dependencies, run E2E, destroy on close
- CronJob nightly — schedule full regression at 2 AM
- Long-running smoke — Deployment that runs synthetic monitoring against prod
- Test infra at scale — Selenium Grid / Playwright workers as deployments, autoscaled by queue depth
Module 52 — Kubernetes Q&A
What's a pod?
Smallest deployable unit in Kubernetes — one or more containers sharing network and storage. Almost always one main container; sidecars for logging/proxy/auth are common.
Deployment vs StatefulSet vs DaemonSet?
Deployment: stateless replicas, interchangeable. StatefulSet: stable identity + persistent storage per pod (DBs, Kafka). DaemonSet: one pod per node (log collectors).
What is a Service?
Stable DNS name + virtual IP load-balancing across the pods matching its selector. Pods come and go; the Service endpoint stays the same.
ConfigMap vs Secret?
Both inject config. ConfigMap = plain text (URLs, feature flags). Secret = sensitive data (passwords, tokens) — base64-encoded at rest and treated specially in dashboards/audit logs. Use cloud KMS-encrypted secrets for production.
What's a readiness probe?
A health check the kubelet runs to decide if a pod is ready to receive traffic. If failing, the Service won't route to it. Critical for rolling deploys (old pod stays alive until new one is ready).
How would you run E2E tests in k8s?
Job kind: one-shot pod that runs the test suite, restarts on failure (up to backoffLimit), writes results to a volume or pushes to a dashboard. CronJob for scheduled regression.
What's Helm and why use it?
Templating layer over Kubernetes YAML. Chart = bundle of templates + default values. Use to deploy complex stacks (DB+app+monitoring) consistently across environments with values overrides.
How do you tail logs from a failing pod?
kubectl logs pod-x -f follow. --previous shows logs from the previous (crashed) container. --all-containers=true for multi-container pods.How do you expose a cluster service to your laptop?
kubectl port-forward svc/web 8080:80 tunnels local 8080 to the cluster service. Useful for debugging or running tests from your laptop against a remote app.What's a namespace and why use one per PR?
Logical isolation boundary — quotas, RBAC, network policies. Per-PR namespace gives each PR its own copy of app + DB without colliding. Spin up on PR open, tear down on close.