Установка системы в кластер Kubernetes¶
Общая информация¶
Статья предназначена для системных администраторов и DevOps-инженеров, которые хотят развернуть Юниверс DG в заранее созданном кластере Kubernetes. В статье описаны шаги по настройке и развертыванию компонентов системы, включая базу данных PostgreSQL и поисковую систему OpenSearch.
Внимание
Дисклеймер.
Инструкция содержит примерный порядок действий по установке. Инструкция призвана описать логику действий по установке на простом абстрактном примере.
Предварительные требования
Наличие кластера Kubernetes, минимальная конфигурация которого включает в себя одну master-node и две worker-node.
Отдельный сервер (или несколько) для установки PostgreSQL и OpenSearch с предустановленным Docker и Docker Compose.
Учетные данные для доступа к приватному Docker registry для скачивания образов контейнеров.
Системные требования к кластеру и компонентам
Юниверс DG 2.10 или новее;
Helm v3.14.0 или новее;
Kubernetes v1.27 или новее;
Минимальные требования к кластеру, позволяющие запустить пакет-приложение (helm-chart) с настройками по умолчанию;
Три узла Kubernetes с настройками, близкими к настройкам по умолчанию.
4GB RAM для JVM.
Все параметры кластера настраиваются.
Подготовка сервера для PostgreSQL и OpenSearch¶
Создание файла docker-compose.yml¶
Создайте файл docker-compose.yml
на отдельном сервере с указанным ниже содержанием. Этот файл определяет конфигурацию для запуска PostgreSQL и OpenSearch с использованием Docker Compose.
docker-compose
setup_json:
image: docker.universe-data.ru/mirror/chatwork/jq:latest
entrypoint: >
sh -c "
cd /opt/json_configs;
[ ! -z ${OVERRIDE_JSON:-''} ] &&
jq -s '.[0] * .[1]' customer.json ${OVERRIDE_JSON}
> ../customer.json ||
cp customer.json ../customer.json"
volumes:
- ./:/opt
ui:
image: ${FRONTEND_IMAGE}
restart: always
ports:
- ${FRONTEND_PORT}:80
networks:
- dg_network
links:
- dg
volumes:
- ${FRONTEND_UE:-/dev/null}:/usr/share/nginx/html/CUX
- ./customer.json:/usr/share/nginx/html/customer.json
environment:
BACKEND_ADDRESS: ${BACKEND_ADDRESS}
CLIENT_MAX_BODY_SIZE: ${CLIENT_MAX_BODY_SIZE}
PROXY_SEND_TIMEOUT: ${PROXY_SEND_TIMEOUT}
PROXY_READ_TIMEOUT: ${PROXY_READ_TIMEOUT}
SEND_TIMEOUT: ${SEND_TIMEOUT}
TZ: ${TIMEZONE:-UTC}
depends_on:
setup_json:
condition: service_completed_successfully
dg:
image: ${BACKEND_IMAGE}
restart: always
ports:
- ${BACKEND_PORT}:8080
networks:
- dg_network
environment:
GUEST_MODE: ${GUEST_MODE}
POSTGRES_ADDRESS: postgres-dg:5432
POSTGRES_USERNAME: ${DG_POSTGRES_USER}
POSTGRES_PASSWORD: ${DG_POSTGRES_PASSWORD}
DATABASE_NAME: ${DG_POSTGRES_DB_NAME}
SEARCH_CLUSTER_ADDRESS: opensearch-dg:9200
SEARCH_CLUSTER_NAME: docker-cluster
EMAIL_ENABLED: ${RESTORE_EMAIL_ENABLED}
EMAIL_SERVER_HOST: ${RESTORE_EMAIL_SERVER_HOST}
EMAIL_SERVER_PORT: ${RESTORE_EMAIL_SERVER_PORT}
EMAIL_USERNAME: ${RESTORE_EMAIL_USERNAME}
EMAIL_PASSWORD: ${RESTORE_EMAIL_PASSWORD}
EMAIL_FRONTEND_URL: ${RESTORE_EMAIL_FRONTEND_URL}
EMAIL_SSL_ENABLE: ${RESTORE_EMAIL_SSL_ENABLE}
EMAIL_STARTTLS_ENABLE: ${RESTORE_EMAIL_STARTTLS_ENABLE}
TZ: ${TIMEZONE:-UTC}
depends_on:
postgres-dg:
condition: service_healthy
opensearch-dg:
condition: service_healthy
postgres-dg:
image: docker.universe-data.ru/mirror/postgres16.3-tsdb2.15.2
restart: always
environment:
POSTGRES_DB: ${DG_POSTGRES_DB_NAME}
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
DG_POSTGRES_USER: ${DG_POSTGRES_USER}
DG_POSTGRES_PASSWORD: ${DG_POSTGRES_PASSWORD}
TZ: ${TIMEZONE:-UTC}
ports:
- ${POSTGRES_OUTER_PORT}:5432
networks:
- dg_network
volumes:
- ./init-db.sh:/docker-entrypoint-initdb.d/initdb.sh
- dg-postgres-data:/var/lib/postgresql/data
command: postgres -N 350 -c max_prepared_transactions=350 -c shared_preload_libraries='timescaledb'
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d $DG_POSTGRES_DB_NAME"]
interval: 10s
timeout: 1s
retries: 20
opensearch-dg:
image: docker.universe-data.ru/mirror/opensearchproject/opensearch:2.14.0
restart: always
environment:
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.type=single-node"
- "DISABLE_SECURITY_PLUGIN=true"
- "TZ=${TIMEZONE:-UTC}"
volumes:
- dg-opensearch-data:/usr/share/opensearch/data
- ./hunspell:/usr/share/opensearch/config/hunspell/
- ./synonyms.txt:/usr/share/opensearch/config/synonyms.txt
- ./plugins:/usr/share/opensearch/plugins-for-install/
- ./opensearch-install-plugins-and-start.sh:/usr/share/opensearch/opensearch-install-plugins-and-start.sh
entrypoint: /usr/share/opensearch/opensearch-install-plugins-and-start.sh
ulimits:
memlock:
soft: -1
hard: -1
ports:
- ${OPENSEARCH_HTTP_OUTER_PORT}:9200
networks:
- dg_network
healthcheck:
test: >
bash -c "curl http://localhost:9200 | grep '\"cluster_name\"'"
interval: 10s
timeout: 2s
retries: 20
volumes:
dg-postgres-data:
driver: local
dg-opensearch-data:
driver: local
networks:
dg_network:
driver: bridge
Параметры command: postgres -c max_prepared_transactions=1000 -c max_connections=1000
представлены из расчёта 4 реплик backend-приложений (dg-deployment).
Примечание: Перед запуском Docker Compose убедитесь, что все используемые файлы и каталоги (init-db.sh, hunspell, plugins, opensearch-install-plugins-and-start.sh) присутствуют в соответствующих директориях. Это стандартный набор поставки для разворачивания DG через Docker.
Запуск Docker Compose¶
Запустите сервисы, используя следующую команду:
docker-compose up -d
Команда запустит PostgreSQL и OpenSearch в отдельных контейнерах, сеть для их взаимодействия, и настроит необходимые параметры, такие как размеры памяти и переменные окружения.
Проверьте работоспособность сервисов командой:
docker ps
Рисунок 1 – Статус контейнера
Развертывание Юниверс DG в Kubernetes¶
Подготовка конфигурационных файлов для Kubernetes¶
Для развертывания Юниверс DG в вашем кластере Kubernetes необходимо подготовить набор манифестов, описывающих необходимые ресурсы: StatefulSets, ConfigMaps, Services, Secrets, Deployments, а также ресурсы для настройки RBAC (Role-Based Access Control).
Создание ConfigMap и Secret¶
Перед созданием основных компонентов системы, вам необходимо создать ConfigMap и Secret, которые будут содержать конфигурационные параметры и секретные данные соответственно.
Создайте файлы config-map-be.yaml
для определения ConfigMap для BE.
ConfigMap для dg-deployment:
configmap be
apiVersion: v1
kind: ConfigMap
metadata:
name: config-dg-deployment
data:
GUEST_MODE: "false"
POSTGRES_ADDRESS: "192.168.1.109:15431"
POSTGRES_USERNAME: "postgres"
POSTGRES_PASSWORD: "postgres"
DATABASE_NAME: "postgres"
SEARCH_CLUSTER_ADDRESS: "192.168.1.109:19201"
SEARCH_CLUSTER_NAME: "docker-cluster"
EMAIL_ENABLED: "false"
EMAIL_SERVER_HOST: "localhost"
EMAIL_SERVER_PORT: "5025"
EMAIL_USERNAME: "universe@example.com"
EMAIL_PASSWORD: "password"
EMAIL_FRONTEND_URL: "''"
EMAIL_SSL_ENABLE: "true"
EMAIL_STARTTLS_ENABLE: "false"
JAVA_TOOL_OPTIONS: ""
CACHE_AUTO_DETECTION_ENABLED: "true"
CACHE_GROUP: "unidata"
CACHE_PASSWORD: "password"
CACHE_PORT: "5701"
CACHE_PORT_AUTOINCREMENT: "true"
SYSTEM_NODE_ID: ""
CACHE_PUBLIC_ADDRESS: ""
TZ: "MSK"
CACHE_KUBERNETES_ENABLED: "true"
CACHE_KUBERNETES_SERVICE_NAME: "dg-service"
CACHE_TCP_IP_ENABLED: "false"
CACHE_TCP_IP_MEMBERS: ""
CACHE_DIAGNOSTICS_ENABLED: "true"
CACHE_SECURITY_RECOMMENDATIONS: "DEBUG"
CACHE_JET_ENABLED: "true"
CACHE_SOCKET_BIND_ANY: "false"
CACHE_REST_ENABLED: "true"
CACHE_INTEGRITY_CHECKER_ENABLED: "true"
Необходимо указать корректные настройки для подключения к базе PostgreSQL и OpenSearch (указать ip и порт сервера,на которым мы ранее запустили docker-compose с указанными сервисами).
POSTGRES_ADDRESS: "192.168.1.109:15431"
SEARCH_CLUSTER_ADDRESS: "192.168.1.109:19201"
Остальные параметры являются базовыми и их можно не трогать.
Создайте файлы config-map-fe.yaml
для определения ConfigMap для FE.
ConfigMap для ui-deployment:
configmap fe
apiVersion: v1
kind: ConfigMap
metadata:
name: ui-configmap
data:
customer.json: |
"APP_TYPE": "systemAdmin,dataSteward,dataAdmin",
"serverUrl": "/universe-backend/api/",
"BULK_SELECTION_LIMIT": 30,
"CHECK_SOURCESYSTEM_WEIGHT_UNIQUE": false,
"OVERRIDES": [],
"EXTERNAL_MODULES": [],
"WIKI_HOST": null,
"WIKI_ENABLED": true
Создайте файл secret.yaml
для определения Secret, содержащего данные для доступа к Docker registry:
secret
apiVersion: v1
kind: Secret
metadata:
name: my-regcred
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: ewogICAgImF1dGhzIjogewoJImRvY2tlci50ZXN0LnJ1IjogewoJICAgICJhdXRoIjogIlpHOWphMlZ5T21oVmFXODNOalUxUjJKbGRFQlBUM0F3TW0wOVBRPT0iCgl9CiAgICB9Cn0=
Для получения <base64-encoded-json>
, необходимо выполнить команду echo -n '{"auths": {"docker.test.ru": {"username": "docker", "password": "hUio7655Gbet@OOp02m=="}}}' | base64.
Пример:
Адрес Docker registry: docker.test.ru
Пользователь: docker
Пароль:
hUio7655Gbet@OOp02m==
Кодируем связку "docker:hUio7655Gbet@OOp02m=="
в base64, получаем ZG9ja2VyOmhVaW83NjU1R2JldEBPT3AwMm09PQ==
.
Далее кодируем по примеру связку в base64:
{
"auths": {
"docker.test.ru": {
"auth": "ZG9ja2VyOmhVaW83NjU1R2JldEBPT3AwMm09PQ=="
}
}
}
Получаем .dockerconfigjson:
ewogICAgImF1dGhzIjogewoJImRvY2tlci50ZXN0LnJ1IjogewoJICAgICJhdXRoIjogIlpHOWphMlZ5T21oVmFXODNOalUxUjJKbGRFQlBUM0F3TW0wOVBRPT0iCgl9CiAgICB9Cn0=
Развертывание основного приложения и его зависимостей¶
StatefulSet для Юниверс DG: Создайте файл dg-statefulset.yaml
для определения StatefulSet, который будет запускать основные компоненты Юниверс DG.
dg-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dg-deployment
spec:
replicas: 2
selector:
matchLabels:
app: dg
template:
metadata:
labels:
app: dg
spec:
containers:
- name: dg-container
image: docker.test.ru/universe/backend:v2.10.0
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: config-dg-deployment
env:
- name: SYSTEM_NODE_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
requests:
ephemeral-storage: "2Gi"
limits:
ephemeral-storage: "3Gi"
imagePullSecrets:
- name: my-regcred
http://docker.test.ru/universe/backend:v2.10.0 - образ с необходимой версией платформы.
Service для обнаружения подов Hazelcast: Создайте файл dg-service.yaml
для определения Service, который будет использоваться для обнаружения подов Hazelcast в кластере.
dg-service.yaml
apiVersion: v1
kind: Service
metadata:
name: dg-service
spec:
selector:
app: dg
ports:
- protocol: TCP
port: 5701
Service для балансировки трафика на порт 8080 подов dg-deployment:
Создайте файл dg-ui-service.yaml
dg-ui-service.yaml
apiVersion: v1
kind: Service
metadata:
name: dg-ui-service
spec:
selector:
app: dg
ports:
- protocol: TCP
port: 9081
targetPort: 8080
type: LoadBalancer
Deployment для пользовательского интерфейса (UI):
Создайте файл ui-deployment.yaml
для определения Deployment, который будет запускать пользовательский интерфейс Юниверс DG.
ui-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ui-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ui
template:
metadata:
labels:
app: ui
spec:
containers:
- name: ui
image: docker.test.ru/universe/frontend:v2.10.0
ports:
- containerPort: 80
env:
- name: BACKEND_ADDRESS
value: "http://dg-ui-service:9081"
- name: CLIENT_MAX_BODY_SIZE
value: "100m"
- name: PROXY_SEND_TIMEOUT
value: "600s"
- name: PROXY_READ_TIMEOUT
value: "600s"
- name: SEND_TIMEOUT
value: "600s"
- name: TIMEZONE
value: "Europe/Moscow"
volumeMounts:
- name: customer-config
mountPath: /usr/share/nginx/html/customer.json
subPath: customer.json
resources:
requests:
ephemeral-storage: "500Mi"
limits:
ephemeral-storage: "800Mi"
volumes:
- name: customer-config
configMap:
name: ui-configmap
imagePullSecrets:
- name: my-regcred
http://docker.test.ru/universe/frontend:v2.10.0 - образ с необходимой версией платформы.
RBAC для Hazelcast:
Создайте файлы hazelcast-cluster-role.yaml
и hazelcast-cluster-role-binding.yaml
для настройки доступа Hazelcast к ресурсам кластера Kubernetes.
hazelcast-cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: hazelcast-cluster-role
rules:
- apiGroups:
- ""
# Access to apps API is only required to support automatic cluster state management
# when persistence (hot-restart) is enabled.
- apps
resources:
- endpoints
- pods
- nodes
- services
# Access to statefulsets resource is only required to support automatic cluster state management
# when persistence (hot-restart) is enabled.
- statefulsets
verbs:
- get
- list
# Watching resources is only required to support automatic cluster state management
# when persistence (hot-restart) is enabled.
- watch
- apiGroups:- "discovery.k8s.io"resources:
- endpointslices verbs:
- get
- list
hazelcast-cluster-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: hazelcast-cluster-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: hazelcast-cluster-role
subjects:
- kind: ServiceAccount
name: default
namespace: default
Применение конфигурации в Kubernetes¶
После подготовки всех необходимых файлов, примените их в вашем кластере Kubernetes с помощью одной команды "kubectl apply -f . "
находясь в корне с файлами.
При ручном применении или изменении манифеста можно запускать с параметром -f:
kubectl apply -f config-map-be.yaml
kubectl apply -f config-map-fe.yaml
kubectl apply -f secret.yaml
kubectl apply -f dg-statefulset.yaml
kubectl apply -f dg-service.yaml
kubectl apply -f dg-ui-service.yaml
kubectl apply -f ui-deployment.yaml
kubectl apply -f ui-service.yaml
kubectl apply -f hazelcast-cluster-role.yaml
kubectl apply -f hazelcast-cluster-role-binding.yaml
Проверка статуса развертывания¶
После применения всех конфигураций и манифестов важно убедиться, что все компоненты были успешно развернуты и работают корректно. Используйте следующие команды для проверки статуса подов и сервисов:
kubectl get pods
kubectl get services
Команды покажут список всех запущенных подов и сервисов в вашем кластере, а также их текущее состояние. Убедитесь, что все компоненты имеют статус Running и нет ошибок в их логах.
Примечания:
Для доступа к фронтенду используйте адрес, предоставляемый сервисом ui-service(порт nodePort: 30082), и убедитесь, что все компоненты системы функционируют корректно.
В случае возникновения проблем, проверьте логи соответствующих компонентов и конфигурации Kubernetes, чтобы выявить и устранить причину неполадок.
Масштабирование¶
Для масштабирования (scaling) вашего развертывания dg-deployment
в Kubernetes, вы можете изменить количество реплик в StatefulSet
. Масштабирование поможет вам увеличить или уменьшить количество подов в вашем развертывании в зависимости от нагрузки или требований к доступности.
Изменение количества реплик в StatefulSet
Использование kubectl для обновления StatefulSet
Вы можете обновить количество реплик в вашем
StatefulSet
с помощью командыkubectl scale
. Допустим, вы хотите увеличить количество реплик до 3. Для этого используйте следующую команду:
kubectl scale statefulsets dg-deployment --replicas=3
Эта команда изменит количество реплик в StatefulSet на 3. Kubernetes автоматически запустит дополнительные поды, чтобы соответствовать заданному числу реплик.
Редактирование манифеста StatefulSet
Альтернативный способ масштабирования — изменение самого манифеста
StatefulSet
. Для этого откройте ваш манифест в текстовом редакторе и найдите секцию spec.replicas. Измените значение на желаемое количество реплик. Например:
dg-backend-deployment.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dg-deployment
spec:
replicas: 3
selector:
matchLabels:
app: dg
После внесения изменений сохраните файл и примените обновленный манифест в вашем кластере Kubernetes с помощью команды: kubectl apply -f dg-deployment.yaml
.
Проверка масштабирования
После масштабирования вы можете проверить статус StatefulSet
, чтобы убедиться, что количество подов соответствует заданному числу реплик. Используйте команду: kubectl get statefulsets dg-deployment
. Команда отобразит информацию о StatefulSet
, включая количество реплик и текущее состояние подов.
При выполнении команды kubectl get pods
мы увидим статус контейнера:
NAME READY STATUS RESTARTS AGE
dg-deployment-0 1/1 Running 0 20m
dg-deployment-1 1/1 Running 0 20m
dg-deployment-2 1/1 Running 0 1m
ui-deployment-577c48448b-gz77p 1/1 Running 0 20m
Посмотреть логи нового пода "dg-deployment-2"
можно введя команду "kubectl logs -f dg-deployment-2"
.
При выполнении команды, будет видно, что новый под в кластере с остальными:
Members {size:3, ver:3} [
Member [10.233.68.230]:5701 - 7a699622-a7e0-4985-93a9-962e17b02964
Member [10.233.87.94]:5701 - 28ff1db4-6e11-4044-bccd-e5193fafcaf3
Member [10.233.68.231]:5701 - cdc7bed2-0c0c-4413-91bb-408f1e59de16 this
Важные замечания при масштабировании StatefulSet
Состояние подов: Поды в
StatefulSet
управляются индивидуально, и каждый из них имеет свое собственное постоянное хранилище. Убедитесь, что ваша система хранения и приложение корректно обрабатывают масштабирование.Порядок запуска и остановки:
StatefulSet
гарантирует порядок запуска и остановки подов. Поды создаются и удаляются строго в обратном порядке к их порядковым номерам. Учитывайте это поведение при планировании масштабирования.
Масштабирование StatefulSet
— эффективный способ адаптации к изменениям в нагрузке и обеспечения высокой доступности вашего приложения.