С помощью 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 Гб свободного места на диске;
— интернет-подключение;
— контейнеры или диспетчеры виртуальных машин.
Последовательность событий
- Установить локально:
— гипервизор;
— Minikube;
— kubectl. - Создать манифест для MongoDB.
- Создать объект Secret.
- Создать внутреннюю службу для MongoDB.
- Создать манифест для Mongo Express.
- Создать ConfigMap для Mongo Express.
- Создать внешнюю службу для Express.
- Протестировать, выполнить отладку и развертывание архитектуры.
Этап 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 и внешнюю службу для доступа к поду за пределами кластера или из внешних источников.
- Ссылка на репозиторий этого проекта.
- Minikube.
- Mongo — официальный образ.
- Mongo-express — официальный образ.
- Шпаргалка по kubectl.
Читайте также:
- K8s: топология подов
- Как подключить визуальный отладчик к задачам МО в Kubernetes
- MongoDB: типы данных
Читайте нас в Telegram, VK и Дзен
Перевод статьи Ray Sylverne: Deploy Front & Backend Application on Kubernetes