Развертывание stateful сервиса в Kubernetes
Cloud Server, VPS | Комментировать запись
Kubernetes – открытый инструмент для оркестровки и управления контейнерными приложениями. В предыдущих частях этой серии вы изучили основные компоненты Kubernetes и спаковали контейнеры как наборы реплик Kubernetes. Наборы реплик (ReplicaSet) гарантируют доступность подзаголовков без учета состояния, однако они не могут использоваться в stateful процессах, таких как кластеры базы данных.
Современные облачные приложения в Kubernetes легко упаковать, развертывать, управлять и масштабировать, но развертывание и управление традиционными рабочими компонентами, такими как базы данных и системы управления контентом в контейнерной среде, требует другого подхода. Для этого есть StatefulSets.
В этой заключительной части серии вы научитесь развертывать высокодоступный MongoDB ReplicaSet в Kubernetes как StatefulSet с помощью Helm, популярного открытого менеджера пакетов для Kubernetes.
Требования
- Активный кластер Kubernetes, установленный через StackPointCloud (об этом – в мануале Начало работы с Kubernetes).
- Тестовое приложение (как в статье Развертывание и масштабирование микросервисов Kubernetes), основанное на Node.js и MongoDB. Дополнительные инструкции по приложению вы найдете в мануале Создание контейнеризированного приложения Docker.
- Аккаунт Docker Hub для хранения Docker образов приложения.
- Git на локальной машине (если вы пользуетесь macOS, установите Homebrew).
1: Установка клиента Helm на машину разработки
Helm позволяет администраторам развертывать сложные приложения Kubernetes с помощью одной команды. Приложения упакованы в чарты, которые определяют, устанавливают и обновляют приложения Kubernetes. Чарты обеспечивают абстракцию от объектов Kubernetes (подов, развертываний и сервисов).
Helm имеет два компонента – сервер и клиент. Серверная часть Helm работает в Kubernetes как сервис под названием Tiller. Клиент – это инструмент командной строки, который взаимодействует с Tiller.
Поскольку вы собираетесь развернуть чарт Helm для ReplicaSet MongoDB, вам понадобится CLI, который взаимодействует с Tiller, серверным компонентом Helm. StackPointCloud, который вы использовали для установки Kubernetes ранее, поставляется с предустановленным Tiller.
Примечание: Эти инструкции предназначены для macOS. Если вы используете другую систему, обратитесь к этому мануалу.
Учитывая, что у вас установлен Homebrew, запустите следующую команду, чтобы установить Helm:
brew install kubernetes-helm
==> Downloading https://homebrew.bintray.com/bottles/kubernetes-helm-2.8.2.high_sierra.bottle.tar.gz
...
==> Summary
🍺 /usr/local/Cellar/kubernetes-helm/2.8.2: 50 files, 121.7MB
После установки Helm убедитесь, что вы можете его запустить, запросив текущую версию:
helm version
Client: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.8.2", GitCommit:"a80231648a1473929271764b920a8e346f6de844", GitTreeState:"clean"}
Это значит, что установка прошла успешно.
Теперь можно использовать Helm, чтобы развернуть MongoDB ReplicaSet в Kubernetes
2: Развертывание MongoDB ReplicaSet в Kubernetes
StorageClass в Kubernetes предоставляет администраторам возможность описывать «классы» хранилища. Например, когда пользователи запрашивают том хранилища, StorageClass определяет, какой класс бэкэнда хранилища оркеструется из них. Классы могут включать стандартный жесткий диск и более быстрый SSD. Для хранения данных StorageClass взаимодействует с базовой инфраструктурой, такой как API провайдера облачных вычислений.
Поскольку для данных MongoDB нужно постоянное хранилище, вы можете смонтировать том на рабочей ноде и создать под MongoDB, чтобы использовать этот том хранилища.
В этом случае StorageClass действует как интерфейс между подом и сервисом блочных хранилищ. Когда вы запрашиваете том блочного хранилища, StorageClass обращается к предварительно сконфигурированному драйверу, который знает, как распределить том.
StackPointCloud позволяет установить специальный драйвер и зарегистрировать StorageClass для Kubernetes во время установки.
Прежде чем развернуть кластер MongoDB, убедитесь, что StorageClass для тома настроен:
kubectl get storageclass
Вывод подтвердит, что StorageClass установлен правильно:
NAME PROVISIONER AGE
block-storage (default) block-storage/flex-volume-provisioner 1d
Если ваш сервис хранения не поддерживает своих классов, создайте StorageClass самостоятельно.
Теперь нужно настроить и развернуть MongoDB ReplicaSet на основе StorageClass.
Создайте новый каталог проекта и перейдите в него:
mkdir ~/mongo-rs
cd ~/mongo-rs
Клонируйте репозиторий charts Helm с GitHub:
git clone https://github.com/kubernetes/charts.git
Перейдите в каталог MongoDB ReplicaSet (charts/stable/mongodb-replicaset/) и убедитесь, что файл values.yaml существует:
cd charts/stable/mongodb-replicaset/
ls values.yaml
values.yaml
Этот файл содержит параметры и конфигурацию чарта. Вам необходимо изменить этот файл, чтобы настроить MongoDB ReplicaSet для поддержки StorageClass.
Отредактируйте values.yaml:
nano values.yaml
Найдите и раскомментируйте следующий раздел:
...
# storageClass: "-"
...
Вместо “-” впишите ваше блочное хранилище:
...
storageClass: "block-storage"
...
Сохраните и закройте редактор.
Перейдите в каталог ~/mongo-rs:
cd ~/mongo-rs
Теперь вы готовы развернуть MongoDB ReplicaSet в кластере Kubernetes, работающем на блочном хранилище. Для запуска кластера базы данных выполните следующую команду.
helm install --name=todo -f charts/stable/mongodb-replicaset/values.yaml stable/mongodb-replicaset
В предыдущей команде –name ссылается на имя чарта Helm. Флаг -f указывает на параметры конфигурации, сохраненные в values.yaml.
Вы сразу увидите результат, подтверждающий начало создания чарта.
NAME: todo
LAST DEPLOYED: Sat Mar 31 10:37:06 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
todo-mongodb-replicaset ClusterIP None <none> 27017/TCP 1s
==> v1beta1/StatefulSet
NAME DESIRED CURRENT AGE
todo-mongodb-replicaset 3 1 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 0/1 Init:0/2 0 0s
==> v1/ConfigMap
NAME DATA AGE
todo-mongodb-replicaset 1 1s
todo-mongodb-replicaset-tests 1 1s
NOTES:
1. After the statefulset is created completely, one can check which instance is primary by running:
$ for ((i = 0; i < 3; ++i)); do kubectl exec --namespace default todo-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done
2. One can insert a key into the primary instance of the mongodb replica set by running the following:
MASTER_POD_NAME must be replaced with the name of the master found from the previous step.
$ kubectl exec --namespace default MASTER_POD_NAME -- mongo --eval="printjson(db.test.insert({key1: 'value1'}))"
3. One can fetch the keys stored in the primary or any of the slave nodes in the following manner.
POD_NAME must be replaced by the name of the pod being queried.
$ kubectl exec --namespace default POD_NAME -- mongo --eval="rs.slaveOk(); db.test.find().forEach(printjson)"
Теперь нужно запустить пару команд, чтобы отследить состояние кластера.
Сначала проверьте StatefulSet:
kubectl get statefulset
Эта команда подтвердит, что MongoDB ReplicaSet был создан как Kubernetes StatefulSet.
NAME DESIRED CURRENT AGE
todo-mongodb-replicaset 3 2 2m
Теперь просмотрите поды:
kubectl get pods
Количество подов и политика их именования подтверждает, что MongoDB ReplicaSet успешно настроен.
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 3m
todo-mongodb-replicaset-1 1/1 Running 0 1m
todo-mongodb-replicaset-2 1/1 Running 0 54s
Обратите внимание, что каждый под имеет последовательный номер, который является отличительной особенностью StatefulSet.
Теперь давайте посмотрим, взаимодействуют ли экземпляры MongoDB друг с другом. Мы сделаем это, выполнив команду в оболочке MongoDB в одном из подов.
Используйте kubectl для запуска консоли mongo на одном из хостов:
kubectl exec -it todo-mongodb-replicaset-0 mongo
После этого у вас будет доступ к оболочке MongoDB:
MongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
For interactive help, type "help".
...
2018-03-31T05:08:20.239+0000 I CONTROL [initandlisten]
Проверьте конфигурацию ReplicaSet:
rs.conf()
Вывод подтверждает, что существует три экземпляра MongoDB, работающих как ReplicaSet.
{
"_id" : "rs0",
"version" : 3,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "todo-mongodb-replicaset-0.todo-mongodb-replicaset.default.svc.cluster.local:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "todo-mongodb-replicaset-1.todo-mongodb-replicaset.default.svc.cluster.local:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "todo-mongodb-replicaset-2.todo-mongodb-replicaset.default.svc.cluster.local:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5abdb4f61d952afc4b0b8218")
}
}
Закройте консоль:
exit
Это также отключит вас от удаленного хоста.
Теперь проверьте панель управления блочного хранилища, связанного с кластером.
Вы должны увидеть, что три тома по 10 ГБ каждый подключены к рабочим нодам Kubernetes. Каждый под MongoDB StatefulSet хранит данные в одном из томов хранилища блоков. Размер 10 ГБ определен в values.yaml в разделе persistentVolume.
persistentVolume:
enabled: true
## mongodb-replicaset data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
storageClass: block-storage
accessModes:
- ReadWriteOnce
size: 10Gi
annotations: {}
Вы успешно настроили MongoDB ReplicaSet в Kubernetes
Теперь нужно развернуть приложение, которое взаимодействует с кластером MongoDB.
3: Развертывание и масштабирование веб-приложения в Kubernetes
Попробуйте расширить приложение ToDo, которое вы использовали в предыдущих частях этой серии мануалов, чтобы воспользоваться кластером MongoDB.
Примечание: Вы также можете создать образ контейнера из исходного кода или напрямую использовать файлы YAML в файлах Kubernetes. Обратитесь к руководству Развертывание и масштабирование микросервисов Kubernetes.
Создайте новый рабочий каталог:
mkdir ~/web-app
cd ~/web-app
Затем клонируйте репозиторий приложения ToDo, содержащий код и артефакты Kubernetes.
git clone https://github.com/janakiramm/todo.git
Перейдите в каталог todo-app/kubernetes, который содержит конфигурационные файлы Kubernetes.
cd todo-app/kubernetes
Откройте файл web-rs-ss.yaml в редакторе:
nano web-rs-ss.yaml
Найдите раздел env:
containers:
- name: web
image: janakiramm/todo
env:
- name: "DBHOST"
value: "mongodb://todo-mongodb-replicaset-0.todo-mongodb-replicaset,todo-mongodb-replicaset-1.todo-mongodb-replicaset,todo-mongodb-replicaset-2.todo-mongodb-replicaset:27017"
ports:
- containerPort: 3000
Это передает строку подключения базы данных к приложению в качестве переменной среды. Вместо того чтобы направлять приложение в простой под MongoDB, эта версия приложения использует созданный StatefulSet. Каждая запись в разделе value относится к одному из подов из MongoDB StatefulSet.
Используйте kubectl для развертывания ReplicaSet вместе с сервисом web:
kubectl create -f web-rs-ss.yaml -f web-service.yaml
Вы увидите, что они были созданы:
replicaset "web" created
service "web" created
Снова просмотрите список подов:
kubectl get pods
Вы увидите все поды, принадлежащие MongoDB и веб-приложению.
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 26m
todo-mongodb-replicaset-1 1/1 Running 0 24m
todo-mongodb-replicaset-2 1/1 Running 0 23m
web-t5zzk 1/1 Running 0 17s
web-x6dh8 1/1 Running 0 17s
Let’s check out the Kubernetes services
```command
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.3.0.1 <none> 443/TCP 1d
todo-mongodb-replicaset ClusterIP None <none> 27017/TCP 27m
web NodePort 10.3.0.167 <none> 3000:31201/TCP 14s
Поды web взаимодействуют с подом MongoDB через сервис todo-mongodb-replicaset. Веб-приложение доступно через сервис web по NodePort 31201.
Открывая этот порт на любой из рабочих нод, вы получите доступ к веб-приложению.
Вы можете масштабировать веб-приложение, увеличив количество подсетей в ReplicaSet.
kubectl scale rs/web --replicas=10
replicaset "web" scaled
Теперь нужно протестировать доступность приложения.
4: Тестирование высокой доступности MongoDB ReplicaSet
Одним из преимуществ StatefulSet является высокая доступность рабочих нод. Давайте проверим это, удалив один из подов в MongoDB StatefulSet.
kubectl delete pod todo-mongodb-replicaset-2
pod "todo-mongodb-replicaset-2" deleted
Проверьте количество подов:
kubectl get pods
Вы увидите, что todo-mongodb-replicaset-2 прекратил работу:
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 33m
todo-mongodb-replicaset-1 1/1 Running 0 32m
todo-mongodb-replicaset-2 0/1 Terminating 0 31m
web-t5zzk 1/1 Running 0 8m
web-x6dh8 1/1 Running 0 8m
Через пару минут вы увидите, что Kubernetes инициализировал другой под вместо удаленного:
kubectl get pods
Вы увидите, что todo-mongodb-replicaset-2 инициализирован:
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 34m
todo-mongodb-replicaset-1 1/1 Running 0 33m
todo-mongodb-replicaset-2 0/1 Init:0/2 0 29s
web-t5zzk 1/1 Running 0 8m
web-x6dh8 1/1 Running 0 8m
Теперь, когда вы знаете, что все работает, вы можете очистить данные.
Удалите все объекты, созданные во время этого руководства, с помощью следующих команд:
helm delete --purge todo
kubectl delete -f web-rs-ss.yaml -f web-service.yaml
replicaset "web" deleted
service "web" deleted
Чтобы удалить кластер Kubernetes, обратитесь к инструкциям StackPointCloud.
Tags: Helm, Kubernetes, Mac OS, MongoDB