Развертывание stateful сервиса в Kubernetes

Kubernetes – открытый инструмент для оркестровки и управления контейнерными приложениями. В предыдущих частях этой серии вы изучили основные компоненты Kubernetes и спаковали контейнеры как наборы реплик Kubernetes. Наборы реплик (ReplicaSet) гарантируют доступность подзаголовков без учета состояния, однако они не могут использоваться в stateful процессах, таких как кластеры базы данных.

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

В этой заключительной части серии вы научитесь развертывать высокодоступный MongoDB ReplicaSet в Kubernetes как StatefulSet с помощью Helm, популярного открытого менеджера пакетов для Kubernetes.

Требования

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: , , ,