feat(aero): PostgreSQL с четырьмя базами и ускоренный цикл реконсиляции
PostgreSQL разворачивается пустым инстансом, состав баз повторяет то, что
сейчас провижинит postgres-init в compose:
sarex_db -> django (ltree)
workflow_db -> processing (uuid-ossp, ltree, hstore)
bim_db -> bim
workspace_db -> workspace
Пароли администратора и владельцев берутся из Vault через
vault-agent-injector, в репозитории их нет. Расширения создаёт бутстрап
заранее: роли не суперпользователи и CREATE EXTENSION в миграциях им
недоступен. timescaledb включён в shared_preload_libraries сразу, хотя этим
базам не нужен, — параметр читается только при старте, и добавить его позже
означает перезапуск СУБД.
nodeSelector снимается postRenderers'ом. Чарт по умолчанию ставит
dedicated: sts в расчёте на выделенный пул нод; в контуре таких нет, и под
навсегда повисал в Pending, а следом застревал PVC, потому что у local-path
режим WaitForFirstConsumer. Через values это недостижимо: Helm сливает карты
по ключам, поэтому ни {}, ни другая метка dedicated: sts не убирают.
Цикл реконсиляции сокращён с 10 до 2 минут у всех Kustomization и
HelmRelease контура. Корневая Kustomization патчится из clusters/aero:
её файл генерирует flux bootstrap с пометкой DO NOT EDIT, а флаг --interval
задаёт периодичность только GitRepository. Таймаут установки postgresql
снижен с 20 до 10 минут — он определяет цену одной неудачной итерации.
Отключение собственных Gateway/VirtualService/Certificate чарта rabbitmq
переведено с JSON6902 на postRenderers: kustomize нормализует null в {}, а
пустую карту Helm сливает с дефолтами, поэтому настоящий null до Helm не
доходит ни одним путём.
This commit is contained in:
parent
565faa0e17
commit
8e14cd1e0b
@ -80,6 +80,7 @@ registry_secrets:
|
||||
# Образы vault-k8s и vault-agent для injector'а тоже лежат в cr.yandex.
|
||||
- {name: regcred, namespace: vault}
|
||||
- {name: regcred, namespace: local-path-provisioner}
|
||||
- {name: regcred, namespace: postgresql}
|
||||
- {name: regcred, namespace: rabbitmq}
|
||||
- {name: regcred, namespace: minio}
|
||||
|
||||
@ -121,6 +122,7 @@ gitea_sync_paths:
|
||||
- infrastructure/istio-pilot
|
||||
- infrastructure/vault-injector
|
||||
- infrastructure/local-path-provisioner
|
||||
- infrastructure/postgresql
|
||||
- infrastructure/rabbitmq
|
||||
- infrastructure/minio
|
||||
|
||||
@ -202,6 +204,7 @@ vault_role_ttl: 24h
|
||||
# vault.hashicorp.com/role, namespace — где живут его поды. Пополняется по мере
|
||||
# переезда приложений из compose в k3s.
|
||||
vault_k8s_roles:
|
||||
- {name: postgresql, namespaces: [postgresql]}
|
||||
- {name: rabbitmq, namespaces: [rabbitmq]}
|
||||
- {name: minio, namespaces: [minio]}
|
||||
- {name: django, namespaces: [django]}
|
||||
@ -214,6 +217,20 @@ vault_k8s_roles:
|
||||
# Пароли не хранятся в репозитории: берутся из sarex_secrets, который
|
||||
# генерирует и персистит в aero/.secrets задача "Сгенерировать/загрузить пароли".
|
||||
vault_app_secrets:
|
||||
# Пароль администратора PostgreSQL. Имя ключа задано чартом
|
||||
# (contour.vault.secretKey) — менять в отрыве от values нельзя.
|
||||
- path: secrets/postgresql/admin
|
||||
data:
|
||||
postgres-password: "{{ sarex_secrets.SAREX_POSTGRES_PASSWORD }}"
|
||||
# Пароли владельцев баз. Ключи сопоставляются с passwordKey каждой базы в
|
||||
# contour.databases (см. infrastructure/postgresql/aero). Добавляешь базу —
|
||||
# добавь сюда ключ, иначе бутстрап не сможет задать роли пароль.
|
||||
- path: secrets/postgresql/users
|
||||
data:
|
||||
django: "{{ sarex_secrets.SAREX_DJANGO_DB_PASSWORD }}"
|
||||
processing: "{{ sarex_secrets.SAREX_PROCESSING_DB_PASSWORD }}"
|
||||
bim: "{{ sarex_secrets.SAREX_BIM_DB_PASSWORD }}"
|
||||
workspace: "{{ sarex_secrets.SAREX_WORKSPACE_DB_PASSWORD }}"
|
||||
- path: secrets/rabbitmq/auth
|
||||
data:
|
||||
username: "{{ sarex_rabbitmq_k8s_user }}"
|
||||
|
||||
@ -12,7 +12,7 @@ metadata:
|
||||
name: apps
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
interval: 2m0s
|
||||
path: ./clusters/aero/apps
|
||||
prune: true
|
||||
wait: true
|
||||
|
||||
@ -22,7 +22,10 @@ resources:
|
||||
- ../../../infrastructure/dashboard/aero
|
||||
# Только Vault Agent Injector: сам Vault живёт в compose, а не в кластере.
|
||||
- ../../../infrastructure/vault-injector/aero
|
||||
# Брокер и объектное хранилище. Креды берут из Vault через injector, поэтому
|
||||
# идут после него. Админки выставлены наружу через istio-config/aero.
|
||||
# СУБД, брокер и объектное хранилище. Креды берут из Vault через injector,
|
||||
# поэтому идут после него. Админки rabbitmq и minio выставлены наружу через
|
||||
# istio-config/aero; postgresql наружу не публикуется — доступ только изнутри
|
||||
# кластера.
|
||||
- ../../../infrastructure/postgresql/aero
|
||||
- ../../../infrastructure/rabbitmq/aero
|
||||
- ../../../infrastructure/minio/aero
|
||||
|
||||
@ -37,7 +37,11 @@ metadata:
|
||||
name: infra-controllers
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
# 2 минуты, а не дефолтные 10: интервал определяет, как быстро слой заметит
|
||||
# новую ревизию и как быстро повторит попытку после неудачи. С 10 минутами
|
||||
# цикл «правка → проверка» растягивался до получаса, а сломанный релиз
|
||||
# держал слой всё это время.
|
||||
interval: 2m0s
|
||||
path: ./clusters/aero/controllers
|
||||
prune: true
|
||||
wait: true
|
||||
@ -52,7 +56,7 @@ metadata:
|
||||
name: infra-configs
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m0s
|
||||
interval: 2m0s
|
||||
path: ./clusters/aero/configs
|
||||
prune: true
|
||||
# dependsOn намеренно отсутствует — см. комментарий в начале файла.
|
||||
|
||||
@ -7,3 +7,26 @@ resources:
|
||||
- ./infrastructure.yaml
|
||||
# Слой приложений. Пока пуст — сюда приедут сервисы при переносе из compose.
|
||||
- ./apps.yaml
|
||||
|
||||
# Корневая Kustomization применяет этот же каталог, поэтому здесь она правит
|
||||
# сама себя — и это единственный способ задать ей интервал.
|
||||
#
|
||||
# Файл flux-system/gotk-sync.yaml генерирует `flux bootstrap` и помечает
|
||||
# "DO NOT EDIT": правка руками затрётся на следующем прогоне. Флаг
|
||||
# --interval=2m у bootstrap (см. docker-compose.yaml) тоже не помогает — он
|
||||
# задаёт периодичность только GitRepository, а Kustomization оставляет
|
||||
# дефолтные 10 минут. Патч же применяется поверх сгенерированного файла и
|
||||
# переживает регенерацию.
|
||||
#
|
||||
# Без этого определения самих слоёв (infrastructure.yaml, apps.yaml)
|
||||
# доезжали бы до кластера с задержкой до 10 минут, даже когда все нижние
|
||||
# слои уже проверяются раз в 2 минуты.
|
||||
patches:
|
||||
- target:
|
||||
kind: Kustomization
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
patch: |
|
||||
- op: replace
|
||||
path: /spec/interval
|
||||
value: 2m0s
|
||||
|
||||
@ -379,6 +379,13 @@ services:
|
||||
|
||||
# Адрес источника — имя Service'а моста (flux-k8s-init), а не IP: так
|
||||
# адрес gitea задан ровно в одном месте — переменной GITEA_BRIDGE_IP.
|
||||
#
|
||||
# --interval=2m задаёт периодичность проверок у GitRepository и корневой
|
||||
# Kustomization в clusters/aero/flux-system/gotk-sync.yaml. Задаётся
|
||||
# именно флагом, потому что этот файл генерирует сам bootstrap и правка
|
||||
# руками затирается при следующем прогоне (в нём так и написано:
|
||||
# "DO NOT EDIT"). Дефолтные 10 минут растягивали цикл «правка → проверка»
|
||||
# до получаса.
|
||||
flux bootstrap git \
|
||||
--url="http://gitea.flux-system.svc.cluster.local:3000/$$GITEA_ORG/$$GITEA_REPO.git" \
|
||||
--branch="$$AERO_GIT_BRANCH" \
|
||||
@ -386,7 +393,8 @@ services:
|
||||
--username="$$GITEA_ADMIN_USER" \
|
||||
--password="$$GITEA_ADMIN_PASSWORD" \
|
||||
--token-auth \
|
||||
--allow-insecure-http
|
||||
--allow-insecure-http \
|
||||
--interval=2m
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Инфраструктурные зависимости apps/django (sarex-backend).
|
||||
|
||||
@ -4,7 +4,7 @@ metadata:
|
||||
name: dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
spec:
|
||||
interval: 5m
|
||||
interval: 2m
|
||||
timeout: 10m
|
||||
values:
|
||||
# Kong слушает 8000 открытым HTTP и ничего не знает про istio. Без этого
|
||||
|
||||
@ -4,7 +4,7 @@ metadata:
|
||||
name: istio-config
|
||||
namespace: default
|
||||
spec:
|
||||
interval: 5m
|
||||
interval: 2m
|
||||
timeout: 10m
|
||||
# disableWait РАЗРЫВАЕТ ДЕДЛОК, не украшательство.
|
||||
#
|
||||
|
||||
@ -4,7 +4,7 @@ metadata:
|
||||
name: local-path-provisioner
|
||||
namespace: local-path-provisioner
|
||||
spec:
|
||||
interval: 5m
|
||||
interval: 2m
|
||||
timeout: 10m
|
||||
values:
|
||||
replicaCount: 1
|
||||
|
||||
@ -4,7 +4,7 @@ metadata:
|
||||
name: minio
|
||||
namespace: minio
|
||||
spec:
|
||||
interval: 5m
|
||||
interval: 2m
|
||||
timeout: 10m
|
||||
values:
|
||||
nameOverride: "minio"
|
||||
|
||||
10
infrastructure/postgresql/aero/kustomization.yaml
Normal file
10
infrastructure/postgresql/aero/kustomization.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../base
|
||||
patches:
|
||||
- path: postgresql.yaml
|
||||
target:
|
||||
kind: HelmRelease
|
||||
name: postgresql
|
||||
176
infrastructure/postgresql/aero/postgresql.yaml
Normal file
176
infrastructure/postgresql/aero/postgresql.yaml
Normal file
@ -0,0 +1,176 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: postgresql
|
||||
namespace: postgresql
|
||||
spec:
|
||||
interval: 2m
|
||||
# Разворачиваем пустой инстанс: базы создаются с нуля, дампы не
|
||||
# восстанавливаются. Поэтому таймауты обычные, а не двухчасовые как в
|
||||
# yc-k8s-test — там они заданы под restoreFromDump.
|
||||
#
|
||||
# 10 минут, а не 20: таймаут — это ещё и цена одной неудачной итерации.
|
||||
# Пока стояло 20, цикл «install → таймаут → откат → install» занимал по
|
||||
# 20 минут на круг, и правка, приехавшая в середине круга, подхватывалась
|
||||
# только на следующем. Здоровый инстанс поднимается примерно за две минуты,
|
||||
# так что 10 — с большим запасом.
|
||||
timeout: 10m
|
||||
install:
|
||||
timeout: 10m
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
timeout: 10m
|
||||
remediation:
|
||||
retries: 3
|
||||
# Снимаем nodeSelector, который чарт ставит по умолчанию.
|
||||
#
|
||||
# В дефолтах чарта (primary.nodeSelector) прописано dedicated: sts — расчёт на
|
||||
# кластер с выделенным пулом нод под StatefulSet'ы. В контуре aero таких нод
|
||||
# нет, все три равнозначны, и под навсегда повисал в Pending:
|
||||
# 0/3 nodes are available: 3 node(s) didn't match Pod's node affinity/selector
|
||||
# а следом застревал PVC, потому что у local-path режим WaitForFirstConsumer
|
||||
# и том создаётся только после планирования пода.
|
||||
#
|
||||
# Через values это не снять: Helm сливает карты по ключам, поэтому и {}, и
|
||||
# любая другая метка оставят dedicated: sts на месте. В yc-k8s-test дефолт не
|
||||
# убирают, а перекрывают на dedicated: db — там выделенные ноды есть.
|
||||
# Тут остаётся убрать ключ из уже отрендеренного манифеста.
|
||||
#
|
||||
# Tolerations чарта не трогаем: они разрешают taint dedicated=sts, которого на
|
||||
# наших нодах нет, и ни на что не влияют.
|
||||
postRenderers:
|
||||
- kustomize:
|
||||
patches:
|
||||
- target:
|
||||
kind: StatefulSet
|
||||
name: postgresql
|
||||
patch: |
|
||||
- op: remove
|
||||
path: /spec/template/spec/nodeSelector
|
||||
values:
|
||||
global:
|
||||
security:
|
||||
allowInsecureImages: true
|
||||
defaultStorageClass: local-path
|
||||
imagePullSecrets:
|
||||
- regcred
|
||||
postgresql:
|
||||
auth:
|
||||
# Пусто осознанно: пользователя и базу заводит не чарт-бутстрап
|
||||
# bitnami, а contour-логика ниже (contour.databases). Оставь здесь
|
||||
# значения — получишь лишнюю базу-пустышку.
|
||||
username: ""
|
||||
database: ""
|
||||
secretKeys:
|
||||
userPasswordKey: "postgres-password"
|
||||
auth:
|
||||
username: ""
|
||||
database: ""
|
||||
secretKeys:
|
||||
userPasswordKey: "postgres-password"
|
||||
image:
|
||||
registry: cr.yandex/crp3ccidau046kdj8g9q
|
||||
repository: contour/postgresql
|
||||
tag: 17.0.7
|
||||
pullPolicy: IfNotPresent
|
||||
metrics:
|
||||
enabled: false
|
||||
prometheusRule:
|
||||
enabled: false
|
||||
primary:
|
||||
# Токен ServiceAccount нужен vault-agent'у для логина в Vault.
|
||||
automountServiceAccountToken: true
|
||||
containerSecurityContext:
|
||||
readOnlyRootFilesystem: false
|
||||
persistence:
|
||||
storageClass: local-path
|
||||
size: 20Gi
|
||||
# В yc-k8s-test здесь nodeSelector/tolerations dedicated=db. В контуре
|
||||
# aero выделенных под БД нод нет — все три равнозначны, ограничивать
|
||||
# планировщик нечем и незачем.
|
||||
customLivenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- exec pg_isready -U "postgres" -d postgres -h 127.0.0.1 -p 5432
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
customReadinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- exec pg_isready -U "postgres" -d postgres -h 127.0.0.1 -p 5432
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
customStartupProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- exec pg_isready -U "postgres" -d postgres -h 127.0.0.1 -p 5432
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 6
|
||||
# contour-логика: создаёт роли, базы и расширения по списку ниже, пароли
|
||||
# берёт из Vault через vault-agent-injector.
|
||||
contour:
|
||||
enabled: true
|
||||
adminUser: "postgres"
|
||||
vault:
|
||||
enabled: true
|
||||
role: postgresql
|
||||
authPath: auth/kubernetes
|
||||
# Пароль администратора.
|
||||
secretPath: secrets/data/postgresql/admin
|
||||
secretKey: postgres-password
|
||||
# Пароли пользователей баз: ключи внутри секрета сопоставляются с
|
||||
# passwordKey каждой базы. Чарт требует этот путь при vault.enabled.
|
||||
# Секрет кладёт ansible (роль sarex_stack, vault_app_secrets).
|
||||
usersSecretPath: secrets/data/postgresql/users
|
||||
# timescaledb включён заранее, хотя нашим четырём базам он не нужен:
|
||||
# shared_preload_libraries читается только при старте, и добавить его
|
||||
# позже — значит перезапустить СУБД. Сервисы, которым он понадобится
|
||||
# (issues, subscriptions, system-log), уже есть в списке на перенос.
|
||||
sharedPreloadLibraries: "timescaledb,pg_stat_statements"
|
||||
# Набор баз повторяет то, что сейчас провижинит postgres-init в
|
||||
# docker-compose.yaml, — контур переезжает в k3s тем же составом.
|
||||
# passwordKey должен совпадать с ключом в секрете Vault
|
||||
# secrets/postgresql/users.
|
||||
databases:
|
||||
- name: sarex_db
|
||||
user: django
|
||||
passwordKey: django
|
||||
extensions:
|
||||
- ltree
|
||||
restoreFromDump: false
|
||||
- name: workflow_db
|
||||
user: processing
|
||||
passwordKey: processing
|
||||
# Роль processing не суперпользователь, а её миграции делают
|
||||
# CREATE EXTENSION — поэтому расширения создаёт бутстрап заранее.
|
||||
extensions:
|
||||
- uuid-ossp
|
||||
- ltree
|
||||
- hstore
|
||||
restoreFromDump: false
|
||||
- name: bim_db
|
||||
user: bim
|
||||
passwordKey: bim
|
||||
extensions: []
|
||||
restoreFromDump: false
|
||||
- name: workspace_db
|
||||
user: workspace
|
||||
passwordKey: workspace
|
||||
extensions: []
|
||||
restoreFromDump: false
|
||||
@ -4,7 +4,7 @@ metadata:
|
||||
name: rabbitmq
|
||||
namespace: rabbitmq
|
||||
spec:
|
||||
interval: 5m
|
||||
interval: 2m
|
||||
timeout: 10m
|
||||
# Вырезаем ресурсы ПОСЛЕ рендера чарта. Через values это недостижимо:
|
||||
# * `null` до Helm не доезжает — kustomize нормализует его в {};
|
||||
@ -55,24 +55,16 @@ spec:
|
||||
global:
|
||||
security:
|
||||
allowInsecureImages: true
|
||||
# Собственные VirtualService/Gateway/Certificate чарта отключаются НЕ здесь,
|
||||
# а JSON6902-патчем в kustomization.yaml рядом. Причина — в противоположной
|
||||
# семантике null у двух инструментов:
|
||||
# Здесь НЕТ ключей virtualService/gateway/certificate, и это намеренно:
|
||||
# через values дефолты чарта не убираются вообще никак.
|
||||
#
|
||||
# Helm : удалить дефолт можно ТОЛЬКО значением null;
|
||||
# {} он глубоко сливает с дефолтом, и дефолт остаётся;
|
||||
# kustomize : в strategic-merge-патче null означает УДАЛИТЬ КЛЮЧ,
|
||||
# то есть до Helm он просто не доедет.
|
||||
# в JSON6902 — нормализуется обратно в {}.
|
||||
#
|
||||
# Значит ни `virtualService: null`, ни `virtualService: {}` здесь не
|
||||
# работают: первое стирается kustomize, второе игнорируется Helm. Нужен
|
||||
# JSON6902, где null — это именно значение, а не команда удаления.
|
||||
#
|
||||
# Цена ошибки не косметическая: чарт создавал rmq-gateway, rmq-virt-service
|
||||
# и сертификат rmq-tls на посторонний домен rabbitmq.infra.sarex.io.
|
||||
# Последний не проходит проверку ACME никогда, впустую жжёт лимиты
|
||||
# Let's Encrypt, а релиз висит в install, ожидая его выпуска, и блокирует
|
||||
# весь слой infra-controllers.
|
||||
# То есть до Helm настоящий null не доходит ни одним путём. Поэтому ресурсы
|
||||
# вырезаются postRenderers'ом выше, уже из отрендеренного манифеста.
|
||||
metrics:
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
|
||||
@ -19,7 +19,7 @@ metadata:
|
||||
name: vault-injector
|
||||
namespace: vault
|
||||
spec:
|
||||
interval: 10m
|
||||
interval: 2m
|
||||
chart:
|
||||
spec:
|
||||
chart: vault-contour
|
||||
|
||||
Loading…
Reference in New Issue
Block a user