«Хочу поделиться с вами моим опытом. Тем, как я изучил основные понятия Kubernetes, создал кластер в Kubernetes с помощью Docker desktop Kubeadm и развернул в нем свое приложение обработки заказов интернет-магазина которое состоит из двух микросервисов (producer, consumer), использует Kafka, Kafdrop, Zookeeper + consumer сохраняет полученное сообщение в базу данных H2», — рассказывает мой коллега Денис Васильев.

Денис Васильев
Разработчик Java компании «Programming store»

История Kubernetes
7 июня 2014 года был выпущен первый выпуск Kubernetes
Kubernetes позволяет разработчикам самостоятельно разворачивать приложения, а системным администраторам, автоматически отслеживая
и перемещая эти приложения в случае аварийного сбоя оборудования
Kubernetes на греческом языке означает «кормчий» или «рулевой» (лицо, держащее рулевое колесо корабля).
Kubernetes использует контейнерные технологии Linux, для того чтобы обеспечить изоляцию выполняющихся приложений. Данные технологии позволяют запускать несколько сервисов на одной хост-машине, не только обеспечивая доступ к разным средам, но и изолируя их друг от друга, подобно виртуальным машинам, но с гораздо меньшими затратами.
Процедура развертывания приложений через Kubernetes всегда одинаковая, независимо от того, содержит ли кластер всего несколько узлов или тысячи. Размер кластера не имеет никакого значения. Дополнительные узлы кластера просто представляют собой дополнительный объем ресурсов, доступных для развернутых приложений.
Основные понятия в Kubernetes
Кластер – это несколько серверов, где нужно развернуть наше приложение.
Под (pod) – минимальный элемент развертывания в Kubernetes, который состоит из одного или нескольких контейнеров, работающих на одном компьютере. Контейнеры внутри пода работают по одному IP-адресу
и могут обмениваться информацией через доступную в контейнере директорию (том, volumes).
Сервисы (Service) – соединяет поды, которые объединяются в группы
с постоянным IP-адресом и балансирует нагрузку между ними.
Развертывание (Deployment) – обеспечивает декларативные обновления для подов и репликационных контроллеров.
Узел (node) – это отдельный сервер (компьютер), который содержит службы (kubelet, прокси kube и др) необходимые для запуска пода.
Метка (labels) – это пары «ключ-значение», есть у каждого объекта (poda). Нужна для идентификации атрибутов объектов, актуальных пользователю
Аннотации – необходимы для связи объектов с метаданными.
Селекторы меток – это инструмент группировки, при использовании которого можно выбрать объекты на основе их меток. Существует два типа селекторов – основанные на наборе значений и основанные на равенстве меток.
Контроллер репликации – это манифест, в котором можно указать количество реплик, селектор и тд. Он использует селектор на равенства меток. Подробнее о манифесте будет описано ниже в статье.
Наборы реплик – тоже манифест, как контроллер репликации, но отличается тем, что использует селекторы на основе набора значений.
Том (volumes) – общее хранилище в поде, для использования объектов
в разных контейнерах. Бывают постоянные (PersistentVolume) и временные (volume).
StatefulSet – помогает обнаружить, добавить, удалить узлы, иными
словами – это контроллер для управления несколькими приложениями, сохраняющими свое состояние.
Secret – объект, который позволяет безопасно передавать конфиденциальные данные (информация о токенах, логины и пароли и тд.) в поды, защищая их
от утечек и ошибочного доступа. Каждый объект в Kubernetes идентифицируется
по имени и идентификатору UID.
Ingress – объект API, который управляет внешним доступом к службам
в кластере, обычно HTTP.
Кластер Kubernetes состоит из большого количества узлов, которые можно разделить на два типа:
1. Master node (Control Plane) – управляющий узел, содержащий компоненты, управляющие кластером Kubernetes.
2. Worker node (Data Plane) – рабочие узлы (node), на которых запускаются контейнеризированные приложения.
Компоненты управляющего узла
1. API-сервер (kube-apiserver) – основной способ взаимодействия
с кластером, не обладает состоянием и хранит все данные в etcd.
2. Controller Manager (kube-controller-manager) – мониторинг за всем кластером (создает, обновляет, удаляет поды (pod), сервисы (service), развертывания (deployment) и тд.).
В Controller Manager входят следующие контроллеры:
Контроллер узла (Node Controller) – уведомляет и реагирует на сбои узла.
Контроллер репликации (Replication Controller) – поддерживает правильное количество подов для каждого объекта контроллера репликации в системе.
Контроллер конечных точек (Endpoints Controller) – заполняет объект конечных точек (Endpoints), то есть связывает сервисы (Services) и поды (Pods).
Контроллеры учетных записей и токенов (Account & Token Controllers) –создают стандартные учетные записи и токены доступа API для новых пространств имен.
3. Sheduler (kube-scheduler) – планировщик, который решает на каком узле запустить под.
4. etcd – хранилище данных в формате «key-value», содержащие информацию о текущем состоянии кластера (конфиги, статусах нод, контейнеров и т.д. Здесь хранится Secret.
Дополнительно отмечу такой компонент как Cloud Controller Manager (cloud-controller-manager) – аналогичен Controller Manager (kube-controller-manager) только для облачных провайдеров.
Компоненты рабочих узлов
1. Kubelet – агент, который запускается на каждом рабочем узле, сначала
он общается с управляющим узлом, получая инструкции, а затем общается
с исполняемой средой контейнера для того, чтобы запустить или остановить контейнер с сервером API и управляет контейнерами на своем узле
2. Docker, rkt или другая исполняемая среда контейнеров – программное обеспечение, отвечающее за запуск, остановку контейнеров и управления ресурсами.
3. kube-proxy – отвечает за коммуникацию и балансирует нагрузку сетевого трафика между компонентами приложения.
Кластер в Kubernetes можно создать с помощью Docker desktop, Minikube, Kubeadm, в облаке, на «голом железе». В начале статьи упомянул, что создал кластер в Kubernetes с помощью Docker desktop Kubeadm. А теперь обо всем
по порядку.
1. Для начала установил Docker Desktop и в его настройках включил Kubernetes.

Kubernetes в Docker Desktop запущен

2. Командой docker image проверил что локально есть docker образы

В Kubernetes все представлено в декларативном виде. Это значит, что для определения всех аспектов своего приложения нужно сначала описать, каким должно быть его состояние в кластере (обычно в формате YAML или JSON), т.е для работы с Kubernetes необходимо создать манифесты.
Манифесты – это основной способ взаимодействия с Kubernetes. Они позволяют декларативно описывать всю инфраструктуру и приложения, делая управление кластером гибким, масштабируемым и воспроизводимым.
Если проект небольшой – монолит, или 1-2 сервиса, манифесты можно создать в папке k8s/ или manifests/ прямо в репозитории приложения. Для средних/больших проектов (микросервисы, Helm, Kustomize) – лучше отдельный репозиторий infra/ или использование Helm Charts. Если используете CI/CD (GitOps), то манифесты могут храниться в отдельном Git-репозитории (например, для ArgoCD).
Напомню, что мое приложение обработки заказа интернет-магазина состоит из двух микросервисов (producer, consumer), использует Kafka, Kafdrop, Zookeeper + consumer сохраняет полученное сообщение в базу данных H2. Также предварительно подготовлены docker-контейнеры все вышеперечисленных компонентов приложения.
Для манифестов Kafka, Kafdrop, Zookeeper, H2 базы решил создать отдельный репозиторий «infra», а для producer, consumer – в папке «k8s/» каждого микросервиса.

Как вы видите из предыдущего скриншота, на каждый микросервис созданы манифесты deployment.yaml и service.yaml, аналогично и для Kafka, Kafdrop, Zookeeper, H2 базы.
Манифесты deployment.yaml и service.yaml – это конфигурационные файлы для Kubernetes, в которых описал какой ресурс хочу создать (Deployment, Service, Pod и тд), какие свойства (образ, порты, переменные окружения) это ресурс должен иметь, какое поведение жду от написанного ресурса (количество реплик, стратегия обновления и тд.), как развернуть и обеспечить доступ к приложению в кластере.
Deployment – это объект Kubernetes, который управляет развертыванием приложений (контейнеров). Он гарантирует, что указанное количество реплик (копий) вашего приложения всегда работает, даже если некоторые поды (Pods) падают.
Service – это абстракция, которая решает задачу балансировки нагрузки (Load Balancing) – распределяя входящие запросы между подами, и обнаружения сервисов (Service Discovery) – предоставляя стабильное имя и IP-адрес для доступа к подам, даже если они меняются (например, при обновлении
или масштабировании).
3. Структура манифестов
Producer


Consumer


Zookeeper


Kafdrop


Kafka



H2-database


4. Применение манифестов
Для того, чтобы применить написанные манифесты в кластере Kubernetes необходимо в терминале зайти в папку, где расположен манифест и выполнить команду kubectl apply -f название манифеста.
В моем случае
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Далее Kubernetes читает манифесты и создает (или обновляет) ресурсы в кластере, основываясь на описанных свойствах и поведении.
Kubernetes управляет жизненным циклом ресурсов, обеспечивая, что они соответствуют желаемому состоянию, описанному в манифестах.
5. Проверка запуска и работоспособности подов

6. Доступ к приложению
Микросервис Producer доступен только внутри кластера (ClusterIP), т.е. я не могу открыть приложение через localhost или IP, поэтому решил использовать команду kubectl port-forward, чтобы перенаправить порт локально
kubectl port-forward service/producer 8080:8080

7. Отправка POST-запроса


Видим, что запрос успешно выполнен
Посмотрим логи producera выполнив команду
kubectl logs -f producer-77c6b94db5-dzr7d

Посмотрим логи consumera выполнив команду
kubectl logs -f consumer-54bcbd5ddd-cf7md

Посмотрим логи базы выполнив команду
kubectl logs -f h2-database-5b5c74878b-chp7h

Зайдем на web-console и посмотрим, что записалось в базу
Для этого в адресной строке вводим http://localhost:30082/ выбираем русский язык, нажимаем кнопку тестовое соединение и видим следующее

Из логов консюмера видно, что у нас создалась в базе таблица SHOP_ORDER, соответственно выполним простой SQL запрос: SELECT * FROM SHOP_ORDER; и нажмем кнопку выполнить

Видим что запрос успешно сохранился в нашей базе данных
Отправлю второй POST-запрос, чтобы еще раз убедиться

Повторяю аналогичный SQL запрос и в web-консоли появляется вторая запись

В завершении хочу поделиться с Вами отличным и полезным инструментом при работе с Kubernetes – OpenLens. Обзор данной утилиты приведен в статье «Обзор Lens – IDE для Kubernetes» https://habr.com/ru/companies/flant/articles/563422/
Нам мой взгляд при использовании данной утилиты удобнее смотреть логи, перезапускать поды и многое другое. Поставил у себя версию 6.2.5, обращаю Ваше внимание что версия 6.5.2 данной утилиты логи не показывает.
Визуализация логов producera

Визуализация логов consumera

При подготовке данной статьи были прочитаны следующие книги:
1. Марко Лукша – Kubernetes в действии, 2019
2. Джиджи Сайфан – Осваиваем Kubernetes Оркестрация контейнерных архитектур, 2019