Mock Exam 3
-
Question 1
-
You are an administrator preparing your environment to deploy a Kubernetes cluster using kubeadm. Adjust the following network parameters on the system to the following values, and make sure your changes persist reboots:
net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1
-
The above two changes are required, essentially before Kubernetes is deployed.
-
Check the documentation for a guide on how to create a cluster with kubeadm:
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
- The first step you need to do is install a container runtime:
https://kubernetes.io/docs/setup/production-environment/container-runtimes/
-
We need to enable IPV4 Packet Forwarding
-
We run the following, which satisfies the
net.ipv4.ip_forward = 1andnet.bridge.bridge-nf-call-iptables = 1parts: ```sysctl params required by setup, params persist across reboots
cat «EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF
Apply sysctl params without reboot
sudo sysctl –system
* **Question 2**
* Create a new service account with the name pvviewer. Grant this Service account access to list all PersistentVolumes in the cluster by creating an appropriate cluster role called pvviewer-role and ClusterRoleBinding called pvviewer-role-binding.
Next, create a pod called pvviewer with the image: redis and serviceAccount: pvviewer in the default namespace.
* Create the Service Account:
kubectl create serviceaccount pvviewer
* Good tip for the exam, make sure to copy and paste the name.
* Check that the Service Account was created:
* Create the `clusterrole`:
kubectl create clusterrole pvviewer-role –resource=persistentvolumes –verb=list
* Creates a clusterrole and we can list persistent volumes.
* We can then check to make sure it is created successfully:
kubectl describe clusterrole pvviewer-role
* It will show that the `Resource` can list them.
* Then need to create a rolebinding, to bind the service account:
kubectl create clusterrolebinding pvviewer-role-binding –clusterole=pvviewer-role –serviceaccount=default:pvviewer
* Then to check the `clusterrolebinding`, run the following:
kubectl describe clusterrolebinding pvviewer-role-binding
* You'll see that the `pvviewer` service account is linked to the `pvviewer` role.
* Then we need to create a pod called `pvviewer`. We need to create a file for this:
apiVersion: v1 kind: Pod metadata: name: pvviewer spec: serviceAccountName: pvviewer containers: - name: pvviewer image: redis
* Apply the above file:
kubectl apply -f
* Check for the pod:
kubectl get pod
* Run the `kubectl describe pod pvviewer` command and make sure that `Service Account` is set to `pvviewer`.
* **Question 3**
* Create a StorageClass named rancher-sc with the following specifications:
The provisioner should be rancher.io/local-path.
The volume binding mode should be WaitForFirstConsumer.
Volume expansion should be enabled.
* Go to the documentation and search for `storageclass`:
https://kubernetes.io/docs/concepts/storage/storage-classes/
* Use this example configuratoin from the documentation:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: low-latency annotations: storageclass.kubernetes.io/is-default-class: “false” provisioner: csi-driver.example-vendor.example reclaimPolicy: Retain # default value is Delete allowVolumeExpansion: true mountOptions:
-
discard # this might enable UNMAP / TRIM at the block storage layer volumeBindingMode: WaitForFirstConsumer parameters: guaranteedReadWriteLatency: “true” # provider-specific ```
-
Create a file and paste in the above configuration.
-
We change the above configuration to the following:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rancher-sc
provisioner: rancher.io/local-path
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
- Then we apply the file:
kubectl apply -f <file.yaml>
-
Question 4
-
Create a ConfigMap named app-config in the namespace cm-namespace with the following key-value pairs:
ENV=production LOG_LEVEL=info
Then, modify the existing Deployment named cm-webapp in the same namespace to use the app-config ConfigMap by setting the environment variables ENV and LOG_LEVEL in the container from the ConfigMap.
-
We run
kubectl create configmap app-config -n cm-namespace --from-literal=ENV=production --from-literal=LOG_LEVEL=INFO -
kubectl get cm -n cm-namespace -
Describe it as well:
kubectl describe cm app-config -n cm-namespace
- Then run:
kubectl get deployment -n cm-namespace
- To make changes in the exam, just run:
kubectl get deploy -o yaml
- Can also do it this way as well:
kubectl edit deployment cm-webapp -n cm-namespace
- Then we look for the container under
containers:and pass in the configmap as environmental variables:
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
envFrom:
- configMapRef:
name: app-config
- The deployment will be updated automatically. All you then need to do is the following:
kubectl get pod -n cm-namespace
-
Question 5
-
Create a PriorityClass named low-priority with a value of 50000. A pod named lp-pod exists in the namespace low-priority. Modify the pod to use the priority class you created. Recreate the pod if necessary.
-
Check the documentation for PriorityClass:
https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
- We take this yaml file:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."
- Create a yaml file from it and change it to this:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low-priority
value: 50000
globalDefault: false
description: "This is a lower priority class"
- Then run an
apply:
kubectl apply -f <file.yaml>
- Check that the pod is running:
kubectl get pod -n low-priority
- We get the yaml from the pod:
kubectl get pod lp-pod -n low-priority -o yaml > file.yaml
- To set the priority in the file, we check under
spec:
spec:
priorityClassName: low-priority
-
Remove the
priority: 0value that is set there. -
Save the file.
-
Can either delete the old pod or apply a new pod.
-
Here we will
replace:
kubectl replace -f <file.yaml> --force
-
The
--forceensures it deletes the old pod and creates the new one. -
If you get an error of
integer value of priority (0) must not be provided in the pod spec.- Remove the
priority: 0line in the manifest file.
- Remove the
-
Question 6
-
We have deployed a new pod called np-test-1 and a service called np-test-service. Incoming connections to this service are not working. Troubleshoot and fix it. Create NetworkPolicy, by the name ingress-to-nptest that allows incoming connections to the service over port 80.
Important: Don’t delete any current objects deployed.
- Check the documentation for
Network Policies:
https://kubernetes.io/docs/concepts/services-networking/network-policies/
- We take this example yaml file:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
- Then check the labels the pod is currently using and then we can match those labels in the network policy:
kubectl get pod --show-labels
-
Shows
np-test-1as a label. -
We change the above yaml file to the following:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
run: np-test-1
policyTypes:
- Ingress
- Egress
ingress:
- ports:
- protocol: TCP
port: 80
- Then we apply the above manifest:
kubectl apply -f <file.yaml>
-
The policy is then created.
-
Question 7
-
Taint the worker node node01 to be Unschedulable. Once done, create a pod called dev-redis, image redis:alpine, to ensure workloads are not scheduled to this worker node. Finally, create a new pod called prod-redis and image: redis:alpine with toleration to be scheduled on node01.
key: env_type, value: production, operator: Equal and effect: NoSchedule
- Search in the documentation for
taint:
https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
- Check the available nodes with:
kubectl get node
-
This then shows the node that is available.
-
Then we need to taint the node:
kubectl taint node node01 env_type=production:NoSchedule
- Check the taint applied with:
kubectl describe node <node> | grep -i taint
- Now to create the
dev-redispod:
kubectl run dev-redis --image=redis:alpine
- Create the next pod, which is
prod-redis, this is not being done imperatively as performed above:
apiVersion: v1
kind: Pod
metadata:
name: prod-redis
spec:
tolerations:
- effect: NoSchedule
key: env_type
operator: Equal
value: production
containers:
- name: prod-redis
image: redis:alpine
- Then perform a
kubectl apply -f:
kubectl apply -f <file.yaml>
- Check which pods are assigned to which nodes:
kubectl get pod -o wide
-
dev-redisis then assigned to the Control Plane Node andprod-redisis then assigned to the Worker Node, due to being assigned a toleration. -
Question 8
-
A PersistentVolumeClaim named app-pvc exists in the namespace storage-ns, but it is not getting bound to the available PersistentVolume named app-pv.
Inspect both the PVC and PV and identify why the PVC is not being bound and fix the issue so that the PVC successfully binds to the PV. Do not modify the PV resource.
- Check out the
pvfirst:
kubectl get pv
-
Can see that it is
AVAILABLE. -
Check the
pvcwith:
kubectl get pvc -n storage-ns -o yaml
-
Need to take a look at the configurations for the
pvand make sure that all of the configs match.-
The configs needs to match, otherwise the
pvcannot be bound properly. -
Need to make sure that the CAPACITY is large enough.
-
-
The problem here is the
pvcis hasaccessModesset to- ReadWriteMany- this needs to be set toReadWriteOnce -
Create a yaml file:
kubectl get pvc -n storage-ns -o yaml > file.yaml
- We then delete the
pvc:
kubectl delete pvc app-pvc -n storage-ns
- Apply the new
pvc:
kubectl apply -f <file.yaml>
-
Running
kubectl get pvcagain shows that thepvcisBound: -
Question 9
-
A kubeconfig file called super.kubeconfig has been created under /root/CKA. There is something wrong with the configuration. Troubleshoot and fix it.
-
A question regarding an issue that needs fixing - verify the question first.
-
Firstly, pass in the
kubeconfigfile:
kubectl get node --kubeconfig=/root/CKA/super.kubeconfig
-
Run the above and observe a
connection refusederror. -
Check the
/root/CKA/super.kubeconfigfile. -
Check the port that the
kube-apiserveris listening on:
sudo netstat -tulpn | grep kube-apiserver
-
Observe that the
kube-apiserveris listening on port6443. -
Therefore in the
super.kubeconfigfile, we change:
server: https://controlplane:9999
to
server: https://controlplane:6443
- Running the same command shows that it works:
kubectl get node --kubeconfig=/root/CKA/super.kubeconfig
-
Question 10
-
We have created a new deployment called nginx-deploy. Scale the deployment to 3 replicas. Has the number of replicas increased? Troubleshoot and fix the issue.
-
Have a look at the deployment:
kubectl get deployment nginx-deploy
- Scale the deployment and replicas to
3:
kubectl scale deploy nginx-deploy --replicas=3
-
Run the
kubectl get deploymentcommand again and only1/3is available. -
If there is an issue with a deployment, run a
kubectl describe deploymentand check for any errors. -
The
Eventswill tell us more information.- Never got a message from the
deployment-controllerto go from 1 to 3.
- Never got a message from the
-
Check the replicaset:
kubectl get rs
- Describe the replicaset:
kubectl describe rs
-
The
deployment-controllernever did its job. Usually that is an issue with the Controlplane Node, that’s what limits us from making changes. -
Check the
kube-systempods:
kubectl get pod -n kube-system
-
In the above output, the
kube-controller-manager-controlplaneis inImagePullBackOffmode. -
Remember, all of the Controlplane components are static pods. Can check the
controller-managerunder/etc/kubernetes/manifests/kube-controller-manager.yaml- Once the above file is opened, check the
imageline and it should say something like:
- Once the above file is opened, check the
image: registry.k8s.io/kube-controller-manager:v1.32.0
-
Check all of the typos that you see in the file.
-
Once you save the changes, Kubernetes will automatically deploy a new pod, regarding the
kube-systempods. -
Again running
kubectl get pod -n kube-systemshould see thecontroller-managerrunning without any issues. -
kubectl get deployshould show all of the 3nginxdeployment pods. -
Question 11
-
Create a Horizontal Pod Autoscaler (HPA) for the deployment named api-deployment located in the api namespace. The HPA should scale the deployment based on a custom metric named requests_per_second, targeting an average value of 1000 requests per second across all pods. Set the minimum number of replicas to 1 and the maximum to 20.
Note: Deployment named api-deployment is available in api namespace. Ignore errors due to the metric requests_per_second not being tracked in metrics-server
- Check in the documentation for Horizontal Pod Autoscaler:
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
- In this example, we create a file from scratch:
apiVersion: autoscaling /v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
namespace: api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-deployment
minReplicas: 1
maxReplicas: 20
metrics:
- type: Pods
pods:
metric:
name: requests_per_second
target:
type: AverageValue
averageValue: "1000"
-
Save the above and run
kubectl apply -f <file.yaml> -
Then to double-check what we deployed with:
kubectl describe hpa -n api
-
Question 12
-
Configure the web-route to split traffic between web-service and web-service-v2.The configuration should ensure that 80% of the traffic is routed to web-service and 20% is routed to web-service-v2.
Note: web-gateway, web-service, and web-service-v2 have already been created and are available on the cluster.
-
Verify the above with
kubectl get serviceand you see both of theweb-service. -
Similarly with the
gateway:
kubectl get gateway
- We create the HTTP Route with the following:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
namespace: default
spec:
parentRefs:
- name: web-gateway
namespace: default
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: web-service
port: 80
weight: 80
- name: web-service-v2
port: 80
weight: 20
-
Then run a
kubectl apply -f <file.yaml> -
Question 13
-
One application, webpage-server-01, is currently deployed on the Kubernetes cluster using Helm. A new version of the application is available in a Helm chart located at /root/new-version.
Validate this new Helm chart, then install it as a new release named webpage-server-02. After confirming the new release is installed, uninstall the old release webpage-server-01.
- To validate a chart, use this command:
helm lint /root/new-version
-
It will say the chart looks good.
-
Then install the chart:
helm install --generate-name /root/new-version
-
The
--generate-namemakes Helm automatically create a name. -
Check it was created with
helm list. -
Remove the old chart with:
helm uninstall webpage-server-01
-
Then do a
helm listand the old one is gone. -
Question 14
-
Identify the pod CIDR network of the node ‘controlplane’ in the kubernetes cluster. This information is crucial for configuring the CNI plugin during installation. Output the pod CIDR network to a file at /root/pod-cidr.txt.
-
To get the pod CIDR, do the following:
kubectl get node
- Can also get the
yamloutput of a node like so:
kubectl get node <node> -o yaml | less
- Then under
spec, check this:
podCIDR: 172.17.0.0/24
-
The above is the pod CIDR network.
-
We want to grab the above
podCIDRline and save it to a file.
kubectl get node -o jsonpath='{.items[0].spec.podCIDR}' > /root/pod-cidr.txt
- The following will then be stored in the file.