5.8 KodeKloud CKAD
Core commands
Pods
| kubectl get pods
kubectl get pods --namepace=test
kubectl run webapp --image=nginx
kubectl run redis --image=redis:alpine --dry-run=client -o=yaml > redis-pod.yaml
kubectl describe pod webapp
kubectl get pods -o wide
kubectl delete pod webapp
|
ReplicaSets
| kubectl get replicaset
kubectl get rs
kubectl describe rs new-replica-set
kubectl edit rs new-replica-set
kubectl replace --force -f /tmp/kubectl-edit.yaml
kubectl scale rs new-replica-set --replicas=5
|
Deployments
| kubectl create deployment nginx --image=nginx --replicas=4
# Используется для получения документации по ресурсу
kubectl explain deployment
# Список всех ресурсов
kubectl api-resources
# Показывает историю изменений для указанного развертывания
kubectl rollout history deployment/my-app
# Используется для просмотра статуса процесса развертывания
kubectl rollout status deployment/my-app
# Откатывает развертывание к предыдущему состоянию
kubectl rollout undo deployment/my-app
# Откатывает развертывание к 3 состоянию
kubectl rollout undo deployment/my-app --to-revision=3
# Сохранить в файл
kubectl get deploy/my-deployment -o yaml > my-deploy.yaml
# Set a deployment's nginx container image to nginx:1.9.1
kubectl set image deployment/nginx nginx=nginx:1.9.1
# Update image of all containers of daemonset abc to nginx:1.9.1
kubectl set image daemonset abc *=nginx:1.9.1
|
Service
| kubectl get svc
kubectl expose pod redis --port=6379 --name redis-service
|
Service
Формат доменного имени для обращения к такому сервису изнутри кластера Kubernetes следующий:
| <service-name>.<namespace>.svc.cluster.local
|
| ---
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app.kubernetes.io/name: MyApp
ports:
- port: 80
targetPort: 80
# will allocate a port from a range (default: 30000-32767)
nodePort: 30007
|
Headless сервисы в Kubernetes — это специальный тип сервиса, который не получает кластерный IP-адрес.
Формат DNS-записи для каждого пода будет
| <pod-name>.<headless-service-name>.<namespace>.svc.cluster.local
|
| ---
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
clusterIP: None
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 9376
|
ConfigMap
| kubectl create configmap webapp-config-map --from-literal=APP_COLOR=darkblue
|
| ---
apiVersion: v1
kind: ConfigMap
data:
testkey: hello
testkey2: hello2
---
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
---
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
---
containers:
- name: mypod
image: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: my-configmap
|
Secret
| kubectl create secret generic db-secret --from-literal=DB_Host=sql01 --from-literal=DB_User=root
|
| ---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
---
apiVersion: v1
kind: Pod
metadata:
name: envfrom-secret
spec:
containers:
- name: envars-test-container
image: nginx
envFrom:
- secretRef:
name: test-secret
---
containers:
- name: envars-test-container
image: nginx
env:
- name: BACKEND_USERNAME
valueFrom:
secretKeyRef:
name: backend-user
key: backend-username
---
containers:
- name: mypod
image: myimage
volumeMounts:
- name: mysecret
mountPath: "/etc/mysecret"
readOnly: true
volumes:
- name: mysecret
secret:
secretName: mysecret
|
Persistent Volume
| ---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-log
spec:
persistentVolumeReclaimPolicy: Retain
accessModes:
- ReadWriteMany
capacity:
storage: 100Mi
hostPath:
path: /pv/log
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: claim-log-1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Mi
---
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: event-simulator
image: kodekloud/event-simulator
env:
- name: LOG_HANDLERS
value: file
volumeMounts:
- mountPath: /log
name: log-volume
volumes:
- name: log-volume
persistentVolumeClaim:
claimName: claim-log-1
|
Network Policies
| ---
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
- namespaceSelector:
matchExpressions:
- key: namespace
operator: In
values: ["frontend", "backend"]
|
Node Affinity
| kubectl label node node01 color=blue
|
| ---
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
|
Pod Anti Affinity
| apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: myapp
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: "kubernetes.io/hostname"
containers:
- name: my-container
image: myapp-image
|
Pod Distruption Budgets
| apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: nginx-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: nginx
|
Taints and Toleration
Taints это запрет, разграничивающий доступ так что попасть туда можно только по приглашениям.
Tolerations – это как раз приглашение для входа.
| kubectl taint nodes node01 spray=mortein:NoSchedule
|
| ---
apiVersion: v1
kind: Pod
metadata:
name: bee
spec:
containers:
- image: nginx
name: bee
tolerations:
- key: spray
value: mortein
effect: NoSchedule
operator: Equal
|
ServiceAccount, Role, Binding
| kubectl create sa dashboard-sa
kubectl create token dashboard-sa
kubectl set serviceaccount deploy/web-dashboard dashboard-sa
|
| kubectl create clusterrole --help
kubectl create clusterrole storage-admin --resource=persistentvolume,storageclasses --verb=list,create,get,watch
kubectl create clusterrolebinding admin --user=admin --clusterrole=storage-admin
|
| ---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups:
- ''
resourceNames:
- my-pod
resources:
- pods
verbs:
- get
- watch
- list
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: ServiceAccount
name: dashboard-sa # Name is case sensitive
namespace: default
roleRef:
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
|
Lightning Lab 1
Task 1
Создать PV, PVC, POD
| ---
apiVersion: v1
kind: PersistentVolume
metadata:
name: log-volume
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
hostPath:
path: /opt/volume/nginx
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: log-claim
spec:
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 200Mi
storageClassName: manual
|
| kubectl run logger --image=nginx:alpine --dry-run=client -oyaml > logger.yaml
|
| volumes:
- name: log
persistentVolumeClaim:
claimName: log-claim
containers:
- image: nginx:alpine
name: logger
volumeMounts:
- name: log
mountPath: /var/www/nginx
|
Task 2
Troubleshoot почему один контейнер не видит другой
| kubectl get svc
kubectl get pods
kubectl exec -it webapp-color -- sh
nc -v -z -w 2 secure-service 80
Operation timed out
|
Команда nc -v -z -w 2 secure-service 80 использует утилиту netcat (или nc) для проверки доступности порта 80 на хосте secure-service. Вот что означают отдельные параметры:
- v (verbose) — включает подробный вывод.
- z — выполняет сканирование порта без отправки данных, просто проверяет доступность порта.
- w 2 — устанавливает таймаут соединения в 2 секунды. Это значит, что netcat будет ждать ответа от secure-service на порт 80 в течение 2 секунд.
| kubectl get netpol
kubectl describe netpol
kubectl get pod --show-labels
kubectl get netpol default-deny -oyaml > netpol.yaml
|
| spec:
podSelector:
matchLabels:
run: secure-pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
name: webapp-color
ports:
- protocol: TCP
port: 80
|
Task 3
Создать Pod, ConfigMap, Volume
| kubectl create ns dvl1987
kubectl create cm time-config -n dvl1987 --from-literal=TIME_FREQ=10
kubectl get cm -n dvl1987
kubectl run time-check --image=busybox --dry-run=client -oyaml > time-check.yaml
|
| volumeMounts:
- name: log-volume
mountPath: /opt/time
env:
- name: TIME_FREQ
valueFrom:
configMapKeyRef:
name: time-config
key: TIME_FREQ
volumes:
- name: log-volume
emptyDir: {}
|
Task 4
Создать Deployment
| kubectl create deploy nginx-deploy --image=nginx:1.16 --replicas=4 --dry-run=client -oyaml > deploy.yaml
|
| strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 2
|
| kubectl set image deployment nginx-deploy nginx=nginx:1.17
kubectl get pod
kubectl rollout undo deployment nginx-deploy
|
Task 5
Создать Deployment с configmap и лимитами
| volumes:
- name: redis-config
configMap:
name: redis-config
containers:
- image: redis:alpine
name: redis
resources:
requests:
cpu: "0.2"
volumeMounts:
- name: redis-config
mountPath: /redis-master
|
Lightning Lab 2
Task 1
Troubleshooting pods в статус != Ready, добавить liveness probe
| kubectl describe pod nginx1401 -n dev
|
Ошибка Readless probe, надо поменять порт
| livenessProbe:
exec:
command:
- ls
- /var/www/html/file_check
initialDelaySeconds: 10
periodSeconds: 60
|
| kubectl replace -f nginx.yaml --force
|
Task 2
Создать cronejob
| completions: 1
backoffLimit: 25
activeDeadlineSeconds: 20
restartPolicy: Never
|
- completions: Этот параметр определяет количество успешных завершений задачи, которые необходимы.
- backoffLimit: Этот параметр указывает, сколько раз Kubernetes попытается повторно запустить задачу.
- activeDeadlineSeconds: Этот параметр задает время ожидания для задачи в секундах. Если задача не завершится в течение указанного времени, она будет прервана и считаться неудачной.
Task 3
Создать секреты
| volumes:
- name: secret-volume
secret:
secretName: dotfile-secret
containers:
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: /etc/secret-name
|
Task 4
Создать ingress
| apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-vh-routing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- host: watch-store.com:30093
http:
paths:
- path: /video
pathType: Prefix
backend:
service:
name: video-service
port:
number: 8080
|
Task 5
Создать pod и просмотреть логи
| kubectl logs dev-pod-dind -c log-x
kubectl logs dev-pod-dind -c log-x | grep WARNING > /opt/dind_logs.txt
|
В данном случае, -c log-x указывает на конкретный контейнер log-x в поде dev-pod-dind, из которого нужно извлечь логи.
Mock Exam 1
Task 1
| kubectl run nignx-44889 --image=nginx:alpine
|
Task 2
| kubectl create ns apx-z9938
|
Task 3
| kubectl create deployment httpd-front --image=httpd:2.4-apline --replicas=3
|
Task 4
| kubectl run messagins --image=redis:apline -l tier=msg
|
Task 5
| kubectl get rs
kubectl describe rs rs-d3393
kubectl edit rs rs-d3393
kubectl delete -l name=busybox-pod
|
Task 6
Создание сервиса
| kubectl expose deploy redis --port=6379 --name messaging-service
|
Task 7
| kubectl get pod webapp-color -oyaml > pod.yaml
change env
kubectl replace -f pod.yaml
|
Task 8
| kubectl create configmap cm-3928 --from-literal=DB_NAME=SQL3322 --from-literal=DB_HOST=sql322.com
kubectl describe cm cm-3928
|
Task 9
| kubectl create secret generic db-secret --from-literal=DB_HOST=sql01 --from-literal=DB_USER=root
|
Task 10
| kubectl get pod
kubectl get pod app-sec -o yaml > app-sec.yaml
|
| containers:
securityContext:
capabilities:
add: ["SYS_TIME"]
securityContext:
runAsUser: 0
|
| kubectl replace -f app-sec.yaml --froce
|
Task 11
| kubectl get ns
kubectl get pod e-com -n e-commerce
kubectl logs e-com --namespace=e-commerce > /opt/log.txt
|
Task 12
| apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-analytics
spec:
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Retain
accessModes:
- ReadWriteMany
capacity:
storage: 100Mi
hostPath:
path: /pv/data-analitycs
|
Task 13
| kubectl create deployment redis --image=redis --replicas=1
kubectl expose deployment redis --name=redis --port=6379 --target-port=6379
|
| apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: redis-access
namespace: default
spec:
podSelector:
matchLabels:
app: redis
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
access: redis
ports:
- protocol: TCP
port: 6379
|
Task 14
| ---
apiVersion: v1
kind: Pod
metadata:
name: sega
spec:
containers:
- name: tails
image: busybox
command:
- sleep
- "3600"
- name: sonic
image: nginx
env:
- name: NGINX_PORT
value: "8080"
|
Mock Exam 2
Task 1
| kubectl create deployment my-webapp --image=nginx --replicas=2 --dry-run=client -oyaml > webapp.yaml
kubectl expose deploymeny my-webapp --name front-end-service --type NodePort --port 80
|
Task 2
| kubectl get node
kubectl tain node node01 app_type=alpha:NoSchedule
kubectl run redis --image=redis
|
| tolerations:
- effect: NoSchedule
key: app_type
value: alpha
|
Task 3
| kubectl label node controlplane app_type=beta
kubectl get node controlplane --show-labels
kubectl create deploy beta-apps --image=nginx --replicas=3 --dry-run=clien
|
| spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app_type
operator: In
values: ["beta"]
|
Task 4
| kubect get svc
kubectl create ingress ingress --rule="ckad-mock.com/video*=my-video-service:8080" --dry-run=client
|
| spec:
rules:
- host: ckad-mock.com
http:
paths:
- backend:
service:
name: my-video-service
port:
number: 8080
path: /video
pathType: Prefix
|
Task 5
| kubectl get pod pod-with-rprobe -oyaml
|
| readinessProbe:
httpGet:
path: /ready
port: 8080
|
Task 6
| apiVersion: v1
kind: Pod
metadata:
name: nginx1401
namespace: default
spec:
containers:
- name: nginx1401
image: nginx
livenessProbe:
exec:
command: ["ls /var/www/html/probe"]
initialDelaySeconds: 10
periodSeconds: 60
|
- initialDelaySeconds: Этот параметр указывает количество секунд, которые Kubernetes должен подождать после запуска контейнера, прежде чем начать выполнение проб.
- periodSeconds: Этот параметр определяет, как часто (в секундах) Kubernetes будет выполнять пробы.
Task 7
| kubectl create job --image=docker/whalesay whalesay --dry-run
|
| completions: 10
backoffLimit: 6
spec:
containers:
- image: docker/whalesay
command:
- sh
- -c
- "cowsay I am going to ace CKAD!"
restartPolicy: Never
|
Task 8
| apiVersion: v1
kind: Pod
metadata:
name: multi-pod
spec:
containers:
- name: jupiter
image: nginx
env:
- name: type
value: planet
- name: europa
image: busybox
command: ["/bin/sh", "-c", "sleep 4800"]
env:
- name: type
value: moon
|
Task 9
| apiVersion: v1
kind: PersistentVolume
metadata:
name: custom-volume
spec:
capacity:
storage: 50Mi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /opt/data
|