From 25047c7607148cb87df8a865ea92ac6ad110bd59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 10 Aug 2026 19:19:45 +0400 Subject: [PATCH] =?UTF-8?q?feat:=20curated/=20directory=20=E2=80=94=20agen?= =?UTF-8?q?t-managed=20examples=20(PG=20+=20user=20+=20DB=20+=20S3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TOOLS/scripts/04_build_and_publish_docs.sh | 6 +- docs/curated/postgres/pg_user_db.md | 138 +++++++++++++++++++++ mkdocs.yml | 2 + 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 docs/curated/postgres/pg_user_db.md diff --git a/TOOLS/scripts/04_build_and_publish_docs.sh b/TOOLS/scripts/04_build_and_publish_docs.sh index 40cc1c9..2c12b56 100755 --- a/TOOLS/scripts/04_build_and_publish_docs.sh +++ b/TOOLS/scripts/04_build_and_publish_docs.sh @@ -159,12 +159,16 @@ load_s3cfg_registry() { TMP_CFG="${ROOT_DIR}/.mkdocs.tmp.yml" export ROOT_DIR -# Copy 30_registry assets into docs dir so guides/nav work when docs_dir is external +# Copy 30_registry assets and curated content into docs dir if [[ -n "${MKDOCS_DOCS_DIR:-}" ]]; then if [[ -d "${ROOT_DIR}/docs/30_registry" ]]; then mkdir -p "${MKDOCS_DOCS_DIR}/30_registry" cp -r "${ROOT_DIR}/docs/30_registry/"* "${MKDOCS_DOCS_DIR}/30_registry/" 2>/dev/null || true fi + if [[ -d "${ROOT_DIR}/docs/curated" ]]; then + mkdir -p "${MKDOCS_DOCS_DIR}/curated" + cp -r "${ROOT_DIR}/docs/curated/"* "${MKDOCS_DOCS_DIR}/curated/" 2>/dev/null || true + fi fi python3 - <<'PY' diff --git a/docs/curated/postgres/pg_user_db.md b/docs/curated/postgres/pg_user_db.md new file mode 100644 index 0000000..12bd424 --- /dev/null +++ b/docs/curated/postgres/pg_user_db.md @@ -0,0 +1,138 @@ +# PostgreSQL: кластер + пользователь + база + S3-бэкап + +Проверенный сценарий. Протестировано 2026-08-10 на TEST-стенде. + +## Что создаётся + +| Ресурс | Имя в манифесте | Назначение | +|--------|----------------|-----------| +| `nubes_postgres` | `main_pg` | Кластер PostgreSQL (1 реплика, 500m CPU, 512MB RAM, 10GB диск) | +| `nubes_postgres_user` | `app_user` | Пользователь БД с правами `ddl_user` | +| `nubes_postgres_database` | `app_db` | База данных, владелец — `app_user` | +| `nubes_s3bucket` | `backups` | S3-бакет для хранения бэкапов | + +## Переменные + +Создай `terraform.tfvars`: + +```hcl +api_token = "***" # токен из Личного кабинета +realm = "k8s-3-sandbox-nubes-ru" # кластер Kubernetes +s3_uid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # UUID твоего S3 +s3_user_uid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # UUID пользователя S3 +``` + +## Провайдер + +```hcl +terraform { + required_providers { + nubes = { + source = "tf-registry.containerk8s.services.ngcloud.ru/nubes-test/nubes" + version = "5.0.5" + } + } +} + +variable "api_token" { type = string; sensitive = true } +variable "realm" { type = string } +variable "s3_uid" { type = string } +variable "s3_user_uid" { type = string } + +provider "nubes" { + api_token = var.api_token + api_endpoint = "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" +} +``` + +## Кластер PostgreSQL + +```hcl +resource "nubes_postgres" "main_pg" { + resource_name = "my-postgres" + + startup_configuration = { + resource_realm = var.realm + } + + cluster_configuration = { + cpu = 500 # milicores (1000 = 1 ядро) + memory = 512 # megabytes + replicas = 1 # 1, 3, 5 или 7 + disk = 10 # gigabytes + } + + access_configuration = { + master_ip_space = "no-needed" + master_access_list = jsonencode(["10.0.0.0/8"]) + slave_ip_space = "no-needed" + slave_access_list = jsonencode([]) + } + + postgres_configuration = { + version = "17" + ssl_required = true + pooler_master = false + pooler_slave = false + } + + backup_configuration = { + s3_uid = var.s3_uid + retain = 14 # хранить 14 копий + schedule = "0 0 * * *" # ежедневно в полночь + } + + autoscale_configuration = { + enabled = false + schedule = 0 + percent = 10 + quota = 100 + } + + mtls_configuration = { + type = "off" + duration_ca = 175200 + duration_server = 87600 + } + + operation_timeout = "11m" +} +``` + +## Пользователь и база данных + +```hcl +# Пользователь с правами создания БД и ролей +resource "nubes_postgres_user" "app_user" { + postgres_id = nubes_postgres.main_pg.id + username = "app_user" + role = "ddl_user" # app_user — только DML; ddl_user — DDL + DML + mtls_access = false +} + +# База данных, владелец — созданный выше пользователь +resource "nubes_postgres_database" "app_db" { + postgres_id = nubes_postgres.main_pg.id + db_name = "my_app_db" + db_owner = nubes_postgres_user.app_user.username +} +``` + +## S3-бакет для бэкапов + +```hcl +resource "nubes_s3bucket" "backups" { + resource_name = "pg-backup-bucket" + s3_user_uid = var.s3_user_uid + bucket_name = "my-app-backups" +} +``` + +## Запуск + +```bash +terraform init +terraform apply +``` + +Все четыре ресурса создаются за один `apply`. Порядок не важен — Terraform сам выстроит зависимости: сначала кластер, потом пользователь, потом БД и бакет. diff --git a/mkdocs.yml b/mkdocs.yml index ff6eb56..6b2dca8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -58,3 +58,5 @@ nav: - Структура манифестов: 30_registry/guides/terraform-structure.md - S3 Notifications: 30_registry/guides/s3-bucket-notifications.md - Глоссарий: 30_registry/guides/glossary.md + - Проверенные примеры: + - PostgreSQL: curated/postgres/pg_user_db.md