Kubernetes interview question
How would you run automated test suites inside Kubernetes?
Short answer
Package the tests as an image and run them as a Kubernetes Job, with config from ConfigMaps and Secrets, resource requests and limits, backoffLimit 0 so failures are not silently retried, and results shipped out as artifacts. For isolation, deploy the app into an ephemeral namespace per pull request.
Answer
There are two common patterns: CI agents running as pods (Jenkins Kubernetes plugin, GitHub Actions Runner Controller, GitLab Kubernetes executor), where Kubernetes just provides compute, and tests running as workloads inside the cluster, which is useful when the tests must reach internal Services. The second is what this question is usually about.
Tests as a Job
Tests run to completion, so they belong in a Job, not a Deployment (a Deployment would restart a finished test container forever). A CronJob suits scheduled runs such as nightly regression or synthetic checks.
apiVersion: batch/v1
kind: Job
metadata:
name: api-tests-1234
namespace: qa
spec:
backoffLimit: 0
activeDeadlineSeconds: 1800
ttlSecondsAfterFinished: 3600
template:
spec:
restartPolicy: Never
containers:
- name: tests
image: registry.example.com/api-tests:1.8.0
args: ["--suite", "regression"]
envFrom:
- configMapRef:
name: api-tests-config
- secretRef:
name: api-tests-credentials
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
memory: "1Gi"
kubectl apply -f job.yaml
kubectl wait --for=condition=complete job/api-tests-1234 -n qa --timeout=30m
kubectl logs job/api-tests-1234 -n qa
In a real pipeline you would wait for either complete or failed, because kubectl wait on complete alone just times out when the Job fails.
Settings that matter
backoffLimit: 0andrestartPolicy: Never: by default a failed Job is retried, which turns a failing suite into a slow, occasionally passing one. Retries should be a deliberate test-runner decision, not a side effect.activeDeadlineSeconds: a hung browser should not hold resources forever.ttlSecondsAfterFinished: cleans up finished Jobs automatically.- Resources: browsers are memory hungry. Without requests, pods get packed onto busy nodes and become slow and flaky; without limits, one runaway test can starve neighbours.
OOMKilledinkubectl describeis a common cause of mysterious failures. - Config and secrets from ConfigMaps and Secrets (ideally synced from a secret manager), so one image runs against any environment.
Getting results out
Container filesystems vanish with the pod. Options: have the runner upload reports to object storage or a test reporting service at the end, write to a persistent volume collected by the CI job, or at minimum print a machine-readable summary to stdout. Exit codes must propagate so the Job status reflects the test result.
Ephemeral environments
For isolation, many teams deploy the application into a namespace per pull request (via Helm or Kustomize, often triggered by CI or a GitOps tool), run tests as a Job in that namespace against service DNS names, then delete the namespace. This avoids shared-environment contention, at the cost of cluster capacity and longer setup; stubbing heavyweight dependencies keeps it affordable.
What interviewers look for
- Job vs Deployment, and correct failure semantics (
backoffLimit,restartPolicy). - Configuration through ConfigMaps/Secrets and sensible resource settings.
- A plan for results and environment isolation.
A strong answer covers
- Run tests as a Job (or CronJob), not a Deployment
- Config via ConfigMaps and Secrets, not baked into image
- Set backoffLimit and restartPolicy so failures are visible
- Resource requests/limits, especially for browsers
- Extract results and use ephemeral namespaces for isolation