출처: https://github.com/dgkanatsios/CKAD-exercises
Create the YAML for a new ResourceQuota called 'myrq' with hard limits of 1 CPU, 1G memory and 2 pods without creating it
정답
kubectl create quota myrq --hard=cpu=1,memory=1G,pods=2 --dry-run=client -o yaml
참고
Create a pod with image nginx called nginx and expose traffic on port 80
정답
kubectl run nginx --image=nginx --restart=Never --port=80
Change pod's image to nginx:1.24.0. Observe that the container will be restarted as soon as the image gets pulled
정답
k set image pod/nginx nginx=nginx:1.24.0
Get nginx pod's ip created in previous step, use a temp busybox image to wget its '/'
정답
kubectl get po -o wide # get the IP, will be something like '10.1.1.131'
# create a temp busybox pod
kubectl run busybox --image=busybox --rm -it --restart=Never -- wget -O- 10.1.1.131:80
If pod crashed and restarted, get logs about the previous instance
정답
kubectl logs nginx -p
Execute a simple shell on the nginx pod
정답
kubectl exec -it nginx -- /bin/sh
Create a busybox pod that echoes 'hello world' and then exits
정답
kubectl run busybox --image=busybox -it --restart=Never -- echo 'hello world'
Do the same, but have the pod deleted automatically when it's completed
정답
k run busybox --image=busybox -it --rm --restart=Never -- echo 'hello world'
Create an nginx pod and set an env value as 'var1=val1'. Check the env value existence within the pod
정답
k run nginx --image=nginx --restart=Never --env=var1=val1
2
Create a pod with an nginx container exposed on port 80. Add a busybox init container which downloads a page using 'echo "Test" > /work-dir/index.html'. Make a volume of type emptyDir and mount it in both containers. For the nginx container, mount it on "/usr/share/nginx/html" and for the initcontainer, mount it on "/work-dir". When done, get the IP of the created pod and create a busybox pod and run "wget -O- IP"
정답
apiVersion: v1
kind: Pod
metadata:
labels:
run: box
name: box
spec:
initContainers:
- args:
- /bin/sh
- -c
- echo "Test" > /work-dir/index.html
image: busybox
name: box
volumeMounts:
- name: vol
mountPath: /work-dir
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
volumeMounts:
- name: vol
mountPath: /usr/share/nginx/html
volumes:
- name: vol
emptyDir: {}
# Apply pod
kubectl apply -f pod-init.yaml
# Get IP
kubectl get po -o wide
# Execute wget
kubectl run box-test --image=busybox --restart=Never -it --rm -- /bin/sh -c "wget -O- $(kubectl get pod box -o jsonpath='{.status.podIP}')"
# you can do some cleanup
kubectl delete po box
내가 쓴 답은 이건데... 결과가 다른지 헷갈린다
k run busybox --image=busybox -- command wget -O- 10.42.0.10
Show all labels of the pods
정답
kubectl get po --show-labels
Get the label 'app' for the pods (show a column with APP labels)
정답
kubectl get po -L app
# or
kubectl get po --label-columns=app
Add a new label tier=web to all pods having 'app=v2' or 'app=v1' labels
정답
kubectl label po -l "app in(v1,v2)" tier=web
Remove the 'app' label from the pods we created before
정답
kubectl label po -l app app-
Annotate pods nginx1, nginx2, nginx3 with "description='my description'" value
정답
kubectl annotate po nginx1 nginx2 nginx3 description='my description'
Check the annotations for pod nginx1
정답
k annoatate pod nginx1 --list
Remove the annotations for these three pods
정답
kubectl annotate po nginx{1..3} description- owner-
description랑 owner는 annotation key값 -> description랑 owner를 지운다는 것
Check how the deployment rollout is going
정답
kubectl rollout status deploy nginx
Delete the deployment and the horizontal pod autoscaler you created
정답
kubectl delete deploy nginx
kubectl delete hpa nginx
Implement canary deployment by running two instances of nginx marked as version=v1 and version=v2 so that the load is balanced at 75%-25% ratio
정답
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v1
spec:
replicas: 3 # 75% weight (3 out of 4 total replicas)
selector:
matchLabels:
app: nginx
version: v1
template:
metadata:
labels:
app: nginx
version: v1
spec:
containers:
- name: nginx
image: nginx:1.19 # v1 image
ports:
- containerPort: 80
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v2
spec:
replicas: 1 # 25% weight (1 out of 4 total replicas)
selector:
matchLabels:
app: nginx
version: v2
template:
metadata:
labels:
app: nginx
version: v2
spec:
containers:
- name: nginx
image: nginx:1.20 # v2 image (newer version)
ports:
- containerPort: 80
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # Selects both v1 and v2 pods
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
kubectl scale --replicas=4 deploy my-app-v2
kubectl delete deploy my-app-v1
Create a job named pi with image perl:5.34 that runs the command with arguments "perl -Mbignum=bpi -wle 'print bpi(2000)'"
정답
kubectl create job pi --image=perl:5.34 -- perl -Mbignum=bpi -wle 'print bpi(2000)'
Wait till it's done, get the output
정답
kubectl get po # get the pod name
kubectl logs pi-**** # get the pi numbers
kubectl delete job pi
Create a job with the image busybox that executes the command 'echo hello;sleep 30;echo world'
정답
kubectl create job busybox --image=busybox -- /bin/sh -c 'echo hello;sleep 30;echo world'
Create a job but ensure that it will be automatically terminated by kubernetes if it takes more than 30 seconds to execute
정답
spec 밑에 activeDeadlineSeconds: 30 넣어주기
Create the same job, make it run 5 times, one after the other. Verify its status and delete it
정답
spec 밑에 completions:5 넣어주기
Create the same cron job again, and watch the status. Once it ran, check which job ran by the created cron job. Check the log, and delete the cron job
정답
--watch 기억하기!kubectl get cj
kubectl get jobs --watch
kubectl get po --show-labels
Create a cron job with image busybox that runs every minute and writes 'date; echo Hello from the Kubernetes cluster' to standard output. The cron job should be terminated if it takes more than 17 seconds to start execution after its scheduled time (i.e. the job missed its scheduled time).
정답
startingDeadlineSeconds: n : 크론잡이 정해진 시간에 실행되지 못하고 n초 이상 지연되면 해당 작업을 건너뜀apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: time-limited-job
spec:
jobTemplate:
metadata:
creationTimestamp: null
name: time-limited-job
spec:
activeDeadlineSeconds: 12 # add this line
template:
metadata:
creationTimestamp: null
spec:
containers:
- args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
image: busybox
name: time-limited-job
resources: {}
restartPolicy: Never
schedule: '* * * * *'
status: {}
Create a cron job with image busybox that runs every minute and writes 'date; echo Hello from the Kubernetes cluster' to standard output. The cron job should be terminated if it successfully starts but takes more than 12 seconds to complete execution.
정답
activeDeadlineSeconds: n: 실행이 시작된 후 n초 이상 걸리면 걸리면 강제 중담apiVersion: batch/v1
kind: CronJob
metadata:
name: busybox-cronjob
spec:
schedule: "* * * * *" # 매 1분마다 실행
jobTemplate:
spec:
activeDeadlineSeconds: 12 # 12초 이상 실행되면 강제 종료
template:
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "date; echo Hello from the Kubernetes cluster; sleep 15"]
restartPolicy: Never
Create a job from cronjob.
정답
--from=크론잡 !!kubectl create job --from=cronjob/sample-cron-job sample-job
Create and display a configmap from a file, giving the key 'special'
정답
from-file과 파일명 사이에 key 값 special을 넣어줌kubectl create cm configmap4 --from-file=special=config4.txt
Create a configMap called 'options' with the value var5=val5. Create a new nginx pod that loads the value from variable 'var5' in an env variable called 'option'
정답
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
env:
- name: option # name of the env variable
valueFrom:
configMapKeyRef:
name: options # name of config map
key: var5 # name of the entity in config map
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
Create a configMap 'cmvolume' with values 'var8=val8', 'var9=val9'. Load this as a volume inside an nginx pod on path '/etc/lala'. Create the pod and 'ls' into the '/etc/lala' directory.
참고
kubectl create configmap cmvolume --from-literal=var8=val8 --from-literal=var9=val9
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
volumes: # add a volumes list
- name: myvolume # just a name, you'll reference this in the pods
configMap:
name: cmvolume # name of your configmap
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
volumeMounts: # your volume mounts are listed here
- name: myvolume # the name that you specified in pod.spec.volumes.name
mountPath: /etc/lala # the path inside your container
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
kubectl create -f pod.yaml
kubectl exec -it nginx -- /bin/sh
cd /etc/lala
ls # will show var8 var9
cat var8 # will show val8
Create a namespace named limitrange with a LimitRange that limits pod memory to a max of 500Mi and min of 100Mi
정답
kubectl create ns limitrange
apiVersion: v1
kind: LimitRange
metadata:
name: ns-memory-limit
namespace: limitrange
spec:
limits:
- max: # max and min define the limit range
memory: "500Mi"
min:
memory: "100Mi"
type: Pod
Create an nginx pod that requests 250Mi of memory in the limitrange namespace
정답
Error from server (Forbidden): error when creating "5.yaml": pods "nginx" is forbidden: maximum memory usage per Pod is 500Mi. No limit is specified
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
namespace: limitrange
spec:
containers:
- image: nginx
name: nginx
resources:
requests:
memory: "250Mi"
limits:
memory: "500Mi" # limit has to be specified and be <= limitrange
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Delete the pod you just created and mount the variable 'username' from secret mysecret2 onto a new nginx pod in env variable called 'USERNAME'
정답
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
env: # our env variables
- name: USERNAME # asked name
valueFrom:
secretKeyRef: # secret reference
name: mysecret2 # our secret's name
key: username # the key of the data in the secret
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
Consuming the Secret. Create a Pod named 'consumer' with the image 'nginx' in the namespace 'secret-ops' and consume the Secret as an environment variable. Then, open an interactive shell to the Pod, and print all environment variables.
정답
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: consumer
name: consumer
namespace: secret-ops
spec:
containers:
- image: nginx
name: consumer
resources: {}
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: ext-service-secret
key: API_KEY
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
k exec -it -n secret-ops consumer -- /bin/sh
#env
Generate an API token for the service account 'myuser'
정답
kubectl create token myuser
Lots of pods are running in qa,alan,test,production namespaces. All of these pods are configured with liveness probe. Please list all pods whose liveness probe are failed in the format of
<namespace>/<pod name>per line.
정답
kubectl get events -o json | jq -r '.items[] | select(.message | contains("Liveness probe failed")).involvedObject | .namespace + "/" + .name'
풀이
LAST SEEN TYPE REASON OBJECT MESSAGE
22m Warning Unhealthy pod/liveness-exec Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
→ 여기서 중요한 부분은 "Liveness probe failed"라는 메시지가 이벤트 로그에 남는다는 점!
kubectl get events -o json-o json 옵션을 추가하면 출력을 JSON 형식으로 반환jq -r '.items[] | select(.message | contains("Liveness probe failed"))'| .involvedObject | .namespace + "/" + .name'Create a busybox pod that runs 'notexist'. Determine if there's an error (of course there is), see it. In the end, delete the pod forcefully with a 0 grace period
정답
kubectl delete po busybox --force --grace-period=0
풀이
Create a pod with image nginx called nginx and expose its port 80
정답
kubectl run nginx --image=nginx --restart=Never --port=80 --expose
풀이
Confirm that ClusterIP has been created. Also check endpoints
정답
kubectl get svc nginx # services
kubectl get ep # endpoints
Get service's ClusterIP, create a temp busybox pod and 'hit' that IP with wget
정답
controlplane ~ ➜ k get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.43.23.205 <none> 80/TCP 3m30s
controlplane ~ ✖ k run busybox1 --rm --image=busybox -it --r
estart=Never -- wget -O- 10.43.23.205:80
Connecting to 10.43.23.205:80 (10.43.23.205:80)
writing to stdout
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
- 100% |********************************| 615 0:00:00 ETA
written to stdout
pod "busybox1" deleted
풀이
kubectl run busybox: busybox라는 Pod을 실행--rm: Pod 실행 후 자동 삭제 (임시 Pod)--image=busybox: busybox 이미지를 사용-it: 인터랙티브 모드 (stdin 및 tty 사용)--restart=Never: 단일 Pod 실행-- wget -O- 10.108.93.130:80: busybox 내부에서 wget 실행하여 nginx 서비스에 요청wget -O-: 웹페이지(응답)를 표준 출력(stdout)에 바로 출력하는 옵션10.108.93.130:80 → 앞에서 얻은 ClusterIP에 요청을 보냄Convert the ClusterIP to NodePort for the same service and find the NodePort port. Hit service using Node's IP. Delete the service and the pod at the end.
정답
controlplane ~ ➜ k get svc nginx -o yaml > np.yaml
controlplane ~ ➜ vi np.yaml
controlplane ~ ➜ k apply -f np.yaml
Warning: resource services/nginx is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
service/nginx configured
controlplane ~ ➜ cat np.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2025-02-15T07:37:54Z"
name: nginx
namespace: default
resourceVersion: "1251"
uid: 9a04bd45-a6ae-4c65-97f5-d61f72767758
spec:
clusterIP: 10.43.23.205
clusterIPs:
- 10.43.23.205
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: nginx
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
controlplane ~ ➜ k get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
controlplane Ready control-plane,master 44m v1.31.0+k3s1 192.168.211.162 <none> Alpine Linux v3.16 5.15.0-1071-gcp containerd://1.7.20-k3s1
controlplane ~ ➜ wget -O- 192.168.211.162:30100
--2025-02-15 07:54:41-- http://192.168.211.162:30100/
Connecting to 192.168.211.162:30100... connected.
HTTP request sent, awaiting response... 200 OK
Length: 615 [text/html]
Saving to: 'STDOUT'
- 0%[ ] 0 --.-KB/s <!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
- 100%[====>] 615 --.-KB/s in 0s
2025-02-15 07:54:41 (112 MB/s) - written to stdout [615/615]
Create a deployment called foo using image 'dgkanatsios/simpleapp' (a simple server that returns hostname) and 3 replicas. Label it as 'app=foo'. Declare that containers in this pod will accept traffic on port 8080 (do NOT create a service yet)
정답
kubectl create deploy foo --image=dgkanatsios/simpleapp --port=8080 --replicas=3
kubectl label deployment foo --overwrite app=foo
kubectl run busybox --image=busybox --restart=Never -it --rm -- sh 요게 맨날 헷갈린다 ㅠㅠ kubectl get pods -l app=foo -o wide # 'wide' will show pod IPs
kubectl run busybox --image=busybox --restart=Never -it --rm -- sh
wget -O- <POD_IP>:8080 # do not try with pod name, will not work
# try hitting all IPs generated after running 1st command to confirm that hostname is different
exit
Create an nginx deployment of 2 replicas, expose it via a ClusterIP service on port 80. Create a NetworkPolicy so that only pods with labels 'access: granted' can access the pods in this deployment and apply it
정답
kubectl create deployment nginx --image=nginx --replicas=2
kubectl expose deployment nginx --port=80
controlplane ~ ➜ kubectl describe svc nginx
Name: nginx
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.43.243.140
IPs: 10.43.243.140
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.42.0.14:80,10.42.0.15:80
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx # pick a name
spec:
podSelector:
matchLabels:
app: nginx # selector for the pods
ingress: # allow ingress traffic
- from:
- podSelector: # from pods
matchLabels: # with this label
access: granted
Create busybox pod with two containers, each one will have the image busybox and will run the 'sleep 3600' command. Make both containers mount an emptyDir at '/etc/foo'. Connect to the second busybox, write the first column of '/etc/passwd' file to '/etc/foo/passwd'. Connect to the first busybox and write '/etc/foo/passwd' file to standard output. Delete pod.
정답
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
dnsPolicy: ClusterFirst
restartPolicy: Never
containers:
- args:
- /bin/sh
- -c
- sleep 3600
image: busybox
imagePullPolicy: IfNotPresent
name: busybox
resources: {}
volumeMounts: #
- name: myvolume #
mountPath: /etc/foo #
- args:
- /bin/sh
- -c
- sleep 3600
image: busybox
name: busybox2 # don't forget to change the name during copy paste, must be different from the first container's name!
volumeMounts: #
- name: myvolume #
mountPath: /etc/foo #
volumes: #
- name: myvolume #
emptyDir: {} #
kubectl exec -it busybox -c busybox2 -- /bin/sh
cut -f 1 -d ':': :(콜론) 기준으로 데이터를 나누고, 첫 번째 필드만 가져옴cat /etc/passwd | cut -f 1 -d ':' > /etc/foo/passwd
cat /etc/foo/passwd
kubectl exec -it busybox -c busybox -- /bin/sh
mount | grep foo
cat /etc/foo/passwd
kubectl exec busybox -it -- /bin/sh✅ emptyDir는 Pod 내부 컨테이너 간 공유 가능하지만, Pod을 넘어서 공유 불가
✅ hostPath는 같은 노드 내에서만 공유 가능
✅ PersistentVolume + PVC를 사용하면 멀티 노드에서도 공유 가능 (외부 스토리지 필요)
Create a busybox pod with 'sleep 3600' as arguments. Copy '/etc/passwd' from the pod to your local folder
정답
kubectl run busybox --image=busybox --restart=Never -- sleep 3600
kubectl cp busybox:/etc/passwd ./passwd
cat passwd
Find pending Helm deployments on all namespaces
정답
helm list --pending -A
참고
https://helm.sh/docs/helm/helm_list/#helm
Write the contents of the values.yaml file of the bitnami/node chart to standard output
정답
helm show values bitnami/node
Install the bitnami/node chart setting the number of replicas to 5
controlplane $ helm show values bitnami/node | grep -i replica
## @param replicaCount Specify the number of replicas for the application
replicaCount: 1
helm install mynode bitnami/node --set replicaCount=5