Skip to content
Published on

Kubernetes CKAD Certification Practice Exam (55 Questions + 10 Practical Simulations)

Authors

CKAD Exam Overview

The CKAD (Certified Kubernetes Application Developer) is a hands-on, performance-based exam focused on deploying and managing applications on Kubernetes.

ItemDetails
Duration120 minutes
Questions15-20 performance-based tasks
Passing Score66% or above
FormatOnline, proctored
Validity3 years
Kubernetes VersionLatest stable release

Domain Weights

DomainWeight
Application Design & Build20%
Application Deployment20%
Application Observability & Maintenance15%
Application Environment, Configuration & Security25%
Services & Networking20%

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

  1. Domain focus: Application Environment, Configuration & Security (25%) has the highest weight
  2. Quick YAML generation: Use --dry-run=client -o yaml for templates
  3. Memorize probe fields: initialDelaySeconds, periodSeconds, failureThreshold
  4. SecurityContext levels: Distinguish Pod-level vs container-level
  5. ConfigMap vs Secret: Always use Secrets for sensitive data
  6. Use kubectl explain: kubectl explain pod.spec.containers.securityContext to look up fields