Compare commits

...

67 Commits

Author SHA1 Message Date
e4e5e06aec ++ camunda legacy wait 2026-10-31 17:45:29 +03:00
9f2c6932d7 ++ camunda timeout 30m 2026-10-31 15:21:43 +03:00
ivan
cd94931c76 ++ merge feat/zitadel-setup: sarex-installer machine user
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 13:53:12 +05:00
ivan
104bde49c4 ++ 2026-10-29 18:23:28 +05:00
ivan
b61571a858 ++ 2026-10-29 17:36:35 +05:00
13b9ca8a9f ++ stand chart repo from vars 2026-10-29 15:05:47 +03:00
ivan
31bdc74c80 ++ 2026-10-29 16:11:54 +05:00
ivan
9f4801af68 ++ contour zitadel: sarex-installer machine user for zitadel-setup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 15:32:27 +05:00
ivan
63b33aaafb ++ 2026-10-29 13:06:42 +05:00
ivan
fb52d422ca ++ 2026-10-29 12:37:46 +05:00
ivan
deb0d5f0eb ++ 2026-10-28 20:06:09 +05:00
1613172dd6 ++ contour kafka client sasl plaintext 2026-10-28 15:47:31 +03:00
b7c36a5348 ++ stand routing layer 2026-10-28 15:31:36 +03:00
0037411aae ++ stand camunda via vault 2026-10-28 15:18:25 +03:00
c23b51e2a5 infra: route GoAlert through VK Istio 2026-10-28 14:39:19 +03:00
448a994fd4 Merge branch 'master' of https://gitlab.sarex.io/infra/iac 2026-10-28 14:38:14 +03:00
Дмитрий Лавренчук
bfad13da2f Merge branch 'pdm/update-image-api-fix-copy' into 'master'
fix: image documentation updated

See merge request infra/iac!14
2026-10-28 10:36:26 +00:00
diamondrigido
f936f5ffb0 fix: image documentation updated 2026-10-28 12:31:00 +02:00
ivan
25b3536124 ++ 2026-10-28 14:51:22 +05:00
ivan
cdc2c34bca ++ 2026-10-28 14:39:15 +05:00
ivan
3b53a99371 ++ 2026-10-28 14:30:36 +05:00
ivan
aa3365cb0d ++ 2026-10-28 14:27:20 +05:00
ivan
7cf8b13f91 ++ 2026-10-28 14:00:45 +05:00
ivan
83bfd4e046 ++ 2026-10-28 13:32:52 +05:00
1c3525fc1b ++ stand platform layer zitadel 2026-10-28 11:15:41 +03:00
a3fa7ba4c0 ++ stand data layer 2026-10-28 10:37:30 +03:00
32e4cff59e ++ stand flux cancel stale health check 2026-10-28 10:33:19 +03:00
4a46bb6626 ++ contour cert-manager images 2026-10-28 10:33:19 +03:00
34cbe7c79e ++ stand mesh layer 2026-10-28 10:33:19 +03:00
ivan
ae911c7d38 ++ 2026-10-28 12:31:10 +05:00
ivan
bd4b6d4ea6 ++ 2026-10-28 12:02:22 +05:00
ivan
56ade56754 ++ 2026-10-28 11:48:59 +05:00
emelinda
8a3540ead7 Add CDE_API_ENABLED environment variable to api and filestream configurations 2026-10-28 08:32:37 +03:00
emelinda
3dadb7a87a Merge branch 'master' of gitlab.sarex.io:infra/iac 2026-10-28 08:30:59 +03:00
emelinda
fc8ddcb511 Add CDE_API_ENABLED environment variable to filestream and api configurations in d8-ugmk-prod 2026-10-28 08:30:40 +03:00
f5a217e793 ++ stand vault layer 2026-10-27 22:48:56 +03:00
eeb27c6e29 ++ slice jobs allow failure 2026-10-27 22:36:55 +03:00
0fb5374e06 ++ slice job per contour 2026-10-27 22:35:41 +03:00
0a81938175 ++ publish contour slices 2026-10-27 22:30:13 +03:00
84f2555494 ++ stand cluster and slicer 2026-10-27 22:30:13 +03:00
faa1dd2cac Merge branch 'task/PDM-2628_download_not_work_wb' into 'master'
fix: update image for filestream wb

See merge request infra/iac!13
2026-10-27 18:55:21 +00:00
diamondrigido
f4a19774a2 fix: update image for filestream wb 2026-10-27 20:11:28 +02:00
emelinda
f39a907a87 [Message]
Update `d8-ugmk-prod` frontend image to `workspaces-v2-frontend:contour_1b5d64e4` in patch configuration
2026-10-27 21:07:58 +03:00
c401cf0dcb Merge branch 'pdm/update_pdf_markings' into 'master'
fix: update pdf markings amqp

See merge request infra/iac!12
2026-10-27 14:16:42 +00:00
diamondrigido
1d349b1a8c fix: move bundle in documentations 2026-10-27 15:47:58 +02:00
ivan
f6d4c2face ++ 2026-10-27 18:07:06 +05:00
diamondrigido
6fda7834ce fix: incorect in asterus pdf markings amqp 2026-10-27 14:49:27 +02:00
diamondrigido
0d4befa985 fix: update pdf markings amqp 2026-10-27 14:48:29 +02:00
ivan
9f263a97f3 ++ 2026-10-27 16:51:18 +05:00
b6f164f85e ++ outline db secret from tf 2026-10-27 13:37:58 +03:00
5e10d54d67 ++ outline pg sslmode 2026-10-27 13:37:58 +03:00
f190a6efa5 Merge branch 'pdm/fix_env_and_doc' into 'master'
fix: output_topic

See merge request infra/iac!10
2026-10-27 10:01:08 +00:00
5bccce5815 Merge branch 'feature/outline-vk-infra' into 'master'
Outline в vk-infra

See merge request infra/iac!11
2026-10-27 09:36:50 +00:00
0c696d3a3e ++ valkey image override 2026-10-27 12:31:57 +03:00
Pavel Ershov
385abf1092
Outline в vk-infra
- infrastructure/outline/vk-infra: namespace, HelmRelease outline-valkey (valkey 0.1.0, standalone) и outline (outline 0.1.0, Outline 1.12.0)
- clusters/vk-infra: подключение outline/vk-infra
- istio-config/vk-infra: Certificate, Gateway и VirtualService для wiki.sarex.space

Секреты outline и outline-valkey созданы в кластере вручную.
2026-10-26 20:49:39 +03:00
diamondrigido
3f7628cc54 fix: output_topic 2026-10-26 18:35:40 +02:00
2182c09031 Merge branch 'feature/infra-3023-pm-wb-kafka-topics' into 'master'
wb/pm: явно задать KAFKA_TOPICS planning → message-hub-prod (INFRA-3023)

See merge request infra/iac!9
2026-10-26 14:33:35 +00:00
emelinda
e33eaa1db8 Merge branch 'master' of gitlab.sarex.io:infra/iac into feature/infra-3023-pm-wb-kafka-topics
# Conflicts:
#	apps/pm/wb/backend.yaml
#	apps/pm/wb/celery.yaml
2026-10-26 19:32:58 +05:00
emelinda
cb99195564 Merge remote-tracking branch 'origin/master' 2026-10-26 18:11:13 +05:00
emelinda
f5ea728d29 Add Kafka configuration to wb backend and Celery YAML files 2026-10-26 18:11:04 +05:00
f86336741b Merge branch 'pdm/fix_env_and_doc' into 'master'
fix: незначительные изменения

See merge request infra/iac!8
2026-10-26 13:07:53 +00:00
4448188464 wb/pm: pin KAFKA_TOPICS planning -> message-hub-prod (INFRA-3023)
pm on WB published to Kafka topic "pm" (stale .env mounted via subPath),
while message-hub consumes "message-hub-prod". PDF export of KSG hung in
PENDING because get_converted_file never reached message-hub.

Set KAFKA_TOPICS explicitly in backend and celery so env overrides .env,
same as prod, d8-ugmk-prod, uralkal and vad.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01173KBT2kTwhxrzr2t3KutB
2026-10-26 12:49:31 +00:00
diamondrigido
af56004006 fix: незначительные изменения
1. Изменения базового образа для документации, чтоб копирование работало
2. output_navis env для wb engine
2026-10-26 13:49:08 +02:00
af112cfffe ++ srx ui kit pages 2026-10-26 14:42:34 +03:00
ivan
03eb83b362 ++ 2026-10-26 14:09:35 +05:00
ivan
a8716d51b3 ++ 2026-10-26 13:55:03 +05:00
ivan
a71b15ae18 ++ 2026-10-26 13:39:04 +05:00
66 changed files with 9014 additions and 50 deletions

View File

@ -4,6 +4,8 @@ include:
stages: stages:
- build - build
- slices
- slices-publish
variables: variables:
RELEASE_NAME: iac-offline RELEASE_NAME: iac-offline
@ -33,3 +35,31 @@ build_offline_mirror:
- docker push ${IMAGE_NAME} - docker push ${IMAGE_NAME}
- docker push ${CR}/${RELEASE_NAME}:latest - docker push ${CR}/${RELEASE_NAME}:latest
timeout: 30m timeout: 30m
generate_slice_jobs:
stage: slices
image: ${CR}/infra/slice-builder:1.0.0
tags:
- build
rules:
- if: $CI_COMMIT_TAG =~ /^v?(?:\d+\.){2}\d+$/
variables:
GIT_DEPTH: "1"
script:
- python3 ci/publish-slice.py generate --release "$CI_COMMIT_TAG" --commit "$CI_COMMIT_SHA" --out slices-pipeline.yml
- cat slices-pipeline.yml
artifacts:
paths:
- slices-pipeline.yml
publish_contour_slices:
stage: slices-publish
rules:
- if: $CI_COMMIT_TAG =~ /^v?(?:\d+\.){2}\d+$/
needs:
- generate_slice_jobs
trigger:
include:
- artifact: slices-pipeline.yml
job: generate_slice_jobs
strategy: depend

View File

@ -18,7 +18,7 @@ spec:
spec: spec:
containers: containers:
- name: debug - name: debug
image: cr.yandex/crp3ccidau046kdj8g9q/mc-files:dev9 image: cr.yandex/crp3ccidau046kdj8g9q/mc-files:dev5
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "while true; do sleep 3600; done"] command: ["/bin/sh", "-c", "while true; do sleep 3600; done"]
imagePullSecrets: imagePullSecrets:

View File

@ -8,6 +8,9 @@ spec:
values: values:
services: services:
backend: backend:
deployment:
replicaCount:
_default: 2
envs: envs:
- name: ALLOWED_HOSTS - name: ALLOWED_HOSTS
value: value:

File diff suppressed because one or more lines are too long

View File

@ -36,7 +36,7 @@ spec:
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings-amqp:prod_3ab263be _default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings-amqp:prod_9dea5b64
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent

View File

@ -65,7 +65,7 @@ spec:
enabled: false enabled: false
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/documentations:prod_179e518c _default: cr.yandex/crp3ccidau046kdj8g9q/documentations:prod_89c8039a
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent
service: service:
@ -89,6 +89,9 @@ spec:
- name: POSTGRES_POOL_SIZE - name: POSTGRES_POOL_SIZE
value: value:
_default: "20" _default: "20"
- name: CDE_API_ENABLED
value:
_default: "false"
- name: USE_LEGACY_BIM_FLOW - name: USE_LEGACY_BIM_FLOW
value: value:
_default: "true" _default: "true"
@ -236,6 +239,9 @@ spec:
- name: VALKEY_PORT - name: VALKEY_PORT
value: value:
_default: "6379" _default: "6379"
- name: CDE_API_ENABLED
value:
_default: "false"
podAnnotations: podAnnotations:
_default: _default:
traffic.sidecar.istio.io/excludeOutboundPorts: "8200" traffic.sidecar.istio.io/excludeOutboundPorts: "8200"

View File

@ -97,6 +97,9 @@ spec:
- name: PUBLIC_LINK_FOLDER_CONNECTOR_ENABLED - name: PUBLIC_LINK_FOLDER_CONNECTOR_ENABLED
value: value:
_default: "true" _default: "true"
- name: CDE_API_ENABLED
value:
_default: "false"
- name: USE_ZITADEL - name: USE_ZITADEL
value: value:
_default: "1" _default: "1"
@ -223,6 +226,9 @@ spec:
- name: VALKEY_PORT - name: VALKEY_PORT
value: value:
_default: "6379" _default: "6379"
- name: CDE_API_ENABLED
value:
_default: "false"
podAnnotations: podAnnotations:
_default: _default:
traffic.sidecar.istio.io/excludeOutboundPorts: "8200" traffic.sidecar.istio.io/excludeOutboundPorts: "8200"

View File

@ -37,7 +37,7 @@ spec:
name: name:
_default: pdf-markings-amqp _default: pdf-markings-amqp
replicaCount: replicaCount:
_default: 1 _default: 2
port: port:
_default: 8000 _default: 8000
command: command:
@ -64,7 +64,7 @@ spec:
enabled: false enabled: false
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings-amqp:prod_3ab263be _default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings-amqp:prod_9dea5b64
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent
service: service:

View File

@ -156,3 +156,6 @@ spec:
- name: VALKEY_PORT - name: VALKEY_PORT
value: value:
_default: "6379" _default: "6379"
- name: CDE_API_ENABLED
value:
_default: "false"

View File

@ -144,3 +144,6 @@ spec:
- name: VALKEY_PORT - name: VALKEY_PORT
value: value:
_default: "6379" _default: "6379"
- name: CDE_API_ENABLED
value:
_default: "false"

View File

@ -8,6 +8,10 @@ spec:
values: values:
services: services:
backend: backend:
image:
name:
_default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings:contour_ce9ed6d7
envs: envs:
- name: MARKS_APP__LOG_LEVEL - name: MARKS_APP__LOG_LEVEL
value: value:
@ -33,8 +37,6 @@ spec:
value: value:
_default: "true" _default: "true"
# Временно: в образе нет CA УГМК для s3.uralmine.com (INFRA-3034).
# Вернуть "true" после монтирования CA и AWS_CA_BUNDLE.
- name: MARKS_S3__SSL_VERIFY - name: MARKS_S3__SSL_VERIFY
value: value:
_default: "false" _default: "false"

View File

@ -36,7 +36,7 @@ spec:
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/documentations:prod_98a23ef5 _default: cr.yandex/crp3ccidau046kdj8g9q/documentations:prod_0be18f51
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent
@ -134,6 +134,10 @@ spec:
- name: POSTGRES_POOL_SIZE - name: POSTGRES_POOL_SIZE
value: value:
_default: "20" _default: "20"
- name: CDE_API_ENABLED
value:
_default: "false"
- name: ZITADEL_ACCOUNT - name: ZITADEL_ACCOUNT
value: value:

View File

@ -36,7 +36,7 @@ spec:
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/documentations-api-files:prod_3f19a21d _default: cr.yandex/crp3ccidau046kdj8g9q/documentations-api-files:prod_fef3add2
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent
@ -137,6 +137,10 @@ spec:
- name: API_ADDRESS - name: API_ADDRESS
value: value:
_default: "0.0.0.0:8080" _default: "0.0.0.0:8080"
- name: CDE_API_ENABLED
value:
_default: "false"
- name: API_ADDRESS_FILE - name: API_ADDRESS_FILE
value: value:

View File

@ -36,7 +36,7 @@ spec:
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings-amqp:prod_3ab263be _default: cr.yandex/crp3ccidau046kdj8g9q/pdf-markings-amqp:prod_9dea5b64
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent

View File

@ -18,7 +18,7 @@ data:
# DEBUG SETTINGS START # DEBUG SETTINGS START
# --------------------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------------------
DEBUG = True DEBUG = False
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
# --------------------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------------------
# DEBUG SETTINGS END # DEBUG SETTINGS END

View File

@ -9,6 +9,8 @@ spec:
services: services:
backend: backend:
deployment: deployment:
replicaCount:
_default: 2
args: args:
_default: _default:
- | - |

View File

@ -1,33 +1,5 @@
--- ---
# ВНИМАНИЕ: data["production.py"] — одна строка, kustomize заменяет её ЦЕЛИКОМ,
# поэтому здесь продублировано всё содержимое из
# apps/issues/base/production-configmap.yaml (та же ловушка, что с envs).
#
# Зачем нужен этот патч:
# production.py делает `from .base import *` (там всё через os.getenv), а затем
# переприсваивает часть значений ХАРДКОДОМ — поэтому для этих переменных
# ConfigMap ПОБЕЖДАЕТ env из HelmRelease, и правка env в оверлее
# backend-s3.yaml/celery-s3.yaml сама по себе ни на что не влияет.
#
# INFRA-3005 (основная причина зависания экспорта в Excel):
# в base хардкодом WORKFLOWS_HOST/WORKFLOWS_URL = workflows-api-service.workflow
# — такого сервиса в УГМК нет. celery собирает xlsx, затем
# ExportFinishedNotification → issues/mailing.py:122 делает POST на
# {WORKFLOWS_HOST}/internal/v1/companies/{id}/workflows и падает с
# ConnectionError (Name or service not known) — задача фейлится, фронт не
# получает завершения и крутит загрузку бесконечно. Тем же путём с 26.08
# падали ВСЕ уведомления (send_notification_on_create/on_update/
# to_new_responsible/on_bulk_update, ~1770 ошибок).
#
# Отличия от base:
# - WORKFLOWS_HOST / WORKFLOWS_URL → backend-svc.processing (через os.getenv,
# чтобы env из оверлея снова начал работать)
# - SAREX_API → https://sarex.uralmine.com (в base зашит https://srx.wb.ru)
# - CORS/CSRF origins → https://sarex.uralmine.com (в base только lk.srx.wb.ru)
# - убраны хардкоды KAFKA_USERNAME/KAFKA_PASSWORD/DJANGO_TOKEN и чужой
# дефолт KAFKA_HOST: в УГМК всё это приходит из Vault
# (см. podAnnotations в backend-s3.yaml / celery-s3.yaml / kafka-app.yaml)
# - BASE_AERO_URL оставлен внутренним — он server-to-server
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
@ -146,9 +118,9 @@ data:
CORS_ALLOW_ALL_ORIGINS = True CORS_ALLOW_ALL_ORIGINS = True
ENABLE_MAILGUN=False ENABLE_MAILGUN=False
SMTP_PORT=465 SMTP_PORT=587
SMTP_HOST="mail.rwb.ru" SMTP_HOST="post.uralmine.com"
EMAIL_FROM="sarex@rwb.ru" EMAIL_FROM="sarex@uralmine.com"
CORS_ALLOW_METHODS = [ CORS_ALLOW_METHODS = [
"DELETE", "DELETE",

View File

@ -12,7 +12,6 @@ data:
# DEBUG SETTINGS START # DEBUG SETTINGS START
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
DEBUG = True
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
TEST_MODE = False TEST_MODE = False
@ -40,7 +39,7 @@ data:
# DEBUG SETTINGS START # DEBUG SETTINGS START
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
DEBUG = True DEBUG = False
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
REVIEW_HOST='http://backend-service.flows.svc.cluster.local:8000' REVIEW_HOST='http://backend-service.flows.svc.cluster.local:8000'

View File

@ -147,6 +147,28 @@ spec:
value: value:
_default: "/api/v1" _default: "/api/v1"
- name: KAFKA_ENABLE
value:
_default: "True"
- name: KAFKA_BOOTSTRAP_SERVERS
value:
_default: '["wb-prod-kafka-bootstrap.kafka.svc.cluster.local:9093"]'
- name: KAFKA_SECURITY_PROTOCOL
value:
_default: "SSL"
- name: KAFKA_SSL_CAFILE
value:
_default: "/usr/local/share/ca-certificates/kafka.crt"
# Обязан совпадать с SETTINGS_TOPICS["planning"] в
# apps/message-hub/wb/message-hub.yaml
- name: KAFKA_TOPICS
value:
_default: '{"planning": "message-hub-prod"}'
commitSha: "" commitSha: ""
gitlabUri: "" gitlabUri: ""
gitlabJobUrl: "" gitlabJobUrl: ""

View File

@ -141,6 +141,26 @@ spec:
value: value:
_default: "/api/v1" _default: "/api/v1"
- name: KAFKA_ENABLE
value:
_default: "True"
- name: KAFKA_BOOTSTRAP_SERVERS
value:
_default: '["wb-prod-kafka-bootstrap.kafka.svc.cluster.local:9093"]'
- name: KAFKA_SECURITY_PROTOCOL
value:
_default: "SSL"
- name: KAFKA_SSL_CAFILE
value:
_default: "/usr/local/share/ca-certificates/kafka.crt"
- name: KAFKA_TOPICS
value:
_default: '{"planning": "message-hub-prod"}'
commitSha: "" commitSha: ""
gitlabUri: "" gitlabUri: ""
gitlabJobUrl: "" gitlabJobUrl: ""

View File

@ -42,7 +42,7 @@ spec:
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/workflows-engine:contour_92b7c257 _default: cr.yandex/crp3ccidau046kdj8g9q/workflows-engine:contour_835b57c1
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent
@ -137,11 +137,15 @@ spec:
_default: "1" _default: "1"
- name: CROSS_SECTION_API_DB - name: CROSS_SECTION_API_DB
value: value:
_default: "/etc/cross_section/cross_sections_api_db_prod.json" _default: "/etc/cross_section/cross-section-api-db-prod.json"
- name: CROSS_SECTION_API_DEBUG - name: CROSS_SECTION_API_DEBUG
value: value:
_default: "0" _default: "0"
- name: IGNORE_RESOURCES
value:
_default: "True"
- name: DJANGO_HOST - name: DJANGO_HOST
value: value:
_default: "http://backend.django.svc.cluster.local:8000" _default: "http://backend.django.svc.cluster.local:8000"

View File

@ -8,6 +8,9 @@ spec:
values: values:
services: services:
backend: backend:
image:
name:
_default: cr.yandex/crp3ccidau046kdj8g9q/workflows-engine:contour_7d2cd329
deployment: deployment:
resources: resources:
requests: requests:

View File

@ -29,7 +29,7 @@ spec:
enabled: true enabled: true
image: image:
name: name:
_default: cr.yandex/crp3ccidau046kdj8g9q/workspaces-v2-frontend:contour_a72e3265 _default: cr.yandex/crp3ccidau046kdj8g9q/workspaces-v2-frontend:contour_2da2a00e
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent
deployment: deployment:

View File

@ -8,6 +8,9 @@ spec:
values: values:
services: services:
frontend: frontend:
image:
name:
_default: cr.yandex/crp3ccidau046kdj8g9q/workspaces-v2-frontend:contour_1b5d64e4
deployment: deployment:
replicaCount: replicaCount:
_default: 1 _default: 1

View File

@ -36,7 +36,7 @@ spec:
image: image:
name: name:
_default: 10.4.10.187:80/library/workspaces-v2-frontend:contour_07373a45 _default: 10.4.10.187:80/library/workspaces-v2-frontend:contour_1b5d64e4
pullPolicy: pullPolicy:
_default: IfNotPresent _default: IfNotPresent

163
ci/build-slice.py Normal file
View File

@ -0,0 +1,163 @@
#!/usr/bin/env python3
import argparse
import io
import subprocess
import sys
import tarfile
from pathlib import Path, PurePosixPath
import yaml
FLUX_KUSTOMIZATION = "kustomize.toolkit.fluxcd.io"
KUSTOMIZATION_FILES = ("kustomization.yaml", "kustomization.yml", "Kustomization")
class SliceError(Exception):
pass
def is_remote(ref: str) -> bool:
return "://" in ref or ref.startswith(("git@", "github.com/", "gitlab.com/"))
def kustomization_file(directory: Path) -> Path | None:
for name in KUSTOMIZATION_FILES:
candidate = directory / name
if candidate.is_file():
return candidate
return None
def local_refs(doc: dict) -> list[str]:
refs = []
refs += doc.get("resources") or []
refs += doc.get("components") or []
refs += doc.get("patchesStrategicMerge") or []
refs += [p["path"] for p in doc.get("patches") or [] if isinstance(p, dict) and "path" in p]
for key in ("configMapGenerator", "secretGenerator"):
for gen in doc.get(key) or []:
for entry in (gen.get("files") or []) + (gen.get("envs") or []):
refs.append(entry.split("=", 1)[-1])
if gen.get("env"):
refs.append(gen["env"])
return [r for r in refs if isinstance(r, str)]
def flux_paths(path: Path) -> list[str]:
try:
docs = list(yaml.safe_load_all(path.read_text()))
except yaml.YAMLError:
return []
return [
d["spec"]["path"]
for d in docs
if isinstance(d, dict)
and str(d.get("apiVersion", "")).startswith(FLUX_KUSTOMIZATION)
and d.get("kind") == "Kustomization"
and d.get("spec", {}).get("path")
]
def collect(repo: Path, start: str) -> tuple[set[PurePosixPath], list[str]]:
repo = repo.resolve()
files: set[PurePosixPath] = set()
entries: list[str] = []
seen_dirs: set[Path] = set()
def rel(p: Path) -> PurePosixPath:
try:
return PurePosixPath(p.resolve().relative_to(repo).as_posix())
except ValueError:
raise SliceError(f"reference outside the repository: {p}")
def add_file(p: Path):
r = rel(p)
if r in files:
return
files.add(r)
if p.suffix in (".yaml", ".yml"):
for fp in flux_paths(p):
visit_dir(repo / fp, entry=True)
def visit_dir(d: Path, entry: bool = False):
d = d.resolve()
if d in seen_dirs:
return
seen_dirs.add(d)
kfile = kustomization_file(d)
if kfile is None:
raise SliceError(f"no kustomization.yaml in {rel(d)}")
if entry:
entries.append(str(rel(d)))
add_file(kfile)
doc = yaml.safe_load(kfile.read_text()) or {}
for ref in local_refs(doc):
if is_remote(ref):
raise SliceError(f"remote reference {ref} in {rel(kfile)}")
target = (d / ref)
if target.is_dir():
visit_dir(target)
elif target.is_file():
add_file(target)
else:
raise SliceError(f"reference {ref} in {rel(kfile)} does not exist")
visit_dir(repo / start, entry=True)
return files, sorted(set(entries))
def write_tar(repo: Path, files: set[PurePosixPath], out: Path):
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w", format=tarfile.PAX_FORMAT) as tar:
for f in sorted(files):
data = (repo / f).read_bytes()
info = tarfile.TarInfo(str(f))
info.size = len(data)
info.mode = 0o644
info.mtime = 0
info.uid = info.gid = 0
info.uname = info.gname = ""
tar.addfile(info, io.BytesIO(data))
out.write_bytes(buf.getvalue())
def kustomize_build(path: Path) -> bytes:
p = subprocess.run(["kubectl", "kustomize", str(path)], capture_output=True)
if p.returncode != 0:
raise SliceError(f"kustomize build {path} failed: {p.stderr.decode().strip()}")
return p.stdout
def verify(repo: Path, out: Path, entries: list[str]):
import tempfile
with tempfile.TemporaryDirectory() as tmp:
with tarfile.open(out) as tar:
tar.extractall(tmp, filter="data")
for e in entries:
if kustomize_build(repo / e) != kustomize_build(Path(tmp) / e):
raise SliceError(f"kustomize build of {e} differs between slice and full repository")
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("contour")
ap.add_argument("--repo", default=".")
ap.add_argument("--out", required=True)
ap.add_argument("--no-verify", action="store_true")
args = ap.parse_args()
repo = Path(args.repo).resolve()
out = Path(args.out)
try:
files, entries = collect(repo, f"clusters/{args.contour}")
write_tar(repo, files, out)
if not args.no_verify:
verify(repo, out, entries)
except SliceError as e:
print(f"slice {args.contour}: {e}", file=sys.stderr)
return 1
print(f"slice {args.contour}: {len(files)} files, entry points: {', '.join(entries)}")
return 0
if __name__ == "__main__":
sys.exit(main())

217
ci/publish-slice.py Normal file
View File

@ -0,0 +1,217 @@
#!/usr/bin/env python3
import argparse
import base64
import hashlib
import importlib.util
import json
import re
import sys
import tempfile
import time
import urllib.error
import urllib.parse
import urllib.request
from datetime import datetime, timezone
from pathlib import Path
import yaml
spec = importlib.util.spec_from_file_location("build_slice", Path(__file__).with_name("build-slice.py"))
bs = importlib.util.module_from_spec(spec)
spec.loader.exec_module(bs)
REGISTRY_HOST = "cr.yandex"
SLICE_REGISTRY = "crpct2b2lsmao4nm0cjk"
CONFIG_TYPE = "application/vnd.sarex.slice.config.v1+json"
LAYER_TYPE = "application/vnd.oci.image.layer.v1.tar"
MANIFEST_TYPE = "application/vnd.oci.image.manifest.v1+json"
JOB_IMAGE = "${CR}/infra/slice-builder:1.0.0"
class PublishError(Exception):
pass
def digest(data: bytes) -> str:
return "sha256:" + hashlib.sha256(data).hexdigest()
def list_contours(repo: Path) -> list[str]:
return sorted(p.parent.name for p in repo.glob("clusters/*/kustomization.yaml"))
def child_pipeline(contours: list[str], release: str, commit: str) -> str:
jobs: dict = {"stages": ["slices"]}
for c in contours:
jobs[f"slice {c}"] = {
"stage": "slices",
"image": JOB_IMAGE,
"tags": ["build"],
"allow_failure": True,
"variables": {"GIT_DEPTH": "1"},
"script": [
"printf '%s' \"$SLICES_PUSHER_KEY\" | base64 -d > /tmp/slices-key.json",
f"python3 ci/publish-slice.py publish --contour {c} --release {release} --commit {commit} --key-file /tmp/slices-key.json",
],
"after_script": ["rm -f /tmp/slices-key.json"],
}
if not contours:
jobs["no contours"] = {"stage": "slices", "image": JOB_IMAGE, "tags": ["build"], "script": ["echo 'no clusters/*/kustomization.yaml found'"]}
return yaml.safe_dump(jobs, sort_keys=False, allow_unicode=False)
def build_manifest(layer: bytes, annotations: dict[str, str]) -> tuple[bytes, bytes]:
config = b"{}"
manifest = {
"schemaVersion": 2,
"mediaType": MANIFEST_TYPE,
"config": {"mediaType": CONFIG_TYPE, "digest": digest(config), "size": len(config)},
"layers": [{
"mediaType": LAYER_TYPE,
"digest": digest(layer),
"size": len(layer),
"annotations": {"org.opencontainers.image.title": "slice.tar"},
}],
"annotations": dict(sorted(annotations.items())),
}
return config, json.dumps(manifest, sort_keys=True, separators=(",", ":")).encode()
class Registry:
def __init__(self, username: str, password: str):
self.base = f"https://{REGISTRY_HOST}"
self.basic = "Basic " + base64.b64encode(f"{username}:{password}".encode()).decode()
self.tokens: dict[str, str] = {}
def _send(self, method, url, data=None, headers=None):
req = urllib.request.Request(url, data=data, method=method, headers=headers or {})
try:
with urllib.request.urlopen(req, timeout=60) as r:
return r.status, dict(r.headers), r.read()
except urllib.error.HTTPError as e:
return e.code, dict(e.headers), e.read()
def _token(self, challenge: str, scope: str) -> str:
params = dict(re.findall(r'(\w+)="([^"]*)"', challenge))
realm = params.pop("realm")
params["scope"] = scope
status, _, body = self._send("GET", f"{realm}?{urllib.parse.urlencode(params)}", headers={"Authorization": self.basic})
if status != 200:
raise PublishError(f"registry auth failed: HTTP {status}")
payload = json.loads(body)
return payload.get("token") or payload.get("access_token")
def request(self, method, repo, path, data=None, headers=None):
scope = f"repository:{repo}:pull,push"
url = path if path.startswith("http") else f"{self.base}/v2/{repo}/{path}"
headers = dict(headers or {})
if scope in self.tokens:
headers["Authorization"] = f"Bearer {self.tokens[scope]}"
status, h, body = self._send(method, url, data, headers)
if status == 401:
challenge = {k.lower(): v for k, v in h.items()}.get("www-authenticate", "")
self.tokens[scope] = self._token(challenge, scope)
headers["Authorization"] = f"Bearer {self.tokens[scope]}"
status, h, body = self._send(method, url, data, headers)
return status, {k.lower(): v for k, v in h.items()}, body
def current_layer(self, repo: str) -> str | None:
status, _, body = self.request("GET", repo, "manifests/current", headers={"Accept": MANIFEST_TYPE})
if status == 404:
return None
if status != 200:
raise PublishError(f"{repo}:current: HTTP {status}")
return json.loads(body)["layers"][0]["digest"]
def put_blob(self, repo: str, data: bytes) -> bool:
d = digest(data)
if self.request("HEAD", repo, f"blobs/{d}")[0] == 200:
return False
status, h, _ = self.request("POST", repo, "blobs/uploads/")
if status != 202:
raise PublishError(f"blob upload to {repo}: HTTP {status}")
location = h["location"]
if location.startswith("/"):
location = self.base + location
sep = "&" if "?" in location else "?"
status, _, _ = self.request("PUT", repo, f"{location}{sep}digest={d}", data, {"Content-Type": "application/octet-stream"})
if status != 201:
raise PublishError(f"blob upload to {repo}: HTTP {status}")
return True
def push(self, repo: str, tags: list[str], layer: bytes, annotations: dict[str, str]) -> bool:
config, manifest = build_manifest(layer, annotations)
self.put_blob(repo, config)
uploaded = self.put_blob(repo, layer)
for tag in tags:
status, _, body = self.request("PUT", repo, f"manifests/{tag}", manifest, {"Content-Type": MANIFEST_TYPE})
if status != 201:
raise PublishError(f"{repo}:{tag}: HTTP {status} {body[:200]!r}")
return uploaded
def log(msg: str):
print(f"[{time.strftime('%H:%M:%S')}] {msg}", flush=True)
def publish(repo: Path, contour: str, release: str, commit: str, key_file: Path) -> int:
target = f"{SLICE_REGISTRY}/{contour}-iac"
log(f"contour {contour}, source iac@{commit[:8]}, release {release}")
try:
with tempfile.TemporaryDirectory() as tmp:
out = Path(tmp) / "slice.tar"
files, entries = bs.collect(repo, f"clusters/{contour}")
log(f"collected {len(files)} files, entry points: {', '.join(entries)}")
bs.write_tar(repo, files, out)
bs.verify(repo, out, entries)
log(f"verified: kustomize build of {len(entries)} entry point(s) identical to full repository")
layer = out.read_bytes()
new = digest(layer)
log(f"slice size {len(layer)} bytes, digest {new}")
registry = Registry("json_key", key_file.read_text())
current = registry.current_layer(f"{target}")
changed = current != new
log(f"registry {REGISTRY_HOST}/{target}, current " + (current or "absent") + (", content changed" if changed else ", content unchanged"))
tags = [commit[:8], release] + (["current"] if changed else [])
uploaded = registry.push(target, tags, layer, {
"org.opencontainers.image.source": "iac",
"org.opencontainers.image.revision": commit,
"org.opencontainers.image.version": release,
"org.opencontainers.image.created": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
"io.sarex.slice.contour": contour,
"io.sarex.slice.kind": "iac",
})
log(f"layer {'uploaded' if uploaded else 'already in registry'}, tags pushed: {', '.join(tags)}")
except (bs.SliceError, PublishError) as e:
log(f"FAILED: {e}")
return 1
log("done")
return 0
def main() -> int:
ap = argparse.ArgumentParser()
sub = ap.add_subparsers(dest="cmd", required=True)
gen = sub.add_parser("generate")
gen.add_argument("--repo", default=".")
gen.add_argument("--release", required=True)
gen.add_argument("--commit", required=True)
gen.add_argument("--out", required=True)
pub = sub.add_parser("publish")
pub.add_argument("--repo", default=".")
pub.add_argument("--contour", required=True)
pub.add_argument("--release", required=True)
pub.add_argument("--commit", required=True)
pub.add_argument("--key-file", required=True)
args = ap.parse_args()
repo = Path(args.repo).resolve()
if args.cmd == "generate":
contours = list_contours(repo)
Path(args.out).write_text(child_pipeline(contours, args.release, args.commit))
log(f"{len(contours)} contours: {', '.join(contours)}")
return 0
return publish(repo, args.contour, args.release, args.commit, Path(args.key_file))
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,93 @@
import importlib.util
import tarfile
from pathlib import Path
import pytest
import yaml
spec = importlib.util.spec_from_file_location("build_slice", Path(__file__).parents[1] / "build-slice.py")
bs = importlib.util.module_from_spec(spec)
spec.loader.exec_module(bs)
def put(root: Path, rel: str, text: str):
p = root / rel
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(text)
@pytest.fixture
def repo(tmp_path):
put(tmp_path, "clusters/a/kustomization.yaml", "resources:\n - ./flux-system\n - ./layers.yaml\n")
put(tmp_path, "clusters/a/flux-system/kustomization.yaml", "resources:\n - gotk-sync.yaml\n")
put(tmp_path, "clusters/a/flux-system/gotk-sync.yaml",
"apiVersion: kustomize.toolkit.fluxcd.io/v1\nkind: Kustomization\nspec:\n path: ./clusters/a\n")
put(tmp_path, "clusters/a/layers.yaml",
"apiVersion: kustomize.toolkit.fluxcd.io/v1\nkind: Kustomization\nspec:\n path: ./layers/a/00-vault\n")
put(tmp_path, "layers/a/00-vault/kustomization.yaml", "resources:\n - ../../../infrastructure/vault/contour-template\n")
put(tmp_path, "infrastructure/vault/contour-template/kustomization.yaml",
"resources:\n - ../base\npatches:\n - path: vault.yaml\n")
put(tmp_path, "infrastructure/vault/contour-template/vault.yaml", "kind: HelmRelease\n")
put(tmp_path, "infrastructure/vault/base/kustomization.yaml", "resources:\n - helmrelease.yaml\n")
put(tmp_path, "infrastructure/vault/base/helmrelease.yaml", "kind: HelmRelease\n")
put(tmp_path, "infrastructure/vault/base/unused.yaml", "kind: ConfigMap\n")
put(tmp_path, "infrastructure/vault/uralkal/kustomization.yaml", "resources:\n - ../base\n")
put(tmp_path, "clusters/b/kustomization.yaml", "resources:\n - ../../infrastructure/vault/uralkal\n")
return tmp_path
def test_slice_follows_flux_paths_and_skips_foreign(repo):
files, entries = bs.collect(repo, "clusters/a")
names = {str(f) for f in files}
assert "infrastructure/vault/base/helmrelease.yaml" in names
assert "infrastructure/vault/contour-template/vault.yaml" in names
assert "layers/a/00-vault/kustomization.yaml" in names
assert not any("uralkal" in n or n.startswith("clusters/b") for n in names)
assert "infrastructure/vault/base/unused.yaml" not in names
assert entries == ["clusters/a", "layers/a/00-vault"]
def test_remote_reference_stops_build(repo):
put(repo, "clusters/a/kustomization.yaml", "resources:\n - https://github.com/x/y//z\n")
with pytest.raises(bs.SliceError, match="remote reference"):
bs.collect(repo, "clusters/a")
def test_dangling_reference_stops_build(repo):
put(repo, "clusters/a/kustomization.yaml", "resources:\n - ./missing.yaml\n")
with pytest.raises(bs.SliceError, match="does not exist"):
bs.collect(repo, "clusters/a")
def test_tar_is_byte_identical_across_runs(repo, tmp_path_factory):
files, _ = bs.collect(repo, "clusters/a")
out1 = tmp_path_factory.mktemp("o") / "s.tar"
out2 = tmp_path_factory.mktemp("o") / "s.tar"
bs.write_tar(repo, files, out1)
(repo / "clusters/a/layers.yaml").touch()
bs.write_tar(repo, files, out2)
assert out1.read_bytes() == out2.read_bytes()
with tarfile.open(out1) as t:
assert all(m.mtime == 0 for m in t.getmembers())
pspec = importlib.util.spec_from_file_location("publish_slice", Path(__file__).parents[1] / "publish-slice.py")
ps = importlib.util.module_from_spec(pspec)
pspec.loader.exec_module(ps)
def test_every_cluster_with_kustomization_is_a_contour(tmp_path):
put(tmp_path, "clusters/stand/kustomization.yaml", "resources: []\n")
put(tmp_path, "clusters/vad/kustomization.yaml", "resources: []\n")
put(tmp_path, "clusters/contour/apps.yaml", "kind: Kustomization\n")
assert ps.list_contours(tmp_path) == ["stand", "vad"]
def test_child_pipeline_has_one_job_per_contour():
doc = yaml.safe_load(ps.child_pipeline(["stand", "vad"], "3.9.68", "abcdef1234"))
jobs = {k: v for k, v in doc.items() if k != "stages"}
assert sorted(jobs) == ["slice stand", "slice vad"]
assert all(j["allow_failure"] for j in jobs.values())
assert "--contour vad --release 3.9.68 --commit abcdef1234" in jobs["slice vad"]["script"][1]
assert all(ord(ch) < 128 for ch in ps.child_pipeline(["stand"], "1.0.0", "a" * 40))

View File

@ -0,0 +1,14 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: yc-oci-charts
namespace: flux-system
spec:
type: oci
interval: 10m0s
url: ${CHART_REPO:=oci://cr.yandex/crp3ccidau046kdj8g9q/charts}
secretRef:
name: ${CHART_REPO_SECRET:=yc-cr-auth}
certSecretRef:
name: chart-repo-ca

View File

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./helm-repositories.yaml
- ../../../infrastructure/vault/contour-template

View File

@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../infrastructure/istio-base/contour-template
- ../../../infrastructure/istio-pilot/contour-template
- ../../../infrastructure/istio-gateway/contour-template
- ../../../infrastructure/cert-manager/contour-template

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../infrastructure/postgresql/contour-template
- ../../../infrastructure/kafka/contour-template
- ../../../infrastructure/rabbitmq/contour-template

View File

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../infrastructure/zitadel/contour-template
- ../../../infrastructure/camunda/contour-template

View File

@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../infrastructure/istio-config/contour-template

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: flux-system
namespace: flux-system
spec:
interval: 1m0s
ref:
branch: main
url: http://gitea.gitea.svc:3000/infra/iac.git
secretRef:
name: flux-system
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: flux-system
namespace: flux-system
spec:
interval: 10m0s
path: ./clusters/stand
prune: true
sourceRef:
kind: GitRepository
name: flux-system

View File

@ -0,0 +1,13 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- gotk-components.yaml
- gotk-sync.yaml
patches:
- target:
kind: Deployment
name: kustomize-controller
patch: |-
- op: add
path: /spec/template/spec/containers/0/args/-
value: --feature-gates=CancelHealthCheckOnNewRevision=true

View File

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./flux-system
- ./layers.yaml

View File

@ -0,0 +1,93 @@
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: 00-vault
namespace: flux-system
spec:
interval: 10m0s
timeout: 10m0s
path: ./clusters/stand/00-vault
prune: true
sourceRef:
kind: GitRepository
name: flux-system
postBuild:
substituteFrom:
- kind: ConfigMap
name: contour-vars
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: 10-mesh
namespace: flux-system
spec:
interval: 10m0s
timeout: 15m0s
path: ./clusters/stand/10-mesh
prune: true
wait: true
sourceRef:
kind: GitRepository
name: flux-system
postBuild:
substituteFrom:
- kind: ConfigMap
name: contour-vars
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: 20-data
namespace: flux-system
spec:
interval: 10m0s
timeout: 20m0s
path: ./clusters/stand/20-data
prune: true
wait: true
sourceRef:
kind: GitRepository
name: flux-system
postBuild:
substituteFrom:
- kind: ConfigMap
name: contour-vars
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: 30-platform
namespace: flux-system
spec:
interval: 10m0s
timeout: 35m0s
path: ./clusters/stand/30-platform
prune: true
wait: true
sourceRef:
kind: GitRepository
name: flux-system
postBuild:
substituteFrom:
- kind: ConfigMap
name: contour-vars
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: 40-routing
namespace: flux-system
spec:
interval: 10m0s
timeout: 10m0s
path: ./clusters/stand/40-routing
prune: true
wait: true
sourceRef:
kind: GitRepository
name: flux-system
postBuild:
substituteFrom:
- kind: ConfigMap
name: contour-vars

View File

@ -12,3 +12,4 @@ resources:
- ../../../infrastructure/kb/vk-infra - ../../../infrastructure/kb/vk-infra
- ../../../infrastructure/gitlab-runner/vk-infra - ../../../infrastructure/gitlab-runner/vk-infra
- ../../../infrastructure/nexus/vk-infra - ../../../infrastructure/nexus/vk-infra
- ../../../infrastructure/outline/vk-infra

View File

@ -0,0 +1,354 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: camunda
namespace: camunda
spec:
dependsOn: []
interval: 5m
timeout: 30m
waitStrategy:
name: legacy
postRenderers:
- kustomize:
patches:
- target:
group: apps
version: v1
kind: Deployment
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: StatefulSet
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: batch
version: v1
kind: Job
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: Deployment
name: camunda-connectors
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: Deployment
name: camunda-identity
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: Deployment
name: camunda-operate
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: Deployment
name: camunda-optimize
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: Deployment
name: camunda-tasklist
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: Deployment
name: camunda-zeebe-gateway
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
- target:
group: apps
version: v1
kind: StatefulSet
name: camunda-zeebe
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: processing
- op: add
path: /spec/template/spec/tolerations
value:
- key: dedicated
operator: Equal
value: processing
effect: NoSchedule
values:
global:
vault:
enabled: true
role: camunda-contour
authPath: auth/kubernetes
secrets:
postgresql:
path: secrets/data/camunda/identity-db
keys:
password: password
postgresPassword: password
image:
pullSecrets:
- name: regcred
identity:
auth:
publicIssuerUrl: "https://${HOST_CAMUNDA_KEYCLOAK}/auth/realms/camunda-platform"
identity:
redirectUrl: "https://${HOST_CAMUNDA_IDENTITY}"
operate:
redirectUrl: "https://${HOST_CAMUNDA}"
tasklist:
redirectUrl: "https://${HOST_CAMUNDA_TASKLIST}"
optimize:
redirectUrl: "https://${HOST_CAMUNDA_OPTIMIZE}"
identityPostgresql:
enabled: false
auth:
usePasswordFiles: true
primary:
automountServiceAccountToken: true
persistence:
size: 10Gi
storageClass: ${STORAGE_CLASS}
identityKeycloak:
externalDatabase:
host: pg-host.storage.svc.cluster.local
port: 5432
user: bn_keycloak
database: bitnami_keycloak
password: ""
existingSecret: ""
existingSecretPasswordKey: password
postgresql:
enabled: false
auth:
usePasswordFiles: true
primary:
automountServiceAccountToken: true
persistence:
size: 10Gi
storageClass: ${STORAGE_CLASS}
vaultEnv:
enabled: true
role: camunda-contour
authPath: auth/kubernetes
envFiles:
KEYCLOAK_ADMIN_PASSWORD:
path: secrets/data/camunda/keycloak-admin
key: admin-password
KEYCLOAK_PASSWORD:
path: secrets/data/camunda/keycloak-admin
key: admin-password
KEYCLOAK_DATABASE_PASSWORD:
path: secrets/data/camunda/keycloak-db
key: password
global:
storageClass: ${STORAGE_CLASS}
tolerations: []
elasticsearch:
sysctlImage:
registry: cr.yandex
repository: crp3ccidau046kdj8g9q/contour/camunda/os-shell
tag: 12-debian-12-r32
pullSecrets:
- regcred
master:
replicaCount: 1
podAntiAffinityPreset: soft
persistence:
size: 10Gi
storageClass: ${STORAGE_CLASS}
tolerations: []
metrics:
enabled: false
serviceMonitor:
enabled: false
prometheusRule:
enabled: false
tolerations: []
camundaCanary:
enabled: false
prometheusServiceMonitor:
enabled: false
console:
image:
pullSecrets:
- name: regcred
tolerations: []
zeebe:
clusterSize: "1"
partitionCount: "1"
replicationFactor: "1"
pvcStorageClassName: ${STORAGE_CLASS}
image:
pullSecrets:
- name: regcred
tolerations: []
zeebeGateway:
replicas: 1
image:
pullSecrets:
- name: regcred
tolerations: []
identity:
fullURL: "https://${HOST_CAMUNDA_IDENTITY}"
externalDatabase:
enabled: true
host: pg-host.storage.svc.cluster.local
port: 5432
username: identity
database: identity
password: ""
existingSecret: ""
existingSecretPasswordKey: password
image:
pullSecrets:
- name: regcred
tolerations: []
operate:
image:
pullSecrets:
- name: regcred
serviceAccount:
automountServiceAccountToken: true
tolerations: []
tasklist:
image:
pullSecrets:
- name: regcred
serviceAccount:
automountServiceAccountToken: true
tolerations: []
optimize:
image:
pullSecrets:
- name: regcred
serviceAccount:
automountServiceAccountToken: true
tolerations: []
executionIdentity:
image:
pullSecrets:
- name: regcred
tolerations: []
webModeler:
image:
pullSecrets:
- name: regcred
restapi:
tolerations: []
webapp:
tolerations: []
websockets:
tolerations: []
connectors:
image:
pullSecrets:
- name: regcred
serviceAccount:
automountServiceAccountToken: true
tolerations: []

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: camunda.yaml

View File

@ -0,0 +1,25 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cert-manager
namespace: cert-manager
spec:
interval: 5m
timeout: 10m
values:
controller:
image:
registry: cr.yandex/crp3ccidau046kdj8g9q/cert-manager
repository: cert-manager
acmesolver:
image:
registry: cr.yandex/crp3ccidau046kdj8g9q/cert-manager
repository: acmesolver
webhook:
image:
registry: cr.yandex/crp3ccidau046kdj8g9q/cert-manager
repository: cert-manager-webhook
cainjector:
image:
registry: cr.yandex/crp3ccidau046kdj8g9q/cert-manager
repository: cainjector

View File

@ -0,0 +1,28 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: cert-manager.yaml
- target:
group: cert-manager.io
version: v1
kind: ClusterIssuer
name: letsencrypt-issuer
patch: |-
$patch: delete
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer
- target:
group: cert-manager.io
version: v1
kind: ClusterIssuer
name: letsencrypt-issuer-istio
patch: |-
$patch: delete
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer-istio

View File

@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base

View File

@ -0,0 +1,117 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: istio-config
namespace: default
spec:
dependsOn: []
interval: 5m
timeout: 10m
values:
global:
env: contour
environments:
contour:
istio:
gateways:
platform:
name: platform-gateway
namespace: default
selector:
istio: ingressgateway
servers:
- hosts:
- ${HOST_LOGIN}
- ${HOST_CAMUNDA}
- ${HOST_CAMUNDA_IDENTITY}
- ${HOST_CAMUNDA_KEYCLOAK}
- ${HOST_CAMUNDA_OPTIMIZE}
- ${HOST_CAMUNDA_TASKLIST}
- ${HOST_RABBITMQ}
tls:
credentialName: istio-ingress-tls
virtualServices:
zitadel:
name: zitadel-virt-service
namespace: default
hosts:
- ${HOST_LOGIN}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: zitadel-idp-contour.zitadel.svc.cluster.local
port: 8080
camunda-operate:
name: camunda-operate-virt-service
namespace: default
hosts:
- ${HOST_CAMUNDA}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: camunda-operate.camunda.svc.cluster.local
port: 80
camunda-identity:
name: camunda-identity-virt-service
namespace: default
hosts:
- ${HOST_CAMUNDA_IDENTITY}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: camunda-identity.camunda.svc.cluster.local
port: 80
camunda-keycloak:
name: camunda-keycloak-virt-service
namespace: default
hosts:
- ${HOST_CAMUNDA_KEYCLOAK}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: camunda-keycloak.camunda.svc.cluster.local
port: 80
camunda-optimize:
name: camunda-optimize-virt-service
namespace: default
hosts:
- ${HOST_CAMUNDA_OPTIMIZE}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: camunda-optimize.camunda.svc.cluster.local
port: 80
camunda-tasklist:
name: camunda-tasklist-virt-service
namespace: default
hosts:
- ${HOST_CAMUNDA_TASKLIST}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: camunda-tasklist.camunda.svc.cluster.local
port: 80
rabbitmq:
name: rabbitmq-virt-service
namespace: default
hosts:
- ${HOST_RABBITMQ}
gateways:
- default/platform-gateway
routes:
- path:
prefix: /
service: rabbitmq.rabbitmq.svc.cluster.local
port: 15672

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: istio-config.yaml

View File

@ -58,6 +58,18 @@ spec:
renewBefore: 360h0m0s renewBefore: 360h0m0s
privateKey: privateKey:
rotationPolicy: Always rotationPolicy: Always
srx-ui-kit-tls:
dnsNames:
- srx-ui-kit.infra.sarex.tech
- srx-ui-kit-stage.infra.sarex.tech
issuerRef:
name: letsencrypt-issuer-istio
kind: ClusterIssuer
spec:
duration: 2160h0m0s
renewBefore: 360h0m0s
privateKey:
rotationPolicy: Always
nexus-tls: nexus-tls:
dnsNames: dnsNames:
- nexus.infra.sarex.tech - nexus.infra.sarex.tech
@ -80,6 +92,28 @@ spec:
renewBefore: 360h0m0s renewBefore: 360h0m0s
privateKey: privateKey:
rotationPolicy: Always rotationPolicy: Always
wiki-tls:
dnsNames:
- wiki.sarex.space
issuerRef:
name: letsencrypt-issuer-istio
kind: ClusterIssuer
spec:
duration: 2160h0m0s
renewBefore: 360h0m0s
privateKey:
rotationPolicy: Always
goalert-tls:
dnsNames:
- goalert.infra.sarex.io
issuerRef:
name: letsencrypt-issuer-istio
kind: ClusterIssuer
spec:
duration: 2160h0m0s
renewBefore: 360h0m0s
privateKey:
rotationPolicy: Always
istio: istio:
gateways: gateways:
vault: vault:
@ -104,6 +138,18 @@ spec:
tls: tls:
credentialName: kb-tls credentialName: kb-tls
mode: SIMPLE mode: SIMPLE
srx-ui-kit:
name: srx-ui-kit-gateway
namespace: istio-system
selector:
istio: ingressgateway
servers:
- hosts:
- srx-ui-kit.infra.sarex.tech
- srx-ui-kit-stage.infra.sarex.tech
tls:
credentialName: srx-ui-kit-tls
mode: SIMPLE
nexus: nexus:
name: nexus-gateway name: nexus-gateway
namespace: istio-system namespace: istio-system
@ -126,6 +172,28 @@ spec:
tls: tls:
credentialName: idp-tls credentialName: idp-tls
mode: SIMPLE mode: SIMPLE
wiki:
name: wiki-gateway
namespace: istio-system
selector:
istio: ingressgateway
servers:
- hosts:
- wiki.sarex.space
tls:
credentialName: wiki-tls
mode: SIMPLE
goalert:
name: goalert-gateway
namespace: istio-system
selector:
istio: ingressgateway
servers:
- hosts:
- goalert.infra.sarex.io
tls:
credentialName: goalert-tls
mode: SIMPLE
virtualServices: virtualServices:
vault-virt-service: vault-virt-service:
namespace: istio-system namespace: istio-system
@ -149,6 +217,28 @@ spec:
prefix: / prefix: /
service: kb-service.kb.svc.cluster.local service: kb-service.kb.svc.cluster.local
port: 80 port: 80
srx-ui-kit-virt-service:
namespace: istio-system
hosts:
- srx-ui-kit.infra.sarex.tech
gateways:
- istio-system/srx-ui-kit-gateway
routes:
- path:
prefix: /
service: universal-static-site-srx-ui-kit-pages.gitlab-pages-srx-ui-kit.svc.cluster.local
port: 80
srx-ui-kit-stage-virt-service:
namespace: istio-system
hosts:
- srx-ui-kit-stage.infra.sarex.tech
gateways:
- istio-system/srx-ui-kit-gateway
routes:
- path:
prefix: /
service: universal-static-site-srx-ui-kit-stage-pages.gitlab-pages-srx-ui-kit-stage.svc.cluster.local
port: 80
nexus-virt-service: nexus-virt-service:
namespace: istio-system namespace: istio-system
hosts: hosts:
@ -171,3 +261,25 @@ spec:
prefix: / prefix: /
service: idp.zitadel.svc.cluster.local service: idp.zitadel.svc.cluster.local
port: 8080 port: 8080
wiki-virt-service:
namespace: istio-system
hosts:
- wiki.sarex.space
gateways:
- istio-system/wiki-gateway
routes:
- path:
prefix: /
service: outline.outline.svc.cluster.local
port: 80
goalert-virt-service:
namespace: istio-system
hosts:
- goalert.infra.sarex.io
gateways:
- istio-system/goalert-gateway
routes:
- path:
prefix: /
service: goalert.goalert.svc.cluster.local
port: 8081

View File

@ -0,0 +1,31 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: ingressgateway
namespace: istio-system
spec:
interval: 5m
timeout: 10m
dependsOn:
- name: istio-base
namespace: istio-system
- name: istiod
namespace: istio-system
values:
_internal_defaults_do_not_set:
replicaCount: ${GATEWAY_REPLICAS}
service:
type: ClusterIP
nodeSelector:
sarex.io/gateway: "true"
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
istio: ingressgateway
topologyKey: kubernetes.io/hostname
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: istio-gateway.yaml

View File

@ -0,0 +1,12 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: istiod
namespace: istio-system
spec:
interval: 5m
timeout: 10m
values:
global:
imagePullSecrets:
- regcred

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: istio-pilot.yaml

View File

@ -0,0 +1,73 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: kafka
namespace: kafka
spec:
interval: 5m
timeout: 10m
postRenderers:
- kustomize:
patches:
- target:
group: apps
version: v1
kind: StatefulSet
namespace: kafka
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: generic
- op: add
path: /spec/template/spec/tolerations
value: []
values:
global:
imagePullSecrets:
- regcred
defaultStorageClass: ${STORAGE_CLASS}
image:
pullSecrets:
- regcred
controller:
replicaCount: 1
automountServiceAccountToken: true
persistence:
size: 8Gi
storageClass: ${STORAGE_CLASS}
overrideConfiguration:
offsets.topic.replication.factor: 1
transaction.state.log.replication.factor: 1
transaction.state.log.min.isr: 1
default.replication.factor: 1
min.insync.replicas: 1
broker:
replicaCount: 0
automountServiceAccountToken: true
listeners:
client:
protocol: SASL_PLAINTEXT
sslClientAuth: "none"
provisioning:
enabled: false
sasl:
managedExistingSecret:
enabled: false
existingSecret: ""
enabledMechanisms: PLAIN,SCRAM-SHA-512
interBrokerMechanism: PLAIN
controllerMechanism: PLAIN
client:
users: []
passwords: ""
tls:
type: PEM
vault:
enabled: true
role: kafka
authPath: auth/kubernetes
secretPath: secrets/data/kafka/bootstrap
clusterIdKey: clusterId
interBrokerPasswordKey: interBrokerPassword
controllerPasswordKey: controllerPassword

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: kafka.yaml

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- valkey.yaml
- outline.yaml

View File

@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
name: outline
labels:
istio-injection: enabled

View File

@ -0,0 +1,139 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: outline
namespace: outline
spec:
interval: 10m
timeout: 10m
chart:
spec:
chart: outline
version: "0.1.0"
sourceRef:
kind: HelmRepository
name: yc-oci-charts
namespace: flux-system
interval: 10m
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
dependsOn:
- name: istiod
namespace: istio-system
- name: outline-valkey
namespace: outline
values:
universal-chart:
global:
env: infra
image:
name:
infra: cr.yandex/crp3ccidau046kdj8g9q/outlinewiki/outline:1.12.0
envs:
- name: NODE_ENV
value:
_default: production
- name: URL
value:
_default: https://wiki.sarex.space
- name: PORT
value:
_default: "3000"
- name: WEB_CONCURRENCY
value:
_default: "1"
# TLS терминируется на istio ingressgateway
- name: FORCE_HTTPS
value:
_default: "false"
- name: ENABLE_UPDATES
value:
_default: "false"
- name: LOG_LEVEL
value:
_default: info
- name: PGSSLMODE
value:
_default: disable
- name: FILE_STORAGE
value:
_default: s3
- name: AWS_REGION
value:
_default: ru-msk
- name: AWS_S3_UPLOAD_BUCKET_URL
value:
_default: https://hb.ru-msk.vkcloud-storage.ru
- name: AWS_S3_UPLOAD_BUCKET_NAME
value:
_default: sarex-wiki
- name: AWS_S3_FORCE_PATH_STYLE
value:
_default: "true"
- name: AWS_S3_ACL
value:
_default: private
# VK Object Storage документирует presigned PUT; presigned POST не описан
- name: AWS_S3_UPLOAD_METHOD
value:
_default: put
- name: OIDC_DISPLAY_NAME
value:
_default: Sarex IAM
- name: OIDC_AUTH_URI
value:
_default: https://iam.sarex.io/oauth/v2/authorize
- name: OIDC_TOKEN_URI
value:
_default: https://iam.sarex.io/oauth/v2/token
- name: OIDC_USERINFO_URI
value:
_default: https://iam.sarex.io/oidc/v1/userinfo
- name: OIDC_LOGOUT_URI
value:
_default: https://iam.sarex.io/oidc/v1/end_session
- name: OIDC_USERNAME_CLAIM
value:
_default: preferred_username
- name: OIDC_SCOPES
value:
_default: openid profile email offline_access
# SMTP подключается отдельным шагом: добавить SMTP_HOST, SMTP_PORT,
# SMTP_FROM_EMAIL сюда и SMTP_USERNAME, SMTP_PASSWORD в secretEnvs.
secretEnvs:
- name: SECRET_KEY
secretName:
_default: outline
secretKey: SECRET_KEY
- name: UTILS_SECRET
secretName:
_default: outline
secretKey: UTILS_SECRET
- name: DATABASE_URL
secretName:
_default: outline-postgresql
secretKey: url
- name: REDIS_URL
secretName:
_default: outline
secretKey: REDIS_URL
- name: AWS_ACCESS_KEY_ID
secretName:
_default: outline
secretKey: AWS_ACCESS_KEY_ID
- name: AWS_SECRET_ACCESS_KEY
secretName:
_default: outline
secretKey: AWS_SECRET_ACCESS_KEY
- name: OIDC_CLIENT_ID
secretName:
_default: outline
secretKey: OIDC_CLIENT_ID
- name: OIDC_CLIENT_SECRET
secretName:
_default: outline
secretKey: OIDC_CLIENT_SECRET

View File

@ -0,0 +1,62 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: outline-valkey
namespace: outline
spec:
interval: 10m
timeout: 10m
chart:
spec:
chart: valkey
version: "0.1.0"
sourceRef:
kind: HelmRepository
name: yc-oci-charts
namespace: flux-system
interval: 10m
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
values:
fullnameOverride: outline-valkey
image:
registry: cr.yandex
repository: crp3ccidau046kdj8g9q/valkey/valkey
tag: 8.0.2-debian-12-r6
global:
imagePullSecrets:
- istio-registry-secret
security:
allowInsecureImages: true
architecture: standalone
auth:
enabled: true
sentinel: false
existingSecret: outline-valkey
existingSecretPasswordKey: valkey-password
# Outline хранит в Valkey очереди фоновых задач и состояние websocket.
# Персистентность не нужна, вытеснение ключей недопустимо для очередей.
commonConfiguration: |-
appendonly no
save ""
maxmemory 256mb
maxmemory-policy noeviction
primary:
podAnnotations:
sidecar.istio.io/inject: "false"
nodeSelector:
sarex.io/pool: svc
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
memory: 384Mi
persistence:
enabled: false
metrics:
enabled: false

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: postgresql.yaml

View File

@ -0,0 +1,104 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: postgresql
namespace: postgresql
spec:
interval: 5m
timeout: 2h
install:
timeout: 2h
remediation:
retries: 3
upgrade:
timeout: 2h
remediation:
retries: 3
values:
global:
security:
allowInsecureImages: true
defaultStorageClass: ${STORAGE_CLASS}
postgresql:
auth:
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: Always
metrics:
enabled: false
prometheusRule:
enabled: false
primary:
automountServiceAccountToken: true
containerSecurityContext:
readOnlyRootFilesystem: false
persistence:
storageClass: ${STORAGE_CLASS}
size: 20Gi
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
nodeSelector:
dedicated: generic
tolerations: []
contour:
enabled: true
adminUser: "postgres"
vault:
enabled: true
role: postgresql-zitadel
authPath: auth/kubernetes
secretPath: secrets/data/postgresql-zitadel/admin
secretKey: postgres-password
usersSecretPath: secrets/data/zitadel/postgresql
sharedPreloadLibraries: "timescaledb,pg_stat_statements"
databases:
- name: zitadel
user: zitadel
passwordKey: password
extensions: []
restoreFromDump: false

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: rabbitmq.yaml

View File

@ -0,0 +1,104 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: rabbitmq
namespace: rabbitmq
spec:
interval: 5m
timeout: 10m
postRenderers:
- kustomize:
patches:
- target:
group: apps
version: v1
kind: StatefulSet
namespace: rabbitmq
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: generic
- op: add
path: /spec/template/spec/tolerations
value: []
- target:
group: cert-manager.io
version: v1
kind: Certificate
namespace: gateway
name: rmq-tls
patch: |-
$patch: delete
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: rmq-tls
namespace: gateway
- target:
group: networking.istio.io
version: v1beta1
kind: Gateway
namespace: gateway
name: rmq-gateway
patch: |-
$patch: delete
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: rmq-gateway
namespace: gateway
- target:
group: networking.istio.io
version: v1
kind: VirtualService
namespace: rabbitmq
name: rmq-virt-service
patch: |-
$patch: delete
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: rmq-virt-service
namespace: rabbitmq
values:
global:
security:
allowInsecureImages: true
virtualService: null
gateway: null
certificate: null
metrics:
serviceMonitor:
enabled: false
default:
enabled: false
perObject:
enabled: false
detailed:
enabled: false
extraServiceMonitors: []
replicaCount: 1
resources:
requests:
memory: 1Gi
persistence:
storageClass: ${STORAGE_CLASS}
size: 10Gi
auth:
securePassword: true
enableLoopbackUser: false
existingPasswordSecret: ""
vault:
enabled: true
role: rabbitmq
authPath: auth/kubernetes
secretPath: secrets/data/rabbitmq/auth
usernameKey: username
passwordKey: password
advancedConfiguration: |-
[
{rabbit, [
{loopback_users, []}
]}
].

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: vault.yaml

View File

@ -0,0 +1,110 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: vault
namespace: vault
spec:
interval: 5m
timeout: 10m
install:
disableWait: true
upgrade:
disableWait: true
postRenderers:
- kustomize:
patches:
- target:
group: apps
version: v1
kind: StatefulSet
namespace: vault
name: vault-vault-contour
patch: |-
- op: replace
path: /spec/template/spec/nodeSelector
value:
dedicated: generic
- op: replace
path: /spec/template/spec/tolerations
value: []
values:
global:
namespace: vault
imagePullSecrets:
- name: regcred
backup:
enabled: false
injector:
nodeSelector:
dedicated: generic
tolerations: []
server:
includeConfigAnnotation: true
nodeSelector:
dedicated: generic
tolerations: []
dataStorage:
size: 10Gi
storageClass: ${STORAGE_CLASS}
volumes:
- name: unseal-keys
secret:
secretName: vault-unseal-keys
optional: true
defaultMode: 0440
extraContainers:
- name: unsealer
image: cr.yandex/crp3ccidau046kdj8g9q/vault/vault:1.21.2
imagePullPolicy: IfNotPresent
env:
- name: VAULT_ADDR
value: http://127.0.0.1:8200
command:
- /bin/sh
- -c
- |
while true; do
if vault status >/dev/null 2>&1; then
:
else
rc=$?
if [ "$rc" -eq 2 ]; then
if [ -s /vault/unseal-keys/key1 ] && [ -s /vault/unseal-keys/key2 ] && [ -s /vault/unseal-keys/key3 ]; then
for k in key1 key2 key3; do
vault operator unseal "$(cat /vault/unseal-keys/$k)" >/dev/null 2>&1 || echo "unseal call failed"
done
if vault status >/dev/null 2>&1; then echo "unsealed"; else echo "still sealed"; fi
else
echo "sealed, keys not mounted"
fi
fi
fi
sleep 10
done
volumeMounts:
- name: unseal-keys
mountPath: /vault/unseal-keys
readOnly: true
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
memory: 64Mi
ha:
replicas: 1
raft:
config: |
ui = true
listener "tcp" {
tls_disable = 1
address = "[::]:8200"
cluster_address = "[::]:8201"
}
storage "raft" {
path = "/vault/data"
}
service_registration "kubernetes" {}

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
patches:
- path: zitadel.yaml

View File

@ -0,0 +1,168 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: zitadel
namespace: zitadel
spec:
interval: 5m
timeout: 10m
dependsOn:
- name: postgresql
namespace: postgresql
postRenderers:
- kustomize:
patches:
- target:
group: apps
version: v1
kind: Deployment
name: zitadel-idp-contour
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: generic
- op: add
path: /spec/template/spec/tolerations
value: []
- op: replace
path: /spec/template/metadata/annotations/vault.hashicorp.com~1agent-inject-template-zitadel-vault-config.yaml
value: |-
{{- with secret "secrets/data/zitadel/postgresql" -}}
Database:
postgres:
User:
Password: |-
{{ index .Data.data "password" }}
Admin:
Password: |-
{{ index .Data.data "password" }}
FirstInstance:
Org:
Human:
Password: |-
{{ index .Data.data "humanPassword" }}
{{- end -}}
- target:
group: batch
version: v1
kind: Job
name: zitadel-idp-contour-init
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: generic
- op: add
path: /spec/template/spec/tolerations
value: []
- op: replace
path: /spec/template/metadata/annotations/vault.hashicorp.com~1agent-inject-template-zitadel-vault-config.yaml
value: |-
{{- with secret "secrets/data/zitadel/postgresql" -}}
Database:
postgres:
User:
Password: |-
{{ index .Data.data "password" }}
Admin:
Password: |-
{{ index .Data.data "password" }}
FirstInstance:
Org:
Human:
Password: |-
{{ index .Data.data "humanPassword" }}
{{- end -}}
- target:
group: batch
version: v1
kind: Job
name: zitadel-idp-contour-setup
patch: |-
- op: add
path: /spec/template/spec/nodeSelector
value:
dedicated: generic
- op: add
path: /spec/template/spec/tolerations
value: []
- op: replace
path: /spec/template/metadata/annotations/vault.hashicorp.com~1agent-inject-template-zitadel-vault-config.yaml
value: |-
{{- with secret "secrets/data/zitadel/postgresql" -}}
Database:
postgres:
User:
Password: |-
{{ index .Data.data "password" }}
Admin:
Password: |-
{{ index .Data.data "password" }}
FirstInstance:
Org:
Human:
Password: |-
{{ index .Data.data "humanPassword" }}
{{- end -}}
values:
zitadel:
configmapConfig:
ExternalDomain: ${HOST_LOGIN}
ExternalSecure: true
# IAM_OWNER service user for sarexctl phase zitadel-setup; the chart stores its key
# in secret zitadel/sarex-installer. Created only on the first instance setup.
FirstInstance:
Org:
Machine:
Machine:
Username: sarex-installer
Name: sarexctl
MachineKey:
ExpirationDate: "2099-01-01T00:00:00Z"
Type: 1
debug:
enabled: false
postgresqlSecret:
create: false
vault:
enabled: true
role: zitadel
authPath: auth/kubernetes
secretPath: secrets/data/zitadel/postgresql
secretKey: password
kvVersion: 2
fileName: zitadel-vault-config.yaml
serviceAccount:
create: true
name: zitadel-idp-contour
replicaCount: 1
pdb:
enabled: false
env:
- name: ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED
value: "false"
- name: ZITADEL_SYSTEMDEFAULTS_PASSWORDHASHER_VERIFIERS
value: "bcrypt,pbkdf2"
- name: ZITADEL_MACHINE_IDENTIFICATION_HOSTNAME_ENABLED
value: "true"
- name: ZITADEL_DATABASE_POSTGRES_HOST
value: "postgresql.postgresql.svc.cluster.local"
- name: ZITADEL_DATABASE_POSTGRES_PORT
value: "5432"
- name: ZITADEL_DATABASE_POSTGRES_USER_USERNAME
value: "zitadel"
- name: ZITADEL_DATABASE_POSTGRES_ADMIN_EXISTINGDATABASE
value: "zitadel"
- name: ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME
value: "zitadel"
- name: ZITADEL_DATABASE_POSTGRES_DATABASE
value: "zitadel"
- name: ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE
value: "disable"
- name: ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE
value: "disable"
- name: ZITADEL_DEFAULTINSTANCE_ORG_HUMAN_USERNAME
value: "zitadel-admin"
- name: ZITADEL_DEFAULTINSTANCE_ORG_NAME
value: "Sarex"