CKAD exam 1
CKAD Exam Instructions and Requirements
You must have a working MiniKube cluster, and you must be able to add extra MiniKube nodes.
You must have a working Docker installation on your machine.
You must have Helm installed.
Read all questions carefully. Exercises must be done in the namespace requested.
You can navigate through questions using the buttons at the top of the screen.
The green bar will show you the rough amount of time remaining.
Total time is 2 hours for 18 questions.
Create 3 Pods with names nginx1 π Copied! , nginx2 π Copied! , and nginx3 π Copied! in the namespace 104ab4 π Copied! running nginx:latest π Copied! .
- Label nginx1 with app=nginx π Copied! .
- Annotate nginx2 with ingress=enabled π Copied! .
- Completely unlabel the nginx3 Pod.
You are a member of team-blue and must prepare a compute node designed only for team-blue deployments.
- Create the namespace team-blue π Copied! .
- Create a new minikube Node named blue π Copied! and label it with node=dedicated π Copied! . For minikube, you can use the command minikube node add blue π Copied! .
- Add a taint to the blue π Copied! node with node=dedicated π Copied! and the NoSchedule π Copied! effect.
- Create a Deployment named blue-dedicated-node π Copied! , with the image nginx:latest π Copied! in the namespace team-blue π Copied! .
- Ensure the Deployment:
- Tolerates the taint on the node.
- Is scheduled only on the node labeled node=dedicated π Copied! .
Team Cr4zy has requested their application to be deployed in a namespace named team-cr4zy π Copied! , which you must create. They use the image webapp-color:v1 π Copied! and require a Deployment named cr4zy-app π Copied! . The deployment should update its Pods using the Recreate π Copied! strategy. Every Pod created by the deployment should request 100m π Copied! CPU. As the load on the application can vary drastically during the day, you suggest using horizontal autoscaling.
Configure the cr4zy-app π Copied! Deployment with a horizontal autoscaler. Configure the autoscaler to deploy between 2-5 Pods, with a target CPU utilization of 75%.
A new version of a web application your company is hosting is available. You are tasked with verifying that the new version of the application can reliably serve traffic. You will do this by creating a so-called canary Deployment. Using this method, the new version of the application is spun up and serves traffic next to the old version of the application.
Create a Deployment called application π Copied! with image hashicorp/http-echo:v0.2.2 π Copied! , and a Deployment called canary π Copied! with image hashicorp/http-echo:v0.2.3 π Copied! both on a new namespace loadbalance π Copied! . Configure a Service that balances the load over the two Deployments. Configure the Deployments in such a way that 75% of the traffic reaches the stable version ( hashicorp/http-echo:v0.2.2 π Copied! ) and 25% reaches the canary version ( hashicorp/http-echo:v0.2.3 π Copied! ) Deployment.
Optional: you can verify your solution by adding the following configuration to your Deployments:
1
2
3
4
5
6
args: ["-text", "Hello from Pod $(POD_NAME)"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
The image should then respond to API GET Requests with the Pod name that handled the request.
As a member of Team Slyce you are responsible for creating PostgreSQL database backups and cleaning up old log files. Team Slyce operates in the pg-slyce π Copied! namespace, that you must create. Both the backup and cleanup Jobs must happen on a regular schedule. The requirements of the two jobs are as follows:
- A CronJob named db-backup π Copied! must exist in the pg-slyce π Copied! namespace. It should run the image postgres:15.17-trixie π Copied! and schedule a Job every night at 02:00 AM.
- The db-backup π Copied! CronJob must not allow concurrent Jobs to run.
The db-backup π Copied! CronJob should always keep the last 7 successful, and last 7 failed Jobs.
- A CronJob named db-cleanup π Copied! must exist in the pg-slyce π Copied! namespace. It should also run the image postgres:15.17-trixie π Copied! .
- The db-cleanup π Copied! CronJob must run once per week on Sunday at 05:00 AM.
- The Jobs created by the db-cleanup π Copied! CronJob should have a maximum of 3 retries upon failure. The container itself must never be allowed to Restart.
Create both CronJobs according to the specifications mentioned above.
You received a message from a developer that Kyverno flagged a Pod in the acceptance π Copied! namespace in another Kubernetes cluster for violating some of the security policies. You do not have access to that Kubernetes cluster, but the developer does send you a log of Error messages:
error: resource was rejected by Kyverno: resource Pod/acceptance/insecure-pod failed policy strict-policy:
- runAsNonRoot: container c1 must not run as root (UID 0).
- seccompProfile: container c1 must have a seccomp profile set to RuntimeDefault.
- allowPrivilegeEscalation: container c1 must not allow privilege escalation.
- readOnlyRootFilesystem: container c1 must have a read-only root filesystem.
- capabilities: container c1 must drop ALL capabilities.
Show the developer how to implement a Pod with the correct security context. Deploy a Pod to the acceptance π Copied! namespace in your cluster that conforms to all the security policies that are mentioned above. You can name the Pod dev-security-demo π Copied! , and for demonstration purposes can use the image nginx:latest π Copied! .
You are investigating Kubernetes credentials inside Pods. You must create a workload and identify the token that this workload uses to talk to the kube-apiserver.
- Create a namespace called ctf π Copied! .
- Create a ServiceAccount named inspector π Copied! in the ctf π Copied! namespace.
- Create a Pod in the ctf π Copied! namespace named app π Copied! with
image: busybox:latest π Copied!
command: sleep 3600 π Copied!
with service account: inspector π Copied!
- Identify the ServiceAccount JWT token mounted inside the Pod.
- Save the value of the token inside the file ~/token.txt π Copied! .
You are contacted by a developer from team June-ior requesting help in troubleshooting their Deployment manifest. Identify and fix all issues in the Deployment manifest and then apply it to your Kubernetes cluster on the june-ior π Copied! namespace. You can create the namespace june-ior π Copied! if it doesnβt exist. You must ensure that all Pods reach a Running & Ready state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: web
image: nginx:last
ports:
- containerPort: "8080"
restartPolicy: Never
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
For this question create the namespace secure-logs π Copied! .
Create a DaemonSet with the following requirements:
- Runs on all nodes.
- uses the image nginx:1.25-alpine π Copied! .
- Mounts a Secret volume at /etc/tls π Copied! named tls-volume π Copied! inside the container.
You must create a TLS secret in the secure-logs π Copied! namespace with these requirements:
- Secret name must be tls-secret π Copied! .
- Must be of type kubernetes.io/tls π Copied! .
- Contains tls.crt π Copied! and tls.key π Copied! .
- You can generate a certificate and key with openssl:
1 2 3 4 5
openssl req -x509 -nodes -days 365 \ -newkey rsa:2048 \ -keyout tls.key \ -out tls.crt \ -subj "/CN=localhost"
You must mount the secret inside the container at /etc/tls π Copied! , and files must be read-only π Copied! . Ensure that the secret keys appear as files:
/etc/tls/tls.crt π Copied!
/etc/tls/tls.key π Copied!
A new development team will deploy workloads into a dedicated Kubernetes namespace. To prevent resource overuse, the cluster administrators want to enforce strict resource boundaries.
Create a namespace called limited π Copied! . Create a ResourceQuota to enforce the below constraints on the limited π Copied! namespace. You donβt need to create any Pods.
- Maximum number of Pods: 5
- Maximum total CPU requests: 200m
- Maximum total CPU limits: 300m
- Maximum total Memory requests: 100Mi
- Maximum total Memory limits: 150Mi
A team is deploying a lightweight internal service that listens for TCP connections on port 80 π Copied! . The application does not expose HTTP health endpoints, so health checks must be performed using TCP socket probes.
The platform team wants to ensure:
- The container is restarted if it becomes unresponsive.
- The Pod only receives traffic when it is ready to accept TCP connections.
Create a Pod in the default π Copied! namespace with the name lightweight-app π Copied! , the image nginx:alpine π Copied! , container name app π Copied! , and the container port 80 π Copied! .
Configure a TCP Liveness probe with an initial delay of 10 π Copied! seconds, and a period of 5 π Copied! seconds. Configure a TCP Readiness probe with an initial delay of 2 π Copied! seconds, and a period of 3 π Copied! seconds, and a failure threshold of 1 π Copied! .
The busy-team has been security audited and was told to implement network policies to better control traffic inside their kubernetes cluster. As they are very busy, this task was assigned to you. Their setup is as follows:
- They run a PostgreSQL database (as Pods with label type=database π Copied! ) in the busy-database π Copied! namespace.
- They run two web-apiβs (as Deployments, with Pod labels app=green π Copied! for the green π Copied! web-api, and with Pod labels app=blue π Copied! for the blue π Copied! web-api) in the busy-api π Copied! namespace.
As they are truly very busy, all the specifications you obtained are in a hastily scribbled note:
- All ingress and egress traffic must be denied by default unless explicitly allowed via NetworkPolicies.
- Egress traffic from the green π Copied! to the blue π Copied! web-api Pods over port 80 π Copied! ALLOWED.
- Egress traffic from the green π Copied! web-api Pods to the database over port 5432 π Copied! ALLOWED.
- Ingress traffic to the database from the green π Copied! web-api Pods over port 5432 π Copied! ALLOWED.
- Ingress traffic to the database from the blue π Copied! web-api Pods NOT ALLOWED.
Create the namespaces busy-database π Copied! and busy-api π Copied! . Label busy-database π Copied! with namespace=busy-database π Copied! and label busy-api π Copied! with namespace=busy-api π Copied! . Create the network policies required to satisfy the above specifications. You do not need to deploy any databases or apiβs.
TODO: Ingress exercise
For this question, you are allowed to use the following url and sub-directories for information: https://github.com/grafana-community/helm-charts/tree/main/charts/grafana π Copied! .
Add the grafana-community π Copied! Helm repository https://grafana-community.github.io/helm-charts π Copied! .
- Create the namespace grafana-dev π Copied! .
- Install Grafana using Helm, and give it the name grafana-dev π Copied! .
- Configure the chart such that the service type is NodePort π Copied! , and the admin password is set to swordfish17 π Copied! .
After installation, upgrade the grafana-dev π Copied! Helm chart such that the service type is now ClusterIP π Copied! .
Given the index.html π Copied! file with the contents:
1
2
3
4
5
6
<!DOCTYPE html>
<html>
<head>
<title>Hello CKAD</title>
</head>
</html>
Create a Dockerfile and the above index.html π Copied! file in the ~/ckad1/q15/docker π Copied! folder. The Dockerfile should use the nginx:latest π Copied! image, and should copy the index.html π Copied! file to /usr/share/nginx/html/index.html π Copied! .
Build a Docker image from the Dockerfile you created, and give it the name dev-app π Copied! and tag it with v0.0.1 π Copied! . Save the image as a tar π Copied! archive in the the directory ~/ckad1/q15/image π Copied! with the name dev-app.tar π Copied! .
A GitOps controller (e.g. FluxCD) will be run by the platform team in the iota π Copied! namespace and must only be able to read Pods in that namespace. The controller will use the service account named controller-sa π Copied! .
Create the required ServiceAccount, Role, and RoleBinding on the iota π Copied! namespace.
Create a ConfigMap named app-config π Copied! in the default π Copied! namespace containing the following key-value pairs:
- APP_COLOR=blue
- APP_MODE=test
- APP_DEBUG=true
Create a Deployment named configured-app π Copied! in the default π Copied! namespace running the image nginx:1.25 π Copied! and 2 π Copied! replicas.
Expose the ConfigMap values as environment variables inside the container. Additional requirement:
- The environment variable names inside the container must match the ConfigMap keys, but with the βAPP_β prefix removed. (e.g., APP_COLOR β COLOR).
Create a Deployment named secure-app π Copied! in the capabilities π Copied! namespace, run it with nginx:latest π Copied! for testing purposes.
The application inside the container requires the ability to bind to privileged ports (<1024). Add the NET_BIND_SERVICE π Copied! capability to the container, and no other capabilities.