Как устроен Deckhouse Commander
Компоненты Deckhouse Commander
У Deckhouse Commander есть внешняя зависимость — база данных PostgreSQL.
Сервер API является центральным компонентом. Данные хранятся в PostgreSQL. Варианты установки Deckhouse Commander с СУБД указаны в разделе «Установка».
Сервер API предоставляет как внешние API — веб-приложения и для внешней интеграции - так и внутренние API для работы с кластерами.
Веб-приложение использует API для управления кластерами и другими сущностями Deckhouse Commander.
Для управления кластерами используются асинхронные операции — задания. Менеджер кластеров — это сервис, который отслеживает задания и выполняет их. Заданиями могут быть установка кластера, удаление кластера или сверка состояния кластера с заданной конфигурацией.
Менеджер кластеров отвечает за запуск установщиков — серверов dhctl. Менеджер кластеров запускает реплику сервера dhctl только нужной версии для каждого кластера Deckhouse Kubernetes Platform (DKP).
В каждом кластере Deckhouse Commander автоматически устанавливает модуль commander-agent
. Этот
модуль отвечает за синхронизацию ресурсов Kubernetes в прикладном кластере, а так же за отправку
телеметрии в сервер API Deckhouse Commander. Телеметрия включает в себя основные метрики (общее
количество ядер, общий объем памяти, количество узлов и общий объем хранилищ), версию DKP, версию
Kubernetes и доступность компонентов DKP.
Требования к сетевой доступности компонентов
Компоненты Deckhouse Commander требуют сетевой доступности с прикладными кластерами. Эта доступность не нужна все время. Однако во время сетевого доступа происходит сравнение целевой и фактической конфигурации кластера, а так же только при сетевом доступе может быть запущено приведение кластера к целевому состоянию. Какой сетевой доступ требуется для полной работоспособности:
-
22/TCP от Deckhouse Commander к прикладному кластеру
- менеджер кластеров (dhctl) подключается по SSH к мастер-узлу для первочной настройки или для уничтожения кластера.
-
443/TCP или 80/TCP от прикладного кластера к Deckhouse Commander
- 443 или 80 или другое значение — зависит от параметров ингресс-контроллера в управляющем
кластере и от параметра
https.mode
в управляющем кластере, который указывается в глобальных настройках или в настройках модуля Deckhouse Commander; - агент собирает конфигурацию, чтобы ее актуализировать, а так же отправляет телеметрию на сервер;
- агент создает TCP-туннель, через который менеджер кластеров контролирует инфраструктурную часть конфигурации.
- 443 или 80 или другое значение — зависит от параметров ингресс-контроллера в управляющем
кластере и от параметра
По умолчанию Deckhouse Commander настраивает commander-agent на использование HTTPS. Чтобы изменить протокол на HTTP, нужно явно задать конфигурацию модуля commander-agent в шаблоне кластера:
1apiVersion: deckhouse.io/v1alpha1
2kind: ModuleConfig
3metadata:
4 name: commander-agent
5spec:
6 enabled: true
7 version: 1
8 settings:
9 # http задан явно ↓
10 commanderUrl: "http://{{ .dc_domain }}/agent_api/{{ .dc_clusterUUID }}"
Шифрование данных
Deckhouse Commander шифрует чувствительные данные в базе данных. Для шифрования используются ключи из
секрета commander-envs
, которые генерируются автоматически при включении модуля.
Внимание: Крайне важно сохранить ключи в надежное место, чтобы иметь возможность восстановить базу данных в случае каких-либо проблем. При отсутствии ключей восстановить данные будет невозможно!
1$ kubectl -n d8-commander get secret commander-envs -oyaml
2apiVersion: v1
3data:
4 ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: YVBBNVh5QUxoZjc1Tk5uTXphc3BXN2FrVGZacDBsUFk=
5 ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: eEVZMGR0NlRaY0FNZzUySzdPODR3WXpranZiQTYySHo=
6 ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: RUdZOFdodWxVT1hpeHlib2Q3Wld3TUlMNjhSOW81a0M=
7kind: Secret
8metadata:
9...
10 name: commander-envs
11 namespace: d8-commander
12type: Opaque
Сбор логов истории изменений
В Deckhouse Commander, начиная с версии 1.9, события из «Истории изменений» направляются в стандартный вывод и помечаются тегом [audit]
. Сбор и отправку таких логов можно настроить при помощи модуля log-shipper
Пример логов:
12024-12-18 17:27:17.503 [2024-12-18 17:27:17.466636971] [1ee79b305b5fdbd577231ad6dd8f2951] [12] [audit] {"auditable_type":"ClusterSettings","auditable_id":"7f0e29e8-f427-4c5f-9ecf-de457b2d427f","action":"create","user_type":"User","remote_address":null,"request_uuid":"05a02066-a8e9-4e23-a79f-5e5a32533e61","workspace_slug":"wfqmr","user_name":"admin@deckhouse.io"}
22024-12-18 17:27:17.503 [2024-12-18 17:27:17.471032472] [1ee79b305b5fdbd577231ad6dd8f2951] [12] [audit] {"auditable_type":"Cluster","auditable_id":"b8004e7e-cc57-499c-a1e8-38cc5ba78220","action":"create","user_type":"User","remote_address":null,"request_uuid":"92f4bef8-a9a4-466b-9644-6bdf1775f24c","workspace_slug":"wfqmr","user_name":"admin@deckhouse.io"}
32024-12-18 17:28:29.121 [2024-12-18 17:28:29.115108882] [8ebaca9149c21f8949a877b27bb363f8] [12] [audit] {"auditable_type":"Record","auditable_id":"477b5718-b18b-4468-b95b-700b3068ad91","action":"create","user_type":"User","remote_address":null,"request_uuid":"7b590af2-acfb-4708-a66f-09e42c1f4b7c","workspace_slug":"wfqmr","user_name":"admin@deckhouse.io"}
42024-12-18 17:28:29.148 [2024-12-18 17:28:29.146244011] [612d6c1911933035ff3a4800a9faa6cf] [12] [audit] {"auditable_type":"Record","auditable_id":"9a5ad514-c7cf-41e1-ad12-edadb6fd521c","action":"create","user_type":"User","remote_address":null,"request_uuid":"e462f9da-e879-4795-9506-2dbb747fed08","workspace_slug":"wfqmr","user_name":"admin@deckhouse.io"}
52024-12-18 17:57:12.360 [2024-12-18 17:57:12.358538533] [6472d45c-bdd7-4c08-8159-4c90939ed47c] [12] [audit] {"auditable_type":"Cluster","auditable_id":"b8004e7e-cc57-499c-a1e8-38cc5ba78220","action":"update","user_type":null,"remote_address":null,"request_uuid":"cfe477a3-3a30-49fe-9a59-55f7030b890d","workspace_slug":"wfqmr","user_name":null}
Пример конфигурации:
1apiVersion: deckhouse.io/v1alpha1
2kind: ClusterLoggingConfig
3metadata:
4 name: commander-audit-logs
5spec:
6 destinationRefs:
7 - loki-example
8 kubernetesPods:
9 labelSelector:
10 matchLabels:
11 app: backend
12 namespaceSelector:
13 matchNames:
14 - d8-commander
15 labelFilter:
16 - field: message
17 operator: Regex
18 values:
19 - .*\audit\.*
20 type: KubernetesPods
21---
22apiVersion: deckhouse.io/v1alpha1
23kind: ClusterLogDestination
24metadata:
25 name: loki-example
26spec:
27 type: Loki
28 loki:
29 endpoint: http://loki-example.loki.svc:3100
Более подробную информацию по настройке смотрите в документации модуля log-shipper.
Изменение класса хранилища для БД (StorageClass)
Эта инструкция нужна только в том случае, если для СУБД используется модуль operator-postgres
. На
это указывает режим подключения к БД Internal
в ModuleConfig/commander
1apiVersion: deckhouse.io/v1alpha1
2kind: ModuleConfig
3metadata:
4 name: commander
5spec:
6 enabled: true
7 version: 1
8 settings:
9 postgres:
10 mode: Internal
11 ...
Вариант 1 (предпочтительный)
-
Выполняем резервное копирование экземпляра БД
1kubectl -n d8-commander exec -t commander-postgres-0 -- su - postgres -c "pg_dump -Fc -b -v -d commander" > commander.dump
-
Изменяем storageClass в настройках модуля, заменив
<NEW_STORAGECLASS_NAME>
на название необходимого класса храненияСписок доступных классов хранения можно узнать при помощи команды
kubectl get storageclasses
1kubectl patch moduleconfig commander --type=merge -p '{"spec":{"settings":{"postgres":{"internal":{"storageClass":"<NEW_STORAGECLASS_NAME>"}}}}}' 2 3moduleconfig.deckhouse.io/commander patched
Дожидаемся, пока очередь deckhouse окажется пустой
1kubectl -n d8-system exec svc/deckhouse-leader -c deckhouse -- deckhouse-controller queue main 2 3Queue 'main': length 0, status: 'waiting for task 5s'
Проверяем логи оператора postgres на отсутствие ошибок
1kubectl -n d8-operator-postgres logs deployments/operator-postgres 2 3{"cluster-name":"d8-commander/commander-postgres","level":"info","msg":"cluster has been updated","pkg":"controller","time":"2024-05-19T20:36:22Z","worker":0}
-
Увеличиваем количество реплик БД PostgreSQL (опционально)
Этот шаг необходимо пропустить, если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики
1kubectl -n d8-commander patch postgresqls.acid.zalan.do commander-postgres --type=merge -p '{"spec":{"numberOfInstances":2}}' 2 3postgresql.acid.zalan.do/commander-postgres patched
Проверяем логи оператора и экземпляра postgres
1kubectl -n d8-operator-postgres logs deployments/operator-postgres 2 3{"cluster-name":"d8-commander/commander-postgres","level":"info","msg":"cluster has been updated","pkg":"controller","time":"2024-05-19T20:36:22Z","worker":0}
1kubectl -n d8-commander logs commander-postgres-1 2 32024-05-19 20:38:15,648 INFO: no action. I am (commander-postgres-1), a secondary, and following a leader (commander-postgres-0)
-
Выполняем переключение мастера
1kubectl -n d8-commander exec -it commander-postgres-0 -- patronictl failover 2 3Current cluster topology 4+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 5| Member | Host | Role | State | TL | Lag in MB | 6+----------------------+--------------+---------+---------+----+-----------+ 7| commander-postgres-0 | 10.111.3.167 | Leader | running | 5 | | 8| commander-postgres-1 | 10.111.2.239 | Replica | running | 5 | 0 | 9+----------------------+--------------+---------+---------+----+-----------+ 10Candidate ['commander-postgres-1'] []: commander-postgres-1 11Are you sure you want to failover cluster commander-postgres, demoting current leader commander-postgres-0? [y/N]: y 122024-05-19 20:40:52.63041 Successfully failed over to "commander-postgres-1" 13+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 14| Member | Host | Role | State | TL | Lag in MB | 15+----------------------+--------------+---------+---------+----+-----------+ 16| commander-postgres-0 | 10.111.3.167 | Replica | stopped | | unknown | 17| commander-postgres-1 | 10.111.2.239 | Leader | running | 5 | | 18+----------------------+--------------+---------+---------+----+-----------+
Убеждаемся, что оба экземпляра БД находятся в состоянии
running
1kubectl -n d8-commander exec -t commander-postgres-0 -- patronictl list 2+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 3| Member | Host | Role | State | TL | Lag in MB | 4+----------------------+--------------+---------+---------+----+-----------+ 5| commander-postgres-0 | 10.111.3.167 | Replica | running | 6 | 0 | 6| commander-postgres-1 | 10.111.2.239 | Leader | running | 6 | | 7+----------------------+--------------+---------+---------+----+-----------+
Проверяем, что диск новой реплики БД создался с необходимым
storageClass
1kubectl -n d8-commander get pvc --selector application=spilo 2NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE 3pgdata-commander-postgres-0 Bound pvc-fd80fde4-d0e2-4b5f-9e3a-eac998191f11 2Gi RWO network-hdd 36h 4pgdata-commander-postgres-1 Bound pvc-7af2f442-3097-4fe3-a795-5ad18bb11351 2Gi RWO network-ssd 2m54s
-
Удаляем диск и под первого экземпляра
1kubectl -n d8-commander delete pvc pgdata-commander-postgres-0 --wait=false 2kubectl -n d8-commander delete po commander-postgres-0
Проверяем логи
1kubectl -n d8-commander logs commander-postgres-0 2 32024-05-19 20:43:33,293 INFO: Lock owner: commander-postgres-1; I am commander-postgres-0 42024-05-19 20:43:33,293 INFO: establishing a new patroni connection to the postgres cluster 52024-05-19 20:43:33,357 INFO: no action. I am (commander-postgres-0), a secondary, and following a leader (commander-postgres-1)
Проверяем, что диск создался с правильным
storageClass
1kubectl -n d8-commander get pvc 2NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE 3pgdata-commander-postgres-0 Bound pvc-fd80fde4-d0e2-4b5f-9e3a-eac998191f11 2Gi RWO network-ssd 2m6s 4pgdata-commander-postgres-1 Bound pvc-7af2f442-3097-4fe3-a795-5ad18bb11351 2Gi RWO network-ssd 7m11s
-
Выполняем обратное переключение мастера
1kubectl -n d8-commander exec -it commander-postgres-0 -- patronictl failover 2 3Current cluster topology 4+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 5| Member | Host | Role | State | TL | Lag in MB | 6+----------------------+--------------+---------+---------+----+-----------+ 7| commander-postgres-0 | 10.111.3.189 | Replica | running | 6 | 0 | 8| commander-postgres-1 | 10.111.2.239 | Leader | running | 6 | | 9+----------------------+--------------+---------+---------+----+-----------+ 10Candidate ['commander-postgres-0'] []: commander-postgres-0 11Are you sure you want to failover cluster commander-postgres, demoting current leader commander-postgres-1? [y/N]: y 122024-05-19 20:46:11.69855 Successfully failed over to "commander-postgres-0" 13+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 14| Member | Host | Role | State | TL | Lag in MB | 15+----------------------+--------------+---------+---------+----+-----------+ 16| commander-postgres-0 | 10.111.3.189 | Leader | running | 6 | | 17| commander-postgres-1 | 10.111.2.239 | Replica | stopped | | unknown | 18+----------------------+--------------+---------+---------+----+-----------+
Убеждаемся, что оба экземпляра БД находятся в состоянии
running
1kubectl -n d8-commander exec -t commander-postgres-0 -- patronictl list 2+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 3| Member | Host | Role | State | TL | Lag in MB | 4+----------------------+--------------+---------+---------+----+-----------+ 5| commander-postgres-0 | 10.111.3.189 | Leader | running | 6 | 0 | 6| commander-postgres-1 | 10.111.2.239 | Replica | running | 6 | | 7+----------------------+--------------+---------+---------+----+-----------+
-
Уменьшаем количество реплик БД PostgreSQL (опционально)
Этот шаг необходимо пропустить, если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики
1kubectl -n d8-commander patch postgresqls.acid.zalan.do commander-postgres --type=merge -p '{"spec":{"numberOfInstances":1}}' 2 3postgresql.acid.zalan.do/commander-postgres patched
Проверяем логи оператора
1kubectl -n d8-operator-postgres logs deployments/operator-postgres 2 3{"cluster-name":"d8-commander/commander-postgres","level":"info","msg":"cluster has been updated","pkg":"controller","time":"2024-05-19T20:50:22Z","worker":0}
-
Удаляем диски
-
Удаляем диск и под первого экземпляра (если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики)
Этот шаг необходимо пропустить, если в кластере не используется режим HighAvailability
1kubectl -n d8-commander delete pvc pgdata-commander-postgres-1 --wait=false 2kubectl -n d8-commander delete po commander-postgres-1
Проверяем логи
1kubectl -n d8-commander logs commander-postgres-1 2 32024-05-19 20:53:33,293 INFO: Lock owner: commander-postgres-0; I am commander-postgres-1 42024-05-19 20:53:33,293 INFO: establishing a new patroni connection to the postgres cluster 52024-05-19 20:53:33,357 INFO: no action. I am (commander-postgres-1), a secondary, and following a leader (commander-postgres-0)
Проверяем, что диск создался с правильным
storageClass
1kubectl -n d8-commander get pvc 2NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE 3pgdata-commander-postgres-0 Bound pvc-fd80fde4-d0e2-4b5f-9e3a-eac998191f11 2Gi RWO network-ssd 7m6s 4pgdata-commander-postgres-1 Bound pvc-7af2f442-3097-4fe3-a795-5ad18bb11351 2Gi RWO network-ssd 1m11s
Убеждаемся, что оба экземпляра БД находятся в состоянии
running
1kubectl -n d8-commander exec -t commander-postgres-0 -- patronictl list 2+ Cluster: commander-postgres --------+---------+---------+----+-----------+ 3| Member | Host | Role | State | TL | Lag in MB | 4+----------------------+--------------+---------+---------+----+-----------+ 5| commander-postgres-0 | 10.111.3.189 | Leader | running | 6 | 0 | 6| commander-postgres-1 | 10.111.2.239 | Replica | running | 6 | | 7+----------------------+--------------+---------+---------+----+-----------+
-
Удаляем неиспользуемый диск, оставшийся от временной реплики БД (если режим HighAvailability не используется)
Этот шаг необходимо пропустить, если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики
1kubectl -n d8-commander delete pvc pgdata-commander-postgres-1 2 3persistentvolumeclaim "pgdata-commander-postgres-1" deleted
Вариант 2
-
Выполняем резервное копирование экземпляра БД
1kubectl -n d8-commander exec -t commander-postgres-0 -- su - postgres -c "pg_dump -Fc -b -v -d commander" > commander.dump
-
Выключаем модуль
commander
1kubectl patch moduleconfig commander --type=merge -p '{"spec":{"enabled":false}}' 2 3moduleconfig.deckhouse.io/commander patched
Дожидаемся, пока очередь deckhouse окажется пустой
1kubectl -n d8-system exec svc/deckhouse-leader -c deckhouse -- deckhouse-controller queue main 2 3Queue 'main': length 0, status: 'waiting for task 5s'
Проверяем, что неймспейс
d8-commander
удален1kubectl get namespace d8-commander 2Error from server (NotFound): namespaces "d8-commander" not found
-
Указываем необходимый класс хранилища и включаем модуль
commander
1 kubectl patch moduleconfig commander --type=merge -p '{"spec":{"enabled":true,"settings":{"postgres":{"internal":{"storageClass":"<NEW_STORAGECLASS_NAME>"}}}}}' 2 3 moduleconfig.deckhouse.io/commander patched
Дожидаемся, пока очередь deckhouse окажется пустой
1kubectl -n d8-system exec svc/deckhouse-leader -c deckhouse -- deckhouse-controller queue main 2 3Queue 'main': length 0, status: 'waiting for task 5s'
Проверяем, что экземпляр БД в статусе
Running
1kubectl -n d8-commander get po commander-postgres-0 2 3NAME READY STATUS RESTARTS AGE 4commander-postgres-0 1/1 Running 0 2m4s
-
Восстанавливаем ранее сохраненную резервную копию БД
1kubectl -n d8-commander exec -it commander-postgres-0 -- su - postgres -c "pg_restore -v -c --if-exists -Fc -d commander" < commander.dump