Learning materials, exam tips, and repeatedly used commands.
Kubernetes CKAD exam is a hands-on exam, unlike other certifications, which are mostly theoretical. In the exam, we have to create and debug Kubernetes resources like pods, deployments, services, ingress, jobs, cronjobs, secrets e.t.c in the given lab environment. So, we need to be quick to set up and verify things.
I am sharing things that worked for me to pass the exam on the first attempt.
Prep Materials
The following 3 courses are more than enough to prepare for CKAD.
Udemy — CKAD prep with Tests by Mumshad: Learn Kubernetes concepts and try everything on a playground. Great course!
killer.shmock exam sessions: You get two sessions when you purchase the certification. Try the first session a bit earlier than the exam to get a feel of the real exam, and save the second session when the exam is near because it expires after 36 hours.
CKAD Mock Exams by Kodecloud: The first two labs will be enough for the majority. But if you want to get quick and 100% confident, you can try these 10 full-length mock exams with a timer. I only managed time to complete 6 of them.
In this blog, I will refer kubectl
command with the alias k
which is pre-configured in all environments.
Terminal / Env Setup
Aliases
Set these up in your terminal before you start solving the problems.
export do="--dry-run=client -o yaml"
# example: k run nginx --image=nginx $do > pod.yaml
# if not forced, you may have to wait for a long time
export now="--force --grace-period 0"
# example: k delete pod test $now
alias kn="k config set-context --current --namespace "
# now set namespace for the whole question without specifying namespace in each command
# example: kn default
# example: kn ckad-ns
# to print current namespace, just to verify
alias gn="k config view | grep namespace"
# by default helm autocompletion is not enabled in the lab environment
# we can do this to enable autocompletion
source <(helm completion bash)
Get familiar with VIM
Indentation in yaml
can be time-consuming to carry out tasks like copy/pasting and editing, if Vim is new for you.
Check Vim basic commands needed for CKADHERE.
I memorized these Vim configs while practicing mock exams and the first step I did was save these in ~/.vimrc
.
# tabstop and shiftwidth
set ts=2 sw=2
set expandtab
set autoindent
filetype plugin indent on
Useful Kubectl Commands
CPU and Memory usage of pods:
➜ k top pods --sort-by memory
NAME CPU(cores) MEMORY(bytes)
fury 119m 253Mi
flash 16m 5Mi
Label and Annotations:
# search pods by a label
➜ k get pods -l type=api
# multiple labels, type=api or type=cron
➜ k get pods -l "type in (api, cron)"
# add a new label private=true in selected pods
➜ k get pods -l "type in (api, cron)" private="true"
# add annotation e.g. owner=team-x in the selected pods
➜ k annonate pods -l "type in (api, cron)" owner="team-x"
Container Commands
Begin any container command with ['sh','-c']
. The third parameter in the list should be the actual command we run, for example, sleep or something else. e.g. ['sh', '-c', '<command>']
This prevents common mistakes like passing commands and arguments in the same item e.g. ['cowsay Hi ckad!']
. It will throw an error as the stringcowsay Hi ckad!
is considered a single command that does not exist.
Searching Pod/Container Logs
# View logs of a specific container
k logs -c
# Search pod logs
# --context flag displays more lines above and below the matched string
k logs nginx | grep OS --context=5
Cronjob/Job
Trigger a cron job by running a test job with the given name:
# do this instead of modifying cron job to run in a minute just for testing
k create job --from=cronjob/my-cron-job test-job
Custom Resource Definition (CRD)
You will be asked to create a custom resource from an existing CRD.
# Get JSON schema of CRD:
# search for openAPIV3Schema
➜ k get crd crontabs.stable.example.com -o json
API Resources
# display group, api version of a resource
➜. k api-resources | grep deployment
deployments deploy apps/v1 true Deployment
# find api resources with particular group/version
➜ k api-resources | grep storage.k8s.io/v1
csidrivers storage.k8s.io/v1 false CSIDriver
csinodes storage.k8s.io/v1 false CSINode
Kubectl output to custom columns:
➜ k get pod --output=custom-columns="NAME:.metadata.name,STATUS:.status.phase"
NAME STATUS
app1 Running
app2 Running
Secrets
Secrets store data in base64 encoded format. To get the base64 decoded format, you can describe the secret: k describe secret my-secret
If you perform get k get secret my-secret -o yaml
, it will return encoded values.
Testing the Connectivity of a Service:
Get the service name or IP first.
~ k get endpoints NAME ENDPOINTS AGE test-service 10.244.0.101:80 38m # use above servicename.namespace or IP to test.
IP is the simplest way to test.
If we use a service name, we need to attach a namespace e.g.<service-name>.namespace
in the DNS to test it from a pod in a different namespace.If
curl
is not present in the Alpine image, install usingapk add curl
.Create a temporary pod to test the service
# using ip, simplest way to test ➜ k run test --restart Never \ --rm -i --image nginx:alpine -- curl 10.244.0.101:80 # using service name to test, but the testpod is in another namespace # service is in ckad namespace so. it's dns will be test-service.ckad ➜ k -n default run test --restart Never \ --rm -i --image nginx:alpine -- curl http://test-service.ckad:80 # using service name in same namespace. not need to append namespace in service name ➜ k run test --restart Never --rm -i \ --image nginx:alpine -- curl http://test-service:80
Testing the Connectivity of an Ingress:
Get the ingress hostname or IP.
➜ k get ingress NAME CLASS HOSTS ADDRESS PORTS AGE ingress-test nginx example.com 192.168.49.2 80 2m38s
Test the connection from a pod
➜ k run test --image nginx:alpine --rm -i \ --restart Never -- curl http://example.com/app1
Helm
Following helm commands to manage releases, charts, and repositories is more than enough for the exam.
Working with repositories
# list repositories
helm repo ls
# add a repository
helm repo add bitnami https://charts.bitnami.com/bitnami
# fetch latest versions of charts eg. if apache has version 15.4.2 available
helm repo update
# search a chart 'nginx' in all repositories
helm search repo nginx
# search in a specific repo e.g. bitnami
helm search repo bitnami/nginx
# install a chart in a namespaace 'dev'
helm -n dev install my-nginx-release bitnami/nginx
# delete a release and all it's resources
helm uninstall my-nginx-release
Charts
Install a chart modifying a value e.g. replicaCount
➜ helm show values bitnami/apache | grep replica
## @param replicaCount Number of replicas of the Apache deployment
replicaCount: 1
# now we can overwrite default value of replicaCount
➜ helm install apacher-server-release bitnami/apache --set replicaCount=2
# we can also see values of a local chart which is inside /mychart folder
➜ helm show values ./mychart | grep image --context=3
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
# now we can overwrite values while creating a release
➜ helm install my-local-release-v1 ./mychart --set image.tag=1.14
# install local chart template
➜ helm install my-local-release ./mychart
# display image version in currently deployed release
➜ helm get manifest my-local-release | grep image
# show values of a local or remote chart
➜ helm show values ./mychart | grep image --context=3
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
# now we can overwrite values while creating a release
➜ helm install my-local-release ./mychart --set image.tag=1.14
Releases
# list running releases
helm ls
# list all releases, include pending (useful for exam)
helm ls -a
Namespaces in Helm
Passing namespace in helm
command is the same as kubectl
.
# list releases from specific namespace
helm -n ls
helm -n ckad install nginx-release bitnami/nginx
Docker
Save docker image as a tar file (this appeared in the exam)
# docker save image:tag > .tar
➜ docker save nginx:1.18 > nginx_img.tar
Kubernetes Doc is your biggest friend
kubernetes.io/docs is the most important asset for the exam. When you try out every lab and mock question, first search in the docs. It has answers and examples for 99% of things.
Even common things like using bash loops(inside Pods/Sidecar containers) and cron expressions(inside CronJob) can be found here which we can easily make mistakes.
Also, memorize the helm doc link: helm.sh/docs.
Exam Environment
The Firefox browser in the real exam environment was a little bit sluggish while scrolling and navigating to the right content on the Kubernetes docs page. The browser window is also small and you will have to zoom out quite a bit. Even then, the right-most section of doc with links to subtopics was not visible.
So, when you are doing a mock exam in killer.sh simulator, practice searching texts with Cmd/Ctrl+F and navigating through the text in the Kubernetes docs. It will save some time in the real exam.
Remember keywords for Kubernetes object names and attributes like Job
, command:
, image:
, env:
, secretRef
e.t.c. to search quickly.
Buy me a coffee :)