Skip to content

CKAD Fact Sheet - Certified Kubernetes Application Developer

Exam Overview

Exam Code: CKAD Duration: 2 hours Format: Performance-based, hands-on terminal Passing Score: 66% Cost: $395 USD (includes one free retake) Delivery: PSI online proctoring Validity: 3 years Kubernetes Docs Access: Allowed during the exam

πŸ“– Official CKAD Page - Linux Foundation CKAD certification page πŸ“– CKAD Exam Curriculum - Official exam curriculum on GitHub πŸ“– CNCF Certification FAQ - Frequently asked questions about the exam πŸ“– Candidate Handbook - Exam policies and procedures πŸ“– Exam Tips from CNCF - Official tips for the exam environment

Target Audience

The CKAD is designed for Kubernetes application developers who: - Build, configure, and deploy applications on Kubernetes - Understand core Kubernetes concepts and workload resources - Work with container images and multi-container Pods - Manage application configuration, storage, and networking - Implement observability and debugging strategies

This certification does not focus on cluster administration tasks (that is the CKA). The CKAD is specifically about deploying and managing applications on an existing Kubernetes cluster.

Exam Domain Breakdown

Domain Weight Focus Areas
Application Design and Build 20% Pods, multi-container patterns, Jobs, CronJobs, volumes
Application Deployment 20% Deployments, rolling updates, Helm, Kustomize
Application Observability and Maintenance 15% Probes, logging, debugging, monitoring
Application Environment, Configuration and Security 25% ConfigMaps, Secrets, SecurityContexts, RBAC, quotas
Services and Networking 20% Services, Ingress, NetworkPolicies, DNS

Domain 1: Application Design and Build (20%)

Pod Design and Multi-Container Patterns

Multi-Container Pod Patterns: - Sidecar: Extends the main container (e.g., log shipper, config reloader, proxy). Runs alongside the main container for the entire Pod lifecycle. - Init Container: Runs to completion before the main container starts. Used for setup tasks like waiting for a service, populating volumes, or running migrations. - Ambassador: Proxy container that handles outbound connections. The main container connects to localhost and the ambassador routes to the appropriate external service. - Adapter: Normalizes or transforms the main container's output (e.g., reformatting logs for a centralized system).

Container Images

Key Concepts: - Image naming: registry/repository:tag (e.g., docker.io/library/nginx:1.25) - Default pull policy: IfNotPresent for tagged images, Always for :latest - Use specific image tags in production, never rely on :latest - ImagePullSecrets reference a Secret with registry credentials

Jobs and CronJobs

Job Configuration: - completions: Number of times the Job should complete successfully - parallelism: Number of Pods running concurrently - backoffLimit: Number of retries before marking the Job as failed - activeDeadlineSeconds: Maximum time a Job can run - restartPolicy: Must be Never or OnFailure (not Always)

CronJob Configuration: - schedule: Cron expression (e.g., "*/5 * * * *" for every 5 minutes) - concurrencyPolicy: Allow, Forbid, or Replace - startingDeadlineSeconds: Deadline for starting a Job if the schedule is missed - successfulJobsHistoryLimit: Number of successful Jobs to retain (default 3) - failedJobsHistoryLimit: Number of failed Jobs to retain (default 1)

Persistent and Ephemeral Volumes

Volume Types to Know: - emptyDir: Temporary directory, exists for the life of the Pod - hostPath: Mounts a file or directory from the node (use carefully) - persistentVolumeClaim: References a PVC for persistent storage - configMap / secret: Mount ConfigMap or Secret data as files - projected: Combines multiple volume sources into a single directory

PVC Access Modes: - ReadWriteOnce (RWO): Mounted as read-write by a single node - ReadOnlyMany (ROX): Mounted as read-only by many nodes - ReadWriteMany (RWX): Mounted as read-write by many nodes - ReadWriteOncePod (RWOP): Mounted as read-write by a single Pod


Domain 2: Application Deployment (20%)

Deployments and Rolling Updates

Rolling Update Parameters: - maxUnavailable: Max Pods that can be unavailable during update (default 25%) - maxSurge: Max Pods that can be created above desired count (default 25%) - minReadySeconds: Minimum seconds a Pod must be ready before considered available - revisionHistoryLimit: Number of old ReplicaSets to retain (default 10)

Rollback Commands:

kubectl rollout status deployment/myapp
kubectl rollout history deployment/myapp
kubectl rollout undo deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=2
kubectl rollout pause deployment/myapp
kubectl rollout resume deployment/myapp

Deployment Strategies

Blue-Green Deployment: 1. Deploy the new version as a separate Deployment with different labels 2. Verify the new version is healthy 3. Update the Service selector to point to the new version 4. Keep the old version running temporarily for quick rollback

Canary Deployment: 1. Create a small Deployment of the new version alongside the existing one 2. Both Deployments share the same label so the Service routes to both 3. Gradually scale up the canary and scale down the old version 4. Monitor for errors before completing the rollout

Helm Package Manager

Essential Helm Commands:

# Add a chart repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# Search for charts
helm search repo nginx
helm search hub wordpress

# Install a chart
helm install my-release bitnami/nginx
helm install my-release bitnami/nginx --set replicaCount=3
helm install my-release bitnami/nginx -f values.yaml

# List releases
helm list
helm list -n my-namespace

# Upgrade a release
helm upgrade my-release bitnami/nginx --set replicaCount=5

# Rollback a release
helm rollback my-release 1

# Uninstall a release
helm uninstall my-release

# Show chart information
helm show values bitnami/nginx
helm show chart bitnami/nginx

Kustomize

Key Kustomize Features: - Generates ConfigMaps and Secrets from files or literals - Applies common labels, annotations, and namespace - Patches resources with strategic merge patches or JSON patches - Builds and applies with kubectl apply -k ./

# kustomization.yaml example
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
namespace: production
commonLabels:
  app: myapp
  env: production
configMapGenerator:
  - name: app-config
    literals:
      - DB_HOST=db.production.svc
      - LOG_LEVEL=info

Domain 3: Application Observability and Maintenance (15%)

Probes and Health Checks

Probe Types: | Probe | Purpose | Failure Action | |-------|---------|---------------| | Liveness | Is the container running correctly? | Restart the container | | Readiness | Is the container ready to serve traffic? | Remove from Service endpoints | | Startup | Has the application finished starting? | Restart (disables liveness/readiness until success) |

Probe Mechanisms: - httpGet: HTTP GET request - success is 200-399 status code - tcpSocket: TCP connection attempt - success if connection established - exec: Execute a command - success if exit code is 0 - grpc: gRPC health check - success if status is SERVING

Probe Parameters: - initialDelaySeconds: Seconds before first probe (default 0) - periodSeconds: How often to perform the probe (default 10) - timeoutSeconds: Seconds after which probe times out (default 1) - successThreshold: Consecutive successes needed (default 1) - failureThreshold: Consecutive failures to trigger action (default 3)

Logging and Monitoring

Key Commands:

# View container logs
kubectl logs <pod-name>
kubectl logs <pod-name> -c <container-name>     # specific container
kubectl logs <pod-name> --previous               # previous instance
kubectl logs <pod-name> -f                       # stream logs
kubectl logs <pod-name> --tail=100               # last 100 lines
kubectl logs <pod-name> --since=1h               # last hour

# Resource usage
kubectl top pods
kubectl top pods -n <namespace>
kubectl top nodes
kubectl top pod <pod-name> --containers

Debugging Applications

Debugging Workflow: 1. kubectl get pods - Check Pod status 2. kubectl describe pod <name> - Check events and conditions 3. kubectl logs <name> - Check application logs 4. kubectl exec -it <name> -- /bin/sh - Interactive shell 5. kubectl get events --sort-by=.metadata.creationTimestamp - Cluster events

API Deprecations

Key Points: - API versions progress: v1alpha1 -> v1beta1 -> v1 - Deprecated APIs are supported for at least the deprecation period before removal - Use kubectl convert or update manifests manually when APIs change - Check kubectl api-resources and kubectl api-versions for available APIs


Domain 4: Application Environment, Configuration and Security (25%)

ConfigMaps

Creation Methods:

kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2
kubectl create configmap my-config --from-file=config.properties
kubectl create configmap my-config --from-env-file=config.env

Consumption Methods: - Environment variables: envFrom or individual env with configMapKeyRef - Volume mounts: Mount as files in a directory - Command arguments: Reference in container command/args

Secrets

Secret Types: - Opaque: Generic key-value pairs (default) - kubernetes.io/dockerconfigjson: Docker registry credentials - kubernetes.io/tls: TLS certificate and key - kubernetes.io/basic-auth: Basic authentication credentials - kubernetes.io/service-account-token: ServiceAccount token

Creation:

kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=secret123
kubectl create secret docker-registry my-reg-secret --docker-server=registry.example.com --docker-username=user --docker-password=pass
kubectl create secret tls my-tls --cert=cert.pem --key=key.pem

SecurityContexts

Common SecurityContext Settings:

securityContext:
  runAsUser: 1000
  runAsGroup: 3000
  runAsNonRoot: true
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop:
      - ALL
    add:
      - NET_BIND_SERVICE

ServiceAccounts

Key Points: - Every namespace has a default ServiceAccount - Pods use the default ServiceAccount unless specified otherwise - Assign specific ServiceAccounts for fine-grained access control - ServiceAccount tokens are automatically mounted (can be disabled with automountServiceAccountToken: false)

ResourceQuotas and LimitRanges

ResourceQuota: Limits total resource consumption per namespace (CPU, memory, number of objects) LimitRange: Sets default, min, and max resource constraints per Pod/container in a namespace

Admission Controllers

Key Admission Controllers: - NamespaceLifecycle: Prevents creation in non-existent namespaces - LimitRanger: Enforces LimitRange constraints - ResourceQuota: Enforces ResourceQuota constraints - ServiceAccount: Automates ServiceAccount assignment - PodSecurity: Enforces Pod Security Standards

Custom Resources and Operators


Domain 5: Services and Networking (20%)

Services

Service Types: | Type | Description | Use Case | |------|-------------|----------| | ClusterIP | Internal cluster IP (default) | Internal communication between services | | NodePort | Exposes on each node's IP at a static port (30000-32767) | Development and testing | | LoadBalancer | Provisions external load balancer (cloud provider) | Production external access | | ExternalName | Maps to a DNS name (CNAME) | Referencing external services |

Imperative Creation:

kubectl expose deployment myapp --port=80 --target-port=8080 --type=ClusterIP
kubectl expose deployment myapp --port=80 --target-port=8080 --type=NodePort
kubectl expose pod mypod --port=80 --target-port=8080 --name=my-service

Ingress

Ingress Features: - Host-based routing (route by domain name) - Path-based routing (route by URL path) - TLS termination - Default backend for unmatched requests - Requires an Ingress controller to be installed in the cluster

Example Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
  tls:
    - hosts:
        - myapp.example.com
      secretName: tls-secret

Network Policies

Key Concepts: - By default, all Pods can communicate with all other Pods - A NetworkPolicy selects Pods using podSelector and defines allowed ingress and egress rules - Once a Pod is selected by any NetworkPolicy, all traffic not explicitly allowed is denied - Rules can select by: podSelector, namespaceSelector, ipBlock (CIDR) - Requires a CNI plugin that supports NetworkPolicies (Calico, Cilium, Weave Net)

Example - Allow only specific Pods:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

DNS for Services and Pods

DNS Naming: - Services: <service-name>.<namespace>.svc.cluster.local - Pods: <pod-ip-dashed>.<namespace>.pod.cluster.local - Within the same namespace, use just the service name: my-service - Across namespaces, use: my-service.other-namespace


Exam Environment Tips

Tools Available in the Exam

  • kubectl with bash/zsh autocompletion
  • vim and nano for text editing
  • tmux for terminal multiplexing
  • curl and wget for HTTP requests
  • jq for JSON processing
  • Access to kubernetes.io/docs, kubernetes.io/blog, and github.com/kubernetes

Time Management

  • 2 hours for approximately 15-20 tasks
  • Average 6-8 minutes per task
  • Flag difficult tasks and come back to them
  • Easy tasks first to bank points quickly
  • Verify your work before moving on - points for partial completion are possible

Critical Shortcuts

# Set up aliases at the start of the exam
alias k=kubectl
export do="--dry-run=client -o yaml"

# Quick resource creation
k run pod1 --image=nginx $do > pod1.yaml
k create deploy d1 --image=nginx --replicas=3 $do > d1.yaml

# Context switching (exam uses multiple clusters)
kubectl config use-context <context-name>
kubectl config get-contexts

Common Pitfalls

  • Forgetting to switch context between tasks
  • Not checking the correct namespace
  • YAML indentation errors
  • Forgetting to verify the resource was created correctly
  • Spending too long on a single question
  • Not reading the full question before starting