CKAD Exercises - Part 2

Pod Design

Labels, Selectors, Annotations

Exercise 1

List all pods with all their labels.

Show Solution

kubectl get pods --show-labels

Exercise 2

Create two pods with image nginx. Add the label env=blue to one of them and and env=green to the other. List all pods that have the app label.

Show Solution

kubectl run nginx-blue --image=nginx --restart=Never -l env=blue 
kubectl run nginx-green --image=nginx --restart=Never -l env=green
kubectl get pods -l env --show-labels

Exercise 3

Assuming there is a pod with label env=green, change the label to env=red.

Show Solution

kubectl label pod nginx-blue env=red --overwrite=true

Exercise 4

Assuming there is a pod with label env=blue, remove the value blue from this label.

Show Solution

kubectl label pod nginx-blue env= --overwrite=true

Exercise 5

Assuming there is a pod labeled with env=blue, remove this label from the pod.

Show Solution

kubectl label pod nginx-blue env-

Exercise 6

Add the label gpu=hardware to one of your cluster nodes. Create a pod with image busybox that will automatically be assigned to run on the previously labeled node.

TIP: Use nodeSelector in the pod specification to assign the pod to a node.

Show Solution

kubectl get nodes

kubectl label node <one-of-your-nodes-here> gpu=hardware

kubectl run gpu-app --image=busybox --restart=Never --dry-run=client -o yaml > pod.yaml 

kubectl create -f pod.yaml

Add a podSelector to pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: gpu-app
  name: gpu-app
spec:
  containers:
  - image: busybox
    name: gpu-app
    resources: {}
  nodeSelector: 
    gpu: hardware
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

Please note that a nodeSelector value is automatically interpreted as a label.

Annotations

Exercise 7

Annotate a pod with team=devops.

Show Solution

kubectl annotate pod nginx team=devops

Exercise 8

Find a pods annotations.

Show Solution

kubectl describe pod nginx
# Please find annotations in the "Annotations" field.

Exercise 9

Remove a pods team=devops annotation.

Show Solution

kubectl annotate pod nginx team-

Pod Design

Deployments

Exercise 10

Create a deployment with image nginx.

Show Solution

kubectl create deploy nginx-webapp --image=nginx:1.20

Exercise 11

Get the replicaset that was created with a deployment.

Show Solution

kubectl get replicaset -l app=nginx-webapp

Exercise 12

Scale an existing deployment to 3 replicas.

Show Solution

kubectl scale deploy nginx-webapp --replicas=3 

Exercise 13

Find all pods of a deployment.

Show Solution

# get the labels from a deployment
kubectl get deploy --show-labels

# use the `app` label to find all deployments
kubectl get pod -l app=nginx-webapp

Exercise 14

Get a deployments rollout status.

Show Solution

kubectl rollout status deployment nginx-webapp

Exercise 15

Change the image version of a deployment. Confirm the image version for the deployment was set correctly. Confirm the pods are started with the new image.

Show Solution

kubectl set image deploy/nginx-webapp nginx=nginx:1.19
kubectl get deployment nginx-webapp -o wide # alternatively: kubectl describe deploy nginx-webapp | grep Image
# Confirm that column "IMAGES" contains "nginx:1.19" 
kubectl get pods -l app=nginx-webapp -o yaml | grep "image: nginx:1.19"
# If, e.g. there are 2 pods within the deployment, confirm that the image was listed 2 times.

One alternative to using the “kubectl set image” command is to use the “edit” command and edit the image inside a text editor instead: kubectl edit deploy nginx-webapp.

Exercise 16

Show the revision history for a deployment.

Show Solution

kubectl rollout history deploy nginx-webapp

Exercise 17

Verify that the rollout of the new image version was successful.

Show Solution

kubectl rollout history deploy nginx-webapp
kubectl rollout status deployment nginx-webapp
# Make sure that you see a positive confirmation: deployment "nginx-webapp" successfully rolled out.
# If there the deployment is still ongoing or there is a problem, you will usually see a message that makes this clear, 
# such as the following: 
# Waiting for deployment "nginx-webapp" rollout to finish: 1 of 3 updated replicas are available…
# or:
# error: deployment "nginx-webapp" exceeded its progress deadline

Exercise 18

Rollback a deployment to the previous version.

Show Solution

kubectl rollout undo deployment nginx-webapp

Exercise 19

Set the image of a deployment to a wrong value. Confirm that the deployment is in an error state.

Show Solution

Use the set image command to change the image:

kubectl set image deploy/nginx-webapp nginx=nginx:does-not-exist

TIP: Alternatively, you can also use kubectl edit deployment nginx-webapp to edit the image in an editor like vim.

Confirm that the rollout is still in a pending state (the corresponding pods should be in status ErrImagePull):

kubectl rollout status deploy nginx-webapp
# Waiting for deployment "nginx-webapp" rollout to finish: 1 old replicas are pending termination...

kubectl get pods -l app=nginx-webapp
# NAME                            READY   STATUS         RESTARTS   AGE
# nginx-webapp-7d85f4f584-v9sqc   0/1     ErrImagePull   0          7s

Exercise 20

Suppose there are 10 revisions of a deployment. Rollback all revisions up to revision 1.

Show Solution

kubectl rollout undo deployment/nginx-webapp --to-revision=1

NOTE: If you leave away parameter --to-revision then the undo command will only undo the latest revision.

Exercise 21

Suppose there are 10 revisions of a deployment. Show the history for revision 4.

Show Solution

kubectl rollout history deploy nginx-webapp --revision=4
# Output:
# deployment.apps/nginx-webapp with revision #4
# Pod Template:
#   Labels:        app=nginx-webapp
#   Containers:
#    nginx:
#     Image:       nginx:1.19
#     Port:        <none>
#     Host Port:   <none>
#     Environment: <none>
#     Mounts:      <none>
#   Volumes:       <none>

NOTE: Observe how the image is part of the output!

Exercise 22

Pause the rollout of a deployment.

Show Solution

kubectl rollout pause deploy nginx-webapp

Exercise 23

Resume the rollout of a deployment.

Show Solution

kubectl rollout resume deploy nginx-webapp

Exercise 24

Create an autoscaling rule for a deployment. Set the autoscaling CPU target to 70%. Use 2 as the minimum and 3 as the maximum number of replicas.

Show Solution

kubectl autoscale deploy webapp --cpu-percent=70 --min=2 --max=3 

Make sure a HorizontalPodAutoscaler was successfully created.

kubectl autoscale deploy webapp --cpu-percent=70 --min=2 --max=3 
# Output:
# NAME           REFERENCE                 TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
# nginx-webapp   Deployment/nginx-webapp   <unknown>/70%   2         3         0          7s

Verify that two pods have been created:

kubectl get pods -l app=nginx-webapp
# Output:
# NAME                          READY   STATUS    RESTARTS   AGE
# nginx-webapp-ccf759f6-czv7s   1/1     Running   0          24m
# nginx-webapp-ccf759f6-xr6r2   1/1     Running   0          24m

Exercise 25

Remove autoscaling for a deployment.

Show Solution

Delete the HorizontalPodAutoscaler that was created when the corresponding autoscaling rule has been created.

kubectl delete hpa nginx-webapp
# Output:
# horizontalpodautoscaler.autoscaling "nginx-webapp" deleted

Exercise 26

Delete a deployment.

Show Solution

kubectl delete deployment nginx-webapp

NOTE: Observe how the pods are being deleted with the deployment as well!

Jobs

Exercise 27

Create a job named envprinter with image busybox that prints all environment variables and then quits.

TIP: To print all environment variables, use the linux command env.

Show Solution

kubectl create job envprinter --image=busybox -- env
# Output: 
# job.batch/envprinter created

Exercise 28

Check the status of a job named envprinter.

Show Solution

kubectl get job envprinter
# Output:
# NAME         COMPLETIONS   DURATION   AGE
# envprinter   1/1           5s         1m14s

kubectl describe job envprinter
# Output: 
# ...
# Type    Reason            Age    From            Message
# ----    ------            ----   ----            -------
# Normal  SuccessfulCreate  4m40s  job-controller  Created pod: envprinter-rn272
# Normal  Completed         4m37s  job-controller  Job completed

TIP: You can add parameter -w to watch for changes (such as the completion status).

Exercise 29

Print the logs for a job with the name envprinter.

Show Solution

kubectl logs job/envprinter
# Output:
# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# HOSTNAME=envprinter-crzbq
# KUBERNETES_PORT=tcp://10.245.0.1:443
# KUBERNETES_PORT_443_TCP=tcp://10.245.0.1:443
# KUBERNETES_PORT_443_TCP_PROTO=tcp
# KUBERNETES_PORT_443_TCP_PORT=443
# KUBERNETES_PORT_443_TCP_ADDR=10.245.0.1
# KUBERNETES_SERVICE_HOST=10.245.0.1
# KUBERNETES_SERVICE_PORT=443
# KUBERNETES_SERVICE_PORT_HTTPS=443
# HOME=/root

TIP: You can add parameter -f to follow the logs. In this case the logs will be streamed.

Exercise 30

Delete the job with the name envprinter.

Show Solution

kubectl delete job envprinter
# Output:
# job.batch "envprinter" deleted

Exercise 31

Create a job named greeter with image busybox that executes sh -c 'echo Hi; sleep 3; echo Bye;' and then exists. Let Kubernetes run it 10 times in a row (sequentially). Watch the execution progress. Delete the job after all executions completed.

Show Solution

kubectl create job greeter --image=busybox --dry-run=client -o yaml -- sh -c 'echo Hi; sleep 3; echo Bye;' > greeter.yaml

The above command will create the YAML file greeter.yaml. Open this file in a text editor like vim and set attribute spec.parallelism to value 10 like this:

apiVersion: batch/v1
kind: Job
metadata:
  creationTimestamp: null
  name: greeter
spec:
  parallelism: 10 # <--- Add this line to the YAML file!
  template:
    metadata:
      creationTimestamp: null
    spec:
      containers:
      - command:
        - sh
        - -c
        - echo Hi; sleep 3; echo Bye;
        image: busybox
        name: greeter
        resources: {}
      restartPolicy: Never
status: {}

Create the job using the spec from greeter.yaml:

kubectl create -f greeter.yaml 
# Output:
# job.batch/greeter created

Watch the progress:

kubectl get job/greeter -w
# Output:
# NAME      COMPLETIONS   DURATION   AGE
# greeter   0/10          3s         3s
# greeter   1/10          6s         6s
# greeter   2/10          11s        11s
# greeter   3/10          16s        16s
# greeter   4/10          21s        21s
# greeter   5/10          26s        26s
# greeter   6/10          31s        31s
# greeter   7/10          37s        37s
# greeter   8/10          42s        42s
# greeter   9/10          47s        47s
# greeter   10/10         52s        52s

IMPORTANT: Observe how we used parameter -w to watch for status changes. This command will then block and update the status regularly.

Delete the job:

kubectl delete job greeter
# Output:
# valuejob.batch "greeter" deleted

Exercise 32

Get all pods that belong to a job named greeter.

Show Solution

kubectl get pods -l job-name=greeter
# Output:
# NAME            READY   STATUS      RESTARTS   AGE
# greeter-4zkm7   0/1     Completed   0          9m8s
# greeter-5hzsv   0/1     Completed   0          9m14s
# greeter-cj22v   0/1     Completed   0          8m56s
# greeter-fq9lk   0/1     Completed   0          9m2s
# greeter-h7xkr   0/1     Completed   0          8m50s
# greeter-jt67x   0/1     Completed   0          9m26s
# greeter-kg7mj   0/1     Completed   0          9m46s
# greeter-qrzv6   0/1     Completed   0          9m20s
# greeter-wm9xx   0/1     Completed   0          9m32s
# greeter-wpxr8   0/1     Completed   0          9m38s

Exercise 33

Create a job named greeter with image busybox that executes sh -c 'echo Hi; sleep 3; echo Bye;' and then exists. Let Kubernetes run it 10 times in parallel. Watch the execution progress. Delete the job after all executions completed.

Show Solution

kubectl create job greeter --image=busybox --dry-run=client -o yaml -- sh -c 'echo Hi; sleep 3; echo Bye;' > greeter.yaml

The above command will create the YAML file greeter.yaml. Open this file in a text editor like vim and set attribute spec.completions to value 10 like this:

apiVersion: batch/v1
kind: Job
metadata:
  creationTimestamp: null
  name: greeter
spec:
  parallelism: 10 # <--- Add this line to the YAML file!
  template:
    metadata:
      creationTimestamp: null
    spec:
      containers:
      - command:
        - sh
        - -c
        - echo Hi; sleep 3; echo Bye;
        image: busybox
        name: greeter
        resources: {}
      restartPolicy: Never
status: {}

Create the job using the spec from greeter.yaml:

kubectl create -f greeter.yaml 
# Output:
# job.batch/greeter created

Watch the progress:

kubectl get job/greeter -w
# Output:
# NAME      COMPLETIONS   DURATION   AGE
# greeter   0/1 of 10     2s         2s
# greeter   1/1 of 10     7s         7s
# greeter   2/1 of 10     8s         8s
# greeter   3/1 of 10     8s         8s
# greeter   4/1 of 10     8s         8s
# greeter   5/1 of 10     8s         8s
# greeter   6/1 of 10     8s         8s
# greeter   7/1 of 10     8s         8s
# greeter   8/1 of 10     12s        12s
# greeter   9/1 of 10     12s        12s
# greeter   10/1 of 10    12s        12s

IMPORTANT: Observe how we used parameter -w to watch for status changes. This command will then block and update the status regularly.

Delete the job:

kubectl delete job greeter
# Output:
# valuejob.batch "greeter" deleted

CronJobs

Exercise 34

Create a cron job named time-printer that runs each minute to print the current date/time and then exit. Verify that the job actually runs each minute. Delete the job when you’re done.

TIP: You can use the unix command date to print the current date/time.

TIP: The cron expression for a 1 minute schedule is */1 * * * *.

Show Solution

Create the job:

kubectl create cronjob time-printer --image=busybox --schedule="*/1 * * * *" -- sh -c "date"
# Output:
# cronjob.batch/time-printer created

Watch new pods being created each minute:

kubectl get pods -w
# Output:
# NAME                            READY   STATUS        RESTARTS   AGE
# time-printer-1621548660-7vbgg   0/1     Completed     0          3m8s
# time-printer-1621548720-lgdk4   0/1     Completed     0          2m8s
# time-printer-1621548780-zg6mk   0/1     Completed     0          67s
# time-printer-1621548840-5t76k   0/1     Completed     0          7s
# time-printer-1621548660-7vbgg   0/1     Terminating   0          3m14s
# time-printer-1621548660-7vbgg   0/1     Terminating   0          3m14s
# time-printer-1621548900-wqgb6   0/1     Pending       0          0s
# time-printer-1621548900-wqgb6   0/1     Pending       0          0s
# ...

NOTE: Observe how we used parameter -w to watch the list of pods. This will block and report status updates.

Delete the job:

kubectl delete cronjob time-printer
# Output:
# cronjob.batch "time-printer" deleted

IMPORTANT: Observe how all pods that were created for the cron job are also being deleted with the cron job!