Practice Enough With These 150 Questions for the CKAD Exam

Exercises get you ready for the Certified Kubernetes Application Developer exam

Bhargav Bachina
Nov 11, 2019 · 21 min read
Image for post
Image for post
Photo by Tim Foster on Unsplash

Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications. The CNCF/Linux Foundation offers this performance-based exam which targets the developer aspect of kubernetes skills such as deploying apps, configuring apps, rolling out the application, creating persistent volumes, etc.

Since this exam is performance-based rather than just multiple choice questions just knowing the concepts are not enough, we need a lot of practice before the exam. This article helps you understand, practice and get you ready for the exam.

We are not going to discuss any concepts here, rather, I just want to create a bunch of practice questions for the CKAD exam based on the curriculum provided here.

Core Concepts (13%)

Practice questions based on these concepts

  • Understand Kubernetes API Primitives
  • Create and Configure Basic Pods
kubectl get namespaceskubectl get ns

kubectl get po --all-namespaces

kubectl get po -n <namespace name>

kubectl get svc -n <namespace name>

kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'metadata.namespace']}"

// creating a pod
kubectl run nginx --image=nginx --restart=Never
// List the pod
kubectl get po

// get the yaml file with --dry-run flag
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx-pod.yaml
// cat nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
// create a pod
kubectl create -f nginx-pod.yaml

kubectl get po nginx -o yaml

kubectl get po nginx -o yaml --export

kubectl describe pod nginx

kubectl delete po nginxkubectl delete -f nginx-pod.yaml

kubectl delete po nginx --grace-period=0 --force

kubectl run nginx --image=nginx:1.17.4 --restart=Never --port=80

1.15-alpine for the pod you just created and verify the image version is updated

kubectl set image pod/nginx nginx=nginx:1.15-alpinekubectl describe po nginx// another way it will open vi editor and change the version
kubeclt edit po nginx
kubectl describe po nginx

1.17.1 for the pod you just updated and observe the changes

kubectl set image pod/nginx nginx=nginx:1.17.1
kubectl describe po nginx
kubectl get po nginx -w # watch it

kubectl get po nginx -o jsonpath='{.spec.containers[].image}{"\n"}'

// creating a pod
kubectl run nginx --image=nginx --restart=Never
// exec into the pod
kubectl exec -it nginx /bin/sh

kubectl get po nginx -o wide

kubectl run busybox --image=busybox --restart=Never -- lskubectl logs busybox

kubectl logs busybox -p

kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "sleep 3600"

kubectl get po nginx -o wide// check the connection
kubectl exec -it busybox -- wget -o- <IP Address>

kubectl run busybox --image=nginx --restart=Never -it -- echo "How are you"kubectl delete po busybox

// notice the --rm flag
kubectl run busybox --image=nginx --restart=Never -it --rm -- echo "How are you"

// create a pod
kubectl run nginx --image=nginx --restart=Never --port=80
// List the pod with different verbosity
kubectl get po nginx --v=7
kubectl get po nginx --v=8
kubectl get po nginx --v=9

kubectl get po -o=custom-columns="POD_NAME:.metadata.name, POD_STATUS:.status.containerStatuses[].state"

kubectl get pods --sort-by=.metadata.name

kubectl get pods--sort-by=.metadata.creationTimestamp

Multi-Container Pods (10%)

Practice questions based on these concepts

  • Understand multi-container pod design patterns (eg: ambassador, adaptor, sidecar)

// first create single container pod with dry run flagkubectl run busybox --image=busybox --restart=Never --dry-run -o yaml -- bin/sh -c "sleep 3600; ls" > multi-container.yaml// edit the pod to following yaml and create it
kubectl create -f multi-container.yaml
kubectl get po busybox
multi-container pod

kubectl logs busybox -c busybox1
kubectl logs busybox -c busybox2
kubectl logs busybox -c busybox3

kubectl logs busybox -c busybox2 --previous

kubectl exec busybox -c busybox3 -- ls

kubectl top pod busybox --containers// putting them into file
kubectl top pod busybox --containers > file.log
cat file.log

// create an initial yaml file with this
kubectl run multi-cont-pod --image=busbox --restart=Never --dry-run -o yaml > multi-container.yaml
// edit the yml as below and create it
kubectl create -f multi-container.yaml
kubectl get po multi-cont-pod
multi-container.yaml

// exec into main container
kubectl exec -it multi-cont-pod -c main-container -- sh
cat /var/log/main.txt
// exec into sidecar container
kubectl exec -it multi-cont-pod -c sidecar-container -- sh
cat /usr/share/nginx/html/index.html
// install curl and get default page
kubectl exec -it multi-cont-pod -c sidecar-container -- sh
# apt-get update && apt-get install -y curl
# curl localhost

Pod Design (20%)

Practice questions based on these concepts

  • Understand how to use Labels, Selectors and Annotations
  • Understand Deployments and how to perform rolling updates
  • Understand Deployments and how to perform rollbacks
  • Understand Jobs and CronJobs

kubectl get pods --show-labels

kubectl run nginx-dev1 --image=nginx --restart=Never --labels=env=dev
kubectl run nginx-dev2 --image=nginx --restart=Never --labels=env=dev
kubectl run nginx-dev3 --image=nginx --restart=Never --labels=env=dev
kubectl run nginx-prod1 --image=nginx --restart=Never --labels=env=prod
kubectl run nginx-prod2 --image=nginx --restart=Never --labels=env=prod

kubeclt get pods --show-labels

kubectl get pods -l env=dev

kubectl get pods -l env=dev --show-labels

kubectl get pods -l env=prod

kubectl get pods -l env=prod --show-labels

kubectl get pods -L env

kubectl get pods -l 'env in (dev,prod)'

kubectl get pods -l 'env in (dev,prod)' --show-labels

kubectl label pod/nginx-dev3 env=uat --overwrite
kubectl get pods --show-labels

kubectl label pod nginx-dev{1..3} env-
kubectl label pod nginx-prod{1..2} env-
kubectl get po --show-labels

kubectl label pod nginx-dev{1..3} app=nginx
kubectl label pod nginx-prod{1..2} app=nginx
kubectl get po --show-labels

kubectl get nodes --show-labels

kubectl label node minikube nodeName=nginxnode

kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > pod.yaml// add the nodeSelector like below and create the pod
kubectl create -f pod.yaml
pod.yaml

kubectl describe po nginx | grep Node-Selectors

kubectl describe po nginx | grep Labels

kubectl annotate pod nginx-dev{1..3} name=webapp
kubectl annotate pod nginx-prod{1..2} name=webapp

kubectl describe po nginx-dev{1..3} | grep -i annotations
kubectl describe po nginx-prod{1..2} | grep -i annotations

kubectl annotate pod nginx-dev{1..3} name-
kubectl annotate pod nginx-prod{1..2} name-
kubectl describe po nginx-dev{1..3} | grep -i annotations
kubectl describe po nginx-prod{1..2} | grep -i annotations

kubectl delete po --all

kubectl create deploy webapp --image=nginx --dry-run -o yaml > webapp.yaml// change the replicas to 5 in the yaml and create it
kubectl create -f webapp.yaml
webapp.yaml

kubectl get deploy webapp --show-labels

kubectl get deploy webapp -o yaml

// get the label of the deployment
kubectl get deploy --show-labels
// get the pods with that label
kubectl get pods -l app=webapp

kubectl scale deploy webapp --replicas=20kubectl get po -l app=webapp

kubectl rollout status deploy webapp

kubectl get rs -l app=webapp

kubectl get rs -l app=webapp -o yaml
kubectl get po -l app=webapp -o yaml

kubectl delete deploy webappkubectl get po -l app=webapp -w

kubectl create deploy webapp --image=nginx:1.17.1 --dry-run -o yaml > webapp.yaml// add the port section and create the deployment
kubectl create -f webapp.yaml
// verify
kubectl describe deploy webapp | grep Image
webapp.yaml

kubectl set image deploy/webapp nginx=nginx:1.17.4kubectl describe deploy webapp | grep Image

kubectl rollout history deploy webappkubectl get deploy webapp --show-labels
kubectl get rs -l app=webapp
kubectl get po -l app=webapp

kubectl rollout undo deploy webappkubectl describe deploy webapp | grep Image

kubectl set image deploy/webapp nginx=nginx:1.16.1kubectl describe deploy webapp | grep Imagekubectl rollout history deploy webapp

kubectl rollout undo deploy webapp --to-revision=3kubectl describe deploy webapp | grep Imagekubectl rollout status deploy webapp

kubectl set image deploy/webapp nginx=nginx:1.100kubectl rollout status deploy webapp (still pending state)kubectl get pods (ImagePullErr)

kubectl rollout undo deploy webapp
kubectl rollout status deploy webapp
kubectl get pods

kubectl rollout history deploy webapp --revision=7

kubectl rollout pause deploy webapp

kubectl set image deploy/webapp nginx=nginx:latestkubectl rollout history deploy webapp (No new revision)

kubectl rollout resume deploy webapp

kubectl rollout history deploy webappkubectl rollout history deploy webapp --revision=9

kubectl autoscale deploy webapp --min=10 --max=20 --cpu-percent=85kubectl get hpakubectl get pod -l app=webapp

kubectl delete deploy webappkubectl delete hpa webapp

kubectl create job nodeversion --image=node -- node -vkubectl get job -w
kubectl get pod

kubectl logs <pod name> // created from the job

kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job"

kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" > hello-job.yamlkubectl create -f hello-job.yaml

kubectl get job
kubectl get po
kubectl logs hello-job-*

kubectl delete job hello-job

kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" > hello-job.yaml// edit the yaml file to add completions: 10
kubectl create -f hello-job.yaml
hello-job.yaml

kubectl get job -w
kubectl get po
kubectl delete job hello-job

kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" > hello-job.yaml// edit the yaml file to add parallelism: 10
kubectl create -f hello-job.yaml
hello-job.yaml

kubectl get job -w
kubectl get po
kubectl delete job hello-job

kubectl create cronjob date-job --image=busybox --schedule="*/1 * * * *" -- bin/sh -c "date; echo Hello from kubernetes cluster"

kubectl get cj date-job -o yaml

kubectl get job
kubectl get po
kubectl logs date-job-<jobid>-<pod>

kubectl delete cj date-job// verify pods and jobs
kubectl get po
kubectl get job

State Persistence (8%)

Practice questions based on these concepts

  • Understand PersistentVolumeClaims for Storage

kubectl get pv

kubectl create -f task-pv-volume.yamlkubectl get pv
task-pv-volume.yaml

kubectl create -f task-pv-claim.yamlkubectl get pvc
task-pv-claim.yaml

kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume

// emptyDir is the volume that lasts for the life of the podkubectl create -f redis-storage.yaml

// first terminal
kubectl exec -it redis-storage /bin/sh
cd /data/redis
echo 'This is called the file' > file.txt
//open another tab
kubectl exec -it redis-storage /bin/sh
cat /data/redis/file.txt

kubectl delete pod rediskubectl create -f redis-storage.yaml
kubectl exec -it redis-storage /bin/sh
cat /data/redis/file.txt // file doesn't exist

kubectl create -f task-pv-volume.yaml
kubectl create -f task-pv-claim.yaml
kubectl get pv
kubectl get pvc

kubectl create -f task-pv-pod.yaml
task-pv-pod.yaml

Configuration (18%)

Practice questions based on these concepts

  • Understand ConfigMaps
  • Understand SecurityContexts
  • Define an application’s resource requirements
  • Create & Consume Secrets
  • Understand ServiceAccounts

kubectl get cm
or
kubectl get configmap

kubectl create cm myconfigmap --from-literal=appname=myapp

// you will see under datakubectl get cm -o yaml
or
kubectl describe cm

kubectl delete cm myconfigmap

cat >> config.txt << EOF
key1=value1
key2=value2
EOF
cat config.txt

kubectl create cm keyvalcfgmap --from-file=config.txtkubectl get cm keyvalcfgmap -o yaml

// first run this command to save the pod yml
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx-pod.yml
// edit the yml to below file and create
kubectl create -f nginx-pod.yml
// verify
kubectl exec -it nginx -- env
kubectl delete po nginx
nginx-pod.yml

echo var1=val1 > file.env
cat file.env
kubectl create cm envcfgmap --from-env-file=file.env
kubectl get cm envcfgmap -o yaml --export

// first run this command to save the pod yml
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx-pod.yml
// edit the yml to below file and create
kubectl create -f nginx-pod.yml
// verify
kubectl exec -it nginx -- env
kubectl delete po nginx
nginx-pod.yaml

// first create a configmap cfgvolume
kubectl create cm cfgvolume --from-literal=var1=val1 --from-literal=var2=val2
// verify the configmap
kubectl describe cm cfgvolume
// create the config map
kubectl create -f nginx-volume.yml
// exec into the pod
kubectl exec -it nginx -- /bin/sh
// check the path
cd /etc/cfg
ls
nginx-volume.yml

// create yml file with dry-run
kubectl run secbusybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600;" > busybox.yml
// edit the pod like below and create
kubectl create -f busybox.yml
// verify
kubectl exec -it secbusybox -- sh
id // it will show the id and group
busybox.yml

// create yml file with dry-run
kubectl run secbusybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600;" > busybox.yml
// edit the pod like below and create
kubectl create -f busybox.yml
// verify
kubectl exec -it secbusybox -- sh
id // you can see container securityContext overides the Pod level
busybox.yml

// create the yaml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// edit as below and create pod
kubectl create -f nginx.yml
// exec and verify
kubectl exec -it nginx -- sh
cd /proc/1
cat status
// you should see these values
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
nginx.yml

// create a yml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// add the resources section and create
kubectl create -f nginx.yml
// verify
kubectl top pod
nginx.yml

// create a yml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// add the resources section and create
kubectl create -f nginx.yml
// verify
kubectl top pod
nginx.yml

// create a yml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// add the resources section and create
kubectl create -f nginx.yml
// verify
kubectl top pod
nginx.yml

// create a yml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// add the resources section and create
kubectl create -f nginx.yml
// verify
kubectl describe po nginx // you can see pending state
nginx.yml

kubectl create secret generic my-secret --from-literal=username=user --from-literal=password=mypassword

kubectl get secret --all-namespaces

kubectl get secret my-secret -o yaml

// create a yml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// add env section below and create
kubectl create -f nginx.yml
//verify
kubectl exec -it nginx -- env
nginx.yml

// create a yml file
kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml
// add env section below and create
kubectl create -f nginx.yml
//verify
kubectl exec -it nginx -- env
nginx.yml

kubectl get sa

kubectl get sa --all-namespaces

kubectl create sa admin

kubectl get sa admin -o yaml

kubectl run busybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600" > busybox.ymlkubectl create -f busybox.yml// verify
kubectl describe po busybox
busybox.yml

Observability (18%)

Practice questions based on these concepts

  • Understand LivenessProbes and ReadinessProbes
  • Understand Container Logging
  • Understand how to monitor applications in kubernetes
  • Understand Debugging in Kubernetes

kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx-pod.yaml// add the readinessProbe section and create
kubectl create -f nginx-pod.yaml
// verify
kubectl describe pod nginx | grep -i readiness
kubectl delete po nginx
nginx-pod.yaml

kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx-pod.yaml// add the livenessProbe section and create
kubectl create -f nginx-pod.yaml
// verify
kubectl describe pod nginx | grep -i readiness
kubectl delete po nginx
nginx-pod.yaml

kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx-pod.yaml// add the livenessProbe and readiness section and create
kubectl create -f nginx-pod.yaml
// verify
kubectl describe pod nginx | grep -i readiness
kubectl describe pod nginx | grep -i liveness
nginx-pod.yaml

kubectl explain Pod.spec.containers.livenessProbe
kubectl explain Pod.spec.containers.readinessProbe

kubectl create -f nginx-pod.yaml
nginx-pod.yaml

kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "echo I am from busybox pod; sleep 3600;"kubectl logs busybox

kubectl logs busybox > busybox-logs.txtcat busybox-logs.txt

kubectl get events --sort-by=.metadata.creationTimestamp// putting them into file.log
kubectl get events --sort-by=.metadata.creationTimestamp > file.log
cat file.log

// create the pod
kubectl run hello --image=alpine --restart=Never -- /bin/sh -c "while true; do echo 'Hi I am from Alpine'; sleep 5;done"
// verify and follow the logs
kubectl logs --follow hello

// create the pod
kubectl create -f https://gist.githubusercontent.com/bbachi/212168375b39e36e2e2984c097167b00/raw/1fd63509c3ae3a3d3da844640fb4cca744543c1c/not-running.yml
// get the pod
kubectl get pod not-running
kubectl describe po not-running
// it clearly says ImagePullBackOff something wrong with image
kubectl edit pod not-running // it will open vim editor
or
kubectl set image pod/not-running not-running=nginx

kubectl create -f https://gist.githubusercontent.com/bbachi/1f001f10337234d46806929d12245397/raw/84b7295fb077f15de979fec5b3f7a13fc69c6d83/problem-pod.yaml// get all the pods in all namespaces
kubectl get po --all-namespaces
// find out which pod is not running
kubectl get po -n namespace2
// update the image
kubectl set image pod/pod2 pod2=nginx -n namespace2
// verify again
kubectl get po -n namespace2

// get the top 3 hungry pods
kubectl top pod --all-namespaces | sort --reverse --key 3 --numeric | head -3
// putting into file
kubectl top pod --all-namespaces | sort --reverse --key 3 --numeric | head -3 > cpu-usage.txt
// verify
cat cpu-usage.txt

Services and Networking (13%)

Practice questions based on these concepts

  • Understand Services
  • Demonstrate a basic understanding of NetworkPolicies

kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx.yaml// edit the label app: my-nginx and create the pod
kubectl create -f nginx.yaml
nginx.yaml

// create the below service
kubectl create -f nginx-svc.yaml
nginx-svc.yaml

// get the pod with labels
kubectl get po nginx --show-labels
// get the service and chekc the selector column
kubectl get svc my-service -o wide

// delete the service
kubectl delete svc my-service
// create the service again
kubectl expose po nginx --port=80 --target-port=9376
// verify the label
kubectl get svc -l app=my-nginx

// delete the service
kubectl delete svc nginx
// create service with expose command
kubectl expose po nginx --port=80 --type=NodePort

// get the clusterIP from this command
kubectl get svc nginx -o wide
// create temporary busybox to check the nodeport
kubectl run busybox --image=busybox --restart=Never -it --rm -- wget -o- <Cluster IP>:80

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress

Conclusion

CKAD is a performance-based exam and it’s all about completing 19 questions within 2 hours. We need a lot of practice for it. These 150 questions give you enough practice for the exam. The more you practice the more comfortable you feel during the exam. Practice. Practice. Practice.

Bachina Labs

Tutorials Ranging from Beginner guides to Advanced | Never…

Sign up for BB Tutorials & Thoughts

By Bachina Labs

Tutorials Ranging from Beginner guides to advanced on Frontend, Backend, Blockchain, Docker, k8s, DevOps, Cloud,AI, ML. Thank you for subscribing and let me know if you want me cover anything?  Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Bhargav Bachina

Written by

Software Architect — Sharing Experiences With Examples | Frontend, Backend, Blockchain, Docker, k8s, DevOps, Cloud,AI, ML | https://www.linkedin.com/in/bachina/

Bachina Labs

Tutorials Ranging from Beginner guides to Advanced | Never Stop Learning

Bhargav Bachina

Written by

Software Architect — Sharing Experiences With Examples | Frontend, Backend, Blockchain, Docker, k8s, DevOps, Cloud,AI, ML | https://www.linkedin.com/in/bachina/

Bachina Labs

Tutorials Ranging from Beginner guides to Advanced | Never Stop Learning

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface.

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox.

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic.

Get the Medium app