- Published on
Kubernetes CKAD Certification Practice Exam (55 Questions + 10 Practical Simulations)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
CKAD Exam Overview
The CKAD (Certified Kubernetes Application Developer) is a hands-on, performance-based exam focused on deploying and managing applications on Kubernetes.
| Item | Details |
|---|---|
| Duration | 120 minutes |
| Questions | 15-20 performance-based tasks |
| Passing Score | 66% or above |
| Format | Online, proctored |
| Validity | 3 years |
| Kubernetes Version | Latest stable release |
Domain Weights
| Domain | Weight |
|---|---|
| Application Design & Build | 20% |
| Application Deployment | 20% |
| Application Observability & Maintenance | 15% |
| Application Environment, Configuration & Security | 25% |
| Services & Networking | 20% |
Developer-Focused kubectl Cheat Sheet
# ConfigMap creation
kubectl create configmap app-config --from-literal=key=value
kubectl create configmap app-config --from-file=config.properties
kubectl create configmap app-config --from-env-file=.env
# Secret creation
kubectl create secret generic db-secret --from-literal=password=mypassword
kubectl create secret docker-registry regcred \
--docker-server=REGISTRY \
--docker-username=USER \
--docker-password=PASS
# Rollout management
kubectl rollout status deployment myapp
kubectl rollout history deployment myapp
kubectl rollout undo deployment myapp
kubectl rollout pause deployment myapp
kubectl rollout resume deployment myapp
# Set resources
kubectl set resources deployment myapp --limits=cpu=200m,memory=512Mi
kubectl set resources deployment myapp --requests=cpu=100m,memory=256Mi
# Set env vars
kubectl set env deployment myapp ENV=production
kubectl set env deployment myapp --from=configmap/app-config
# Label management
kubectl label pod mypod env=production
kubectl label pod mypod env- # remove label
# Ephemeral debug container
kubectl debug -it POD_NAME --image=busybox --target=CONTAINER_NAME
# Helm basics
helm repo add stable https://charts.helm.sh/stable
helm install myrelease stable/nginx
helm upgrade myrelease stable/nginx --set image.tag=latest
helm rollback myrelease 1
helm uninstall myrelease
helm list
# Generate YAML with dry-run
kubectl create deployment myapp --image=nginx --dry-run=client -o yaml > deploy.yaml
kubectl run mypod --image=nginx --dry-run=client -o yaml > pod.yaml
Multiple Choice Questions (Q1 ~ Q55)
Domain 1: Application Design & Build
Q1. What is the difference between the Sidecar pattern and the Ambassador pattern?
A) Sidecar replaces the main container; Ambassador provides auxiliary functions B) Sidecar extends the main container (logging, monitoring); Ambassador proxies communication with external services C) Both patterns are identical D) Ambassador was removed in Kubernetes 1.25
Answer: B
Explanation: The Sidecar pattern adds supplementary capabilities (log collection, monitoring, security) alongside the main container. The Ambassador pattern acts as a proxy between the main container and external services. The Adapter pattern transforms the output format of the main container.
Q2. Which statement about Init Containers is correct?
A) Run concurrently with main containers B) Run sequentially before main containers start; main containers start only after all Init Containers complete C) If they fail, the Pod maintains Running state D) They run indefinitely
Answer: B
Explanation: Init Containers run sequentially before main containers start. Main containers start only after all Init Containers complete successfully. If an Init Container fails, it is restarted according to the Pod's restartPolicy. Common uses: DB migrations, config file preparation.
Q3. What is the role of the backoffLimit field in a Job?
A) Maximum execution time for the Job B) Maximum number of retry attempts on Job failure C) Limits the number of concurrent Pods D) Automatically deletes completed Jobs
Answer: B
Explanation: backoffLimit specifies the maximum retry attempts when a Job fails. The default is 6. Retry intervals increase exponentially (10s, 20s, 40s...). activeDeadlineSeconds limits the Job's total execution time.
Q4. What is the advantage of multi-stage builds in a Dockerfile?
A) Speeds up the build process B) Reduces the final image size by excluding unnecessary build tools C) Disables caching D) Enables simultaneous builds across multiple OS platforms
Answer: B
Explanation: Multi-stage builds separate the build environment (compiler, build tools) from the runtime environment. The first stage creates build artifacts; the second stage (with a lightweight base image) copies only the artifacts. This dramatically reduces image size.
Q5. What does concurrencyPolicy: Forbid do in a CronJob?
A) Runs a new Job concurrently even if the previous one has not completed B) Skips the new Job if the previous one is still running C) Forcibly terminates the previous Job and starts a new one D) Queues all Jobs
Answer: B
Explanation: concurrencyPolicy: Forbid skips new Job creation if a previous Job is still running. Allow (default) permits concurrent execution. Replace terminates the running Job and starts a new one.
Q6. How should you write a Dockerfile to optimize layer caching?
A) Combine all RUN commands into one B) Place frequently changing commands (COPY source code) near the bottom C) Use FROM multiple times D) Use many LABEL commands
Answer: B
Explanation: To optimize Docker layer caching, place infrequently changing commands (package installs) near the top and frequently changing commands (source code copy) near the bottom. This way, when source code changes, the package install layer cache is reused.
Q7. Which restartPolicy values should be used in Jobs and CronJobs?
A) Always — recommended for Jobs B) OnFailure or Never — used for Jobs and CronJobs C) OnSuccess — only available in Jobs D) Never — recommended in all cases
Answer: B
Explanation: Job and CronJob Pods must use OnFailure (restart on failure) or Never (no restart). Always is for long-running workloads like Deployments and DaemonSets. Using Always in a Job Pod causes it to restart indefinitely even after completion.
Q8. What is the key difference between StatefulSet and Deployment?
A) StatefulSet supports more replicas B) StatefulSet provides ordered Pod names, stable network identities, and per-Pod PVCs C) Deployment is better suited for stateful apps D) StatefulSet does not support rolling updates
Answer: B
Explanation: StatefulSet is designed for stateful applications: 1) Predictable Pod names (app-0, app-1), 2) Stable network IDs (via headless service), 3) Independent PVCs per Pod (volumeClaimTemplates), 4) Ordered deployment/update/deletion. Ideal for databases, Kafka, ZooKeeper.
Domain 2: Application Deployment
Q9. What is the difference between the Recreate and RollingUpdate strategies in a Deployment?
A) Recreate uses more resources B) Recreate deletes all Pods first and then creates new ones (causing downtime); RollingUpdate gradually replaces them (no downtime) C) RollingUpdate is only available on large clusters D) Both behave identically
Answer: B
Explanation: Recreate deletes all Pods in the current ReplicaSet before creating new ones. This causes downtime but prevents old and new versions from running simultaneously. RollingUpdate gradually replaces Pods without service interruption, controlled by maxSurge and maxUnavailable.
Q10. What is the purpose of kubectl rollout pause and kubectl rollout resume?
A) Pauses/resumes Pods B) Suspends a rollout mid-way for canary testing, then resumes to complete the update C) Completely stops a Deployment D) Pauses auto-scaling
Answer: B
Explanation: kubectl rollout pause deployment suspends an in-progress rollout. This allows canary testing with only some Pods on the new version. Once validated, kubectl rollout resume continues updating the remaining Pods.
Q11. What is the role of values.yaml in a Helm chart?
A) List of required chart components B) Defines default configuration values used when deploying the chart C) Kubernetes manifest files D) Helm repository credentials
Answer: B
Explanation: values.yaml defines default configuration values for the Helm chart. Override them at deploy time with --set or -f custom-values.yaml. Templates reference them as {{ .Values.image.tag }}.
Q12. What is the relationship between overlay and base in Kustomize?
A) overlay is identical to base B) base contains common configuration; overlay defines environment-specific (dev/staging/prod) changes C) overlay completely replaces base D) Kustomize does not support overlays
Answer: B
Explanation: In Kustomize, base contains common Kubernetes resource definitions. Overlay references base and adds environment-specific patches. Use with kubectl apply -k overlays/production/. This enables multi-environment deployments without Helm charts.
Q13. How do you update only a specific container image with kubectl set image?
A) kubectl set image deployment/myapp *=nginx:1.26 B) kubectl set image deployment/myapp nginx=nginx:1.26 C) kubectl update image deployment/myapp nginx:1.26 D) kubectl patch image deployment/myapp nginx=nginx:1.26
Answer: B
Explanation: Use the format kubectl set image deployment/DEPLOY_NAME CONTAINER_NAME=IMAGE:TAG. Example: kubectl set image deployment/myapp nginx=nginx:1.26. Update multiple containers by listing them space-separated.
Q14. What does the revisionHistoryLimit field in a Deployment control?
A) Specifies the number of rollout histories (old ReplicaSets) to retain B) Limits the maximum number of Pods C) Limits the number of automatic rollbacks D) Specifies time in hours to retain old versions
Answer: A
Explanation: revisionHistoryLimit controls how many old ReplicaSets the Deployment retains. Default is 10. Directly correlates to how many versions you can roll back to. Setting it to 0 immediately removes old ReplicaSets.
Q15. What is the command to roll back a Helm release to a previous version?
A) helm undo myrelease B) helm rollback myrelease REVISION C) helm revert myrelease D) helm restore myrelease
Answer: B
Explanation: helm rollback myrelease REVISION_NUMBER rolls back to a specific revision. Use helm history myrelease to see release history and revision numbers. Without a revision number, it rolls back to the most recent previous version.
Q16. How do you implement Blue/Green deployment in Kubernetes?
A) Use Deployment's Recreate strategy B) Run two Deployments (blue/green) and switch the Service selector to redirect traffic C) Implement with StatefulSet D) Implement with DaemonSet
Answer: B
Explanation: Blue/Green deployment: 1) Run blue Deployment (current production) and green Deployment (new version) simultaneously, 2) After green passes testing, change the Service selector from blue to green for instant traffic cutover, 3) Remove blue once confirmed stable. Enables instant switchover and fast rollback.
Domain 3: Application Observability & Maintenance
Q17. What happens when a Liveness Probe fails?
A) The Pod is deleted and recreated B) The container is restarted C) The Pod is moved to another node D) An alert is sent
Answer: B
Explanation: When a Liveness Probe fails, Kubernetes restarts the specific container (not the entire Pod). The restartPolicy is applied. After failureThreshold consecutive failures, a restart is triggered. Used to detect application deadlocks or infinite loops.
Q18. What happens when a Readiness Probe fails?
A) The container is restarted B) The Pod is removed from the Service's endpoints C) The Pod is deleted D) A new Pod is created
Answer: B
Explanation: When a Readiness Probe fails, the Pod is removed from the Service's Endpoints list and stops receiving traffic. The container is NOT restarted. When the Probe passes again, the Pod is re-added to Endpoints. Prevents traffic from going to unready Pods during rollouts.
Q19. What is the primary use case for a Startup Probe?
A) For legacy apps with slow startup times, delays Liveness Probe activation until the app is ready B) Initializes environment variables before container startup C) Performs cleanup tasks after container termination D) Checks external dependency status
Answer: A
Explanation: Startup Probe prevents Liveness Probes from failing too early on slow-starting applications. Liveness and Readiness Probes are not activated until the Startup Probe succeeds. Especially useful when containerizing legacy monolithic applications.
Q20. What does kubectl logs --since=1h mean?
A) Shows only logs within the last 1 hour B) Shows logs from 1 hour ago to the present C) Shows the first hour of log file content D) Streams logs for 1 hour
Answer: B
Explanation: kubectl logs POD_NAME --since=1h shows only logs from the past 1 hour. Use --since-time=2024-01-01T00:00:00Z for logs since a specific time. --tail=100 shows only the last 100 lines.
Q21. What is required for kubectl top pod to work?
A) Prometheus must be installed B) Metrics Server must be installed in the cluster C) Grafana must be configured D) kube-proxy must be in IPVS mode
Answer: B
Explanation: kubectl top pod and kubectl top node retrieve CPU and memory usage via the Kubernetes Metrics Server, which must be installed separately. Prometheus and other monitoring tools do not affect the kubectl top command.
Q22. What is the purpose of an Ephemeral Container?
A) Creates a temporary Pod B) Adds a temporary debugging container to an already-running Pod that lacks debugging tools C) Pauses a Pod D) Reduces resource usage
Answer: B
Explanation: Ephemeral Containers are used to debug containers that lack shells or debugging tools (like distroless or slim images). Use kubectl debug -it POD_NAME --image=busybox --target=CONTAINER to add one. GA since Kubernetes 1.23.
Q23. How do you configure an HTTP Liveness Probe for a container?
A) Use livenessProbe.tcpSocket B) Use livenessProbe.httpGet C) Use livenessProbe.exec D) Use livenessProbe.http
Answer: B
Explanation: HTTP Liveness Probe uses httpGet with path and port. A response code of 200-399 is considered success. tcpSocket checks TCP connectivity; exec runs a command and checks if the exit code is 0.
Domain 4: Application Environment, Configuration & Security
Q24. How do you inject a ConfigMap as environment variables into a Pod?
A) Use spec.containers.env.valueFrom.configMapKeyRef B) Use spec.containers.configmap C) Use spec.volumes.configmap D) Use spec.env.configmap
Answer: A
Explanation: Two ways to inject ConfigMaps as env vars: 1) Specific key: env[].valueFrom.configMapKeyRef references a specific key-value pair. 2) All keys: envFrom[].configMapRef injects all keys as environment variables. Volume mounting is best when you need files.
Q25. How are Kubernetes Secrets stored in etcd?
A) Encrypted with AES-256 B) Base64-encoded by default (not encrypted); etcd encryption requires separate configuration C) Stored as SHA-256 hashes D) Fully encrypted by default
Answer: B
Explanation: Kubernetes Secrets are only base64-encoded in etcd by default — not encrypted. To encrypt secrets at rest, configure --encryption-provider-config on kube-apiserver. Best practices: enforce RBAC on Secrets and enable etcd encryption.
Q26. What does setting runAsNonRoot: true in SecurityContext do?
A) Runs the container as the root user B) Rejects container startup if it would run as root (UID 0) C) Makes all container files read-only D) Removes network privileges
Answer: B
Explanation: securityContext.runAsNonRoot: true prevents the container from starting if it would run as root (UID 0). Combine with runAsUser: 1000 to enforce a specific UID. A security best practice to minimize blast radius from container escape attacks.
Q27. What is the difference between PodSecurityContext and container-level SecurityContext?
A) PodSecurityContext applies only to specific containers B) spec.securityContext applies to all containers in the Pod; container-level settings apply to that container only and override Pod-level settings C) Both settings are identical D) Container-level SecurityContext was removed in Kubernetes 1.24
Answer: B
Explanation: spec.securityContext (Pod level) applies to all containers (runAsUser, fsGroup, supplementalGroups, etc.). spec.containers[].securityContext (container level) applies only to that container and overrides Pod-level settings (capabilities, readOnlyRootFilesystem, etc.).
Q28. What does capabilities.drop: ["ALL"] do?
A) Adds all Linux capabilities to the container B) Removes all Linux capabilities from the container for least-privilege execution C) Runs the container in privileged mode D) Blocks network access
Answer: B
Explanation: capabilities.drop: ["ALL"] removes all Linux capabilities from the container. Then add back only what's needed via capabilities.add, applying the principle of least privilege. For example, a web server might only need NET_BIND_SERVICE.
Q29. What is the role of a LimitRange?
A) Limits total resource usage across the entire cluster B) Sets default and maximum resource requests/limits for individual Pods/Containers within a namespace C) Limits PVC sizes D) Limits the number of Pods per user
Answer: B
Explanation: LimitRange sets default, minimum, and maximum values for individual resources (Pod, Container, PVC) within a namespace. Containers without explicit requests/limits automatically get the default values applied. ResourceQuota limits the total sum across the namespace.
Q30. What is the purpose of a ResourceQuota?
A) Limits the max CPU/memory of individual Pods B) Limits the total sum of resources available across an entire namespace C) Limits resource usage on a node D) Limits container network bandwidth
Answer: B
Explanation: ResourceQuota limits the total number and capacity of resources that can be created within a namespace: CPU, memory, Pod count, PVC count, LoadBalancer service count, etc. Prevents one team from monopolizing resources in a shared cluster.
Q31. What is the difference between imagePullPolicy: IfNotPresent and Always?
A) IfNotPresent always pulls a fresh image; Always uses the cache B) IfNotPresent pulls only when the image is absent locally; Always checks the registry and pulls the latest image each time C) Both options are identical D) IfNotPresent only works with the latest tag
Answer: B
Explanation: IfNotPresent: Pulls only if the image is not present on the node. Uses the existing image if available. Always: Checks the registry and pulls the latest image every time. Recommended when using the latest tag or no digest.
Q32. How do you safely inject a Secret as an environment variable into a Pod?
A) Enter the value directly in spec.containers.env.value B) Use spec.containers.env.valueFrom.secretKeyRef C) Include secret value in spec.containers.args D) Store secret values in ConfigMap
Answer: B
Explanation: Use env[].valueFrom.secretKeyRef to inject a specific Secret key as an env var. Use envFrom[].secretRef to inject all keys at once. Storing Secret values directly in YAML or in a ConfigMap is a security risk.
Q33. Where is the ServiceAccount token automatically mounted?
A) /etc/kubernetes/ B) /var/run/secrets/kubernetes.io/serviceaccount/ C) /home/app/.kube/ D) /tmp/secrets/
Answer: B
Explanation: ServiceAccount tokens are automatically mounted at /var/run/secrets/kubernetes.io/serviceaccount/. This directory contains token, ca.crt, and namespace files. Disable auto-mounting with automountServiceAccountToken: false when not needed.
Domain 5: Services & Networking
Q34. What happens when a Service selector doesn't match any Pod labels?
A) The Service returns an error B) The Service has empty endpoints and delivers no traffic C) Traffic is delivered to all Pods D) The Service is automatically deleted
Answer: B
Explanation: If a Service selector doesn't match any Pod labels, the Service has no Endpoints. kubectl get endpoints SERVICE_NAME shows "none". The Endpoints field in kubectl describe service will be empty.
Q35. What is the difference between path-based routing and host-based routing in Ingress?
A) path-based is IP-based; host-based is domain-based B) path-based routes by URL path (/api, /web); host-based routes by hostname (api.example.com, web.example.com) C) Both methods are identical D) host-based does not support TLS
Answer: B
Explanation: Path-based routing routes different paths on the same domain to different services (example.com/api → api-service, example.com/web → web-service). Host-based routing routes different hostnames to different services (api.example.com → api-service).
Q36. How do you configure TLS in an Ingress?
A) Use the spec.ssl field B) Specify secretName (Secret containing the TLS certificate) and hosts in spec.tls C) Include TLS info in spec.annotations D) Only possible via Ingress Controller configuration
Answer: B
Explanation: Ingress TLS: set spec.tls with hosts (list of hosts to apply TLS to) and secretName (a kubernetes.io/tls type Secret). The Secret must contain tls.crt and tls.key keys.
Q37. Why would you configure egress rules in a NetworkPolicy?
A) Controls incoming traffic B) Controls outbound traffic from Pods to prevent unintended external connections C) Controls inter-node communication D) Blocks DNS queries
Answer: B
Explanation: Egress rules control outbound traffic from Pods. For example, prevent a database Pod from connecting to the internet, or restrict outbound traffic to specific ports (e.g., 5432 for PostgreSQL). DNS communication (port 53) must be explicitly allowed.
Q38. Which Service type maps a Service to an external DNS name?
A) ClusterIP B) NodePort C) LoadBalancer D) ExternalName
Answer: D
Explanation: ExternalName service allows using an external DNS name as if it were an internal service name. For example, it CNAME-maps my-database.default.svc.cluster.local to mysql.external.com. Useful for accessing external services from within the cluster.
Q39. What is the default behavior for Pod-to-Pod communication without NetworkPolicy?
A) All traffic is blocked by default B) Without NetworkPolicy, all Pod-to-Pod communication is allowed C) Only Pods in the same namespace can communicate D) Communication is only possible through Services
Answer: B
Explanation: In the default Kubernetes network model, all Pod-to-Pod communication is allowed when no NetworkPolicy is applied. When a NetworkPolicy targets a Pod, only traffic explicitly permitted by the policy is allowed. Security best practice: apply a default-deny NetworkPolicy and allow only necessary communication.
Q40. What is the difference between Ingress pathType: Prefix and Exact?
A) Prefix checks only the beginning of the path; Exact requires the full path to match exactly B) Prefix uses regex; Exact compares strings C) Both types are identical D) Exact is case-insensitive
Answer: A
Explanation: Prefix matches any URL that starts with the specified path (/api matches /api/users, /api/posts). Exact matches only URLs that are exactly equal to the specified path (/api matches only /api, not /api/users). ImplementationSpecific behavior depends on the Ingress Controller.
Q41. What happens when you set sessionAffinity: ClientIP on a Service?
A) Requests from the same client IP always route to the same Pod B) The session expires C) All requests concentrate on a single Pod D) Load balancing is disabled
Answer: A
Explanation: With sessionAffinity: ClientIP, requests from the same client IP always route to the same Pod (sticky session). sessionAffinityConfig.clientIP.timeoutSeconds sets the session duration. The default is None (random routing).
Q42. What is the correct DNS name for calling another service within the same namespace?
A) service-name.cluster.local B) service-name (or service-name.namespace.svc.cluster.local) C) namespace.service-name D) http://service-name:port
Answer: B
Explanation: Within the same namespace, just the service name is sufficient. From a different namespace, use service-name.namespace or the full FQDN service-name.namespace.svc.cluster.local.
Q43. Which Service types allow external access to Pods?
A) ClusterIP B) NodePort and LoadBalancer C) headless service D) ExternalName
Answer: B
Explanation: NodePort allows external access via a specific port (30000-32767) on every node. LoadBalancer automatically creates a cloud provider load balancer and provides an external IP. ClusterIP is only accessible within the cluster.
Q44. What is the purpose of kubectl port-forward?
A) Permanently changes a Service's port B) Temporarily forwards a local port to a Pod's port for local access to in-cluster services C) Maps a node port to a Pod D) Tests Ingress configuration
Answer: B
Explanation: kubectl port-forward pod/POD_NAME LOCAL_PORT:POD_PORT temporarily forwards a local port to a Pod's port. Useful for accessing in-cluster services during development or debugging. Also works with services: kubectl port-forward service/SVC_NAME LOCAL_PORT:SVC_PORT.
Q45. How do you attach multiple network interfaces to a Pod?
A) Specify additional networks in spec.networks B) Use Multus CNI with NetworkAttachmentDefinition for additional interfaces C) Change kube-proxy configuration D) Create multiple Services
Answer: B
Explanation: Multus CNI is a meta CNI plugin that enables multiple network interfaces on Pods. Define additional networks with the NetworkAttachmentDefinition CRD and reference them via Pod annotations. Used in telecom, NFV, and high-performance networking environments.
Q46. How do you inject only a specific key from a ConfigMap as an environment variable?
A) Use envFrom.configMapRef B) Specify the key with env[].valueFrom.configMapKeyRef.key C) Use volumeMounts D) Use spec.config.env
Answer: B
Explanation: For a specific key: set name (ConfigMap name) and key (key name) in env[].valueFrom.configMapKeyRef. To inject all keys: use envFrom[].configMapRef.name. Injecting specific keys avoids polluting the environment with unnecessary variables.
Q47. What settings enable graceful shutdown for a Pod's container?
A) Use spec.terminationGracePeriodSeconds for adequate shutdown time and handle SIGTERM in the container B) Set restartPolicy: Never C) Disable Liveness Probe D) Set privileged: true
Answer: A
Explanation: spec.terminationGracePeriodSeconds (default 30s) is the wait time between SIGTERM and forced termination (SIGKILL). Applications should finish in-flight requests upon receiving SIGTERM. Use Readiness Probes to stop new requests to the terminating Pod. Use preStop lifecycle hooks for additional cleanup.
Q48. Which of the following kubectl alias configurations is correct for the CKAD exam?
A) alias kubectl=k B) alias k=kubectl; export do="--dry-run=client -o yaml" C) kubectl config set alias k=kubectl D) export KUBECTL_ALIAS=k
Answer: B
Explanation: alias k=kubectl and export do="--dry-run=client -o yaml" are key time-saving settings. Example: k create deploy myapp --image=nginx $do > deploy.yaml quickly generates a YAML template. Also important: vim YAML indentation: :set et ts=2 sw=2.
Q49. What happens when you set readOnlyRootFilesystem: true in a container's SecurityContext?
A) The container cannot read files B) The container's root filesystem becomes read-only, preventing file modifications at runtime C) Volume mounts are disabled D) Network access is blocked
Answer: B
Explanation: readOnlyRootFilesystem: true makes the container's root filesystem read-only. Even if an attacker enters the container, they cannot modify files or install malicious code. Mount emptyDir volumes for directories that need write access.
Q50. Which fields allow a container to use the host's namespaces?
A) spec.hostPID, spec.hostNetwork, spec.hostIPC B) spec.network.host = true C) spec.containers.hostNamespace = true D) spec.shareHostNamespace = true
Answer: A
Explanation: spec.hostPID: true shares the host PID namespace. spec.hostNetwork: true uses the host network stack. spec.hostIPC: true shares the host IPC namespace. These settings pose security risks and should only be used when necessary.
Q51. What is the difference between kubectl apply and kubectl create?
A) kubectl create does not support YAML files B) kubectl apply uses a declarative approach applying only changes and updating if resource exists; kubectl create returns an error if the resource already exists C) kubectl create is faster D) kubectl apply also performs deletions
Answer: B
Explanation: kubectl apply manages resources declaratively: creates if not present, updates only changes if exists. kubectl create is imperative and returns an error for existing resources. kubectl apply is recommended for CI/CD pipelines.
Q52. How do you mount a specific host path as a volume in a Pod?
A) Use spec.volumes.emptyDir B) Use spec.volumes.hostPath C) Use spec.volumes.configMap D) Use spec.volumes.secret
Answer: B
Explanation: hostPath volumes mount a node's filesystem path into the container. Used to access Docker socket (/var/run/docker.sock), node logs (/var/log), etc. Security risk (direct node filesystem access) so use with caution. The type field accepts Directory, File, Socket, etc.
Q53. What does the KUBERNETES_SERVICE_HOST environment variable represent?
A) The IP of the node running kubelet B) The ClusterIP for accessing the Kubernetes API server from within a Pod (auto-injected) C) The address of the etcd server D) The address of the Ingress Controller
Answer: B
Explanation: Kubernetes automatically injects KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT into all Pods. These are used to programmatically access the Kubernetes API from within a Pod. Combined with a ServiceAccount token, you can call the cluster API from within the cluster.
Q54. What are the roles of initialDelaySeconds, periodSeconds, and failureThreshold in a Probe?
A) Set maximum time, period, and retry count respectively B) initialDelaySeconds: wait before first Probe; periodSeconds: Probe execution interval; failureThreshold: consecutive failure count threshold C) All are timeout-related settings D) All are database connection settings
Answer: B
Explanation: initialDelaySeconds: wait after container start before first Probe (accounts for app init time). periodSeconds: how often to run the Probe (default 10s). failureThreshold: number of consecutive failures before restart (Liveness) or traffic removal (Readiness). timeoutSeconds: timeout for a single Probe execution.
Q55. What does the Pod-level fsGroup setting in SecurityContext do?
A) Specifies the filesystem encryption group B) Sets the ownership of mounted volume files to the specified GID, enabling group-based file access C) Specifies the container user D) Specifies the network group
Answer: B
Explanation: spec.securityContext.fsGroup sets the owning group GID for files in volumes mounted to the Pod (including PVCs). File permissions on mounted volumes are automatically changed to that GID. Useful for resolving file access permission issues when multiple containers share a volume.
Practical Simulations (P1 ~ P10)
P1. Multi-Container Pod with Sidecar
Scenario: Create a Pod with an nginx main container and a busybox sidecar. The sidecar reads /var/log/nginx/access.log and outputs it to stdout. Both containers share the log directory via an emptyDir volume.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-sidecar
labels:
app: nginx-sidecar
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
- name: log-sidecar
image: busybox:latest
command: ['sh', '-c', 'tail -f /var/log/nginx/access.log']
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
volumes:
- name: log-volume
emptyDir: {}
EOF
kubectl logs nginx-with-sidecar -c log-sidecar -f
P2. Deployment with ConfigMap and Secret
Scenario: Create a db-config ConfigMap and db-secret Secret, then create a Deployment that injects them as environment variables.
kubectl create configmap db-config \
--from-literal=DB_HOST=mysql-service \
--from-literal=DB_PORT=3306 \
--from-literal=DB_NAME=myapp
kubectl create secret generic db-secret \
--from-literal=DB_USER=admin \
--from-literal=DB_PASSWORD=secretpassword
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx:latest
envFrom:
- configMapRef:
name: db-config
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-secret
key: DB_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD
EOF
kubectl exec -it deploy/myapp -- env | grep -E "DB_"
P3. Configuring Probes
Scenario: Set up a Liveness Probe (HTTP, /healthz, port 80), Readiness Probe (HTTP, /ready, port 80), and a Startup Probe on an nginx Deployment.
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-with-probes
spec:
replicas: 2
selector:
matchLabels:
app: nginx-probes
template:
metadata:
labels:
app: nginx-probes
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
startupProbe:
httpGet:
path: /
port: 80
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 15
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
successThreshold: 1
EOF
P4. Rolling Update and Rollback
Scenario: Create a webapp Deployment, update its image, monitor the rollout, and roll back.
kubectl create deployment webapp \
--image=nginx:1.24 \
--replicas=4
kubectl patch deployment webapp -p \
'{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":1}}}}'
kubectl set image deployment/webapp nginx=nginx:1.25
kubectl rollout status deployment/webapp
kubectl rollout history deployment/webapp
kubectl rollout pause deployment/webapp
kubectl get pods -l app=webapp -o wide
kubectl rollout resume deployment/webapp
# Or rollback
kubectl rollout undo deployment/webapp
P5. SecurityContext Configuration
Scenario: Create a Pod with these security requirements: run as UID 1000, non-root enforced, read-only root filesystem, all capabilities dropped.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsUser: 1000
runAsNonRoot: true
fsGroup: 2000
containers:
- name: app
image: nginx:latest
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp-dir
mountPath: /tmp
- name: var-cache
mountPath: /var/cache/nginx
- name: var-run
mountPath: /var/run
volumes:
- name: tmp-dir
emptyDir: {}
- name: var-cache
emptyDir: {}
- name: var-run
emptyDir: {}
EOF
kubectl exec secure-pod -- id
kubectl exec secure-pod -- cat /proc/1/status | grep Cap
P6. Using Init Containers
Scenario: Create a Pod that uses an Init Container to verify database connectivity before the main container starts.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: wait-for-db
image: busybox:latest
command: ['sh', '-c',
'until nc -z mysql-service 3306; do echo "Waiting for MySQL..."; sleep 5; done; echo "MySQL is ready!"']
- name: migrate-db
image: busybox:latest
command: ['sh', '-c', 'echo "Running DB migration..."; sleep 2; echo "Migration complete"']
containers:
- name: app
image: nginx:latest
ports:
- containerPort: 80
EOF
kubectl logs app-with-init -c wait-for-db
kubectl logs app-with-init -c migrate-db
kubectl describe pod app-with-init
P7. ResourceQuota and LimitRange
Scenario: Configure a ResourceQuota (4 CPU cores, 8Gi memory, 10 Pods) and LimitRange (default CPU 100m/memory 128Mi, max CPU 1/memory 1Gi) for namespace team-dev.
kubectl create namespace team-dev
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-quota
namespace: team-dev
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "10"
services: "5"
---
apiVersion: v1
kind: LimitRange
metadata:
name: container-limits
namespace: team-dev
spec:
limits:
- type: Container
default:
cpu: 200m
memory: 256Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "1"
memory: 1Gi
min:
cpu: 50m
memory: 64Mi
EOF
kubectl describe resourcequota team-quota -n team-dev
kubectl describe limitrange container-limits -n team-dev
P8. Ingress with TLS
Scenario: Configure an Ingress with TLS to make secure.example.com accessible via HTTPS.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /tmp/tls.key \
-out /tmp/tls.crt \
-subj "/CN=secure.example.com/O=myorg"
kubectl create secret tls secure-tls \
--cert=/tmp/tls.crt \
--key=/tmp/tls.key
kubectl create deployment secure-app --image=nginx --replicas=2
kubectl expose deployment secure-app --port=80 --name=secure-app-service
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- secure.example.com
secretName: secure-tls
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: secure-app-service
port:
number: 80
EOF
kubectl get ingress secure-ingress
P9. Egress NetworkPolicy
Scenario: Set an egress NetworkPolicy so that backend Pods can only send traffic to database Pods on port 5432. DNS queries must be allowed.
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-egress-policy
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
EOF
kubectl get networkpolicy backend-egress-policy
kubectl describe networkpolicy backend-egress-policy
P10. Job and CronJob
Scenario: Create a Job that calculates the sum of 1 to 10, and a CronJob that prints the current time and hostname every minute.
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
name: sum-calculator
spec:
completions: 1
parallelism: 1
backoffLimit: 3
template:
spec:
containers:
- name: calculator
image: busybox:latest
command:
- /bin/sh
- -c
- |
sum=0
for i in 1 2 3 4 5 6 7 8 9 10; do
sum=$((sum + i))
done
echo "Sum of 1 to 10 is: $sum"
restartPolicy: OnFailure
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: heartbeat
spec:
schedule: "* * * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: heartbeat
image: busybox:latest
command:
- /bin/sh
- -c
- echo "Heartbeat at $(date) from $(hostname)"
restartPolicy: OnFailure
EOF
kubectl logs -l job-name=sum-calculator
kubectl get cronjob heartbeat
kubectl get jobs --watch
Exam Tips
- Domain focus: Application Environment, Configuration & Security (25%) has the highest weight
- Quick YAML generation: Use
--dry-run=client -o yamlfor templates - Memorize probe fields: initialDelaySeconds, periodSeconds, failureThreshold
- SecurityContext levels: Distinguish Pod-level vs container-level
- ConfigMap vs Secret: Always use Secrets for sensitive data
- Use kubectl explain:
kubectl explain pod.spec.containers.securityContextto look up fields