Вступление
Kubernetes - это система для масштабного запуска современных контейнерных приложений. С его помощью разработчики могут развертывать приложения и управлять ими на кластерах компьютеров. И хотя его можно использовать для повышения эффективности и надежности при настройке приложений с одним экземпляром, Kubernetes предназначен для запуска нескольких экземпляров приложения на группах компьютеров.
При создании мультисервисных развертываний с Kubernetes многие разработчики предпочитают использовать менеджер пакетовHelm. Helm оптимизирует процесс создания нескольких ресурсов Kubernetes, предлагая диаграммы и шаблоны, которые координируют взаимодействие этих объектов. Он также предлагает готовые графики для популярных проектов с открытым исходным кодом.
В этом руководстве вы развернете приложениеNode.js с базой данных MongoDB в кластере Kubernetes с помощью диаграмм Helm. Вы будете использоватьofficial Helm MongoDB replica set chart для созданияStatefulSet object, состоящего из трехPods, aHeadless Service и трехPersistentVolumeClaims. Вы также создадите диаграмму для развертывания приложения Node.js с несколькими репликами, используя собственный образ приложения. Настройка, которую вы создадите в этом руководстве, будет отражать функциональность кода, описанного вContainerizing a Node.js Application with Docker Compose, и станет хорошей отправной точкой для создания устойчивого приложения Node.js с хранилищем данных MongoDB, которое может масштабироваться в соответствии с вашими потребностями.
Предпосылки
Для завершения этого урока вам понадобится:
-
Кластер Kubernetes 1.10+ с включенным управлением доступом на основе ролей (RBAC). Эта установка будет использоватьDigitalOcean Kubernetes cluster, но вы можете использоватьcreate a cluster using another method.
-
Инструмент командной строки
kubectl
, установленный на вашем локальном компьютере или сервере разработки и настроенный для подключения к вашему кластеру. Вы можете узнать больше об установкеkubectl
вofficial documentation. -
Helm, установленный на вашем локальном компьютере или сервере разработки, и Tiller установлен в вашем кластере, следуя указаниям, изложенным в шагах 1 и 2How To Install Software on Kubernetes Clusters with the Helm Package Manager.
-
Docker установлен на вашем локальном компьютере или сервере разработки. Если вы работаете с Ubuntu 18.04, выполните шаги 1 и 2How To Install and Use Docker on Ubuntu 18.04; в противном случае следуйтеofficial documentation для получения информации об установке в других операционных системах. Обязательно добавьте своего пользователя без полномочий root в группу
docker
, как описано в шаге 2 связанного руководства. -
АккаунтDocker Hub. Чтобы узнать, как это настроить, обратитесь кthis introduction в Docker Hub.
[[шаг-1 -—- клонирование-и-упаковка-приложения]] == Шаг 1. Клонирование и упаковка приложения
Чтобы использовать наше приложение с Kubernetes, нам нужно упаковать его, чтобыkubelet
agent мог извлекать изображение. Однако перед упаковкой приложения нам нужно будет изменить MongoDBconnection URI в коде приложения, чтобы гарантировать, что наше приложение может подключаться к членам набора реплик, который мы создадим с помощью диаграммы Helmmongodb-replicaset
. .
Нашим первым шагом будет клонированиеnode-mongo-docker-dev repository изDigitalOcean Community GitHub account. Этот репозиторий включает код из настройки, описанной вContainerizing a Node.js Application for Development With Docker Compose, в которой используется демонстрационное приложение Node.js с базой данных MongoDB, чтобы продемонстрировать, как настроить среду разработки с помощью Docker Compose. Вы можете найти больше информации о самом приложении в серииFrom Containers to Kubernetes with Node.js.
Клонируйте репозиторий в каталог с именемnode_project
:
git clone https://github.com/do-community/node-mongo-docker-dev.git node_project
Перейдите в каталогnode_project
:
cd node_project
Каталогnode_project
содержит файлы и каталоги для приложения информации об акулах, которое работает с вводом пользователя. Он был модернизирован для работы с контейнерами: конфиденциальная и конкретная информация о конфигурации была удалена из кода приложения и реорганизована для внедрения во время выполнения, а состояние приложения было выгружено в базу данных MongoDB.
Для получения дополнительных сведений о разработке современных контейнерных приложений см.Architecting Applications for Kubernetes иModernizing Applications for Kubernetes.
Когда мы развернем диаграмму Helmmongodb-replicaset
, она создаст:
-
Объект StatefulSet с тремя подами - членами MongoDBreplica set. Каждый Pod будет иметь связанный PersistentVolumeClaim и будет поддерживать фиксированную идентификацию в случае перепланирования.
-
Набор реплик MongoDB, состоящий из модулей в StatefulSet. В набор войдут один первичный и два вторичных. Данные будут реплицированы с основного на второстепенные, обеспечивая высокую доступность данных нашего приложения.
Чтобы наше приложение могло взаимодействовать с репликами базы данных, URI соединения MongoDB в нашем коде должен включать как имена хостов членов набора реплик, так и имя самого набора реплик. Поэтому нам необходимо включить эти значения в URI.
Файл в нашем клонированном репозитории, который определяет информацию о подключении к базе данных, называетсяdb.js
. Откройте этот файл, используяnano
или ваш любимый редактор:
nano db.js
В настоящее время файл включаетconstants, на которые ссылается URI соединения с базой данных во время выполнения. Значения для этих констант вводятся с помощью свойстваprocess.env
узла, которое возвращает объект с информацией о вашей пользовательской среде во время выполнения. Динамическая установка значений в коде нашего приложения позволяет нам отделить код от базовой инфраструктуры, что необходимо в динамической среде без сохранения состояния. Для получения дополнительной информации о таком рефакторинге кода приложения см.Step 2 ofContainerizing a Node.js Application for Development With Docker Compose и соответствующее обсуждение вThe 12-Factor App.
Константы для URI соединения и самой строки URI в настоящее время выглядят так:
~/node_project/db.js
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB
} = process.env;
...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
...
В соответствии с подходом 12FA, мы не хотим жестко кодировать имена хостов наших экземпляров реплик или нашего набора реплик в эту строку URI. Существующая константаMONGO_HOSTNAME
может быть расширена, чтобы включить несколько имен хостов - членов нашего набора реплик - поэтому мы оставим это на месте. Однако нам нужно будет добавить константу набора реплик кoptions
section строки URI.
ДобавьтеMONGO_REPLICASET
как к объекту константы URI, так и к строке подключения:
~/node_project/db.js
...
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB,
MONGO_REPLICASET
} = process.env;
...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?replicaSet=${MONGO_REPLICASET}&authSource=admin`;
...
ИспользованиеreplicaSet
option в разделе параметров URI позволяет нам передать имя набора реплик, что вместе с именами хостов, определенными в константеMONGO_HOSTNAME
, позволит нам подключиться к набору члены.
Сохраните и закройте файл, когда вы закончите редактирование.
После изменения информации о подключении к базе данных для работы с наборами реплик вы можете упаковать приложение, создать образ с помощью командыdocker build
и отправить его в Docker Hub.
Создайте изображение сdocker build
и флагом-t
, который позволяет вам пометить изображение запоминающимся именем. В этом случае пометьте изображение своим именем пользователя Docker Hub и назовите егоnode-replicas
или другое имя по вашему выбору:
docker build -t your_dockerhub_username/node-replicas .
.
в команде указывает, что контекст сборки - это текущий каталог.
Это займет минуту или две, чтобы построить изображение. После завершения проверьте ваши изображения:
docker images
Вы увидите следующий вывод:
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
your_dockerhub_username/node-replicas latest 56a69b4bc882 7 seconds ago 90.1MB
node 10-alpine aa57b0242b33 6 days ago 71MB
Затем войдите в учетную запись Docker Hub, которую вы создали в условиях:
docker login -u your_dockerhub_username
При появлении запроса введите пароль учетной записи Docker Hub. При таком ведении журнала в домашнем каталоге вашего пользователя без полномочий root будет создан файл~/.docker/config.json
с вашими учетными данными Docker Hub.
Отправьте образ приложения в Docker Hub с помощьюdocker push
command. Не забудьте заменитьyour_dockerhub_username
своим именем пользователя Docker Hub:
docker push your_dockerhub_username/node-replicas
Теперь у вас есть образ приложения, который вы можете использовать для запуска своего реплицированного приложения с Kubernetes. Следующим шагом будет настройка конкретных параметров для использования с диаграммой MongoDB Helm.
[[step-2 -—- created-secrets-for-the-mongodb-replica-set]] == Шаг 2. Создание секретов для набора реплик MongoDB
Диаграммаstable/mongodb-replicaset
предоставляет различные варианты использования секретов, и мы создадим два для использования с нашим развертыванием диаграммы:
-
Секрет для нашегоreplica set keyfile, который будет работать как общий пароль между членами набора реплик, позволяя им аутентифицировать других членов.
-
Секрет для нашего пользователя-администратора MongoDB, который будет создан какroot user в базе данных
admin
. Эта роль позволит вам создавать последующих пользователей с ограниченными разрешениями при развертывании приложения в рабочей среде.
Имея эти секреты, мы сможем установить наши предпочтительные значения параметров в отдельном файле значений и создать объект StatefulSet и реплику MongoDB с помощью диаграммы Хелма.
Во-первых, давайте создадим ключевой файл. Мы будем использоватьopenssl
command с опциейrand
, чтобы сгенерировать 756-байтовую случайную строку для ключевого файла:
openssl rand -base64 756 > key.txt
Вывод, сгенерированный командой, будет закодирован вbase64, обеспечивая единообразную передачу данных, и перенаправлен в файл с именемkey.txt
, следуя рекомендациям, изложенным вmongodb-replicaset
chart authentication documentation. key itself должен иметь длину от 6 до 1024 символов и состоять только из символов из набора base64.
Теперь вы можете создать секрет с именемkeyfilesecret
, используя этот файл сkubectl create
:
kubectl create secret generic keyfilesecret --from-file=key.txt
Это создаст объект Secret вdefault
namespace, поскольку мы не создали конкретное пространство имен для нашей установки.
Вы увидите следующий вывод, указывающий, что ваш Секрет был создан:
Outputsecret/keyfilesecret created
Удалитьkey.txt
:
rm key.txt
В качестве альтернативы, если вы хотите сохранить файл, убедитесь, чтоrestrict its permissions и добавьте его в свой.gitignore
file, чтобы он не попадал под контроль версий.
Затем создайте секрет для вашего администратора MongoDB. Первым шагом будет преобразование желаемого имени пользователя и пароля в base64.
Преобразуйте имя пользователя вашей базы данных:
echo -n 'your_database_username' | base64
Запишите значение, которое вы видите в выводе.
Далее конвертируйте ваш пароль:
echo -n 'your_database_password' | base64
Также обратите внимание на значение в выводе.
Откройте файл для секрета:
nano secret.yaml
[.Примечание]##
Note: Объекты Kubernetes - этоtypically defined, использующиеYAML, что строго запрещает табуляцию и требует двух пробелов для отступа. Если вы хотите проверить форматирование любого из ваших файлов YAML, вы можете использоватьlinter или проверить правильность своего синтаксиса, используяkubectl create
с--dry-run
и--validate
флаги:
kubectl create -f your_yaml_file.yaml --dry-run --validate=true
В общем, рекомендуется проверить синтаксис перед созданием ресурсов с помощьюkubectl
.
Добавьте в файл следующий код, чтобы создать секрет, который будет определятьuser
иpassword
с только что созданными закодированными значениями. Не забудьте заменить здесь фиктивные значения своим собственным именем пользователя и паролемencoded:
~/node_project/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
data:
user: your_encoded_username
password: your_encoded_password
Здесь мы используем ключевые имена, которые ожидает диаграммаmongodb-replicaset
:user
иpassword
. Мы назвали секретный объектmongo-secret
, но вы можете называть его как угодно.
Сохраните и закройте файл, когда вы закончите редактирование.
Создайте объект Secret с помощью следующей команды:
kubectl create -f secret.yaml
Вы увидите следующий вывод:
Outputsecret/mongo-secret created
Опять же, вы можете удалитьsecret.yaml
или ограничить его разрешения и добавить его в свой файл.gitignore
.
Создав свои секретные объекты, вы можете перейти к указанию значений параметров, которые вы будете использовать с диаграммойmongodb-replicaset
, и созданию развертывания MongoDB.
[[step-3 -—- configuring-the-mongodb-helm-chart-and-create-a-deployment]] == Шаг 3. Настройка диаграммы управления MongoDB и создание развертывания
Helm поставляется с активно поддерживаемым репозиторием под названиемstable, который содержит диаграмму, которую мы будем использовать:mongodb-replicaset
. Чтобы использовать эту диаграмму с только что созданными секретами, мы создадим файл со значениями параметров конфигурации под названиемmongodb-values.yaml
, а затем установим диаграмму, используя этот файл.
Наш файлmongodb-values.yaml
будет в значительной степени отражать значение по умолчаниюvalues.yaml
file в репозитории диаграммmongodb-replicaset
. Однако мы внесем следующие изменения в наш файл:
-
Мы установим для параметра
auth
значениеtrue
, чтобы гарантировать, что наши экземпляры базы данных начинаются сauthorization enabled. Это означает, что все клиенты должны будут проходить аутентификацию для доступа к ресурсам и операциям базы данных. -
Мы добавим информацию о секретах, которые мы создали на предыдущем шаге, чтобы диаграмма могла использовать эти значения для создания ключевого файла набора реплик и пользователя-администратора.
-
Мы уменьшим размер PersistentVolumes, связанных с каждым модулем в StatefulSet, чтобы использоватьminimum viable DigitalOcean Block Storage unit, 1 ГБ, хотя вы можете изменить это в соответствии с вашими требованиями к хранилищу.
Однако перед записью файлаmongodb-values.yaml
необходимо сначала убедиться, что у вас естьStorageClass, созданный и настроенный для предоставления ресурсов хранения. Каждый из подов в вашей базе данных StatefulSet будет иметь закрепленный идентификатор и связанныйPersistentVolumeClaim, который будет динамически предоставлять PersistentVolume для пода. Если Pod перенесен, PersistentVolume будет подключен к любому узлу, на который запланирован Pod (хотя каждый Том должен быть удален вручную, если связанный с ним Pod или StatefulSet окончательно удален).
Поскольку мы работаем сDigitalOcean Kubernetes, наш класс StorageClassprovisioner
по умолчанию установлен наdobs.csi.digitalocean.com
-DigitalOcean Block Storage, что мы можем проверить, набрав:
kubectl get storageclass
Если вы работаете с кластером DigitalOcean, вы увидите следующий вывод:
OutputNAME PROVISIONER AGE
do-block-storage (default) dobs.csi.digitalocean.com 21m
Если вы не работаете с кластером DigitalOcean, вам нужно будет создать StorageClass и настроитьprovisioner
по вашему выбору. Подробнее о том, как это сделать, см. Вofficial documentation.
Теперь, когда вы убедились, что у вас настроен StorageClass, откройтеmongodb-values.yaml
для редактирования:
nano mongodb-values.yaml
В этом файле вы установите значения, которые будут делать следующее:
-
Включить авторизацию.
-
Ссылайтесь на свои объекты
keyfilesecret
иmongo-secret
. -
Укажите
1Gi
для ваших PersistentVolumes. -
Установите имя набора реплик на
db
. -
Укажите реплики
3
для набора. -
Закрепите образ
mongo
в последней версии на момент написания:4.1.9
.
Вставьте следующий код в файл:
~/node_project/mongodb-values.yaml
replicas: 3
port: 27017
replicaSetName: db
podDisruptionBudget: {}
auth:
enabled: true
existingKeySecret: keyfilesecret
existingAdminSecret: mongo-secret
imagePullSecrets: []
installImage:
repository: unguiculus/mongodb-install
tag: 0.7
pullPolicy: Always
copyConfigImage:
repository: busybox
tag: 1.29.3
pullPolicy: Always
image:
repository: mongo
tag: 4.1.9
pullPolicy: Always
extraVars: {}
metrics:
enabled: false
image:
repository: ssalaues/mongodb-exporter
tag: 0.6.1
pullPolicy: IfNotPresent
port: 9216
path: /metrics
socketTimeout: 3s
syncTimeout: 1m
prometheusServiceDiscovery: true
resources: {}
podAnnotations: {}
securityContext:
enabled: true
runAsUser: 999
fsGroup: 999
runAsNonRoot: true
init:
resources: {}
timeout: 900
resources: {}
nodeSelector: {}
affinity: {}
tolerations: []
extraLabels: {}
persistentVolume:
enabled: true
#storageClass: "-"
accessModes:
- ReadWriteOnce
size: 1Gi
annotations: {}
serviceAnnotations: {}
terminationGracePeriodSeconds: 30
tls:
enabled: false
configmap: {}
readinessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
livenessProbe:
initialDelaySeconds: 30
timeoutSeconds: 5
failureThreshold: 3
periodSeconds: 10
successThreshold: 1
Здесь закомментирован параметрpersistentVolume.storageClass
: удаление комментария и установка его значения на"-"
отключили бы динамическую подготовку. В нашем случае, поскольку мы оставляем это значение неопределенным, диаграмма выберет значение по умолчаниюprovisioner
- в нашем случаеdobs.csi.digitalocean.com
.
Также обратите внимание наaccessMode
, связанный с ключомpersistentVolume
:ReadWriteOnce
означает, что подготовленный том будет доступен для чтения и записи только одним узлом. Пожалуйста, смотритеdocumentation для получения дополнительной информации о различных режимах доступа.
Чтобы узнать больше о других параметрах, включенных в файл, см.configuration table, включенные в репо.
Сохраните и закройте файл, когда вы закончите редактирование.
Перед развертыванием диаграммыmongodb-replicaset
вам нужно обновить репоstable с помощьюhelm repo update
command:
helm repo update
Это позволит получить самую свежую информацию о диаграммах из репозиторияstable.
Наконец, установите диаграмму с помощью следующей команды:
helm install --name mongo -f mongodb-values.yaml stable/mongodb-replicaset
[.Примечание]##
Note: Перед установкой диаграммы вы можете запуститьhelm install
с параметрами--dry-run
и--debug
, чтобы проверить сгенерированные манифесты для вашего выпуска:
helm install --name your_release_name -f your_values_file.yaml --dry-run --debug your_chart
Обратите внимание, что мы называем Helmreleasemongo
. Это имя будет относиться к конкретному развертыванию диаграммы с указанными нами параметрами конфигурации. Мы указали на эти параметры, включив флаг-f
и наш файлmongodb-values.yaml
.
Также обратите внимание, что поскольку мы не включили флаг--namespace
сhelm install
, наши объекты диаграммы будут созданы в пространстве именdefault
.
Создав релиз, вы увидите вывод о его состоянии, а также информацию о созданных объектах и инструкции по взаимодействию с ними:
OutputNAME: mongo
LAST DEPLOYED: Tue Apr 16 21:51:05 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
mongo-mongodb-replicaset-init 1 1s
mongo-mongodb-replicaset-mongodb 1 1s
mongo-mongodb-replicaset-tests 1 0s
...
Теперь вы можете проверить создание ваших модулей с помощью следующей команды:
kubectl get pods
По мере создания Pod вы увидите вывод, подобный следующему:
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 67s
mongo-mongodb-replicaset-1 0/1 Init:0/3 0 8s
ВыводыREADY
иSTATUS
здесь указывают, что модули в нашем StatefulSet не полностью готовы:Init Containers, связанные с контейнерами Pod, все еще работают. Поскольку членами StatefulSet являютсяcreated in sequential order, каждый Pod в StatefulSet должен бытьRunning
иReady
, прежде чем будет создан следующий Pod.
После создания модулей и запуска всех связанных с ними контейнеров вы увидите следующий вывод:
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 2m33s
mongo-mongodb-replicaset-1 1/1 Running 0 94s
mongo-mongodb-replicaset-2 1/1 Running 0 36s
Running
STATUS
указывает, что ваши модули привязаны к узлам и что контейнеры, связанные с этими модулями, работают. READY
указывает, сколько контейнеров в поде работает. Для получения дополнительной информации обратитесь кdocumentation on Pod lifecycles.
[.Примечание]##
Note:
Если вы видите неожиданные фазы в столбцеSTATUS
, помните, что вы можете устранить неполадки в модулях с помощью следующих команд:
kubectl describe pods your_pod
kubectl logs your_pod
Каждый из подов в вашем StatefulSet имеет имя, которое объединяет имя StatefulSet сordinal index пода. Поскольку мы создали три реплики, наши члены StatefulSet пронумерованы от 0 до 2, и каждый имеетstable DNS entry, состоящий из следующих элементов:$(statefulset-name)-$(ordinal).$(service name).$(namespace).svc.cluster.local
.
В нашем случае StatefulSet иHeadless Service, созданные диаграммойmongodb-replicaset
, имеют одинаковые имена:
kubectl get statefulset
OutputNAME READY AGE
mongo-mongodb-replicaset 3/3 4m2s
kubectl get svc
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 443/TCP 42m
mongo-mongodb-replicaset ClusterIP None 27017/TCP 4m35s
mongo-mongodb-replicaset-client ClusterIP None 27017/TCP 4m35s
Это означает, что первый член нашего StatefulSet будет иметь следующую запись DNS:
mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local
Поскольку нам нужно, чтобы наше приложение подключалось к каждому экземпляру MongoDB, важно, чтобы у нас была эта информация, чтобы мы могли напрямую взаимодействовать с модулями, а не со службой. Когда мы создаем нашу пользовательскую диаграмму Helm приложения, мы передадим записи DNS для каждого Pod в наше приложение, используя переменные среды.
Когда ваши экземпляры базы данных запущены и работают, вы готовы создать диаграмму для вашего Node-приложения.
[[step-4 -—- created-a-custom-application-chart-and-configuring-parameters]] == Шаг 4 - Создание пользовательской диаграммы приложения и настройка параметров
Мы создадим пользовательскую диаграмму Хелма для нашего приложения Node и изменим файлы по умолчанию в стандартном каталоге диаграмм, чтобы наше приложение могло работать с только что созданным набором реплик. Мы также создадим файлы для определения объектов ConfigMap и Secret для нашего приложения.
Сначала создайте новый каталог диаграмм с именемnodeapp
с помощью следующей команды:
helm create nodeapp
Это создаст каталог с именемnodeapp
в вашей папке~/node_project
со следующими ресурсами:
-
Файл
Chart.yaml
с основной информацией о вашем графике. -
Файл
values.yaml
, который позволяет вам устанавливать определенные значения параметров, как вы это делали при развертывании MongoDB. -
Файл
.helmignore
с шаблонами файлов и каталогов, которые будут игнорироваться при упаковке диаграмм. -
Каталог
templates/
с файлами шаблонов, которые будут генерировать манифесты Kubernetes. -
Каталог
templates/tests/
для тестовых файлов. -
Каталог
charts/
для любых диаграмм, от которых зависит эта диаграмма.
Первым файлом, который мы изменим из этих файлов по умолчанию, будетvalues.yaml
. Откройте этот файл сейчас:
nano nodeapp/values.yaml
Значения, которые мы здесь установим, включают:
-
Количество реплик.
-
Изображение приложения, которое мы хотим использовать. В нашем случае это будет изображение
node-replicas
, которое мы создали вStep 1. -
ServiceType. В этом случае мы укажемLoadBalancer, чтобы создать точку доступа к нашему приложению в целях тестирования. Поскольку мы работаем с кластером DigitalOcean Kubernetes, это создастDigitalOcean Load Balancer при развертывании нашей диаграммы. В производственной среде вы можете настроить диаграмму для использованияIngress Resources иIngress Controllers для маршрутизации трафика к вашим Сервисам.
-
targetPort, чтобы указать порт на модуле, где будет отображаться наше приложение.
Мы не будем вводить переменные среды в этот файл. Вместо этого мы создадим шаблоны для объектов ConfigMap и Secret и добавим эти значения в манифест развертывания нашего приложения, расположенный в~/node_project/nodeapp/templates/deployment.yaml
.
Настройте следующие значения в файлеvalues.yaml
:
~/node_project/nodeapp/values.yaml
# Default values for nodeapp.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 3
image:
repository: your_dockerhub_username/node-replicas
tag: latest
pullPolicy: IfNotPresent
nameOverride: ""
fullnameOverride: ""
service:
type: LoadBalancer
port: 80
targetPort: 8080
...
Сохраните и закройте файл, когда вы закончите редактирование.
Затем откройте файлsecret.yaml
в каталогеnodeapp/templates
:
nano nodeapp/templates/secret.yaml
В этом файле добавьте значения для констант приложенияMONGO_USERNAME
иMONGO_PASSWORD
. Это константы, к которым ваше приложение ожидает получить доступ во время выполнения, как указано вdb.js
, файле подключения к базе данных. Добавляя значения для этих констант, не забывайте использовать значения base64 -encoded, которые вы использовали ранее вStep 2 при создании объектаmongo-secret
. Если вам нужно восстановить эти значения, вы можете вернуться к шагу 2 и снова запустить соответствующие команды.
Добавьте следующий код в файл:
~/node_project/nodeapp/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-auth
data:
MONGO_USERNAME: your_encoded_username
MONGO_PASSWORD: your_encoded_password
Имя этого секретного объекта будет зависеть от имени вашего релиза Helm, которое вы укажете при развертывании диаграммы приложения.
Сохраните и закройте файл, когда вы закончите.
Затем откройте файл, чтобы создать ConfigMap для вашего приложения:
nano nodeapp/templates/configmap.yaml
В этом файле мы определим оставшиеся переменные, которые ожидает наше приложение:MONGO_HOSTNAME
,MONGO_PORT
,MONGO_DB
иMONGO_REPLICASET
. Наша переменнаяMONGO_HOSTNAME
будет включать запись DNS для экземпляраeach в наш набор реплик, поскольку это то, чтоMongoDB connection URI requires.
СогласноKubernetes documentation, когда приложение реализует проверки работоспособности и готовности, при подключении к подам следует использоватьSRV records. Как обсуждалось вStep 3, наши записи Pod SRV следуют этому шаблону:$(statefulset-name)-$(ordinal).$(service name).$(namespace).svc.cluster.local
. Поскольку наш MongoDB StatefulSet реализует проверки работоспособности и готовности, мы должны использовать эти стабильные идентификаторы при определении значений переменнойMONGO_HOSTNAME
.
Добавьте в файл следующий код, чтобы определить переменныеMONGO_HOSTNAME
,MONGO_PORT
,MONGO_DB
иMONGO_REPLICASET
. Вы можете использовать другое имя для своей базы данныхMONGO_DB
, но ваши значенияMONGO_HOSTNAME
иMONGO_REPLICASET
должны быть записаны так, как они указаны здесь:
~/node_project/nodeapp/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
data:
MONGO_HOSTNAME: "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local,mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local"
MONGO_PORT: "27017"
MONGO_DB: "sharkinfo"
MONGO_REPLICASET: "db"
Поскольку мы уже создали объект StatefulSet и набор реплик, перечисленные здесь имена хостов должны быть перечислены в вашем файле в точности так, как они отображаются в этом примере. Если вы уничтожите эти объекты и переименуете ваш выпуск MongoDB Helm, вам потребуется пересмотреть значения, включенные в эту ConfigMap. То же самое относится и кMONGO_REPLICASET
, поскольку мы указали имя набора реплик в нашей версии MongoDB.
Также обратите внимание, что перечисленные здесь значения указаны в кавычках, что составляетthe expectation for environment variables in Helm.
Сохраните и закройте файл, когда вы закончите редактирование.
Определив значения параметров диаграммы и создав манифесты Secret и ConfigMap, вы можете отредактировать шаблон развертывания приложения, чтобы использовать переменные среды.
[[step-5 -—- integration-environment-variables-into-your-helm-deployment]] == Шаг 5. Интеграция переменных среды в ваше развертывание Helm
Имея файлы для нашего приложения Secret и ConfigMap, мы должны убедиться, что наше приложение Deployment может использовать эти значения. Мы также настроимliveness and readiness probes, которые уже определены в манифесте развертывания.
Откройте шаблон развертывания приложения для редактирования:
nano nodeapp/templates/deployment.yaml
Хотя это файл YAML, шаблоны Helm используют синтаксис, отличный от стандартных файлов YAML Kubernetes, для создания манифестов. Дополнительные сведения о шаблонах см. ВHelm documentation.
В файле сначала добавьте ключenv
в спецификации контейнера приложения, ниже ключаimagePullPolicy
и вышеports
:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
ports:
Затем добавьте следующие ключи в список переменныхenv
:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
key: MONGO_USERNAME
name: {{ .Release.Name }}-auth
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
key: MONGO_PASSWORD
name: {{ .Release.Name }}-auth
- name: MONGO_HOSTNAME
valueFrom:
configMapKeyRef:
key: MONGO_HOSTNAME
name: {{ .Release.Name }}-config
- name: MONGO_PORT
valueFrom:
configMapKeyRef:
key: MONGO_PORT
name: {{ .Release.Name }}-config
- name: MONGO_DB
valueFrom:
configMapKeyRef:
key: MONGO_DB
name: {{ .Release.Name }}-config
- name: MONGO_REPLICASET
valueFrom:
configMapKeyRef:
key: MONGO_REPLICASET
name: {{ .Release.Name }}-config
Каждая переменная включает ссылку на свое значение, определяемое либоsecretKeyRef
key, в случае значений Secret, либоconfigMapKeyRef
для значений ConfigMap. Эти ключи указывают на файлы Secret и ConfigMap, которые мы создали на предыдущем шаге.
Затем под ключомports
измените определениеcontainerPort
, чтобы указать порт в контейнере, где будет отображаться наше приложение:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
...
env:
...
ports:
- name: http
containerPort: 8080
protocol: TCP
...
Далее, давайте изменим проверки живучести и готовности, которые включены в этот манифест развертывания по умолчанию. Эти проверки гарантируют, что наши приложения работают и готовы обслуживать трафик:
-
Датчики готовности оценивают, готов ли Pod обслуживать трафик, останавливая все запросы к Pod до тех пор, пока проверки не пройдут успешно.
-
Датчики жизнеспособности проверяют базовое поведение приложения, чтобы определить, работает ли приложение в контейнере и работает ли оно должным образом. В случае сбоя датчика жизнеспособности Kubernetes перезапустит контейнер.
Подробнее об обоих см.relevant discussion вArchitecting Applications for Kubernetes.
В нашем случае мы будем использоватьhttpGet
request, которые Helm предоставил по умолчанию, и проверим, принимает ли наше приложение запросы на конечной точке/sharks
. kubelet
service выполнит зонд, отправив запрос GET на сервер Node, работающий в контейнере пода приложения и прослушивая порт8080
. Если код состояния для ответа находится между 200 и 400, тоkubelet
сделает вывод, что контейнер исправен. В противном случае, в случае статуса 400 или 500,kubelet
либо остановит трафик к контейнеру, в случае проверки готовности, либо перезапустит контейнер, в случае проверки работоспособности.
Добавьте следующую модификацию к указаннымpath
для датчиков живучести и готовности:
~/node_project/nodeapp/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
containers:
...
env:
...
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /sharks
port: http
readinessProbe:
httpGet:
path: /sharks
port: http
Сохраните и закройте файл, когда вы закончите редактирование.
Теперь вы готовы создать релиз приложения с помощью Helm. Запустите следующийhelm install
command, который включает имя выпуска и расположение каталога диаграмм:
helm install --name nodejs ./nodeapp
Помните, что вы можете сначала запуститьhelm install
с параметрами--dry-run
и--debug
, как описано вStep 3, чтобы проверить сгенерированные манифесты для вашего выпуска.
Опять же, поскольку мы не включаем флаг--namespace
сhelm install
, наши объекты диаграммы будут созданы в пространстве именdefault
.
Вы увидите следующий вывод, указывающий, что ваш выпуск создан:
OutputNAME: nodejs
LAST DEPLOYED: Wed Apr 17 18:10:29 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
nodejs-config 4 1s
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nodejs-nodeapp 0/3 3 0 1s
...
Опять же, выходные данные будут указывать состояние выпуска вместе с информацией о созданных объектах и о том, как вы можете взаимодействовать с ними.
Проверьте статус ваших стручков:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 57m
mongo-mongodb-replicaset-1 1/1 Running 0 56m
mongo-mongodb-replicaset-2 1/1 Running 0 55m
nodejs-nodeapp-577df49dcc-b5fq5 1/1 Running 0 117s
nodejs-nodeapp-577df49dcc-bkk66 1/1 Running 0 117s
nodejs-nodeapp-577df49dcc-lpmt2 1/1 Running 0 117s
После того, как ваши Pod запущены и работают, проверьте свои Услуги:
kubectl get svc
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.245.0.1 443/TCP 96m
mongo-mongodb-replicaset ClusterIP None 27017/TCP 58m
mongo-mongodb-replicaset-client ClusterIP None 27017/TCP 58m
nodejs-nodeapp LoadBalancer 10.245.33.46 your_lb_ip 80:31518/TCP 3m22s
EXTERNAL_IP
, связанный со службойnodejs-nodeapp
, - это IP-адрес, по которому вы можете получить доступ к приложению извне кластера. Если вы видите статус<pending>
в столбцеEXTERNAL_IP
, это означает, что ваш балансировщик нагрузки все еще создается.
Как только вы увидите IP-адрес в этом столбце, перейдите к нему в своем браузере:http://your_lb_ip
.
Вы должны увидеть следующую целевую страницу:
Теперь, когда ваше реплицированное приложение работает, давайте добавим некоторые тестовые данные, чтобы убедиться, что репликация работает между членами набора реплик.
[[step-6 -—- testing-mongodb-replication]] == Шаг 6. Тестирование репликации MongoDB
Когда наше приложение работает и доступно через внешний IP-адрес, мы можем добавить некоторые тестовые данные и обеспечить их репликацию между членами нашего набора реплик MongoDB.
Сначала убедитесь, что вы переместили свой браузер на целевую страницу приложения:
Щелкните по кнопкеGet Shark Info. Вы увидите страницу с формой ввода, где вы можете ввести имя акулы и описание общего характера этой акулы:
В форме добавьте начальную акулу по вашему выбору. Чтобы продемонстрировать, мы добавимMegalodon Shark
в полеShark Name иAncient
в полеShark Character:
Щелкните по кнопкеSubmit. Вы увидите страницу с этой информацией об акулах, отображенной для вас:
Теперь вернитесь к форме информации об акулах, нажавSharks на верхней панели навигации:
Введите новую акулу по вашему выбору. Мы пойдем сWhale Shark
иLarge
:
Как только вы нажметеSubmit, вы увидите, что новая акула была добавлена в коллекцию акул в вашей базе данных:
Давайте проверим, что введенные нами данные были реплицированы между первичными и вторичными членами нашего набора реплик.
Получить список ваших стручков:
kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
mongo-mongodb-replicaset-0 1/1 Running 0 74m
mongo-mongodb-replicaset-1 1/1 Running 0 73m
mongo-mongodb-replicaset-2 1/1 Running 0 72m
nodejs-nodeapp-577df49dcc-b5fq5 1/1 Running 0 5m4s
nodejs-nodeapp-577df49dcc-bkk66 1/1 Running 0 5m4s
nodejs-nodeapp-577df49dcc-lpmt2 1/1 Running 0 5m4s
Чтобы получить доступ кmongo
shell на ваших модулях, вы можете использоватьkubectl exec
command и имя пользователя, которое вы использовали для создания вашегоmongo-secret
вStep 2. Получите доступ к оболочкеmongo
на первом поде в StatefulSet с помощью следующей команды:
kubectl exec -it mongo-mongodb-replicaset-0 -- mongo -u your_database_username -p --authenticationDatabase admin
При появлении запроса введите пароль, связанный с этим именем пользователя:
OutputMongoDB shell version v4.1.9
Enter password:
Вы попадете в административную оболочку:
OutputMongoDB server version: 4.1.9
Welcome to the MongoDB shell.
...
db:PRIMARY>
Хотя сама подсказка включает эту информацию, вы можете вручную проверить, какой член набора реплик является основным сrs.isMaster()
method:
rs.isMaster()
Вы увидите вывод, подобный следующему, с указанием имени хоста первичного сервера:
Outputdb:PRIMARY> rs.isMaster()
{
"hosts" : [
"mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
"mongo-mongodb-replicaset-1.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
"mongo-mongodb-replicaset-2.mongo-mongodb-replicaset.default.svc.cluster.local:27017"
],
...
"primary" : "mongo-mongodb-replicaset-0.mongo-mongodb-replicaset.default.svc.cluster.local:27017",
...
Затем переключитесь на вашу базу данныхsharkinfo
:
use sharkinfo
Outputswitched to db sharkinfo
Перечислите коллекции в базе данных:
show collections
Outputsharks
Вывести документы в сборник:
db.sharks.find()
Вы увидите следующий вывод:
Output{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }
Выход из оболочки MongoDB:
exit
Теперь, когда мы проверили данные на нашем первичном сервере, давайте проверим, реплицируются ли они на вторичный сервер. kubectl exec
вmongo-mongodb-replicaset-1
с помощью следующей команды:
kubectl exec -it mongo-mongodb-replicaset-1 -- mongo -u your_database_username -p --authenticationDatabase admin
Оказавшись в административной оболочке, нам нужно будет использовать методdb.setSlaveOk()
, чтобы разрешить операции чтения из вторичного экземпляра:
db.setSlaveOk(1)
Переключитесь на базу данныхsharkinfo
:
use sharkinfo
Outputswitched to db sharkinfo
Разрешите операцию чтения документов в коллекцииsharks
:
db.setSlaveOk(1)
Вывести документы в сборник:
db.sharks.find()
Теперь вы должны увидеть ту же информацию, что и при запуске этого метода на своем основном экземпляре:
Outputdb:SECONDARY> db.sharks.find()
{ "_id" : ObjectId("5cb7702c9111a5451c6dc8bb"), "name" : "Megalodon Shark", "character" : "Ancient", "__v" : 0 }
{ "_id" : ObjectId("5cb77054fcdbf563f3b47365"), "name" : "Whale Shark", "character" : "Large", "__v" : 0 }
Эти выходные данные подтверждают, что данные вашего приложения реплицируются между членами вашего набора реплик.
Заключение
Теперь вы развернули реплицированное высокодоступное информационное приложение об акулах в кластере Kubernetes, используя диаграммы Хелма. Это демонстрационное приложение и рабочий процесс, описанный в этом руководстве, могут выступать в качестве отправной точки при построении пользовательских диаграмм для вашего приложения и использовании репозитория Helmstable иother chart repositories.
По мере продвижения к производству рассмотрите возможность реализации следующего:
-
Centralized logging and monitoring. Пожалуйста, посмотритеrelevant discussion вModernizing Applications for Kubernetes для общего обзора. Вы также можете посмотретьHow To Set Up an Elasticsearch, Fluentd and Kibana (EFK) Logging Stack on Kubernetes, чтобы узнать, как настроить стек протоколирования сElasticsearch,Fluentd иKibana. Также ознакомьтесь сAn Introduction to Service Meshes для получения информации о том, как сервисные сети, такие какIstio, реализуют эту функциональность.
-
Ingress Resources to route traffic to your cluster. Это хорошая альтернатива LoadBalancer в тех случаях, когда вы запускаете несколько Сервисов, для каждого из которых требуется собственный LoadBalancer, или если вы хотите реализовать стратегии маршрутизации на уровне приложений (например, A / B и канареечные тесты). Для получения дополнительной информации просмотритеHow to Set Up an Nginx Ingress with Cert-Manager on DigitalOcean Kubernetes иrelated discussion маршрутизации в контексте служебной сети вAn Introduction to Service Meshes.
-
Backup strategies for your Kubernetes objects. Инструкции по реализации резервного копирования с помощьюVelero (ранее Heptio Ark) с помощью продукта Kubernetes от DigitalOcean см. ВHow To Back Up and Restore a Kubernetes Cluster on DigitalOcean Using Heptio Ark.