Tips and tricks for passing the CKAD exam — Notes #3 of 4

Shambhu Kumar Sinha
11 min readJan 9, 2024

--

You don’t understand anything until you learn it more than one way,”

Marvin Minsky

This is Part 3 of this series, and if you landed up here first, you may would like to start reading from Part 1. In this article, I am covering some tips these are related to the CKAD concept but needed for improving efficiency in the exam.

  1. Kubectl
  2. Imperatives vs declarative
  3. Help and Documentation
  4. explain
  5. Docker
  6. Helm

Kubectl

kubectl is client tool of Kubernetes to create a variety of objects. There are several ways to apply all of the K8s objects into the k8s cluster.

  1. Using Generators (Run, Expose)
  2. Using Imperative way (Create)
  3. Using Declarative way (Apply)

All of the above ways have a different purpose and simplicity. For instance, If we want to check quickly whether the container is working as we desired then we might use Generators. Check details here: refrence

Get YAML for deployed Kubernetes services

Imperative way vs declarative way

Imperative way: define on command line for quickly, generate a definition template easily.

Declarative way: define in manifest file as steps or using definition files,

Imperative Commands

Imperative commands must be used to quickly do one-time activities and to create definition templates with ease.

Some examples for creating Object using Imperative commands.

Create an NGINX Pod and a Deployment

kubectl run nginx --image=nginx
kubectl create deployment - image=nginx nginx

Generate POD and Deployment Manifest YAML file (-o yaml). Don’t create it( — dry-run)

kubectl run nginx --image=nginx --dry-run=client -o yaml
kubectl create deployment - image=nginx nginx - dry-run -o yaml

Another way to do this is to save the YAML definition to a file and modify the definition file

kubectl create deployment nginx - image=nginx - dry-run=client -o yaml > nginx-deployment.yaml

You can then update the YAML file with the replicas or any other field before creating the deployment.

Tips: During your tests, this will help you saving a significant amount of time. Following two options that will be useful while working with the instructions below:

  1. Use the -dry-run=client argument if all you want to generate Object template on client side with bare minimum attributes requires, however, use the -dry-run=server option to view more attributes possibilities.
  2. Along with -o yaml option resource definition will appear on the screen in YAML format and can be used for constructing object.
    Instead of starting from scratch with each file, use the two above to rapidly construct a resource definition file that you can then edit and add resources to as needed.

— dry-run=client will not create the resource, use -o yaml to output the resource definition in YAML format on screen.

Create yamls file template

Kubectl get deployment -o yaml >file.yaml

Kubectl create

Imperative command is not available for, so has to create by declarative way using yaml

  1. Netpol
  2. PV
  3. PVC
  4. StorageClass
  5. LimitRange

Kubectl: Debug — Verbose Output

Use the following syntax of the kubectl command to set the verbosity level from 0 to 9:

$ kubectl <command> - v=<verbosity_level>
Examples:
# Minimum verbosity
$ kubectl cluster-info - v=0
# Debug level verbosity
$ kubectl cluster-info - v=4
# Maximum verbosity
$ kubectl cluster-info - v=9

All the available verbosity levels of the kubectl command:
- v=0 : Generally useful for this to always be visible to a cluster operator.
- v=1 : A reasonable default log level if you don not want verbosity.
- v=2 : Useful steady state information about the service and important log messages that may correlate to significant changes in the system. This is the recommended default log level for most systems.
- v=3 : Extended information about changes.
- v=4 : Debug level verbosity.
- v=5: Trace level verbosity.
- v=6: Display requested resources.
- v=7: Display HTTP request headers.
- v=8: Display HTTP request contents.
- v=9: Display HTTP request contents without truncation of contents.

Help and Documentation

Focus on Kubernetes documentation for following: https://kubernetes.io/docs/reference/kubectl/conventions/

  1. Concepts
  2. Tasks
  3. Tutorials
  4. Reference
    — on command line tool (kubectl)
    — four sections # for understanding imperative commands and docker commands
  5. Practice all imperative commands referring documentation page: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands

Command line documentation using explain

Get all Object properties details using kubectl explain.

kubectl explain pods|svc|deploy|rs

Get all Object properties and any specific property details

kubectl explain pods.spec
kubectl explain configMap.data

Get all Object properties and any specific property details recursive

kubectl explain configMap.data - recursive

Docker Container and POD

https://github.com/wsargent/docker-cheat-sheet#dockerfile

docker run - name
docker run -it - rm busybox
docker pull shambhusinha/spring-boot-rest-hello:0.0.1-latest
docker run shambhusinha/spring-boot-rest-hello

Option is to view the docker image history:

docker image history my-image:latest

Docker ENTRYPOINT vs Pod command

Source: Docker for Beginners — Commands vs Entrypoint — Kubernetes (youtube.com)

Docker example practice

Create a Java class that keep executing for longer time

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 0; i < 10000; i++) {
System.out.println("I am now: " +i);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Create Dockerfile

FROM eclipse-temurin:17-jdk-jammy
WORKDIR /app
COPY Main.java ./
RUN javac Main.java
CMD ["java", "Main"]

Build and tag the image

# Building image and tagging with name javatest abd default version :latest
$ docker build . -t javatest
# Building image and tagging with name javatest abd default version :v1.0.0
$ docker build . -t javatest:v1.0.0

# show all images
$ docker image ls
# Run the image javatest:v1.0.0
$ docker run javatest:v1.0.0

# show all running container
$ docekr ps
$ docekr ps -a

$ docker image inspect javatest:v1.0.0
# Run local registry on port 5000
$ docker run -d -p 5000:5000 --name registry registry:2

curl localhost:5000
curl localhost:5000/v2/_catalog

# loging to docker hub - user is shambhusinha
$ docker login

# tag image with shambhusinha namespace name
$ docker image tag javatest:v1.0.0 shambhusinha/javatest:v1.0.0
$ docker push shambhusinha/javatest:v1.0.0

$ docker push shambhusinha/ckadi:latest

Docker local registry

docker run -d -p 5000:5000 — name registry registry:2

https://distribution.github.io/distribution/

https://stackoverflow.com/questions/23733678/how-to-search-images-from-private-1-0-registry-in-docker

Play with registry

So I know this is a rapidly changing field but (as of 2015–09–08) I found the following in the Docker Registry HTTP API V2:

Listing Repositories (link)

GET /v2/_catalog

Listing Image Tags (link)

GET /v2/<name>/tags/list

controlplane $ curl -X GET http://localhost:5000/v2/_catalog
{"repositories":["ubuntu"]}
controlplane $ curl -X GET http://localhost:5000/v2/ubuntu/tags/list
{"name":"ubuntu","tags":["latest"]}
controlplane $ docker build . -t localhost:5000/javatest
controlplane $ docker push localhost:5000/javatest:latest
controlplane $ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
javatest latest f23c59e62376 39 minutes ago 407MB
localhost:5000/javatest latest f23c59e62376 39 minutes ago 407MB
controlplane $ docker build . -t localhost:5000/javatest:v1.0
controlplane $ curl -X GET http://localhost:5000/v2/_catalog
{"repositories":["javatest"]}
controlplane $ curl -X GET http://localhost:5000/v2/javatest/tags/list
{"name":"javatest","tags":["latest","v1.0"]}
controlplane $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aeded6944d99 registry:2 "/entrypoint.sh /etc…" 11 minutes ago Up 11 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry

Dockerfile

https://docs.docker.com/engine/reference/builder/#dockerfile-reference

Docker Instructions https://stackify.com/docker-build-a-beginners-guide-to-building-docker-images/

Dockerfile Instruction

Explanation

  1. FROM — We use “FROM” to specify the base image we want to start from.
  2. RUN — RUN is used to run commands during the image build process.
  3. ENV — Sets environment variables within the image, making them accessible both during the build process and while the container is running. If you only need to define build-time variables, you should utilize the ARG instruction.
  4. COPY — The COPY command is used to copy a file or folder from the host system into the docker image.
  5. EXPOSE — Used to specify the port you want the docker image to listen to at runtime.
  6. ADD — An advanced form of COPY instruction. You can copy files from the host system into the docker image. You can also use it to copy files from a URL into a destination in the docker image. In fact, you can use it to copy a tarball from the host system and automatically have it extracted into a destination in the docker image.
  7. WORKDIR — It’s used to set the current working directory.
  8. VOLUME — It is used to create or mount the volume to the Docker container
  9. USER — Sets the user name and UID when running the container. You can use this instruction to set a non-root user of the container.
  10. LABEL — Specify metadata information of Docker image
  11. ARG — Defines build-time variables using key-value pairs. However, these ARG variables will not be accessible when the container is running. To maintain a variable within a running container, use ENV instruction instead.
  12. CMD — Executes a command within a running container. Only one CMD instruction is allowed, and if multiple are present, only the last one takes effect.
  13. ENTRYPOINT — Specifies the commands that will execute when the Docker container starts. If you don’t specify any ENTRYPOINT, it defaults to “/bin/sh -c”.

Dockerfile sample

FROM centos:7
MAINTAINER Devopscube
RUN yum -y update && \
yum -y install httpd-tools && \
yum clean all
ENTRYPOINT ["ab" , "http://google.com/" ]
FROM ubuntu
RUN sh -c "echo hello"
COPY test.html /opt
ENTRYPOINT ["sh" , "-c" , "echo" , "Hello"]

Docker command

sudo docker build -t docker-practice .
# Run image with psuedo-tty being attached to the screen
sudo docker run \
- interactive - tty \
- publish 12345:27017 \
- volume /srv/docker-practice/db:/data/db \
- rm - name docker-practice docker-practice
# Run image as a daemon
sudo docker run \
- detach \
- publish 12345:27017 \
- volume /srv/docker-practice/db:/data/db \
- rm - name docker-practice docker-practice
# Attach to the running docker image
sudo docker exec -it docker-practice /bin/sh
# Stop running docker container
sudo docker stop docker-practice
kubectl exec -it demo-pod - /bin/sh
This specifies that you want to run the /bin/sh command in the first container within your demo-pod pod. The - separates the command to run from the kubectl arguments. Anything after the - will be passed to the container, as opposed to kubectl.
The -it is equivalent to using the - stdin (-i) and - tty (-t) flags. These instruct kubectl to route your terminal's stdin input stream to the container (-i) and treat it as a TTY (-t). This sets up an interactive session where you can supply input to the process inside the container. Without these flags, you'd see a read-only output stream.
Whereas SSH automatically starts a shell process and binds your terminal's input and output streams, kubectl makes each of these aspects customizable. You don't have to start a shell in the container; you could run an arbitrary process instead, supply it some interactive input, and receive its output:
kubectl exec -it demo-pod - node my-script.js

From <https://www.containiq.com/post/using-kubectl-exec-shell-commands-examples>

Helm

Helm requirs understanding and concept for

  1. chart
  2. hub
  3. repo
  4. release
  5. Local repo

High level diagram on chart

Helm basic commands

helm search hub
helm search hub - list-repo-url -o yaml
helm repo add k8sonlab https://charts.billias.cc
helm repo ls
helm search repo k8sonlab
helm install k8sonlab-1 k8sonlab/librephotos
helm ls
helm ls -a
helm ls -a -A
kubectl get all -A
helm search repo k8sonla

Helm commands for adding a chart name truecharts from hub and install

controlplane $ helm search repo truecharts
No results found

controlplane $ helm repo add truecharts https://charts.truecharts.org/
controlplane $ helm repo add truecharts https://charts.truecharts.org/
"truecharts" has been added to your repositories

controlplane $ helm repo ls
NAME URL
nginx-stable https://helm.nginx.com/stable
bitnami https://charts.bitnami.com/bitnami
k8sonlab https://charts.billias.cc
truecharts https://charts.truecharts.org/

controlplane $ helm search repo truecharts # repo added with many charts, so list all
NAME CHART VERSION APP VERSION DESCRIPTION
truecharts/acestream 3.0.0 2.0.2.8 IPTV service providing streaming, playlist, sea…
truecharts/actualserver 3.0.13 23.2.9 Actual is a super fast privacy-focused app for …
truecharts/adguard-home 4.0.16 0.107.25 Free and open source, powerful network-wide ads…

controlplane $ helm install my-truecharts-1 truecharts/acestream
NAME: my-truecharts-1
...

helm ls -a -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
apiserver team-yellow 1 2023–03–24 01:41:25.547304669 +0000 UTC deployed apache-9.2.19 2.4.56
my-truecharts-1 default 1 2023–03–24 01:51:49.568541287 +0000 UTC deployed acestream-3.0.0 2.0.2.8
webserver team-blue 1 2023–03–24 01:41:21.232856285 +0000 UTC deployed apache-9.2.19 2.4.56

controlplane $ helm uninstall my-truecharts-1
release "my-truecharts-1" uninstalled

controlplane $ helm install my-truecharts-1 truecharts/acestream -n shambhu
controlplane $ helm install my-truecharts-1 truecharts/notea -n shambhu
Error: INSTALLATION FAILED: create: failed to create: namespaces "shambhu" not found

controlplane $ k create ns shambhu
namespace/shambhu created

controlplane $ helm install my-truecharts-1 truecharts/notea -n shambhu
Release my-truecharts-1 has been cancelled.
Error: INSTALLATION FAILED: context canceled

controlplane $ helm ls -a -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
apiserver team-yellow 1 2023–03–24 01:41:25.547304669 +0000 UTC deployed apache-9.2.19 2.4.56
my-truecharts-1 shambhu 1 2023–03–24 02:01:20.745806305 +0000 UTC failed notea-2.0.9 latest
webserver team-blue 1 2023–03–24 01:41:21.232856285 +0000 UTC deployed apache-9.2.19 2.4.56

controlplane $ helm create my-test-chart
Creating my-test-chart

controlplane $ helm install ./my-test-chart/
Error: INSTALLATION FAILED: must either provide a name or specify - generate-name

controlplane $ helm install sellf-created-chart ./my-test-chart/
NAME: sellf-created-chart
...

controlplane $ helm ls -a -A
sellf-created-chart default 1 2023–03–24 02:12:27.653425951 +0000 UTC deployed my-test-chart-0.1.01.16.0
...

controlplane $ helm install sellf-created-chart ./my-test-chart/ -n self - create-namespace
NAME: sellf-created-chart
...

controlplane $ helm ls -a -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
sellf-created-chart self 1 2023–03–24 02:16:05.794302757 +0000 UTC deployed my-test-chart-0.1.0 1.16.0

Kubernetes CRD

  1. Generally understand how CRD works and Practice creating CRD
  2. Practice if created CRD is appearing in list of Kubernetes Objects using api-version as well as creating Object of CRDs
  3. Memorizing their attributes and structure, as well as important configurations.
  4. Practice on debugging misconfiguration of YAML file for issues.

Controller and Admission Controller

I have not seen any question from this but building concept would be always helpful.

API version

Generally one easy question is asked from this chapater, so must have

  1. Good concpet on API versioning in kubernetes
  2. Mostly question is for migration of old version manifest file to latest version and that requires Convert tool
  3. practice installing Covert tool as well as manifest file migration and deployment with latest Kubernetes version. Documentation: https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-convert-plugin
  4. Example: kubectl convert plugin (pet2cattle.com)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: beta-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/target-type: ip
spec:
rules:
- http:
paths:
- backend:
serviceName: example
servicePort: 8080
path: /*

Command

controlplane $ kubectl convert -f ingress.yaml --output-version networking.k8s.io/v1 >v1.ingress.yaml
controlplane $ k apply -f v1.ingress.yaml

Gathering the information necessary to succeed on the CKAD exam is the goal of this blog. Consider yourself prepared for the test; you should be aware of all the material and know where to put your emphasis. By reading this, you may get the correct information and save a lot of time compared to doing your own research. Please do your best on the exam and let me know what you think by leaving a comment on this blog.

Summary of this series

  1. Part 1 — About CKAD Test, CKAD Domains & Competencies (Syllabus) # What to practice
  2. Part 2 — Working with Linux commands, usage of JSON, YAML etc. for CKAD exam
  3. Part 3 — How to improve efficiency and some details on non Kubernetes object practice
  4. Part 4 — All about Kubernetes objects

--

--