Занятие №1



Pod - минимально запущенное абстракция в кластере кубернетеса

Внутри пода запускается как минимум два контейнера. основной контейнер под, который несет в себе базовую настройку(network namspaces). С контейнерами напрямую кубер не работает. Для запуска двух реплик приложения, нужно создать два пода.

Снимок экрана 2021-10-05 в 19.36.50.png

Контейнеры внутри одного пода:

  1. Если их нужно запускать на одном физ.хосте
  2. Если масштабир. линейно
  3. Если компоненты имеют сильную связь

Базовые команды для работы с подами:

kubectl describe pod  # Полное описание пода
kubectl delete pod --all # Полное удаление подов, вместо --all можно указать конкретный под
kubectl get pod # Получение списка имеющихся подов
kubectl apply -f ~/school-dev-k8s/practice/2.application-abstractions/1.pod/pod.yaml # Создание или обновление пода
kubectl run # Для создания развертываний + (-f *.yml) 

Для каждой программы за которой нужно следить, Кубернетес создает соответствующий объект Deployment, записывающий некоторую связанную с ней информацию: имя образа контейнера, количество реплик и любые другие параметры для запуска контейнера.

На самом деле deployment не управляет репликами напрямую, оно автоматически создает сопутствующий объект под названием ReplicaSet

Для просмотра имеющихся развертываний:

kubectl get deployments

Развертывания не управляют Под оболочками напрямую, это обязанность ReplicaSet



Занятие №2



ReplicaSet - является следующей абстракцией над Pod-ами и необходим для поддержания их количества, установленного в файле конфигурации

kubectl get rs

Обновление образа

  1. Можно заменить название образа в ямле и после чего выполнить команду apply

  2. Ввод команды

k set image replicaset my-replicaset nginx=[quay.io/testing-farm/nginx:1.13](http://quay.io/testing-farm/nginx:1.13)
# Можно использовать регулярки для получение образов
k set image replicaset my-replicaset '*=[quay.io/testing-farm/nginx:1.13](http://quay.io/testing-farm/nginx:1.13)'
# Команда для получения описания к деплойменту
k explain deployment.spec
k explain deployment.spec.strategy

Strategy - The deployment strategy to use to replace existing pods with new ones.

strategy:

  1. RollingUpdate - плавный перезапуск под of pods

maxSurge 1 - (The maximum number of pods that can be scheduled above the desired number)

maxUnavailable 0

Значения maxSurge и maxUnavailable могут быть выражены в числах или процентах

  1. Recreate - полностью сносим поды с наличием даунтайма

Ресурсы:

Limits:

Количество ресурсов которые под может использовать, верхняя граница, выше этих лимитов просто не получится

Омкиллер(out of memory killer, в ядре линукс) убивает образы которые съедают больше памяти, чем под них выделили. После чего replicaset поднимет инстанс приложения заново.

Requests:

количество ресурсов, которые резервируются для Пода на ноте

не делятся с другими Подами на ноде

Check this:

k rollout history deployment my-deployment
k rollout undo deployment my-deployment



Занятие №3



Для хранение переменных используется специальный ресурс ConfigMap (не для конфиденциальных данных)

k apply -f configmap.yml  # создается как и любой другой ресурс
k get po cm  # получение списка конфигмапов
k get po cm my-configmap-env -o json  # в конкретно заданном формате

Для того, чтобы зайти в под и посмотреть его переменные (аналогично докеру, только для входа в контейнер добавляется — bash, —env):

k exec -it my-deployment-7d7cff784b-9rvkl -- env

SECRETS:

  1. generic - пароли/токены приложений
  2. docker-registry - Данные авторизации в docker-registry
  3. tls - TLS сертификаты для Ingress
  1. Создаем секрет Для этого выполним команду:
kubectl create secret generic test --from-literal=test1=asdf --from-literal=dbpassword=1q2w3e
kubectl get secret
kubectl get secret test -o yaml

В Кубернетес есть специальная утилита для ограничения прав доступа к определенным сервисам. Например, разработчикам можно выдать стандартную роль Edit и они смогут смотреть ConfigMap-ы, администраторы же смогут иметь доступ к секретам.

Для того, чтобы пробросить порты энжинкса наружу, можно использовать следующую команду:

k port-forward my-deployment-5dbbd56b95-r4nbm 8873:80 &

Пример использования: разрабатывая какой то сервис локально, нам может понадобиться тестирование интеграции с каким либо сервисом, пробросив порт сервиса на нашу локальную машину, можно будет с ним взаимодействовать

Для изменений конфигмапа:

kubectl edit configmap my-configmap

Внутри контейнера с подом можно посмотреть доп.информацию о поде в виде аннотаций и лейблов по пути /etc/podinfo



Занятие №4



Работа с кубернетес подразумевает оперирование stateless приложениями, состояние которых не изменится при падении реплики

Все необходимые данные нужно хранить в хранилищах данных и не допускать наличия state

  1. Один из возможных способов маунта данных реализован с помощью директивы hostPath
volumeMounts:
        - name: data
          mountPath: /files
      volumes:
      - name: data
        hostPath:
          path: /data_pod

Его использование крайне не рекомендуется в связи с его не безопасностью, используется только некоторыми внутренними сервисами, возможность его использования лучше блокировать при помощи политик безопасности

  1. Emptydir - создает временный диск и этот временный диск прокидывается в содержимое контейнера, после ребута пода все данные с него удаляются
volumeMounts:
        - name: data
          mountPath: /files
      volumes:
      - name: data
        emptyDir: {}
  1. PersistantVolumeClaim - постоянный вольюм указанной в спеке директории, какого-либо стороннего ресурса(например s3), для определения его характеристик описывается отдельным манифест.
volumes:
- name: data
  persistentVolumeClaim:
    claimName: fileshare

Для того, чтобы разрешить нескольким ресурсам иметь доступ к pvc, нужно указать следующие данные в спеке: accessModes: - ReadWriteMany (ReadWriteMany), но есть одно “но”, если указанный в storageClassName диск не поддерживает множественное чтение-запись, то доступ к нему получит первый “урвавший” его под.

Provisioner - может ходить в облако и нарезать имеющиеся ресурсы на диски и соотвественно получать айди этих дисков, создавать манифесты PV в кубернетесе

Provisioner создает диски именно того размера, который указан в PVC

Снимок экрана 2021-10-18 в 22.55.45.png

Provisioner можно использовать встроенный и предоставляемый сторонними ресурсами, например от openstack

k edit pvc fileshare  # Команда для внесения правок в конфиг персистант вольюма
k get pwc  # команда для получения информации о имеющихся персистанс вольюмах

initcontainers - позволяет выполнить настройки перед запуском основного приложения

  1. выполняются по порядку определения в манифесте
  2. можно монтировать те же тома, что и в основных контейнерах
  3. можно запускать от другого пользователя
  4. должен выполнить действие и остановиться


Занятие №5



Probes

Нужны для проверки работоспособности приложения в поде

Делятся на:

  1. Liveness Probe

    1. Контроль за состоянием приложения во время его жизни

    2. Исполняется постоянно

  2. Readiness Probe

    1. Проверяет, готово ли приложение принимать трафик

    2. В случае неудачного выполнения приложение убирается из балансировки

  3. Startup Probe

    1. Проверяет, запустилось ли приложение

    2. Исполняется при старте

readinessProbe:
  failureThreshold: 3 # Допустимое количество провальных попыток, дойдя до которых, кубер не будет убирать под из балансировки
  httpGet: # Помимо проверки на httpGet, может быть использована команда exec, будет вызвана внутри контейнера(например, select 1 внутри контейнера с бд), tcpsocket
    path: /
    port: 80
  periodSeconds: 10 # Указывает на то, с какой периодичностью нужно проверять приложение
  successThreshold: 1 # Какое количество успешно выполненных попыток сбросит failureThreshold
  timeoutSeconds: 1
  initialDelaySeconds: 10 # Указывает, сколько нужно подождать перед запуском первой пробы. Использовался активно до того как внедрили startup probe
 

Сетевое взаимодействие

Можно посмотреть айпи адреса подов и в переменных окружения фронтенда указать DB_HOST=x.x.x.x.x и это будет работать до тех пор пока под не перезапустится, так как каждый перезапуск пода влечет за собой смену айпи адреса. Поэтому полагаться на айпи адреса и поды мы не можем и будем полагаться на абстракцию сервис.

k get svc # получение активных сервисов
k describe svc my-service # подробное описание сервиса, для получения инфы о сервисе в другом namespace, нужно добавить название namespace через "." после имени сервиса
k get pod --show-labels # получение информации с лейблами
kubectl run test --image=centosadmin/utils:0.3 -it bash # дебаг под
k get ing # получение активных ingress
  1. Service (L3 OSI, NAT, kube-proxy)

    1. Это какой то статический ip адрес

    2. DNS имя в kube-dns на этот IP(myservice.mynamespace.svc.cluster.local)

    3. Правила для роутинга iptables(Service на низком уровне представляет собой набор правил iptables, которые с равной вероятностью распределяют трафик по подам)

    4. Service - это не прокси!

    Снимок экрана 2021-11-05 в 20.48.47.png

    Типы сервисов, которые есть в кубернетес:

    1. ClusterIP

      apiVersion: v1
      kind: Service
      metadata:
        name: my-service # на основе имени сервиса будет создаваться днс запись в кластере кубернетем
      spec:
        ports:
        - port: 80
          targetPort: 80
        selector:
          app: my-app # Указываем лейблы тех подов, на которые мы хотим отправлять трафик с этого сервиса
        type: ClusterIP

      Тип сервиса, который используется для того, чтобы наладить внутрикластерное взаимодействие.

      Выставляется по умолчанию.

      Чтобы сервис работал правильно нужно:

      1). чтобы селектор сервиса совпадал с лейблами подов раздела spec.

      2). поды и сервисы должны находиться в одном неймспейсе (при этом мы можем обратиться к сервису из другого неймспейса, после чего сервис отправит траффик на поды из того же неймспейса, где и сервис)

      При помощи clusterip действительно можно пробросить порты приложения в поде наружу и тем самым опубликовать приложение.

      Например, с помощью:

       kubectl proxy —port=8000 http://localhost:8080/api/v1/proxy/ namespacesdefault/services/my-service:http/ # уже не используется
       kubectl port-forward service/my-service 10000:80 # активно используется для того, чтобы прокинуть порт приложения с кластера на локальную машину 
      (избавляет от необходходимости разворачивать лишние зависимости на своей локальной машине)
    2. NodePort

      С его помощью можно опубликовать сервисы наружу

      Его selector: app также, как и для clusterip должен совпадать с лейблами подов

      apiVersion: v1
      kind: Service
      metadata:
        name: hello-service
      spec:
        selector:
          app: hello
        ports:
          - name: hello-port
            port: 5678 # CLUSTER-IP PORT
            targetPort: 50001 # PORT WHICH YOUR APPLICATION IS RUNNING ON
            nodePort: 30051 # NODEPORT PORT
        type: NodePort

      У вас будет доступ к вашему приложению по адресу::

      • NodeIP:NodePort(30051) (внешний доступ)
      • ClusterIP:port(5678) (внутренний доступ)
      • PodIP:targetPort(50001) (внутренний доступ)

      Задав данный тип сервиса, у нас на мастер и воркер нодах создастся правило, которое будет транслировать входящий трафик, приходящий на порт снаружи в наше приложение, порт будет открываться из заранее заданного диапазона 30000-32767

      Снимок экрана 2021-11-05 в 21.11.41.png

      Если вы хотите выставить свое приложение на порт 6001 для внешнего использования, вы можете попробовать тип службы LoadBalancer .

      NodePort используется преимущественно для двух кейсов:

      1). Если снаружи кластера есть балансировщик вроде nginx, в котором мы прописываем конкретные locations, порты, которые нужно пробросить в кластер

      2). Служебный. Данный тип сервиса используется при работе LoadBalancer, который в свою очередь используется у облачных провайдеров.

      Можно использовать, например, при переносе монолита в кубернетес. В данном случае через внешний балансировщик нагрузки часть траффика будет идти на монолит и часть на кубернетес.

    3. LoadBalancer

      В манифесте можно можно указать loadBalancerIP: “1.1.1.1” статический айпи адрес, который будет являться входной точкой в кластер

      Снимок экрана 2021-11-05 в 21.56.41.png

    4. ExternalName

      Позволяет сделать хитрость с днс записью. Обращаясь на имя сервиса мы в итоге попадем на некий хост, который описан в манифесте сервиса

      Снимок экрана 2021-11-05 в 22.10.10.png

    5. ExternalIPs

      По схеме работы очень похож на NodePort, но если в NodePort создаются правила трансляции для работы с портом, то в externalPs происходит работа с айпи адресом

      Кейсы использования могут быть также связаны с наличием внешнего балансировщика

      Полезен при работе с плавающим айпи адресом

      Например, айпи адрес находится на первой ноде и с ней что-то происходит и тогда KeepAlive этот адрес переносит на другую ноду и мы можем быть уверены что на новой ноде все необходимые правила трансляции есть и мы можем продолжить работу

      Снимок экрана 2021-11-05 в 22.19.13.png

    6. Headless

      У этого сервиса CluserIP=none, это означает что у этого сервиса не будет создан айпи адрес, но будет создана днс за

      При создания сервиса в кластере происходит две вещи:

      1). Создается днс запись в днс сервере кластера кубернетес

      Снимок экрана 2021-11-05 в 22.34.39.png

      StatefullSet - абстракция, которая реализует поддержку stateful приложений, подключать pv, pvc. Является заменой деплойменту, когда нам нужно запустить базу данных

      Для дебаггинга можно поднимать под на базе образа с набором необходимых сетевых утилит:

      kubectl run test --image=centosadmin/utils:0.3 -it bash

  2. Ingress (L7 OSI, HTTP и HTTPS, nginx, envoy, traefik, haproxy):

    Изучив services приходим к выводу, что для полноценной публикации типового веб приложения они не подходят. NodePort предлагает небольшой диапазон портов большого значения, LoadBalancer работает только в облаках

    Если же необходимо опубликовать приложение, то можно использовать Ingress

    Ingress controller - по сути представляет собой балансировщик нагрузки, например, nginx-haproxy-traefik

Снимок экрана 2021-11-06 в 02.49.11.png

Снимок экрана 2021-11-06 в 02.49.55.png

Внутри ингресс контроллер видит имеющийся сервис, он достает оттуда айпи адреса, который стоят за этим сервисом и отправляет на них трафик

Для указания дополнительных характеристик в ингрес, необходимо указывать annotations

По умолчанию ингресс работает через http протокол и выставить https можно с помощью annotations, также может быть grpc и т.д.



Занятие №6



Уcтройство кластера Kubernetes

Для проверки состояния всех компонентов кластера используется следующая команда:

k get componentstatuses

  1. Etcd

    Является базой данных кластера кубернетес(key-value). Хранит в себе всю информацию о кластере.

    Обычно в отказоустойчивом кластере кубернетеса есть три разных ноды с etcd, называемых мастер нодами. В рамках дев разработки можно работать и с одной нодой.

  2. API server

    Центральный компонент кластера.

    Единственный кто общается с etcd.

    Работает по протоколу REST.

    Authentication and authorization

    Снимок экрана 2021-11-06 в 15.51.01.png

  3. Controller manager

    Снимок экрана 2021-11-06 в 16.15.24.png

    Контроллер для кластера кубернетеса - это практически то, что реализует абстракции кубернетеса - создает поды из репликасетов, запускает джобы, занимается gc

    Набор базовых контроллеров:

    • Node controller

      Все ноды кластера периодически пингуют api server о том, что они еще живы. Если вдруг какая то из нод перестанет это делать, по дефолту в настройках в рамках пяти минут, то Node controller передаст информацию в апи сервер о том, что эта нода недоступна и начнет процесс переноса подов этой ноды на другие ноды кластера.

      Т.е. он не ходит и не опрашивает ноды как обычные хэлсчек утилиты, а просто проверяет факт того, что ноды постят свой статус на апи сервер.

    • ReplicaSet controller

      Деплоймент и репликасет являются просто абстракцией(кусочком ямла), а процедуру создания и обработки реплик реализует данный контроллер

    • Endpoint controller

      Автоматическое создание эндпоинтов для сервиса

    Garbage collector: при внесение изменений деплоймент, изменяется репликасет и старые репликасеты не удаляются

    RevisionHistoryLimit по умолчанию равен 10, показывает сколько необходимо хранить старых версий репликасетов

    Если RevisionHistoryLimit равен 10 и появляется 11 репликасет, который принадлежит одному и тому же деплойменту, то он будет удален при помощи gc

  4. Scheduler

    Снимок экрана 2021-11-06 в 16.37.05.png

    Назначает поды на ноды, учитывая:

    • QoS(Quality of Service) политики. В зависимости от ресурсов(limits, requests), scheduler будет решать на какую ноду назначать поды
    • Affinity/ anti-affinity. Фактическое указание запуска подов на определенной группе нод.
    • Requested resources
    • Priority class

    Если в scheduler что-то произойдет, то при попытке создать новый деплоймент, его поды будет висеть в состоянии pending

    До этого момента рассматривались мастер комоненты, которые располагаются на мастер нодах

  5. Kubelet

    Снимок экрана 2021-11-06 в 16.46.05.png

    Работает на каждой ноде

    Единственный компонент, который работает не в докере

    Он непосредственно взаимодействует с системами контейнеризации, обменивается с ними информацией о том, что какие то контейнеры нужно запускать, останавливать и тд

    Работает просто как процесс на хосте и отдает команды докер демону

    Дополнительно выполняет проверки probes

    kubelet выполняя проверки приложения, делает это с той же ноды, где находится приложения и если вдруг нода отвалилась от кластера кубелет этого знать не будет, в то время как NodeController уже отрубит ноду из балансировки

    Кубелет занимается отправкой информации о своей ноде в куб апи сервер о том что он жив, нода на месте, сколько контейнеров запущено и в каком они статусе

    Кубелет имеет встроенный gc, как только на ноде организуется 90% занятого образами места, кубелет запускает механизм очистки устаревших образов до тех пор, пока количество занимаемой ими памяти не снизится на 10%, т.е. до 80%.

  6. Kube-proxy

    Стоит на всех серверах и смотрит в kube api и читает оттуда информацию и подписывается на события

    Занимается управлением сетевыми правилами на нодах

    Сервисы представляют собой несколько правил в iptables на каждой ноде, а эти правила в iptables создает компонент kube proxy

    Kube proxy также живет в контейнере

  7. Контейнеризация, Сеть, DNS



Занятие №7



Локальная разработка в minikube

k get pod -A - для получения информации о всех подах, даже системных

minikube addons list - список имеющихся расширений для миникуба

minikube addons enable ingress - пример подключение аддона игресса

Для получения доступа к встроенным дашбордам кубернетеса, нужно добавить аддон:

minikube addons enable dashboards

после чего его можно запустить, указав его имя и нэймспейс

minikube service kubernetes-dashboard -n kubernetes-dashboard

для просмотра имеющихся внутри миникуба образов: minikube image ls

после подключения миникуба к докеру с помощью следующей команды: eval $(minikube docker-env)(эвалы живут в рамках одной сессии).

можно билдить образы напрямую с интерфейса миникуба:

minikube image build . -t myapp:dev

далее можно обращаться к данным образам в манифестах для запуска приложений

Чтобы замаунтить директории при локальной разработке в миникубе, необходимо ввести следующую команду:

minikube mount .:/app

где также, как и в докере первая часть маунта это директория в основной файловой системе, а вторая часть в контейнере

Для автоматизации задач локальной разработки, можно воспользоваться skaffold

Для работы с дополнительными нодами в кластере на миникуб:

minikube node [add|start|stop|delete|list]



Занятие №8



Job

  • Создает под для выполнения задачи
  • Перезапускает поды до успешного выполнения задачи или истечения таймаута
    • activeDeadLineSeconds. - временной лимит на исполнение задачи (после чего джоба будет прибита и под удален)
    • backoffLimit. - лимит количественный, сколько попыток будет выдано джобе на исполнение задачи

У джобы поля неизменяемые и его нельзя обновить командой apply

Получение джобы:

k get job

k decribe job hello

Для того, чтобы удалить джобу после выполнения, необходимо указывать параметр ttlSecondsAfterFinished

.spec.completions и .spec.parallelismотвечают за желаемое количество успешно выполненных Pod’ов в рамках Job’а и за параллельный запуск Pod’ов в рамках Job’а соответственно.

CronJob

Позволяет запускать джобы по расписанию

Важной опцией является concurrencyPolicy, при помощи которой можно согласовать выполнение джоб в случае, если одна джоба не успела завершиться за минуту, а вторая уже должна начать отрабатывать в это время

Есть три варианта запуска concurrencyPolicy :

  1. “Allow” (default): allows CronJobs to run concurrently;
  2. “Forbid”: forbids concurrent runs, skipping next run if previous run hasn’t finished yet; (best practise)
  3. “Replace”: cancels currently running job and replaces it with a new one

Для указания количества сохраненных успешных джоб после их выполнения используется - successfulJobsHistoryLimit. (best practise)

Для указания количества сохраненных упавших джоб - failedJobsHistoryLimit (best practise)

Важным параметром является startingDeadlineSeconds (best practise)

Каждый раз при запуске кронджобы может происходить какая то задержка по времени и он отработает не в 0.0, а в 0.05 и допустимое время отставания может явно указать вышеупомянутым ключом

Может произойти ситуация, когда что-то произошло с кластером(например, упал controller manager или scheduler не понимает как назначить под) и тогда кронджоба перестает выполнять задачи, но как только кластер придет в норму, кронджоба высчитает количество невыполненных задач в пропущенный промежуток времени и если это значение превышает 100, то кронджоба будет считаться сломанной и выполняться больше не будет

Кронджоб нельзя запускать с учетом секунд, минимальная величина между запусками минута



Занятие №9



Альтернатива Deployment

DaemonSet

В манифестах не имеют replicas, вместо этого запускают по одному поду на всех узлах кластера При добавлении ноды, добавляет под При удалении ноды GC, также удаляет под

В спеке пода можно указать следующую опцию для выбора ноды на которой поднимать под, кубелет проставляет эту метку kubernetes.io/os автоматически

nodeSelector:
  kubernetes.io/os: linux

StatefulSet

В отличие от деплойментов, в стейтфулсете каждый из подов уникальный

Позволяет запускать группу подов(как деплоймент):

  1. Гарантирует их уникальность

  2. Гарантирует их последовательность(после удаления пода mysql-1 и создания заново, под будет называться mysql1, а не mysql2)

PVC Template - При удалении пода стейтфулсета, pvc этого пода остается

Используется для запуска с сохранением состояния → Rabbit, DBs, Redis, Kafka

В случае падения пода, деплоймент поднимает +1 под и из-за того, что все поды одинаковы, нам абсолютно все равно куда идет трафик

Affinity - раздел в ямл манифесте пода, который позволяет потребовать у scheduler то, каким образом он должен запускать поды по узлам кластера



Занятие №10



Авторизация в кластере

RBAC

  1. Role
  2. RoleBinding
  3. ClusterRole
  4. ClusterRoleBinding
  5. ServiceAccount

Role - это список прав на объект

Role и RoleBinding являются объектами namespace-зависимыми

Для получения информации о имеющихся кластерных ролях используется следующая команда: k get clusterrole

Для обращения к сервис аккаунтам:

k get sa <account-name> -o yaml

RoleBinding:

 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: Role
   name: nginx-ingress
subjects:
- kind: ServiceAccount
   name: nginx-ingress
   namespace: ingress-nginx
 - kind: User
   name: jane              # "name" is case sensitive
   apiGroup: rbac.authorization.k8s.io
 - kind: Group
name: developer # for example organization in user certificate apiGroup: rbac.authorization.k8s.io

В кубернетес доступ можно выдать либо на уровне кластера (ClusterRole, ClusterRoleBinding), либо точечно к отдельным неймспейсам. Как пример, нельзя выдать доступы ко всем неймспейсам которые начинаются с stage-, dev-, prod- и т.д. Так как в кубе нет юзеров и групп, то для авторизации пользователей и проверки наличия у них каких-либо прав в кластере(rolebindings) используются внешние сервисы Например, гитлаб может взаимодействовать с апи куба для отдачи данных об имеющихся пользователях

Команды для выставления конфига при подключении к кластеру:

Снимок экрана 2022-01-12 в 22.14.20.png

Дополнительные инструменты для ограничения прав пользователей в kubernetes:

Resource Quota

Устанавливает количество доступных ресурсов и объектов для нэймспейса в кластере

k get resourcequotas

Limit Range

k get limitranges limit-range -o yaml

Решает две задачи:

  1. Выдает defalult для тех подов у которых не описаны requests и limits
  2. Позволяет ограничить потребление для конкретного контейнера в каждом поде

Особенно полезно когда в конкретном неймспейсе разработчик забыл указать ресурсы или же указал их некорректно. Там можно задать параметры min и max, чтобы ограничить в минимально значение(так как если под потребляет слишком мало ресурсов, высока вероятность ошибки запуска приложения) и максимально значение(если разработчик ошибся и задал слишком большое или вовсе не задал и приложение начало потреблять больше чем положено. В случае указания разработчиком слишком большим значений ресурсов для пода, приложение потребляеющее много ресурсов пройдет валидацию на ресурсы указанные в манифесте пода, но не пройдет валидацию Limit Range).

Pod Security Policy

Контролирует аспекты безопасности в описании подов Включается как admission controller plugin “PodSecurityPolicy” - при включении запрещает запуск подов без PSP.

Применяется к подам, которые используют различные небезопасные механизмы. Например, поды которые подключают тома типа HostPath, т.е. поды, которые могут подключить любой каталог с узла к себе внутрь контейнера и каким-либо образом получить доступ к данным, к которым доступа быть не должно.

Также можно указать, чтобы нельзя было запускать поды от рута. Запретить подам использование секретов, системные capabilities вроде отсутствие админа. Является deprecated и в будущем будет заменена.



Занятие №11


Дебаг приложений в кластере

Что усложняет дебаг приложений:

  1. Отсутствие в контейнере нужных команд
  2. Запрет на exec. в проде
  3. Readonly файловая система

Три главные команды дебага:

  1. k describe …
  2. k get events
  3. k logs [—previous] - ключ помогает посмотреть логи предыдущего запущенного контейнера

Если в выводе describe в termination reason омкилл - нужно изменять выделенную память, так как омкиллер убил под из-за превышение установленных ограничений по памяти. Если же в выводе error, гарантированно что у приложения произошла какая то ошибка и само приложение завершилось в контейнере.

Если что то не так пошло в кубернетесе, можно проверить их командой на events(нужно учитывать что ивенты хранятся один часи )

Профилировщики/дебаггеры:

  • Большинство могут работать по сети
  • Нужно использовать отдельный порт, либо роутинг на ингрессе

Для Java: Actuator, Jprofiler Для Python: Prometheus, Rookout Для Golang: Pprof

Дебаг из контейнера: Можно сделать exec, но очень аккуратно (кейс, когда разработчик заходит в контейнер и коннектится к базе, отсылая запросы не допустим, так как в оперативная память загружается и можно легко выйти за лимиты и используемый под будет убит омкиллером) Лучше сделать run c образом приложения (со всеми прод.кредами)



Занятие №12


Horizontal Pod Autoscaler

  • HPA

Увеличивает количество подов в деплойменте в зависимости от поступающей нагрузки

  • Metrics server

Для запуска HPA так же воспользуемся возможностями kubectl. Для создания абстракции HPA без манифеста можно использовать ключ autoscale. kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=5 В результате выполнения команды будет создан HPA, который отслеживает состояние Deployment с именем php-apache. При достижении средней нагрузки на все Pod 50% (для расчетов суммируется процент нагрузки на каждый Pod и делится на их количество) scaling будет производиться в границах от 1-го Pod до 5 Pod. Смотрим на HPA kubectl get hpa Она будет скейлить Pod, как только их использование cpu начнет составлять 50% от request. После того как нагрузка спадет, автоскейлер дает пять минут на down scale, т.е. только через пять начнет прибивать поды до минимального количества.

  • Дефолтные и кастомные метрики

Метрики автоскейлер получает с metric server. Metric server из себя представляет отдельный под, который раз в минуту ходит ко всем кублетами кластера и собирает данные с кадвизоров. Данные он не хранит и предоставляет только данные за минуту.

Снимок экрана 2022-01-14 в 16.08.49.png

Снимок экрана 2022-01-14 в 16.11.08.png

Снимок экрана 2022-01-14 в 16.14.46.png

Снимок экрана 2022-01-14 в 16.17.26.png

Снимок экрана 2022-01-14 в 16.21.46.png

  • Cluster autoscaler

Снимок экрана 2022-01-14 в 16.42.28.png



Занятие №13


Templating. Helm.

Снимок экрана 2022-01-15 в 01.50.35.png

При работе с хэлмом можно создавать стартовый шаблон с заготовкой чарта следующей командой: helm create <chart_name>

Снимок экрана 2022-01-16 в 04.09.57.png

Снимок экрана 2022-01-16 в 04.11.45.png

Снимок экрана 2022-01-16 в 04.14.45.png

Снимок экрана 2022-01-16 в 04.16.26.png

При создании джобы или пода для тестов релиза, нужно убедиться что имеется хук “helm.sh/hook-delete-policy”: hook-succeeded, чтобы удалить выполненный тест, так как хуки не входят в релиз и даже после его удаления под или джоба останутся висеть в кластере.



Занятие №14


Kubernetes CI/CD

Устновка ранера гитлаб в кластер: helm repo add gitlab https://charts.gitlab.io

Далее нужно указать токен Settings - CI/CD - Runners - Specific runners - registration token. Скопируйте его из Gitlab и вставьте в файл values.yaml, в переменную runnerRegistrationToken.

gitlabUrl: https://gitlab.com/
 
runnerRegistrationToken: <token> 
 
runners:
  config: |
    [[runners]]
      [runners.kubernetes]
        image = "alpine:3.14"
        cpu_request = "100m"
        cpu_limit = "1000m"
        memory_limit = "2048Mi"
        memory_request = "1024Mi"
  tags: slurm-k8s
 
## For RBAC support:
rbac:
  create: true
 
  ## Run the gitlab-bastion container with the ability to deploy/manage containers of jobs
  ## cluster-wide or only within namespace
  clusterWideAccess: false
 
  ## Use the following Kubernetes Service Account name if RBAC is disabled in this Helm chart (see rbac.create)
  ##
  # serviceAccountName: gitlabrunnersa
 
  ## Use podSecurity Policy
  ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/
  podSecurityPolicy:
    enabled: false
    resourceNames:
    - gitlab-runner
 
## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
  limits:
    memory: 256Mi
    cpu: 200m
  requests:
    memory: 128Mi
    cpu: 50m

Далее нужно запустить команду хэлма в директории с файлом values.yaml указанным выше: helm upgrade -i gitlab-runner gitlab/gitlab-runner -f values.yaml -n gitlab-runner --create-namespace После чего можно проверить что раннер установлен в том разделе, где получали токен.


Памятка:

Создание объектов:

kubectl apply -f ./my-manifest.yaml # создать ресурсы
kubectl apply -f ./my1.yaml -f ./my2.yaml # создать ресурсы из нескольких файлов
kubectl apply -f ./dir # создать ресурсы из всех файлов манифеста в директории
kubectl apply -f https://git.io/vPieo # создать ресурсы из URL-адреса
kubectl create deployment nginx --image=nginx # запустить один экземпляр nginx
kubectl explain pods # посмотреть документацию по манифестам подов

Просмотр и поиск ресурсов

# Get-команды с основном выводом
kubectl get services # Вывести все сервисы в пространстве имён
kubectl get pods --all-namespaces # Вывести все поды во всех пространств имён
kubectl get pods -o wide # Вывести все поды в текущем пространстве имён с подробностями
kubectl get deployment my-dep # Вывести определённое развёртывание
kubectl get pods # Вывести все поды в пространстве имён
kubectl get pod my-pod -o yaml # Получить информацию по поду в формате YAML
# Посмотреть дополнительные сведения команды с многословным выводом
kubectl describe nodes my-node
kubectl describe pods my-pod
# Вывести сервисы, отсортированные по имени
kubectl get services --sort-by=.metadata.name
# Вывести поды, отсортированные по количеству перезагрузок
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
# Вывести постоянные тома (PersistentVolumes), отсортированные по емкости
kubectl get pv --sort-by=.spec.capacity.storage
# Получить метку версии всех подов с меткой app=cassandra
kubectl get pods --selector=app=cassandra -o \
  jsonpath='{.items[*].metadata.labels.version}'
# Получить все рабочие узлы (с помощью селектора исключаем узлы с меткой 'node-role.kubernetes.io/master')
kubectl get node --selector='!node-role.kubernetes.io/master'
# Получить все запущенные поды в пространстве имён
kubectl get pods --field-selector=status.phase=Running
# Показать метки всех подов (или любого другого объекта Kubernetes, которым можно прикреплять метки)
kubectl get pods --show-labels
 

Обновление ресурсов

kubectl set image deployment/frontend www=image:v2 # Плавающее обновление контейнеров "www" развёртывания "frontend", обновление образа
kubectl rollout history deployment/frontend # Проверить историю развёртывания, включая ревизии.
kubectl rollout undo deployment/frontend # Откатиться к предыдущему развёртыванию
kubectl rollout undo deployment/frontend --to-revision=2 # Откатиться к определённой ревизии
kubectl rollout status -w deployment/frontend # Отслеживать статус плавающего развёртывания "frontend" до его завершения
kubectl rollout restart deployment/frontend # Перезапуск плавающего развёртывания "frontend"
# Принудительно заменить, удалить, а затем пересоздать ресурс. Это приведет к простою приложения
kubectl replace --force -f ./pod.json
# Создать сервис с реплицированным nginx на порту 80, который подключается к контейнерам на порту 8000.
kubectl expose rc nginx --port=80 --target-port=8000
kubectl label pods my-pod new-label=awesome                      # Добавить метку
kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq       # Добавить аннотацию
kubectl autoscale deployment foo --min=2 --max=10                # Автоматически промасштабировать развёртывание "foo"

Масштабирование ресурсов

kubectl scale --replicas=3 rs/foo # Промасштабировать набор реплик (replicaset) 'foo' до 3
kubectl scale --replicas=3 -f foo.yaml # Промасштабировать ресурс в "foo.yaml" до 3
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql # Если количество реплик в развёртывании mysql равен 2, промасштабировать его до 3
kubectl scale --replicas=5 rc/foo rc/bar rc/baz # Промасштабировать несколько контроллеров репликации

Удаление ресурсов

kubectl delete -f ./pod.json # Удалить под по типу и имени в pod.json
kubectl delete pod,service baz foo # Удалить поды и сервисы с одноимёнными именам "baz" и "foo"
kubectl delete pods,services -l name=myLabel # Удалить поды и сервисы с именем метки myLabel
kubectl -n my-ns delete pod,svc --all # Удалить все поды и сервисы в пространстве имен my-ns

Работа с запущенными подами

kubectl logs my-pod # вывести логи пода (в stdout)
kubectl logs -l name=myLabel # вывести логи пода с меткой myLabel (в stdout)
kubectl logs my-pod --previous # вывести логи пода (в stdout) по предыдущему экземпляру контейнера
kubectl logs my-pod -c my-container # вывести логи контейнера пода (в stdout, при работе с несколькими контейнерами)
kubectl logs -l name=myLabel -c my-container # вывести логи пода с меткой myLabel (в stdout)
kubectl logs my-pod -c my-container --previous # вывести логи контейнера пода (в stdout, при работе с несколькими контейнерами) по предыдущему экземпляру контейнера
kubectl logs -f my-pod # вывести логи пода в режиме реального времени (в stdout)
kubectl logs -f my-pod -c my-container # вывести логи контейнера пода в режиме реального времени (в stdout, при работе с несколькими контейнерами)
kubectl logs -f -l name=myLabel --all-containers # вывести логи всех подов с меткой myLabel (в stdout)
kubectl run -i --tty busybox --image=busybox -- sh # запустить под как интерактивную оболочку
kubectl run nginx --image=nginx --restart=Never -n
mynamespace # Запустить под nginx в заданном пространстве имён
kubectl run nginx --image=nginx --restart=Never # Запустить под nginx и записать его спецификацию в файл pod.yaml

Работа с узлами и кластером

kubectl cordon my-node # Отметить узел my-node как неназначаемый
kubectl drain my-node # Вытеснить узел my-node, чтобы подготовиться к эксплуатации
kubectl uncordon my-node # Отметить узел my-node как назначаемый
kubectl top node my-node # Показать метрики по заданному узлу
kubectl cluster-info # Показать адреса главного узла и сервисов
kubectl cluster-info dump # Вывести состояние текущего кластера в stdout

Типы ресурсов

kubectl api-resources
kubectl api-resources --namespaced=true      *# Все ресурсы с пространством имён*
kubectl api-resources --namespaced=false     *# Все ресурсы без пространства имён*
kubectl api-resources -o name                *# Все ресурсы с простым выводом  (только имя ресурса)*
kubectl api-resources -o wide                *# Все ресурсы с расширенным (с неограниченной длинной) выводом*
kubectl api-resources --verbs=list,get       *# Все ресурсы, которые поддерживают глаголы запроса "list" и "get"*
kubectl api-resources --api-group=extensions *# Все ресурсы в API-группе "extensions"*