Skip to content

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

1
2
3
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

1
2
3
4
5
6
7
8
9
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

1
2
3
4
5
kubectl create sa dashboard-sa

kubectl create token dashboard-sa

kubectl set serviceaccount deploy/web-dashboard dashboard-sa
1
2
3
4
5
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 почему один контейнер не видит другой

1
2
3
4
5
6
7
8
9
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 секунд.

1
2
3
4
5
6
7
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

1
2
3
4
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
1
2
3
4
strategy:
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 2
1
2
3
4
5
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, надо поменять порт

1
2
3
4
5
6
7
livenessProbe:
  exec:
    command:
    - ls
    - /var/www/html/file_check
  initialDelaySeconds: 10
  periodSeconds: 60
kubectl replace -f nginx.yaml --force

Task 2

Создать cronejob

1
2
3
4
5
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 и просмотреть логи

1
2
3
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
1
2
3
4
5
6
7
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

1
2
3
4
5
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

1
2
3
kubectl get pod

kubectl get pod app-sec -o yaml > app-sec.yaml
1
2
3
4
5
6
7
containers:
  securityContext:
    capabilities:
      add: ["SYS_TIME"]

securityContext:
  runAsUser: 0
kubectl replace -f app-sec.yaml --froce

Task 11

1
2
3
4
5
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

1
2
3
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

1
2
3
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
NodePort: 30083

Task 2

1
2
3
4
5
kubectl get node

kubectl tain node node01 app_type=alpha:NoSchedule

kubectl run redis --image=redis
1
2
3
4
tolerations:
  - effect: NoSchedule
    key: app_type
    value: alpha

Task 3

1
2
3
4
5
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
1
2
3
4
5
6
7
8
9
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: app_type
            operator: In
            values: ["beta"]

Task 4

1
2
3
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
1
2
3
4
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