27/07/2022

Kubernetes

Kubernetes

Kubernetes

Kubernetes - открытая платформа созданная для автомтаического деплоя, масштабирования и оперирования контейнерами приложений.

Портативная расширяемая платформа с открытым исходным кодом для управления контейнеризованными рабочими нагрузками и сервисами которая облегчает как декларативную настройку так и автоматизацию.

Kubernetes состоит из нод. Как правило рекомендуют использовать не менее 3х нод для Kubernetes. Master Node и 2 Work Nodes.

Master Node - отвечает за поддержание желаемого состояния для вашего кластера. С Master Node взаимодействует kubectl - интерфейс командной строки, который позволяет через командную строку управлять Kubernetes кластером.

С другой стороны у нас есть пользователь, который через интернет обращается к нашему приложению через Work Node и через kube-proxy ходит непосредственно на pod'ы.Основные фундаментальные концепции Kubernetes -  это pod и node, а также kublet, kube-proxy, etcd.

Nodes(узлы) - это виртуальные либо физические машины в Kubernetes кластере на которых будут запускаться контейнеры. Нода содержит kublet, Docker, kube-proxy. Также нода может содержать 1 или несколько под.

Pod - минимальный юнит в Kubernetes с которым можно взаимодействовать, абстрактный объект Kubernetes представляющий группу из одного или нескольких контейнеров приложения (например Docker).

Поды можно создавать, деплоить и удалять. Одна пода - один процесс в кластере. Под содержит: Docker container, storage resources, уникальный IP.

Cluster - совокупность мастер-сервисов и нод.

Namespace - это способ разделения ресурсов кластера между несколькими пользователями. Например, namespace команд, проектов и тд.

Чтобы зайти в кластер и начать запускать команды нужно установить kubectl.

kubectl - это инструмент командной строки kubernetes, который позволяет запускать команды для кластеров Kubernetes. Вы можете использовать kubectl для развертывания приложений проверки и управлени ресурсов кластера а также просмотра логов

Жизненный цикл Pod

  • Pending - ожидание, под ждет ресурсов. Под был принят кластером но один или несколько контейнеров еще не были запущены и нужно подождать.
  • Running - запуск, созданы контейнеры необходимые для пода и запуска непосредственно на этой ноде. Под привязан к узлу и все контейнеры созданы.
  • ContainerCreating - собираются контейнеры.
  • Succeeded/Completed - успешный запуск, все контейнеры созданы, работают, нода запущена.
  • CreateContainerConfigError - ошибка конфигурации.
  • Failed - неуспешный запуск, запуск зафейлился приходит response != 1
  • CrashLoopBackOff - под уходит в бесконечный цикл. Под был запущен крашнулся перезапустился и заново крашнулся (установлено значение restartPolicy: Always) нужно изучить логи.
  • Terminating - трафик не идет на под, под тушится после его удаления

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

source <(kubectl completion bash)

Далее нужно получить доступ к кластеру:

  • Получить список всех неймспейсов
kubectl get namespaces
  • получить список всех подов во всех неймспейсах
kubectl get pods --all-namespaces
  • получить список всех подов во всех неймспейсах там где есть название ssr с подробным выводом логов
kubectl get pods --all-namespaces -o wide |grep ssr
  • получить список подов в определенном неймспейсе
kubectl get pods -n core-team
kubectl get pods -n core-team|grep besida-madmax

После того как вышел список подов мы можем увидеть статусы в которых они находятся:

  • Обзор запущенного пода
kubectl -n core-team describe pod besida-trunk-ua-685d5d4f-hpdw2
  • Вывести логи пода
kubectl -n core-team logs besida-trunk-ua-685d5d4f-hpdw2

отображает логи на лету

kubectl -n core-team logs -f besida-trunk-ua-685d5d4f-hpdw2

Controllers

Управляется Controller Manager'ом.

Виды контроллеров:

  • ReplicaSets - проверяет что необходимое количество pod запущено все время. Если pods стало меньше (например одна изпод закрешилась), то replicaSet создаст новую. ReplicaSets существует не самостоятельно а в рамках Deployment.

  • Deployments - предоставляет декларативное описание для апдейта ReplicaSet и Pod. В ранних версиях Kubernetes вместо ReplicaSet и Deployment использовался Replication Controller. Но это нарушало принцип single responsibilities и в дальнейшем он был разделен и облегчилась задача rollback'a - если во время деплоймента что то пошло не так то в текущих условиях легко откатиться назад и востановить работоспособность приложения.

  • DeamonSets - проверяет что на каждой ноде запущен экземпляр конкретной поды. Если ноды добавляются в кластер или удаляются из кластера то DeamonSet добавить или удалить поды на этой ноде. Удаление DeamonSet означает удаление всех под из кластера.

  • Jobs - это процесс верхнего уровня для пода. Используется когда нужно запустить pod для выполнения какой то задачи один раз или по расписанию. Типичный пример - cron job.

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

Например: FrontEnd Pod взаимодействует с BackEnd Pods через Backend Service.

Виды сервисов:

Internal - ip-адрес доступен только внутри кластера.

External - эндпоинт доступен по ip адресу ноды(такой сервис называют NodePod).

Load Balancer - открывает приложение в интернет через лоад балансер (обычно используется когда кубернетис кластер развернут в облаке (GCP, AWS, Azure).

Labels

Пара ключ/значение, может быть присоединена к таким объектам как поды, сервисы и доплойменты. Используются пользователями Кубернетис для идентификации аттрибутов для объектов. Уникальны в пределах объекта.

Пример: "environment": "dev", "environment": "qa", "environment": "prod"

Labels как правило используются не одни а с selectors.

Selectors

  • equality-based: '=' и '!='
  • Set-based: 'IN', 'NOTIN' и 'EXISTS'

Labels и Selectors обычно используются в kubectl командах для получения списков объектов и их фильтрации. НапримерЖ получение списка под на QA env.

Namespaces

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

Kublet

  • Запущен на каждой work-ноде
  • Коммуницирует с API сервером, который запущен на Master Node
  • Запускает контейнеры для под через docker engine
  • Подключает и запускает диски и сикреты для под
  • Запускает хелсчеки для проверки статусов под/нод и сообщает статус API серверу

Kube-proxy

  • Запущен на каждой work-ноде
  • Рефлицирует сетевой трафик для сервисов (NodePort и LoadBalancer) конфигурирует правила сети на узлах. При помощи них разрешаются сетевые подключения к вашими подам изнутри и снаружи кластера.

Режимы Kube-proxy

  • User space mode (наиболее широко используемый)
  • Iptables mode
  • Ipvs mode (alpha version)

etcd

Распределённое и высоконадёжное хранилище данных в формате "ключ-значение", которое используется как основное хранилище всех данных кластера в Kubernetes.

kube-scheduler

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

Команды Kubernetes

  • получить список подов
kubectl get pods
  • получить список сервисов
kubectl get services
  • получить список деплойментов
kubectl get deployments
  • поднимаем selenium-hub
kubectl create -f selenium-hub-deployment.yaml
  • поднимаем selenium-hub-svc
kubectl create -f selenium-hub-svc.yaml
  • поднимаем selenium-node
kubectl create -f selenium-node-chrome-deployment.yaml

CI/CD microservices

CI - Continious Integration это когда разработчики интегрируют свои код в общий репозиторий на постоянной основе и постоянно проходят некий quality gate который показывает что их код синтегрировался корректно.

CD - Continious Delivery это когда артефакт который мы собрали в рамках Continious Integration и начинаем поставлять его на разные окружения. Continious De[loyment это когда мы в процессе Continious Delivery не ждем ручного апрува а автоматом через энвайронменты проводим и выкатываем на продакшен.

Как этого достичь: 1. Докеризация микросервисов нужно получить артефакт который будет неизменным - нужно быть уверенным что тот артефакт который мы собрали в таком же виде дойдет до продакшена 2. Мы можем присваивать артефакту теги и тем самым продвигать его на следущую стадию 3. Мы не завязываемся на технический стек 4. Это прощает деплоймент, управление окружением, конфигурацию и т.д. 5. Эфективное использование ресурсов

У нас есть контейнер - запущенный процесс который представляет наш микросервис и image - immutable артефакт который мы собрали в рамках CI и выложили его в registry - реестр images, где хранятся наши артефакты.

Версионирование

Семантическое версионирование - главная версия отвечает за то какие знаковые изменения были сделаны в микросервисе(то что мы не поломали API), если мы не имеем обратной совместимости то увеличиваем эту версию либо по большим релизом и с каждым релизом увеличиваем; минорная версия - либо начинаем каждый раз с нуля в рамках каждого нового большошо релиза либо если девелопим интерациями то используют номер интерации, тогда можно быстро востановить когда эта версия была выпущена. патч версия - для хот фиксов комит хештег как суффикс и дата как дополнительный суффикс

CI pipeline

Разработчик делает комит в гит репозиторий на CI делается: build code, run unit tests, build image, push image(пушится в реестр контейнеров). На выходе мы получаем кодовые артифакты, результаты тестов, image контейнер.

Quality Gates:

  • unit tests
  • integration tests
  • static code analysis
  • api tests
  • contract tests
  • security checks

Чтобы поставить полностью всю систему нужно знать версии всех микросервисов.

Здесь нужно учитывать совместимость - это когда мы взяли набор микросервисов подняли провели тесты и после этого мы говорим что этот набор сервисов совместим

Поэтому нужно сохранять нобор версий этих сервисов как отдельный артефакт Этот артефакт можно положить в систему контроля версий(например гит) Дальше в Continious Delivery будет участвовать этот набор. и дальше можно промоутить этот артефакт между разными окружениями. Если мы добавим зависимость на какую то версию postgress или elastic то мы получим полную совместимсоть

Это делается с помощью property файла и прописываем версии. Можно использовать helm.

Пример:

У нас есть 3 сервиса с соответсвущими версиями и мы их собрали в compatible set.

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

Мы собираем новый set с этим кандидатом и пытаемся его запустить и билд падает(возможно оказалась проблема в несовместимости например с ui частью).

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

Если билд проходит успешно, то мы делаем совместимый между собой set и сохраняем его в сисетму контроля версий.

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

После того как артефакт появился в системе контроля версий, то либо jenkins джоба это проверяет, либо оператор в Kubernetes переодически мониторит что появляется и говорит что надо это деплоить - вручную или по расписанию.

Flux CD мониторит появление новых images в гите и говорит что можно их задеплоить.

Выполняем деплой на окружение

Для этого мы создаем Jenkins джобу или github actions которая показывает нам список окружений который нам доступен: dev, qa, stage, prod либо оставляем создаем новое окружение. Также показываются для выбора не отдельные микросервисы а показыватся сеты. Еще нужно указать TTL(Time To Live) окружение будет автоматически очищаться по истечению времени.

Но если будет много окружений - это займет все ресурс и для решения этой проблемы нужен Kubernetes.

Как ускорить создание окружения в Kubernetes:

  • каждое окружение уходит в отдельый namespace
  • конфигурируем минимальные лимиты и scale фактор
  • выносим основные внешние ресурсы (DB, Elastcsearch, Redis, Kafka)
  • используем готовые images с данными
  • сконфигурируем все тулы
  • асинхронное удаление окружение
  • задаем TTL

zhuk.__