├── README.md ├── services-and-networking.md ├── state-persistence.md ├── multi-container-pod.md ├── core-concepts.md ├── observability.md ├── configuration.md └── pod-design.md /README.md: -------------------------------------------------------------------------------- 1 | # CKAD-Practice-Questions 2 | 3 | This repo contains all the consolidated list of questions based on the DCA study guide 4 | 5 | **Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications. The CNCF/Linux Foundation offers this performance-based exam which targets the developer aspect of kubernetes skills such as deploying apps, configuring apps, rolling out the application, creating persistent volumes, etc.** 6 | 7 | **Since this exam is performance-based rather than just multiple choice questions just knowing the concepts are not enough, we need a lot of practice before the exam. This article helps you understand, practice and get you ready for the exam.** 8 | 9 | **We are not going to discuss any concepts here, rather, I just want to create a bunch of practice questions for the CKAD exam based on the curriculum provided here.** 10 | 11 | 12 | ## Table of Contents: 13 | 1. [Core Concepts (13%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/core-concepts.md) 14 | 2. [Multi-Container Pods (10%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/multi-container-pod.md) 15 | 3. [Pod Design (20%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/pod-design.md) 16 | 4. [State Persistence (8%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/state-persistence.md) 17 | 5. [Configuration (18%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/configuration.md) 18 | 6. [Observability (18%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/observability.md) 19 | 7. [Services and Networking (13%)](https://github.com/bbachi/CKAD-Practice-Questions/blob/master/services-and-networking.md) 20 | 21 | 22 | ## Other Important Links 23 | 1. [All You Need To Know About The Exam](https://medium.com/bb-tutorials-and-thoughts/how-to-pass-the-certified-kubernetes-application-developer-ckad-exam-503e9562d022) 24 | 2. [Practice Questions](https://medium.com/bb-tutorials-and-thoughts/practice-enough-with-these-questions-for-the-ckad-exam-2f42d1228552) 25 | 3. [Exam Study Guide](https://github.com/cncf/curriculum/blob/master/CKAD_Curriculum_V1.15.0.pdf) 26 | 4. [How to install and get started with kubernetes](https://medium.com/bb-tutorials-and-thoughts/how-to-get-started-with-kubernetes-e06ea82d23b) 27 | 28 | 29 | ## Other Certifications 30 | * [Docker Certified Associate](https://github.com/bbachi/DCA-Practice-Questions) 31 | -------------------------------------------------------------------------------- /services-and-networking.md: -------------------------------------------------------------------------------- 1 | # Services and Networking (13%) 2 | 3 | ## Practice questions based on these concepts 4 | 5 | * Understand Services 6 | * Demonstrate a basic understanding of NetworkPolicies 7 | 8 | ## Questions 9 | 10 | 11 |
Create an nginx pod with a yaml file with label my-nginx and expose the port 80 12 |

13 | 14 | ``` 15 | kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx.yaml 16 | 17 | // edit the label app: my-nginx and create the pod 18 | apiVersion: v1 19 | kind: Pod 20 | metadata: 21 | creationTimestamp: null 22 | labels: 23 | app: my-nginx 24 | name: nginx 25 | spec: 26 | containers: 27 | - image: nginx 28 | name: nginx 29 | ports: 30 | - containerPort: 80 31 | resources: {} 32 | dnsPolicy: ClusterFirst 33 | restartPolicy: Never 34 | status: {} 35 | 36 | kubectl create -f nginx.yaml 37 | ``` 38 |

39 |
40 | 41 | 42 |
Create the service for this nginx pod with the pod selector app: my-nginx 43 |

44 | 45 | ``` 46 | // create the below service 47 | apiVersion: v1 48 | kind: Service 49 | metadata: 50 | name: my-service 51 | spec: 52 | selector: 53 | app: my-nginx 54 | ports: 55 | - protocol: TCP 56 | port: 80 57 | targetPort: 9376 58 | 59 | kubectl create -f nginx-svc.yaml 60 | ``` 61 |

62 |
63 | 64 | 65 |
Find out the label of the pod and verify the service has the same label 66 |

67 | 68 | ``` 69 | // get the pod with labels 70 | kubectl get po nginx --show-labels 71 | 72 | // get the service and chekc the selector column 73 | kubectl get svc my-service -o wide 74 | ``` 75 |

76 |
77 | 78 | 79 |
Delete the service and create the service with kubectl expose command and verify the label 80 |

81 | 82 | ``` 83 | // delete the service 84 | kubectl delete svc my-service 85 | 86 | // create the service again 87 | kubectl expose po nginx --port=80 --target-port=9376 88 | 89 | // verify the label 90 | kubectl get svc -l app=my-nginx 91 | ``` 92 |

93 |
94 | 95 | 96 |
Delete the service and create the service again with type NodePort 97 |

98 | 99 | ``` 100 | // delete the service 101 | kubectl delete svc nginx 102 | 103 | // create service with expose command 104 | kubectl expose po nginx --port=80 --type=NodePort 105 | ``` 106 |

107 |
108 | 109 | 110 |
Create the temporary busybox pod and hit the service. Verify the service that it should return the nginx page index.html 111 |

112 | 113 | ``` 114 | // get the clusterIP from this command 115 | kubectl get svc nginx -o wide 116 | 117 | // create temporary busybox to check the nodeport 118 | kubectl run busybox --image=busybox --restart=Never -it --rm -- wget -o- :80 119 | ``` 120 |

121 |
122 | 123 | 124 |
Create a NetworkPolicy which denies all ingress traffic 125 |

126 | 127 | ``` 128 | apiVersion: networking.k8s.io/v1 129 | kind: NetworkPolicy 130 | metadata: 131 | name: default-deny 132 | spec: 133 | podSelector: {} 134 | policyTypes: 135 | - Ingress 136 | ``` 137 |

138 |
139 | -------------------------------------------------------------------------------- /state-persistence.md: -------------------------------------------------------------------------------- 1 | 2 | # State Persistence (8%) 3 | 4 | ## Practice questions based on these concepts 5 | 6 | * Understand PersistentVolumeClaims for Storage 7 | 8 | ## Questions 9 | 10 | 11 |
List Persistent Volumes in the cluster 12 |

13 | 14 | ``` 15 | kubectl get pv 16 | ``` 17 |

18 |
19 | 20 | 21 |
Create a hostPath PersistentVolume named task-pv-volume with storage 10Gi, access modes ReadWriteOnce, storageClassName manual, and volume at /mnt/data and verify 22 |

23 | 24 | ``` 25 | // task-pv-volume.yaml 26 | 27 | apiVersion: v1 28 | kind: PersistentVolume 29 | metadata: 30 | name: task-pv-volume 31 | labels: 32 | type: local 33 | spec: 34 | storageClassName: manual 35 | capacity: 36 | storage: 10Gi 37 | accessModes: 38 | - ReadWriteOnce 39 | hostPath: 40 | path: "/mnt/data" 41 | 42 | kubectl create -f task-pv-volume.yaml 43 | 44 | kubectl get pv 45 | ``` 46 |

47 |
48 | 49 | 50 | 51 |
Create a PersistentVolumeClaim of at least 3Gi storage and access mode ReadWriteOnce and verify status is Bound 52 |

53 | 54 | ``` 55 | // task-pv-claim.yaml 56 | 57 | apiVersion: v1 58 | kind: PersistentVolumeClaim 59 | metadata: 60 | name: task-pv-claim 61 | spec: 62 | storageClassName: manual 63 | accessModes: 64 | - ReadWriteOnce 65 | resources: 66 | requests: 67 | storage: 3Gi 68 | 69 | kubectl create -f task-pv-claim.yaml 70 | 71 | kubectl get pvc 72 | ``` 73 |

74 |
75 | 76 | 77 |
Delete persistent volume and PersistentVolumeClaim we just created 78 |

79 | 80 | ``` 81 | kubectl delete pvc task-pv-claim 82 | kubectl delete pv task-pv-volume 83 | ``` 84 |

85 |
86 | 87 | 88 |
Create a Pod with an image Redis and configure a volume that lasts for the lifetime of the Pod 89 |

90 | 91 | ``` 92 | // emptyDir is the volume that lasts for the life of the pod 93 | 94 | apiVersion: v1 95 | kind: Pod 96 | metadata: 97 | name: redis 98 | spec: 99 | containers: 100 | - name: redis 101 | image: redis 102 | volumeMounts: 103 | - name: redis-storage 104 | mountPath: /data/redis 105 | volumes: 106 | - name: redis-storage 107 | emptyDir: {} 108 | 109 | kubectl create -f redis-storage.yaml 110 | ``` 111 |

112 |
113 | 114 | 115 |
Exec into the above pod and create a file named file.txt with the text ‘This is called the file’ in the path /data/redis and open another tab and exec again with the same pod and verifies file exist in the same path. 116 |

117 | 118 | ``` 119 | // first terminal 120 | kubectl exec -it redis-storage /bin/sh 121 | cd /data/redis 122 | echo 'This is called the file' > file.txt 123 | 124 | //open another tab 125 | kubectl exec -it redis-storage /bin/sh 126 | cat /data/redis/file.txt 127 | ``` 128 |

129 |
130 | 131 | 132 |
Delete the above pod and create again from the same yaml file and verifies there is no file.txt in the path /data/redis. 133 |

134 | 135 | ``` 136 | kubectl delete pod redis 137 | 138 | kubectl create -f redis-storage.yaml 139 | kubectl exec -it redis-storage /bin/sh 140 | cat /data/redis/file.txt // file doesn't exist 141 | ``` 142 |

143 |
144 | 145 | 146 |
Create PersistentVolume named task-pv-volume with storage 10Gi, access modes ReadWriteOnce, storageClassName manual, and volume at /mnt/data and Create a PersistentVolumeClaim of at least 3Gi storage and access mode ReadWriteOnce and verify status is Bound 147 |

148 | 149 | ``` 150 | kubectl create -f task-pv-volume.yaml 151 | kubectl create -f task-pv-claim.yaml 152 | 153 | kubectl get pv 154 | kubectl get pvc 155 | ``` 156 |

157 |
158 | 159 | 160 |
Create an nginx pod with containerPort 80 and with a PersistentVolumeClaim task-pv-claim and has a mouth path "/usr/share/nginx/html" 161 |

162 | 163 | ``` 164 | // task-pv-pod.yaml 165 | 166 | apiVersion: v1 167 | kind: Pod 168 | metadata: 169 | name: task-pv-pod 170 | spec: 171 | volumes: 172 | - name: task-pv-storage 173 | persistentVolumeClaim: 174 | claimName: task-pv-claim 175 | containers: 176 | - name: task-pv-container 177 | image: nginx 178 | ports: 179 | - containerPort: 80 180 | name: "http-server" 181 | volumeMounts: 182 | - mountPath: "/usr/share/nginx/html" 183 | name: task-pv-storage 184 | 185 | kubectl create -f task-pv-pod.yaml 186 | ``` 187 |

188 |
189 | 190 | -------------------------------------------------------------------------------- /multi-container-pod.md: -------------------------------------------------------------------------------- 1 | # Multi-Container Pods (10%) 2 | 3 | ## Practice questions based on these concepts 4 | 5 | * Understand Multi-container pod design patterns (eg: ambassador, adaptor, sidecar) 6 | 7 | ## Questions 8 | 9 |
Create a Pod with three busy box containers with commands “ls; sleep 3600;”, “echo Hello World; sleep 3600;” and “echo this is the third container; sleep 3600” respectively and check the status 10 |

11 | 12 | ``` 13 | // first create single container pod with dry run flag 14 | kubectl run busybox --image=busybox --restart=Never --dry-run -o yaml -- bin/sh -c "sleep 3600; ls" > multi-container.yaml 15 | 16 | // edit the pod like below 17 | 18 | apiVersion: v1 19 | kind: Pod 20 | metadata: 21 | creationTimestamp: null 22 | labels: 23 | run: busybox 24 | name: busybox 25 | spec: 26 | containers: 27 | - args: 28 | - bin/sh 29 | - -c 30 | - ls; sleep 3600 31 | image: busybox 32 | name: busybox1 33 | resources: {} 34 | - args: 35 | - bin/sh 36 | - -c 37 | - echo Hello world; sleep 3600 38 | image: busybox 39 | name: busybox2 40 | resources: {} 41 | - args: 42 | - bin/sh 43 | - -c 44 | - echo this is third container; sleep 3600 45 | image: busybox 46 | name: busybox3 47 | resources: {} 48 | dnsPolicy: ClusterFirst 49 | restartPolicy: Never 50 | status: {} 51 | 52 | // create it 53 | kubectl create -f multi-container.yaml 54 | 55 | kubectl get po busybox 56 | ``` 57 |

58 |
59 | 60 |
Check the logs of each container that you just created 61 |

62 | 63 | ``` 64 | kubectl logs busybox -c busybox1 65 | kubectl logs busybox -c busybox2 66 | kubectl logs busybox -c busybox3 67 | ``` 68 |

69 |
70 | 71 |
Check the previous logs of the second container busybox2 if any 72 |

73 | 74 | ``` 75 | kubectl logs busybox -c busybox2 --previous 76 | ``` 77 |

78 |
79 | 80 |
Run command ls in the third container busybox3 of the above pod 81 |

82 | 83 | ``` 84 | kubectl exec busybox -c busybox3 -- ls 85 | ``` 86 |

87 |
88 | 89 |
Show metrics of the above pod containers and puts them into the file.log and verify 90 |

91 | 92 | ``` 93 | kubectl top pod busybox --containers 94 | 95 | // putting them into file 96 | kubectl top pod busybox --containers > file.log 97 | cat file.log 98 | ``` 99 |

100 |
101 | 102 | 103 |
Create a Pod with main container busybox and which executes this “while true; do echo ‘Hi I am from Main container’ >> /var/log/index.html; sleep 5; done” and with sidecar container with nginx image which exposes on port 80. Use emptyDir Volume and mount this volume on path /var/log for busybox and on path /usr/share/nginx/html for nginx container. Verify both containers are running. 104 |

105 | 106 | ``` 107 | // create an initial yaml file with this 108 | kubectl run multi-cont-pod --image=busbox --restart=Never --dry-run -o yaml > multi-container.yaml 109 | 110 | // edit the yml as below and create it 111 | apiVersion: v1 112 | kind: Pod 113 | metadata: 114 | creationTimestamp: null 115 | labels: 116 | run: multi-cont-pod 117 | name: multi-cont-pod 118 | spec: 119 | volumes: 120 | - name: var-logs 121 | emptyDir: {} 122 | containers: 123 | - image: busybox 124 | command: ["/bin/sh"] 125 | args: ["-c", "while true; do echo 'Hi I am from Main container' >> /var/log/index.html; sleep 5;done"] 126 | name: main-container 127 | resources: {} 128 | volumeMounts: 129 | - name: var-logs 130 | mountPath: /var/log 131 | - image: nginx 132 | name: sidecar-container 133 | resources: {} 134 | ports: 135 | - containerPort: 80 136 | volumeMounts: 137 | - name: var-logs 138 | mountPath: /usr/share/nginx/html 139 | dnsPolicy: ClusterFirst 140 | restartPolicy: Never 141 | status: {} 142 | 143 | kubectl create -f multi-container.yaml 144 | 145 | kubectl get po multi-cont-pod 146 | ``` 147 |

148 |
149 | 150 | 151 |
Exec into both containers and verify that main.txt exist and query the main.txt from sidecar container with curl localhost 152 |

153 | 154 | ``` 155 | // exec into main container 156 | kubectl exec -it multi-cont-pod -c main-container -- sh 157 | cat /var/log/main.txt 158 | 159 | // exec into sidecar container 160 | kubectl exec -it multi-cont-pod -c sidecar-container -- sh 161 | cat /usr/share/nginx/html/index.html 162 | 163 | // install curl and get default page 164 | kubectl exec -it multi-cont-pod -c sidecar-container -- sh 165 | # apt-get update && apt-get install -y curl 166 | # curl localhost 167 | ``` 168 |

169 |
170 | -------------------------------------------------------------------------------- /core-concepts.md: -------------------------------------------------------------------------------- 1 | # Core Concepts (13%) 2 | 3 | ## Practice questions based on these concepts 4 | 5 | * Understand Kubernetes API Primitives 6 | * Create and Configure Basic Pods 7 | 8 | ## Questions 9 | 10 |
List all the namespaces in the cluster 11 |

12 | 13 | ``` 14 | kubectl get namespaces 15 | 16 | kubectl get ns 17 | ``` 18 |

19 |
20 | 21 |
List all the pods in all namespaces 22 |

23 | 24 | ``` 25 | kubectl get po --all-namespaces 26 | ``` 27 |

28 |
29 | 30 |
List all the pods in the particular namespace 31 |

32 | 33 | ``` 34 | kubectl get po -n 35 | ``` 36 |

37 |
38 | 39 |
List all the services in the particular namespace 40 |

41 | 42 | ``` 43 | kubectl get svc -n 44 | ``` 45 |

46 |
47 | 48 |
List all the pods showing name and namespace with a json path expression 49 |

50 | 51 | ``` 52 | kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'metadata.namespace']}" 53 | ``` 54 |

55 |
56 | 57 |
Create an nginx pod in a default namespace and verify the pod running 58 |

59 | 60 | ``` 61 | // creating a pod 62 | kubectl run nginx --image=nginx --restart=Never 63 | 64 | // List the pod 65 | kubectl get po 66 | ``` 67 |

68 |
69 | 70 | 71 |
Create the same nginx pod with a yaml file 72 |

73 | 74 | ``` 75 | // get the yaml file with --dry-run flag 76 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx-pod.yaml 77 | 78 | // cat nginx-pod.yaml 79 | apiVersion: v1 80 | kind: Pod 81 | metadata: 82 | creationTimestamp: null 83 | labels: 84 | run: nginx 85 | name: nginx 86 | spec: 87 | containers: 88 | - image: nginx 89 | name: nginx 90 | resources: {} 91 | dnsPolicy: ClusterFirst 92 | restartPolicy: Never 93 | status: {} 94 | 95 | // create a pod 96 | kubectl create -f nginx-pod.yaml 97 | ``` 98 |

99 |
100 | 101 | 102 |
Output the yaml file of the pod you just created 103 |

104 | 105 | ``` 106 | kubectl get po nginx -o yaml 107 | ``` 108 |

109 |
110 | 111 | 112 |
Output the yaml file of the pod you just created without the cluster-specific information 113 |

114 | 115 | ``` 116 | kubectl get po nginx -o yaml --export 117 | ``` 118 |

119 |
120 | 121 | 122 |
Get the complete details of the pod you just created 123 |

124 | 125 | ``` 126 | kubectl describe pod nginx 127 | ``` 128 |

129 |
130 | 131 | 132 |
Delete the pod you just created 133 |

134 | 135 | ``` 136 | kubectl delete po nginx 137 | 138 | kubectl delete -f nginx-pod.yaml 139 | ``` 140 |

141 |
142 | 143 | 144 |
Delete the pod you just created without any delay (force delete) 145 |

146 | 147 | ``` 148 | kubectl delete po nginx --grace-period=0 --force 149 | ``` 150 |

151 |
152 | 153 | 154 |
Create the nginx pod with version 1.17.4 and expose it on port 80 155 |

156 | 157 | ``` 158 | kubectl run nginx --image=nginx:1.17.4 --restart=Never --port=80 159 | ``` 160 |

161 |
162 | 163 | 164 |
Change the Image version to 1.15-alpine for the pod you just created and verify the image version is updated 165 |

166 | 167 | ``` 168 | kubectl set image pod/nginx nginx=nginx:1.15-alpine 169 | 170 | kubectl describe po nginx 171 | 172 | // another way it will open vi editor and change the version 173 | kubeclt edit po nginx 174 | 175 | kubectl describe po nginx 176 | ``` 177 |

178 |
179 | 180 | 181 |
Change the Image version back to 1.17.1 for the pod you just updated and observe the changes 182 |

183 | 184 | ``` 185 | kubectl set image pod/nginx nginx=nginx:1.17.1 186 | 187 | kubectl describe po nginx 188 | 189 | kubectl get po nginx -w # watch it 190 | ``` 191 |

192 |
193 | 194 | 195 |
Check the Image version without the describe command 196 |

197 | 198 | ``` 199 | kubectl get po nginx -o jsonpath='{.spec.containers[].image}{"\n"}' 200 | ``` 201 |

202 |
203 | 204 | 205 |
Create the nginx pod and execute the simple shell on the pod 206 |

207 | 208 | ``` 209 | // creating a pod 210 | kubectl run nginx --image=nginx --restart=Never 211 | 212 | // exec into the pod 213 | kubectl exec -it nginx /bin/sh 214 | ``` 215 |

216 |
217 | 218 | 219 |
Get the IP Address of the pod you just created 220 |

221 | 222 | ``` 223 | kubectl get po nginx -o wide 224 | ``` 225 |

226 |
227 | 228 |
Create a busybox pod and run command ls while creating it and check the logs 229 |

230 | 231 | ``` 232 | kubectl run busybox --image=busybox --restart=Never -- ls 233 | 234 | kubectl logs busybox 235 | ``` 236 |

237 |
238 | 239 | 240 |
If pod crashed check the previous logs of the pod 241 |

242 | 243 | ``` 244 | kubectl logs busybox -p 245 | ``` 246 |

247 |
248 | 249 | 250 |
Create a busybox pod with command sleep 3600 251 |

252 | 253 | ``` 254 | kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "sleep 3600" 255 | ``` 256 |

257 |
258 | 259 | 260 |
Check the connection of the nginx pod from the busybox pod 261 |

262 | 263 | ``` 264 | kubectl get po nginx -o wide 265 | 266 | // check the connection 267 | kubectl exec -it busybox -- wget -o- 268 | ``` 269 |

270 |
271 | 272 | 273 |
Create a busybox pod and echo message ‘How are you’ and delete it manually 274 |

275 | 276 | ``` 277 | kubectl run busybox --image=nginx --restart=Never -it -- echo "How are you" 278 | 279 | kubectl delete po busybox 280 | ``` 281 |

282 |
283 | 284 | 285 |
Create a busybox pod and echo message ‘How are you’ and have it deleted immediately 286 |

287 | 288 | ``` 289 | // notice the --rm flag 290 | kubectl run busybox --image=nginx --restart=Never -it --rm -- echo "How are you" 291 | ``` 292 |

293 |
294 | 295 | 296 |
Create an nginx pod and list the pod with different levels of verbosity 297 |

298 | 299 | ``` 300 | // create a pod 301 | kubectl run nginx --image=nginx --restart=Never --port=80 302 | 303 | // List the pod with different verbosity 304 | kubectl get po nginx --v=7 305 | kubectl get po nginx --v=8 306 | kubectl get po nginx --v=9 307 | ``` 308 |

309 |
310 | 311 | 312 |
List the nginx pod with custom columns POD_NAME and POD_STATUS 313 |

314 | 315 | ``` 316 | kubectl get po -o=custom-columns="POD_NAME:.metadata.name, POD_STATUS:.status.containerStatuses[].state" 317 | ``` 318 |

319 |
320 | 321 | 322 |
List all the pods sorted by name 323 |

324 | 325 | ``` 326 | kubectl get pods --sort-by=.metadata.name 327 | ``` 328 |

329 |
330 | 331 | 332 |
List all the pods sorted by created timestamp 333 |

334 | 335 | ``` 336 | kubectl get pods--sort-by=.metadata.creationTimestamp 337 | ``` 338 |

339 |
340 | -------------------------------------------------------------------------------- /observability.md: -------------------------------------------------------------------------------- 1 | # Observability (18%) 2 | 3 | ## Practice questions based on these concepts 4 | 5 | * Understand LivenessProbes and ReadinessProbes 6 | * Understand Container Logging 7 | * Understand how to monitor applications in kubernetes 8 | * Understand Debugging in Kubernetes 9 | 10 | ## Questions 11 | 12 |
Create an nginx pod with containerPort 80 and it should only receive traffic only it checks the endpoint / on port 80 and verify and delete the pod 13 |

14 | 15 | ``` 16 | kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx-pod.yaml 17 | 18 | // add the readinessProbe section and create 19 | apiVersion: v1 20 | kind: Pod 21 | metadata: 22 | creationTimestamp: null 23 | labels: 24 | run: nginx 25 | name: nginx 26 | spec: 27 | containers: 28 | - image: nginx 29 | name: nginx 30 | ports: 31 | - containerPort: 80 32 | readinessProbe: 33 | httpGet: 34 | path: / 35 | port: 80 36 | resources: {} 37 | dnsPolicy: ClusterFirst 38 | restartPolicy: Never 39 | status: {} 40 | 41 | kubectl create -f nginx-pod.yaml 42 | 43 | // verify 44 | kubectl describe pod nginx | grep -i readiness 45 | kubectl delete po nginx 46 | ``` 47 |

48 |
49 | 50 | 51 |
Create an nginx pod with containerPort 80 and it should check the pod running at endpoint / healthz on port 80 and verify and delete the pod 52 |

53 | 54 | ``` 55 | kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx-pod.yaml 56 | 57 | // add the livenessProbe section and create 58 | apiVersion: v1 59 | kind: Pod 60 | metadata: 61 | creationTimestamp: null 62 | labels: 63 | run: nginx 64 | name: nginx 65 | spec: 66 | containers: 67 | - image: nginx 68 | name: nginx 69 | ports: 70 | - containerPort: 80 71 | livenessProbe: 72 | httpGet: 73 | path: /healthz 74 | port: 80 75 | resources: {} 76 | dnsPolicy: ClusterFirst 77 | restartPolicy: Never 78 | status: {} 79 | 80 | kubectl create -f nginx-pod.yaml 81 | 82 | // verify 83 | kubectl describe pod nginx | grep -i readiness 84 | kubectl delete po nginx 85 | ``` 86 |

87 |
88 | 89 | 90 |
Create an nginx pod with containerPort 80 and it should check the pod running at endpoint /healthz on port 80 and it should only receive traffic only it checks the endpoint / on port 80. verify the pod 91 |

92 | 93 | ``` 94 | kubectl run nginx --image=nginx --restart=Never --port=80 --dry-run -o yaml > nginx-pod.yaml 95 | 96 | // add the livenessProbe and readiness section and create 97 | apiVersion: v1 98 | kind: Pod 99 | metadata: 100 | creationTimestamp: null 101 | labels: 102 | run: nginx 103 | name: nginx 104 | spec: 105 | containers: 106 | - image: nginx 107 | name: nginx 108 | ports: 109 | - containerPort: 80 110 | livenessProbe: 111 | httpGet: 112 | path: /healthz 113 | port: 80 114 | readinessProbe: 115 | httpGet: 116 | path: / 117 | port: 80 118 | resources: {} 119 | dnsPolicy: ClusterFirst 120 | restartPolicy: Never 121 | status: {} 122 | 123 | kubectl create -f nginx-pod.yaml 124 | 125 | // verify 126 | kubectl describe pod nginx | grep -i readiness 127 | kubectl describe pod nginx | grep -i liveness 128 | ``` 129 |

130 |
131 | 132 | 133 |
Check what all are the options that we can configure with readiness and liveness probes 134 |

135 | 136 | ``` 137 | kubectl explain Pod.spec.containers.livenessProbe 138 | kubectl explain Pod.spec.containers.readinessProbe 139 | ``` 140 |

141 |
142 | 143 | 144 |
Create the pod nginx with the above liveness and readiness probes so that it should wait for 20 seconds before it checks liveness and readiness probes and it should check every 25 seconds. 145 |

146 | 147 | ``` 148 | // nginx-pod.yaml 149 | 150 | apiVersion: v1 151 | kind: Pod 152 | metadata: 153 | creationTimestamp: null 154 | labels: 155 | run: nginx 156 | name: nginx 157 | spec: 158 | containers: 159 | - image: nginx 160 | name: nginx 161 | ports: 162 | - containerPort: 80 163 | livenessProbe: 164 | initialDelaySeconds: 20 165 | periodSeconds: 25 166 | httpGet: 167 | path: /healthz 168 | port: 80 169 | readinessProbe: 170 | initialDelaySeconds: 20 171 | periodSeconds: 25 172 | httpGet: 173 | path: / 174 | port: 80 175 | resources: {} 176 | dnsPolicy: ClusterFirst 177 | restartPolicy: Never 178 | status: {} 179 | 180 | kubectl create -f nginx-pod.yaml 181 | ``` 182 |

183 |
184 | 185 | 186 |
Create a busybox pod with this command “echo I am from busybox pod; sleep 3600;” and verify the logs 187 |

188 | 189 | ``` 190 | kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "echo I am from busybox pod; sleep 3600;" 191 | 192 | kubectl logs busybox 193 | ``` 194 |

195 |
196 | 197 | 198 |
copy the logs of the above pod to the busybox-logs.txt and verify 199 |

200 | 201 | ``` 202 | kubectl logs busybox > busybox-logs.txt 203 | 204 | cat busybox-logs.txt 205 | ``` 206 |

207 |
208 | 209 | 210 |
List all the events sorted by timestamp and put them into file.log and verify 211 |

212 | 213 | ``` 214 | kubectl get events --sort-by=.metadata.creationTimestamp 215 | 216 | // putting them into file.log 217 | kubectl get events --sort-by=.metadata.creationTimestamp > file.log 218 | 219 | cat file.log 220 | ``` 221 |

222 |
223 | 224 | 225 |
Create a pod with an image alpine which executes this command ”while true; do echo ‘Hi I am from alpine’; sleep 5; done” and verify and follow the logs of the pod 226 |

227 | 228 | ``` 229 | // create the pod 230 | kubectl run hello --image=alpine --restart=Never -- /bin/sh -c "while true; do echo 'Hi I am from Alpine'; sleep 5;done" 231 | 232 | // verify and follow the logs 233 | kubectl logs --follow hello 234 | ``` 235 |

236 |
237 | 238 | 239 |
Create the pod with this kubectl create -f https://gist.githubusercontent.com/bbachi/212168375b39e36e2e2984c097167b00/raw/1fd63509c3ae3a3d3da844640fb4cca744543c1c/not-running.yml. The pod is not in the running state. Debug it. 240 |

241 | 242 | ``` 243 | // create the pod 244 | kubectl create -f https://gist.githubusercontent.com/bbachi/212168375b39e36e2e2984c097167b00/raw/1fd63509c3ae3a3d3da844640fb4cca744543c1c/not-running.yml 245 | 246 | // get the pod 247 | kubectl get pod not-running 248 | kubectl describe po not-running 249 | 250 | // it clearly says ImagePullBackOff something wrong with image 251 | kubectl edit pod not-running // it will open vim editor 252 | or 253 | kubectl set image pod/not-running not-running=nginx 254 | ``` 255 |

256 |
257 | 258 | 259 |
This following yaml creates 4 namespaces and 4 pods. One of the pod in one of the namespaces are not in the running state. Debug and fix it. `https://gist.githubusercontent.com/bbachi/1f001f10337234d46806929d12245397/raw/84b7295fb077f15de979fec5b3f7a13fc69c6d83/problem-pod.yaml` 260 |

261 | 262 | ``` 263 | kubectl create -f https://gist.githubusercontent.com/bbachi/1f001f10337234d46806929d12245397/raw/84b7295fb077f15de979fec5b3f7a13fc69c6d83/problem-pod.yaml 264 | 265 | // get all the pods in all namespaces 266 | kubectl get po --all-namespaces 267 | 268 | // find out which pod is not running 269 | kubectl get po -n namespace2 270 | 271 | // update the image 272 | kubectl set image pod/pod2 pod2=nginx -n namespace2 273 | 274 | // verify again 275 | kubectl get po -n namespace2 276 | ``` 277 |

278 |
279 | 280 | 281 |
Get the memory and CPU usage of all the pods and find out top 3 pods which have the highest usage and put them into the cpu-usage.txt file 282 |

283 | 284 | ``` 285 | // get the top 3 hungry pods 286 | kubectl top pod --all-namespaces | sort --reverse --key 3 --numeric | head -3 287 | 288 | // putting into file 289 | kubectl top pod --all-namespaces | sort --reverse --key 3 --numeric | head -3 > cpu-usage.txt 290 | 291 | // verify 292 | cat cpu-usage.txt 293 | ``` 294 |

295 |
296 | -------------------------------------------------------------------------------- /configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration (18%) 2 | 3 | ## Practice questions based on these concepts 4 | 5 | * Understand ConfigMaps 6 | * Understand SecurityContexts 7 | * Define an application’s resource requirements 8 | * Create & Consume Secrets 9 | * Understand ServiceAccounts 10 | 11 | ## Questions 12 | 13 | ### TBD 14 | 15 |
List all the configmaps in the cluster 16 |

17 | 18 | ``` 19 | kubectl get cm 20 | or 21 | kubectl get configmap 22 | ``` 23 |

24 |
25 | 26 | 27 |
Create a configmap called myconfigmap with literal value appname=myapp 28 |

29 | 30 | ``` 31 | kubectl create cm myconfigmap --from-literal=appname=myapp 32 | ``` 33 |

34 |
35 | 36 | 37 |
Verify the configmap we just created has this data 38 |

39 | 40 | ``` 41 | // you will see under data 42 | kubectl get cm -o yaml 43 | or 44 | kubectl describe cm 45 | ``` 46 |

47 |
48 | 49 | 50 |
delete the configmap myconfigmap we just created 51 |

52 | 53 | ``` 54 | kubectl delete cm myconfigmap 55 | ``` 56 |

57 |
58 | 59 | 60 |
Create a file called config.txt with two values key1=value1 and key2=value2 and verify the file 61 |

62 | 63 | ``` 64 | cat >> config.txt << EOF 65 | key1=value1 66 | key2=value2 67 | EOF 68 | 69 | cat config.txt 70 | ``` 71 |

72 |
73 | 74 | 75 |
Create a configmap named keyvalcfgmap and read data from the file config.txt and verify that configmap is created correctly 76 |

77 | 78 | ``` 79 | kubectl create cm keyvalcfgmap --from-file=config.txt 80 | 81 | kubectl get cm keyvalcfgmap -o yaml 82 | ``` 83 |

84 |
85 | 86 | 87 | 88 |
Create an nginx pod and load environment values from the above configmap keyvalcfgmap and exec into the pod and verify the environment variables and delete the pod 89 |

90 | 91 | ``` 92 | // first run this command to save the pod yml 93 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx-pod.yml 94 | 95 | // edit the yml to below file and create 96 | apiVersion: v1 97 | kind: Pod 98 | metadata: 99 | creationTimestamp: null 100 | labels: 101 | run: nginx 102 | name: nginx 103 | spec: 104 | containers: 105 | - image: nginx 106 | name: nginx 107 | resources: {} 108 | envFrom: 109 | - configMapRef: 110 | name: keyvalcfgmap 111 | dnsPolicy: ClusterFirst 112 | restartPolicy: Never 113 | status: {} 114 | 115 | kubectl create -f nginx-pod.yml 116 | 117 | // verify 118 | kubectl exec -it nginx -- env 119 | kubectl delete po nginx 120 | ``` 121 |

122 |
123 | 124 | 125 |
Create an env file file.env with var1=val1 and create a configmap envcfgmap from this env file and verify the configmap 126 |

127 | 128 | ``` 129 | echo var1=val1 > file.env 130 | cat file.env 131 | 132 | kubectl create cm envcfgmap --from-env-file=file.env 133 | kubectl get cm envcfgmap -o yaml --export 134 | ``` 135 |

136 |
137 | 138 | 139 |
Create an nginx pod and load environment values from the above configmap envcfgmap and exec into the pod and verify the environment variables and delete the pod 140 |

141 | 142 | ``` 143 | // first run this command to save the pod yml 144 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx-pod.yml 145 | 146 | // edit the yml to below file and create 147 | apiVersion: v1 148 | kind: Pod 149 | metadata: 150 | creationTimestamp: null 151 | labels: 152 | run: nginx 153 | name: nginx 154 | spec: 155 | containers: 156 | - image: nginx 157 | name: nginx 158 | resources: {} 159 | env: 160 | - name: ENVIRONMENT 161 | valueFrom: 162 | configMapKeyRef: 163 | name: envcfgmap 164 | key: environment 165 | dnsPolicy: ClusterFirst 166 | restartPolicy: Never 167 | status: {} 168 | 169 | kubectl create -f nginx-pod.yml 170 | 171 | // verify 172 | kubectl exec -it nginx -- env 173 | kubectl delete po nginx 174 | ``` 175 |

176 |
177 | 178 | 179 |
Create a configmap called cfgvolume with values var1=val1, var2=val2 and create an nginx pod with volume nginx-volume which reads data from this configmap cfgvolume and put it on the path /etc/cfg 180 |

181 | 182 | ``` 183 | // first create a configmap cfgvolume 184 | kubectl create cm cfgvolume --from-literal=var1=val1 --from-literal=var2=val2 185 | 186 | // verify the configmap 187 | kubectl describe cm cfgvolume 188 | 189 | // create the config map 190 | apiVersion: v1 191 | kind: Pod 192 | metadata: 193 | creationTimestamp: null 194 | labels: 195 | run: nginx 196 | name: nginx 197 | spec: 198 | volumes: 199 | - name: nginx-volume 200 | configMap: 201 | name: cfgvolume 202 | containers: 203 | - image: nginx 204 | name: nginx 205 | resources: {} 206 | volumeMounts: 207 | - name: nginx-volume 208 | mountPath: /etc/cfg 209 | dnsPolicy: ClusterFirst 210 | restartPolicy: Never 211 | status: {} 212 | 213 | kubectl create -f nginx-volume.yml 214 | 215 | // exec into the pod 216 | kubectl exec -it nginx -- /bin/sh 217 | 218 | // check the path 219 | cd /etc/cfg 220 | ls 221 | ``` 222 |

223 |
224 | 225 | 226 |
Create a pod called secbusybox with the image busybox which executes command sleep 3600 and makes sure any Containers in the Pod, all processes run with user ID 1000 and with group id 2000 and verify. 227 |

228 | 229 | ``` 230 | // create yml file with dry-run 231 | kubectl run secbusybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600;" > busybox.yml 232 | 233 | // edit the pod like below and create 234 | apiVersion: v1 235 | kind: Pod 236 | metadata: 237 | creationTimestamp: null 238 | labels: 239 | run: secbusybox 240 | name: secbusybox 241 | spec: 242 | securityContext: # add security context 243 | runAsUser: 1000 244 | runAsGroup: 2000 245 | containers: 246 | - args: 247 | - /bin/sh 248 | - -c 249 | - sleep 3600; 250 | image: busybox 251 | name: secbusybox 252 | resources: {} 253 | dnsPolicy: ClusterFirst 254 | restartPolicy: Never 255 | status: {} 256 | 257 | kubectl create -f busybox.yml 258 | 259 | // verify 260 | kubectl exec -it secbusybox -- sh 261 | id // it will show the id and group 262 | ``` 263 |

264 |
265 | 266 | 267 |
Create the same pod as above this time set the securityContext for the container as well and verify that the securityContext of container overrides the Pod level securityContext. 268 |

269 | 270 | ``` 271 | // create yml file with dry-run 272 | kubectl run secbusybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600;" > busybox.yml 273 | 274 | // edit the pod like below and create 275 | apiVersion: v1 276 | kind: Pod 277 | metadata: 278 | creationTimestamp: null 279 | labels: 280 | run: secbusybox 281 | name: secbusybox 282 | spec: 283 | securityContext: 284 | runAsUser: 1000 285 | containers: 286 | - args: 287 | - /bin/sh 288 | - -c 289 | - sleep 3600; 290 | image: busybox 291 | securityContext: 292 | runAsUser: 2000 293 | name: secbusybox 294 | resources: {} 295 | dnsPolicy: ClusterFirst 296 | restartPolicy: Never 297 | status: {} 298 | 299 | kubectl create -f busybox.yml 300 | 301 | // verify 302 | kubectl exec -it secbusybox -- sh 303 | id // you can see container securityContext overides the Pod level 304 | ``` 305 |

306 |
307 | 308 | 309 |
Create pod with an nginx image and configure the pod with capabilities NET_ADMIN and SYS_TIME verify the capabilities 310 |

311 | 312 | ``` 313 | // create the yaml file 314 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 315 | 316 | // edit as below and create pod 317 | apiVersion: v1 318 | kind: Pod 319 | metadata: 320 | creationTimestamp: null 321 | labels: 322 | run: nginx 323 | name: nginx 324 | spec: 325 | containers: 326 | - image: nginx 327 | securityContext: 328 | capabilities: 329 | add: ["SYS_TIME", "NET_ADMIN"] 330 | name: nginx 331 | resources: {} 332 | dnsPolicy: ClusterFirst 333 | restartPolicy: Never 334 | status: {} 335 | 336 | kubectl create -f nginx.yml 337 | 338 | // exec and verify 339 | kubectl exec -it nginx -- sh 340 | cd /proc/1 341 | cat status 342 | 343 | // you should see these values 344 | CapPrm: 00000000aa0435fb 345 | CapEff: 00000000aa0435fb 346 | ``` 347 |

348 |
349 | 350 | 351 |
Create a Pod nginx and specify a memory request and a memory limit of 100Mi and 200Mi respectively. 352 |

353 | 354 | ``` 355 | // create a yml file 356 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 357 | 358 | // add the resources section and create 359 | apiVersion: v1 360 | kind: Pod 361 | metadata: 362 | creationTimestamp: null 363 | labels: 364 | run: nginx 365 | name: nginx 366 | spec: 367 | containers: 368 | - image: nginx 369 | name: nginx 370 | resources: 371 | requests: 372 | memory: "100Mi" 373 | limits: 374 | memory: "200Mi" 375 | dnsPolicy: ClusterFirst 376 | restartPolicy: Never 377 | status: {} 378 | 379 | kubectl create -f nginx.yml 380 | 381 | // verify 382 | kubectl top pod 383 | ``` 384 |

385 |
386 | 387 | 388 |
Create a Pod nginx and specify a CPU request and a CPU limit of 0.5 and 1 respectively. 389 |

390 | 391 | ``` 392 | // create a yml file 393 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 394 | 395 | // add the resources section and create 396 | apiVersion: v1 397 | kind: Pod 398 | metadata: 399 | creationTimestamp: null 400 | labels: 401 | run: nginx 402 | name: nginx 403 | spec: 404 | containers: 405 | - image: nginx 406 | name: nginx 407 | resources: 408 | requests: 409 | cpu: "0.5" 410 | limits: 411 | cpu: "1" 412 | dnsPolicy: ClusterFirst 413 | restartPolicy: Never 414 | status: {} 415 | 416 | kubectl create -f nginx.yml 417 | 418 | // verify 419 | kubectl top pod 420 | ``` 421 |

422 |
423 | 424 | 425 |
Create a Pod nginx and specify both CPU, memory requests and limits together and verify. 426 |

427 | 428 | ``` 429 | // create a yml file 430 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 431 | 432 | // add the resources section and create 433 | apiVersion: v1 434 | kind: Pod 435 | metadata: 436 | creationTimestamp: null 437 | labels: 438 | run: nginx 439 | name: nginx 440 | spec: 441 | containers: 442 | - image: nginx 443 | name: nginx 444 | resources: 445 | requests: 446 | memory: "100Mi" 447 | cpu: "0.5" 448 | limits: 449 | memory: "200Mi" 450 | cpu: "1" 451 | dnsPolicy: ClusterFirst 452 | restartPolicy: Never 453 | status: {} 454 | 455 | kubectl create -f nginx.yml 456 | 457 | // verify 458 | kubectl top pod 459 | ``` 460 |

461 |
462 | 463 | 464 |
Create a Pod nginx and specify a memory request and a memory limit of 100Gi and 200Gi respectively which is too big for the nodes and verify pod fails to start because of insufficient memory 465 |

466 | 467 | ``` 468 | // create a yml file 469 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 470 | 471 | // add the resources section and create 472 | apiVersion: v1 473 | kind: Pod 474 | metadata: 475 | creationTimestamp: null 476 | labels: 477 | run: nginx 478 | name: nginx 479 | spec: 480 | containers: 481 | - image: nginx 482 | name: nginx 483 | resources: 484 | requests: 485 | memory: "100Gi" 486 | cpu: "0.5" 487 | limits: 488 | memory: "200Gi" 489 | cpu: "1" 490 | dnsPolicy: ClusterFirst 491 | restartPolicy: Never 492 | status: {} 493 | 494 | kubectl create -f nginx.yml 495 | 496 | // verify 497 | kubectl describe po nginx // you can see pending state 498 | ``` 499 |

500 |
501 | 502 | 503 |
Create a secret mysecret with values user=myuser and password=mypassword 504 |

505 | 506 | ``` 507 | kubectl create secret generic my-secret --from-literal=username=user --from-literal=password=mypassword 508 | ``` 509 |

510 |
511 | 512 | 513 |
List the secrets in all namespaces 514 |

515 | 516 | ``` 517 | kubectl get secret --all-namespaces 518 | ``` 519 |

520 |
521 | 522 | 523 |
Output the yaml of the secret created above 524 |

525 | 526 | ``` 527 | kubectl get secret my-secret -o yaml 528 | ``` 529 |

530 |
531 | 532 | 533 |
Create an nginx pod which reads username as the environment variable 534 |

535 | 536 | ``` 537 | // create a yml file 538 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 539 | 540 | // add env section below and create 541 | apiVersion: v1 542 | kind: Pod 543 | metadata: 544 | creationTimestamp: null 545 | labels: 546 | run: nginx 547 | name: nginx 548 | spec: 549 | containers: 550 | - image: nginx 551 | name: nginx 552 | env: 553 | - name: USER_NAME 554 | valueFrom: 555 | secretKeyRef: 556 | name: my-secret 557 | key: username 558 | resources: {} 559 | dnsPolicy: ClusterFirst 560 | restartPolicy: Never 561 | status: {} 562 | 563 | kubectl create -f nginx.yml 564 | 565 | //verify 566 | kubectl exec -it nginx -- env 567 | ``` 568 |

569 |
570 | 571 | 572 |
Create an nginx pod which loads the secret as environment variables 573 |

574 | 575 | ``` 576 | // create a yml file 577 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > nginx.yml 578 | 579 | // add env section below and create 580 | apiVersion: v1 581 | kind: Pod 582 | metadata: 583 | creationTimestamp: null 584 | labels: 585 | run: nginx 586 | name: nginx 587 | spec: 588 | containers: 589 | - image: nginx 590 | name: nginx 591 | envFrom: 592 | - secretRef: 593 | name: my-secret 594 | resources: {} 595 | dnsPolicy: ClusterFirst 596 | restartPolicy: Never 597 | status: {} 598 | 599 | kubectl create -f nginx.yml 600 | 601 | //verify 602 | kubectl exec -it nginx -- env 603 | ``` 604 |

605 |
606 | 607 | 608 |
List all the service accounts in the default namespace 609 |

610 | 611 | ``` 612 | kubectl get sa 613 | ``` 614 |

615 |
616 | 617 | 618 |
List all the service accounts in all namespaces 619 |

620 | 621 | ``` 622 | kubectl get sa --all-namespaces 623 | ``` 624 |

625 |
626 | 627 | 628 |
Create a service account called admin 629 |

630 | 631 | ``` 632 | kubectl create sa admin 633 | ``` 634 |

635 |
636 | 637 | 638 |
Output the YAML file for the service account we just created 639 |

640 | 641 | ``` 642 | kubectl get sa admin -o yaml 643 | ``` 644 |

645 |
646 | 647 | 648 |
Create a busybox pod which executes this command sleep 3600 with the service account admin and verify 649 |

650 | 651 | ``` 652 | kubectl run busybox --image=busybox --restart=Never --dry-run -o yaml -- /bin/sh -c "sleep 3600" > busybox.yml 653 | 654 | kubectl create -f busybox.yml 655 | 656 | apiVersion: v1 657 | kind: Pod 658 | metadata: 659 | creationTimestamp: null 660 | labels: 661 | run: busybox 662 | name: busybox 663 | spec: 664 | serviceAccountName: admin 665 | containers: 666 | - args: 667 | - /bin/sh 668 | - -c 669 | - sleep 3600 670 | image: busybox 671 | name: busybox 672 | resources: {} 673 | dnsPolicy: ClusterFirst 674 | restartPolicy: Never 675 | status: {} 676 | 677 | // verify 678 | kubectl describe po busybox 679 | ``` 680 |

681 |
682 | 683 | -------------------------------------------------------------------------------- /pod-design.md: -------------------------------------------------------------------------------- 1 | 2 | # Pod Design (20%) 3 | 4 | ## Practice questions based on these concepts 5 | 6 | * Understand how to use Labels, Selectors and Annotations 7 | * Understand Deployments and how to perform rolling updates 8 | * Understand Deployments and how to perform rollbacks 9 | * Understand Jobs and CronJobs 10 | 11 | ## Questions 12 | 13 |
Get the pods with label information 14 |

15 | 16 | ``` 17 | kubectl get pods --show-labels 18 | ``` 19 |

20 |
21 | 22 | 23 |
Create 5 nginx pods in which two of them is labeled env=prod and three of them is labeled env=dev 24 |

25 | 26 | ``` 27 | kubectl run nginx-dev1 --image=nginx --restart=Never --labels=env=dev 28 | kubectl run nginx-dev2 --image=nginx --restart=Never --labels=env=dev 29 | kubectl run nginx-dev3 --image=nginx --restart=Never --labels=env=dev 30 | kubectl run nginx-prod1 --image=nginx --restart=Never --labels=env=prod 31 | kubectl run nginx-prod2 --image=nginx --restart=Never --labels=env=prod 32 | ``` 33 |

34 |
35 | 36 | 37 |
Verify all the pods are created with correct labels 38 |

39 | 40 | ``` 41 | kubeclt get pods --show-labels 42 | ``` 43 |

44 |
45 | 46 |
Get the pods with label env=dev 47 |

48 | 49 | ``` 50 | kubectl get pods -l env=dev 51 | ``` 52 |

53 |
54 | 55 |
Get the pods with label env=dev and also output the labels 56 |

57 | 58 | ``` 59 | kubectl get pods -l env=dev --show-labels 60 | ``` 61 |

62 |
63 | 64 |
Get the pods with label env=prod 65 |

66 | 67 | ``` 68 | kubectl get pods -l env=prod 69 | ``` 70 |

71 |
72 | 73 |
Get the pods with label env=prod and also output the labels 74 |

75 | 76 | ``` 77 | kubectl get pods -l env=prod --show-labels 78 | ``` 79 |

80 |
81 | 82 | 83 |
Get the pods with label env 84 |

85 | 86 | ``` 87 | kubectl get pods -L env 88 | ``` 89 |

90 |
91 | 92 | 93 |
Get the pods with labels env=dev and env=prod 94 |

95 | 96 | ``` 97 | kubectl get pods -l 'env in (dev,prod)' 98 | ``` 99 |

100 |
101 | 102 | 103 |
Get the pods with labels env=dev and env=prod and output the labels as well 104 |

105 | 106 | ``` 107 | kubectl get pods -l 'env in (dev,prod)' --show-labels 108 | ``` 109 |

110 |
111 | 112 | 113 |
Change the label for one of the pod to env=uat and list all the pods to verify 114 |

115 | 116 | ``` 117 | kubectl label pod/nginx-dev3 env=uat --overwrite 118 | 119 | kubectl get pods --show-labels 120 | ``` 121 |

122 |
123 | 124 | 125 |
Remove the labels for the pods that we created now and verify all the labels are removed 126 |

127 | 128 | ``` 129 | kubectl label pod nginx-dev{1..3} env- 130 | kubectl label pod nginx-prod{1..2} env- 131 | 132 | kubectl get po --show-labels 133 | ``` 134 |

135 |
136 | 137 | 138 |
Let’s add the label app=nginx for all the pods and verify 139 |

140 | 141 | ``` 142 | kubectl label pod nginx-dev{1..3} app=nginx 143 | kubectl label pod nginx-prod{1..2} app=nginx 144 | 145 | kubectl get po --show-labels 146 | ``` 147 |

148 |
149 | 150 | 151 |
Get all the nodes with labels (if using minikube you would get only master node) 152 |

153 | 154 | ``` 155 | kubectl get nodes --show-labels 156 | ``` 157 |

158 |
159 | 160 | 161 |
Label the node (minikube if you are using) nodeName=nginxnode 162 |

163 | 164 | ``` 165 | kubectl label node minikube nodeName=nginxnode 166 | ``` 167 |

168 |
169 | 170 | 171 |
Create a Pod that will be deployed on this node with the label nodeName=nginxnode 172 |

173 | 174 | ``` 175 | kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml > pod.yaml 176 | 177 | // add the nodeSelector like below and create the pod 178 | 179 | apiVersion: v1 180 | kind: Pod 181 | metadata: 182 | creationTimestamp: null 183 | labels: 184 | run: nginx 185 | name: nginx 186 | spec: 187 | nodeSelector: 188 | nodeName: nginxnode 189 | containers: 190 | - image: nginx 191 | name: nginx 192 | resources: {} 193 | dnsPolicy: ClusterFirst 194 | restartPolicy: Never 195 | status: {} 196 | 197 | kubectl create -f pod.yaml 198 | ``` 199 |

200 |
201 | 202 | 203 |
Verify the pod that it is scheduled with the node selector 204 |

205 | 206 | ``` 207 | kubectl describe po nginx | grep Node-Selectors 208 | ``` 209 |

210 |
211 | 212 | 213 |
Verify the pod nginx that we just created has this label 214 |

215 | 216 | ``` 217 | kubectl describe po nginx | grep Labels 218 | ``` 219 |

220 |
221 | 222 | 223 |
Annotate the pods with name=webapp 224 |

225 | 226 | ``` 227 | kubectl annotate pod nginx-dev{1..3} name=webapp 228 | kubectl annotate pod nginx-prod{1..2} name=webapp 229 | ``` 230 |

231 |
232 | 233 | 234 |
Verify the pods that have been annotated correctly 235 |

236 | 237 | ``` 238 | kubectl describe po nginx-dev{1..3} | grep -i annotations 239 | kubectl describe po nginx-prod{1..2} | grep -i annotations 240 | ``` 241 |

242 |
243 | 244 | 245 | 246 |
Remove the annotations on the pods and verify 247 |

248 | 249 | ``` 250 | kubectl annotate pod nginx-dev{1..3} name- 251 | kubectl annotate pod nginx-prod{1..2} name- 252 | 253 | kubectl describe po nginx-dev{1..3} | grep -i annotations 254 | kubectl describe po nginx-prod{1..2} | grep -i annotations 255 | ``` 256 |

257 |
258 | 259 | 260 |
Remove all the pods that we created so far 261 |

262 | 263 | ``` 264 | kubectl delete po --all 265 | ``` 266 |

267 |
268 | 269 | 270 |
Create a deployment called webapp with image nginx with 5 replicas 271 |

272 | 273 | ``` 274 | kubectl create deploy webapp --image=nginx --dry-run -o yaml > webapp.yaml 275 | 276 | // change the replicas to 5 in the yaml and create it 277 | 278 | apiVersion: apps/v1 279 | kind: Deployment 280 | metadata: 281 | creationTimestamp: null 282 | labels: 283 | app: webapp 284 | name: webapp 285 | spec: 286 | replicas: 5 287 | selector: 288 | matchLabels: 289 | app: webapp 290 | strategy: {} 291 | template: 292 | metadata: 293 | creationTimestamp: null 294 | labels: 295 | app: webapp 296 | spec: 297 | containers: 298 | - image: nginx 299 | name: nginx 300 | resources: {} 301 | status: {} 302 | 303 | kubectl create -f webapp.yaml 304 | ``` 305 |

306 |
307 | 308 | 309 |
Get the deployment you just created with labels 310 |

311 | 312 | ``` 313 | kubectl get deploy webapp --show-labels 314 | ``` 315 |

316 |
317 | 318 | 319 |
Output the yaml file of the deployment you just created 320 |

321 | 322 | ``` 323 | kubectl get deploy webapp -o yaml 324 | ``` 325 |

326 |
327 | 328 | 329 |
Get the pods of this deployment 330 |

331 | 332 | ``` 333 | // get the label of the deployment 334 | kubectl get deploy --show-labels 335 | 336 | // get the pods with that label 337 | kubectl get pods -l app=webapp 338 | ``` 339 |

340 |
341 | 342 | 343 |
Scale the deployment from 5 replicas to 20 replicas and verify 344 |

345 | 346 | ``` 347 | kubectl scale deploy webapp --replicas=20 348 | 349 | kubectl get po -l app=webapp 350 | ``` 351 |

352 |
353 | 354 | 355 |
Get the deployment rollout status 356 |

357 | 358 | ``` 359 | kubectl rollout status deploy webapp 360 | ``` 361 |

362 |
363 | 364 | 365 |
Get the replicaset that created with this deployment 366 |

367 | 368 | ``` 369 | kubectl get rs -l app=webapp 370 | ``` 371 |

372 |
373 | 374 | 375 |
Get the yaml of the replicaset and pods of this deployment 376 |

377 | 378 | ``` 379 | kubectl get rs -l app=webapp -o yaml 380 | 381 | kubectl get po -l app=webapp -o yaml 382 | ``` 383 |

384 |
385 | 386 | 387 |
Delete the deployment you just created and watch all the pods are also being deleted 388 |

389 | 390 | ``` 391 | kubectl delete deploy webapp 392 | 393 | kubectl get po -l app=webapp -w 394 | ``` 395 |

396 |
397 | 398 | 399 |
Create a deployment of webapp with image nginx:1.17.1 with container port 80 and verify the image version 400 |

401 | 402 | ``` 403 | kubectl create deploy webapp --image=nginx:1.17.1 --dry-run -o yaml > webapp.yaml 404 | 405 | // add the port section and create the deployment 406 | 407 | apiVersion: apps/v1 408 | kind: Deployment 409 | metadata: 410 | creationTimestamp: null 411 | labels: 412 | app: webapp 413 | name: webapp 414 | spec: 415 | replicas: 1 416 | selector: 417 | matchLabels: 418 | app: webapp 419 | strategy: {} 420 | template: 421 | metadata: 422 | creationTimestamp: null 423 | labels: 424 | app: webapp 425 | spec: 426 | containers: 427 | - image: nginx:1.17.1 428 | name: nginx 429 | ports: 430 | - containerPort: 80 431 | resources: {} 432 | status: {} 433 | 434 | kubectl create -f webapp.yaml 435 | 436 | // verify 437 | kubectl describe deploy webapp | grep Image 438 | ``` 439 |

440 |
441 | 442 | 443 |
Update the deployment with the image version 1.17.4 and verify 444 |

445 | 446 | ``` 447 | kubectl set image deploy/webapp nginx=nginx:1.17.4 448 | 449 | kubectl describe deploy webapp | grep Image 450 | ``` 451 |

452 |
453 | 454 | 455 |
Check the rollout history and make sure everything is ok after the update 456 |

457 | 458 | ``` 459 | kubectl rollout history deploy webapp 460 | 461 | kubectl get deploy webapp --show-labels 462 | kubectl get rs -l app=webapp 463 | kubectl get po -l app=webapp 464 | ``` 465 |

466 |
467 | 468 | 469 |
Undo the deployment to the previous version 1.17.1 and verify Image has the previous version 470 |

471 | 472 | ``` 473 | kubectl rollout undo deploy webapp 474 | 475 | kubectl describe deploy webapp | grep Image 476 | ``` 477 |

478 |
479 | 480 | 481 | 482 |
Update the deployment with the image version 1.16.1 and verify the image and also check the rollout history 483 |

484 | 485 | ``` 486 | kubectl set image deploy/webapp nginx=nginx:1.16.1 487 | 488 | kubectl describe deploy webapp | grep Image 489 | 490 | kubectl rollout history deploy webapp 491 | ``` 492 |

493 |
494 | 495 | 496 | 497 |
Update the deployment to the Image 1.17.1 and verify everything is ok 498 |

499 | 500 | ``` 501 | kubectl rollout undo deploy webapp --to-revision=3 502 | 503 | kubectl describe deploy webapp | grep Image 504 | 505 | kubectl rollout status deploy webapp 506 | ``` 507 |

508 |
509 | 510 | 511 |
Update the deployment with the wrong image version 1.100 and verify something is wrong with the deployment 512 |

513 | 514 | ``` 515 | kubectl set image deploy/webapp nginx=nginx:1.100 516 | 517 | kubectl rollout status deploy webapp (still pending state) 518 | 519 | kubectl get pods (ImagePullErr) 520 | ``` 521 |

522 |
523 | 524 | 525 |
Undo the deployment with the previous version and verify everything is Ok 526 |

527 | 528 | ``` 529 | kubectl rollout undo deploy webapp 530 | kubectl rollout status deploy webapp 531 | 532 | kubectl get pods 533 | ``` 534 |

535 |
536 | 537 | 538 |
Check the history of the specific revision of that deployment 539 |

540 | 541 | ``` 542 | kubectl rollout history deploy webapp --revision=7 543 | ``` 544 |

545 |
546 | 547 | 548 | 549 |
Pause the rollout of the deployment 550 |

551 | 552 | ``` 553 | kubectl rollout pause deploy webapp 554 | ``` 555 |

556 |
557 | 558 | 559 |
Update the deployment with the image version latest and check the history and verify nothing is going on 560 |

561 | 562 | ``` 563 | kubectl set image deploy/webapp nginx=nginx:latest 564 | 565 | kubectl rollout history deploy webapp (No new revision) 566 | ``` 567 |

568 |
569 | 570 | 571 | 572 |
Resume the rollout of the deployment 573 |

574 | 575 | ``` 576 | kubectl rollout resume deploy webapp 577 | ``` 578 |

579 |
580 | 581 | 582 |
Check the rollout history and verify it has the new version 583 | 584 |

585 | 586 | ``` 587 | kubectl rollout history deploy webapp 588 | 589 | kubectl rollout history deploy webapp --revision=9 590 | ``` 591 |

592 |
593 | 594 | 595 |
Apply the autoscaling to this deployment with minimum 10 and maximum 20 replicas and target CPU of 85% and verify hpa is created and replicas are increased to 10 from 1 596 | 597 |

598 | 599 | ``` 600 | kubectl autoscale deploy webapp --min=10 --max=20 --cpu-percent=85 601 | 602 | kubectl get hpa 603 | 604 | kubectl get pod -l app=webapp 605 | ``` 606 |

607 |
608 | 609 | 610 |
Clean the cluster by deleting deployment and hpa you just created 611 |

612 | 613 | ``` 614 | kubectl delete deploy webapp 615 | 616 | kubectl delete hpa webapp 617 | ``` 618 |

619 |
620 | 621 | 622 |
Create a Job with an image node which prints node version and also verifies there is a pod created for this job 623 |

624 | 625 | ``` 626 | kubectl create job nodeversion --image=node -- node -v 627 | 628 | kubectl get job -w 629 | kubectl get pod 630 | ``` 631 |

632 |
633 | 634 | 635 | 636 |
Get the logs of the job just created 637 |

638 | 639 | ``` 640 | kubectl logs // created from the job 641 | ``` 642 |

643 |
644 | 645 | 646 | 647 |
Output the yaml file for the Job with the image busybox which echos “Hello I am from job” 648 |

649 | 650 | ``` 651 | kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" 652 | ``` 653 |

654 |
655 | 656 | 657 |
Copy the above YAML file to hello-job.yaml file and create the job 658 |

659 | 660 | ``` 661 | kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" > hello-job.yaml 662 | 663 | kubectl create -f hello-job.yaml 664 | ``` 665 |

666 |
667 | 668 | 669 |
Verify the job and the associated pod is created and check the logs as well 670 |

671 | 672 | ``` 673 | kubectl get job 674 | kubectl get po 675 | 676 | kubectl logs hello-job-* 677 | ``` 678 |

679 |
680 | 681 | 682 | 683 |
Delete the job we just created 684 |

685 | 686 | ``` 687 | kubectl delete job hello-job 688 | ``` 689 |

690 |
691 | 692 | 693 |
Create the same job and make it run 10 times one after one 694 |

695 | 696 | ``` 697 | kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" > hello-job.yaml 698 | 699 | // edit the yaml file to add completions: 10 700 | 701 | apiVersion: batch/v1 702 | kind: Job 703 | metadata: 704 | creationTimestamp: null 705 | name: hello-job 706 | spec: 707 | completions: 10 708 | template: 709 | metadata: 710 | creationTimestamp: null 711 | spec: 712 | containers: 713 | - command: 714 | - echo 715 | - Hello I am from job 716 | image: busybox 717 | name: hello-job 718 | resources: {} 719 | restartPolicy: Never 720 | status: {} 721 | 722 | kubectl create -f hello-job.yaml 723 | ``` 724 |

725 |
726 | 727 | 728 |
Watch the job that runs 10 times one by one and verify 10 pods are created and delete those after it’s completed 729 |

730 | 731 | ``` 732 | kubectl get job -w 733 | kubectl get po 734 | 735 | kubectl delete job hello-job 736 | ``` 737 |

738 |
739 | 740 | 741 | 742 |
Create the same job and make it run 10 times parallel 743 |

744 | 745 | ``` 746 | kubectl create job hello-job --image=busybox --dry-run -o yaml -- echo "Hello I am from job" > hello-job.yaml 747 | 748 | // edit the yaml file to add parallelism: 10 749 | 750 | apiVersion: batch/v1 751 | kind: Job 752 | metadata: 753 | creationTimestamp: null 754 | name: hello-job 755 | spec: 756 | parallelism: 10 757 | template: 758 | metadata: 759 | creationTimestamp: null 760 | spec: 761 | containers: 762 | - command: 763 | - echo 764 | - Hello I am from job 765 | image: busybox 766 | name: hello-job 767 | resources: {} 768 | restartPolicy: Never 769 | status: {} 770 | 771 | kubectl create -f hello-job.yaml 772 | ``` 773 |

774 |
775 | 776 | 777 | 778 |
Watch the job that runs 10 times parallelly and verify 10 pods are created and delete those after it’s completed 779 |

780 | 781 | ``` 782 | kubectl get job -w 783 | kubectl get po 784 | 785 | kubectl delete job hello-job 786 | ``` 787 |

788 |
789 | 790 | 791 | 792 |
Create a Cronjob with busybox image that prints date and hello from kubernetes cluster message for every minute 793 |

794 | 795 | ``` 796 | kubectl create cronjob date-job --image=busybox --schedule="*/1 * * * *" -- bin/sh -c "date; echo Hello from kubernetes cluster" 797 | ``` 798 |

799 |
800 | 801 | 802 | 803 |
Output the YAML file of the above cronjob 804 |

805 | 806 | ``` 807 | kubectl get cj date-job -o yaml 808 | ``` 809 |

810 |
811 | 812 | 813 | 814 |
Verify that CronJob creating a separate job and pods for every minute to run and verify the logs of the pod 815 |

816 | 817 | ``` 818 | kubectl get job 819 | kubectl get po 820 | 821 | kubectl logs date-job-- 822 | ``` 823 |

824 |
825 | 826 | 827 | 828 |
Delete the CronJob and verify all the associated jobs and pods are also deleted 829 |

830 | 831 | ``` 832 | kubectl delete cj date-job 833 | 834 | // verify pods and jobs 835 | kubectl get po 836 | kubectl get job 837 | ``` 838 |

839 |
840 | 841 | 842 | --------------------------------------------------------------------------------