Развертывание фронтенда и бэкенда приложения на Kubernetes

С помощью MongoDB и Mongo Express целиком развернем на Kubernetes полнофункциональное приложение. Чтобы оптимизировать развертывание приложений, при создании этого кластера мы изучим и проанализируем совместную работу различных компонентов Kubernetes. Все это делается локально на компьютере. Задействуем для этой цели minikube, функции и возможности которого подробно рассмотрим в процессе настройки.

Что такое MongoDB и Mongo Express?

MongoDB  —  это платформа для документных баз данных общего назначения, а Mongo Express  —  серверный фреймворк веб-приложений для Node.js. Эти инструменты можно сочетать: с Mongo Express создавать веб-приложение, а в MongoDB сохранять данные. К любому экземпляру базы данных MongoDB подключаются и делают запросы, используя драйвер Node.js для работы с MongoDB, потому что Express  —  это модуль, запускаемый поверх Node.js.

Что понадобится

  • знание интерфейса командной строки Linux;
  • учетная запись DockerHub;
  • следовать инструкциям по установке minikube в зависимости от ОС, архитектуры, типа выпуска и типа установщика;
  • соответствовать требованиям по ресурсам Minikube:
     —  не менее 2 ЦП;
     —  2 Гб свободной памяти;
     —  20 Гб свободного места на диске;
     —  интернет-подключение;
     —  контейнеры или диспетчеры виртуальных машин.

Последовательность событий

  1. Установить локально:
     —  гипервизор;
     —  Minikube;
     —  kubectl.
  2. Создать манифест для MongoDB.
  3. Создать объект Secret.
  4. Создать внутреннюю службу для MongoDB.
  5. Создать манифест для Mongo Express.
  6. Создать ConfigMap для Mongo Express.
  7. Создать внешнюю службу для Express.
  8. Протестировать, выполнить отладку и развертывание архитектуры.

Этап 1. Локальная настройка

Minikube  —  это инструмент с открытым исходным кодом для создания локальной среды Kubernetes в любой системе Linux, Mac или Windows, тестирования и экспериментирования с развертываниями Kubernetes локально. Minikube запускается на компьютере с помощью некой формы гипервизора: на ноутбуке создается виртуальная машина, и внутри этого виртуального ящика запускается узел. По умолчанию создается одноузловой кластер, но при желании с помощью среды Minikube можно сделать и многоузловой. У меня macOS, в других операционных системах команды и этапы могут отличаться. В конце статьи даны ссылки на документацию с этапами для вашей ОС.

Устанавливаем minikube:

brew install minikube

Устанавливаем kubectl:

kubectl  —  это зависимость Minikube, уже установленная предыдущей командой:

Устанавливаем гипервизор:

brew install hyperkit

Создаем и запускаем кластер:

Нужен контейнер Docker или аналогично совместимый или среда виртуальной машины, кластер K8s создается и запускается одной командой:

minikube start --vm-driver=hyperkit

Для запуска кластера указываем, какой гипервизор использовать: он должен запускаться внутри виртуальной машины. Поэтому в команде на запуск прописываем гипервизор Hyperkit. На моем M1 MacBook имеется аналогичная настройка, но из-за многочисленных проблем с виртуализацией я в итоге использовал docker в качестве драйвера при работе на этом устройстве.

Вот команда для применения docker в качестве драйвера: minikube start --driver=docker

Этап 2. Создание манифеста для MongoDB

Прежде чем создавать манифест, отправимся на DockerHub и ознакомимся с документацией по использованию этого контейнера. Там мы ищем порт и внешние конфигурации. Например, сервером MongoDB в образе прослушивается стандартный порт MongoDB 27017, поэтому подключение через сети Docker будет таким же, как к удаленной БД:

vi mongodb-depl.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
labels:
app: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password

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

В нашем сценарии передаются переменные MONGO_INITDB_ROOT_USERNAME и MONGO_INITDB_ROOT_PASSWORD. Когда они применяются совместно, в базе данных аутентификации admin создается новый пользователь, ему дается роль суперпользователя, устанавливается пароль. В secretKeyRef.name и secretKeyRef.key указывается секрет с именем ключа, объявим его на следующем этапе.

Внимание: секрет создается до развертывания, ведь на этапе развертывания имеется зависимость, которая относится к этапу с Secret.

Манифест MongoDB в итоге извлекается в репозиторий, но это не идеальное место для помещаемого в обычный текст логина и пароля admin. Решение  —  создать объект Secret, который бы ссылался на значения в манифесте и находился внутри кластера k8, недоступный в репозитории.

Согласно документации Kubernetes, Secret  —  это объект, в котором содержится небольшой объем конфиденциальных данных, например пароль, токен и ключ. Используя Secret, не нужно включать эти данные в код приложения.

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

Этап 3. Создание объекта Secrets

Прежде чем применять манифест MongoDB, создадим объект Secret, на который ссылается развертывание. Значения Secret при этом  —  не обычный текст, они кодируются в base64 такими командами терминала:

echo -n 'rootlogin' | base64
cm9vdGxvZ2lu
echo -n 'rootpassword' | base64
cm9vdHBhc3N3b3Jk

Вставляем эти значения в файл конфигурации Secret. Для редактирования в терминале используем vi или VSCode:

vi mongo-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
type: Opaque
data:
mongo-root-username: cm9vdGxvZ2lu
mongo-root-password: cm9vdHBhc3N3b3Jk

Мы еще ничего не создали, занимались лишь подготовительной работой. При попытке создать развертывание, которое ссылается на несуществующий Secret, мы бы получили сообщение об ошибке. Применяем Secret:

kubectl apply -f mongo-secret.yaml 
kubectl get service #запуская это, подтверждаем создание

Разворачиваем MongoDB:

kubectl apply -f mongodb-depl.yaml

Этап 4. Создание внутренней службы для MongoDB

Внутренняя служба нужна для взаимодействия с контейнером MongoDB других компонентов или подов. Создадим для службы отдельный YAML-файл или добавим его в развертывание MongoDB. Тройным тире --- в синтаксисе Yaml обозначается разделение документа:

apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
labels:
app: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
---
apiVersion: v1
kind: Service
metadata:
name: mongodb-service
spec:
selector:
app: mongodb
ports:
- protocol: TCP
port: 27017
targetPort: 27017

Применяем изменения той же командой, которой создавали развертывание:

kubectl apply -f mongodb-depl.yaml

Следующими командами подтверждаем создание внутренней службы и добавление ее в под MongoDB:

kubectl get service
kubectl describe service mongodb-service
kubectl get pod -o wide

При текущей настройке доступ к MongoDB имеется только у компонентов с кластером. На этом внутренний дизайн завершен, переходим к внешней конфигурации.

Этап 5. Создание манифеста для Mongo Express

Mongo Express  —  это интерактивный и легковесный веб-инструмент для эффективного управления базами данных MongoDB, который написан на Node.js, Express и Bootstrap 3. С ним упрощаются многие задачи администрирования: создание, обновление, удаление БД, коллекций и документов. Как и с MongoDB, будем посматривать в документацию docker hub по использованию этого образа.

Чтобы аутентифицироваться и подключиться, передадим параметры mongodb в манифест mongo-express:

При доступе к кодированному в base64 паролю, присвоенному MongoDB, будем ссылаться на объект mongodb-secret. Значение для URL-адреса MongoDB ME_CONFIG_MONGODB_SERVER передается напрямую в развертывание, но мы создадим ConfigMap, на который будем ссылаться и где хранятся параметры конфигурации кода, такие как неконфиденциальные данные, имена хостов и URL-адреса в парах ключ  —  значение. Этим ConfigMap конфигурация отделяется от приложения.

Внимание! Согласно документации Kubernetes, с ConfigMap секретность данных и шифрование не обеспечиваются. Для сохранения конфиденциальных данных используйте не ConfigMap, а Secret или дополнительные/сторонние инструменты обеспечения безопасности данных.

vi mongoexpress-depl.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-express
labels:
app: mongo-express
spec:
replicas: 1
selector:
matchLabels:
app: mongo-express
template:
metadata:
labels:
app: mongo-express
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_ADMINUSERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-username
- name: ME_CONFIG_MONGODB_ADMINPASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: mongo-root-password
- name: ME_CONFIG_MONGODB_SERVER
valueFrom:
configMapKeyRef:
name: mongodb-configmap
key: database_url

Для подключения этому образу потребуется имя базы данных, то есть нужен адрес MongoDB или внутренняя служба. URL-адрес БД внутри ConfigMap укажем на следующем этапе.

Этап 6. Создание ConfigMap для Mongo Express

В предыдущем развертывании, прежде чем ссылаться на Secret, этот Secret создается. Так же и с Configmap.

vi mongo-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service

database_url  —  это имя внутренней службы MongoDB, указанное при ее создании на этапе 4.

Вот оба развертывания:

kubectl apply -f mongo-configmap.yaml
kubectl apply -f mongo-express.yaml

Этап 8. Создание внешней службы для Express

Аналогично MongoDB, внешняя служба для express добавляется в манифесте Mongo Express. Но на этот раз не будем их объединять и покажем, что служба разворачивается сама:

vi express-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mongo-express-service
spec:
selector:
app: mongo-express
type: LoadBalancer
ports:
- protocol: TCP
port: 8081
targetPort: 8081
nodePort: 30000

«Распакуем», что в этом файле происходит. Мы указали порт службы 8081.

targetPort:8081  —  здесь прослушивается порт контейнера.

type:LoadBalancer  —  здесь служба делается внешней за счет присвоения ей внешнего IP-адреса.

nodePort: 30000—  порт, через который этот под доступен извне. Диапазон nodePort  —  30000–32767.

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

kubectl get service
kubectl describe service mongodb-service
kubectl get pod -o wide

Этап 9. Проверка качества

Этой командой присваиваем внешней службе общедоступный IP-адрес:

minikube service mongo-express-service

Приложение доступно в браузере через порт 30000, как указано в yaml-файле внешней службы:

Удаление локального кластера Kubernetes

Завершив в Minikube тестирование или разработку, выполняем очистку. Виртуальная машина и все связанные с ней файлы удаляются одной командой:

minikube delete

Заключение

Мы настроили полнофункциональное приложение Mongodb на Kubernetes с доступом через браузер. Используя внутреннюю службу, создали под mongodb, сделали его доступным для другого компонента. А еще разработали единый под для изменения mongodb в mongo-express и внешнюю службу для доступа к поду за пределами кластера или из внешних источников.

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Ray Sylverne: Deploy Front & Backend Application on Kubernetes

Предыдущая статьяSQL: загадки на сообразительность
Следующая статья8 инструментов для предпринимателей, похожих на ChatGPT