Skip to content

Consul

Consul служит хранилищем конфигурации ключей-значений (KV) для Meduza. Конфигурация приложений — URL баз данных, API-ключи, feature-флаги — хранится в виде JSON в KV-хранилище Consul и инжектится в контейнеры при деплое через блок template в Nomad.

Структура KV-хранилища

Конфигурация организована по сервисам и окружениям:

hub/
├── prod/
│   └── config    → {"DATABASE_URL": "...", "API_KEY": "...", ...}
├── stage/
│   └── config    → {"DATABASE_URL": "...", "API_KEY": "...", ...}
└── dev/
    └── config    → {"DATABASE_URL": "...", "API_KEY": "...", ...}

Каждый ключ config содержит один JSON-объект, где ключи — это имена переменных окружения, а значения — соответствующие значения:

json
{
  "DATABASE_URL": "postgresql://user:pass@db-host:5432/hub_prod",
  "REDIS_URL": "redis://redis-host:6379/0",
  "API_KEY": "sk-prod-abc123",
  "LOG_LEVEL": "info",
  "FEATURE_NEW_DASHBOARD": "true"
}

WARNING

Значения Consul KV хранятся незашифрованными по умолчанию. Чувствительные данные (пароли к базам данных, API-ключи) видны любому, кто имеет доступ к UI или API Consul. Ограничьте доступ к порту Consul (8500) и используйте SSH-туннелирование.

Как Nomad читает конфигурацию Consul

Блок template в Nomad связывает данные Consul KV с работающими контейнерами. Вот паттерн, используемый в задаче backend для hub:

hcl
task "backend" {
  driver = "docker"

  # ...

  template {
    data = <<-TPL
    {{ with consulKey "hub/${var.env}/config" }}
    {{ range $key, $value := .Data | parseJSON }}
    {{ $key }}={{ $value }}
    {{ end }}
    {{ end }}
    TPL

    destination = "secrets/env.env"
    env         = true
  }
}

Что это делает

  1. consulKey "hub/${var.env}/config" — читает необработанное значение из пути Consul KV (например, hub/prod/config).
  2. parseJSON — парсит JSON-строку в Go-карту.
  3. range $key, $value — итерирует по каждой паре ключ-значение.
  4. $key=$value — записывает каждую пару в формате KEY=VALUE.
  5. destination = "secrets/env.env" — результат рендеринга записывается в этот файл внутри директории аллокации.
  6. env = true — указывает Nomad парсить файл как переменные окружения и инжектить их в окружение контейнера.

Результат рендеринга

Для JSON-конфигурации выше файл secrets/env.env будет выглядеть так:

env
DATABASE_URL=postgresql://user:pass@db-host:5432/hub_prod
REDIS_URL=redis://redis-host:6379/0
API_KEY=sk-prod-abc123
LOG_LEVEL=info
FEATURE_NEW_DASHBOARD=true

Эти значения становятся переменными окружения, доступными приложению внутри контейнера.

mermaid
flowchart LR
    Consul["Consul KV\nhub/prod/config\n(JSON)"]
    Template["Nomad Template\nBlock"]
    EnvFile["secrets/env.env\nKEY=VALUE lines"]
    Container["Container\nEnvironment"]

    Consul -->|"consulKey"| Template
    Template -->|"parseJSON + range"| EnvFile
    EnvFile -->|"env = true"| Container

Обновление конфигурации

Через Consul CLI

bash
# Read current config
consul kv get hub/prod/config | jq .

# Update config (replace entire JSON blob)
consul kv put hub/prod/config @config.json

# Update config inline
consul kv put hub/prod/config '{
  "DATABASE_URL": "postgresql://user:pass@db-host:5432/hub_prod",
  "REDIS_URL": "redis://redis-host:6379/0",
  "API_KEY": "sk-prod-new-key",
  "LOG_LEVEL": "debug",
  "FEATURE_NEW_DASHBOARD": "true"
}'

Через Consul HTTP API

bash
# Read
curl -s http://localhost:8500/v1/kv/hub/prod/config?raw | jq .

# Write (value must be the raw body)
curl -X PUT \
  -d '{"DATABASE_URL":"postgresql://...","LOG_LEVEL":"debug"}' \
  http://localhost:8500/v1/kv/hub/prod/config

Через Consul UI

  1. SSH-туннель к хосту: ssh -L 8500:localhost:8500 user@kvm-host
  2. Откройте http://localhost:8500 в браузере
  3. Перейдите в Key/Value > hub > prod > config
  4. Отредактируйте JSON и нажмите Save

TIP

После обновления значения Consul KV необходимо переразвернуть Nomad-задачу, чтобы изменения вступили в силу. Блок template вычисляется при деплое, а не во время выполнения.

bash
# Re-deploy to pick up new config
nomad job run -var-file=prod.vars.hcl hub.nomad.hcl

Рабочий процесс: добавление новой переменной конфигурации

  1. Определите имя и значение переменной — следуйте конвенции UPPER_SNAKE_CASE.

  2. Прочитайте текущую конфигурацию, чтобы не перезаписать существующие значения:

    bash
    consul kv get hub/prod/config | jq . > /tmp/config.json
  3. Отредактируйте JSON, добавив или изменив переменную:

    bash
    # Using jq to add a key
    jq '. + {"NEW_VARIABLE": "new-value"}' /tmp/config.json > /tmp/config-updated.json
  4. Запишите обратно в Consul:

    bash
    consul kv put hub/prod/config @/tmp/config-updated.json
  5. Переразверните Nomad-задачу:

    bash
    nomad job run -var-file=prod.vars.hcl hub.nomad.hcl
  6. Убедитесь, что переменная присутствует в работающем контейнере:

    bash
    nomad alloc exec <alloc-id> env | grep NEW_VARIABLE

WARNING

Всегда выполняйте чтение-изменение-запись для всего JSON-блоба. Команда Consul KV put заменяет всё значение целиком — она не объединяет. Если вы запишете частичный JSON-объект, вы потеряете все остальные переменные конфигурации.

Изоляция окружений

Каждое окружение имеет собственный KV-путь, обеспечивая полную изоляцию:

ОкружениеKV-путьПеременная Nomad
prodhub/prod/configvar.env = "prod"
stagehub/stage/configvar.env = "stage"
devhub/dev/configvar.env = "dev"

Один и тот же блок template работает для всех окружений, потому что он подставляет ${var.env} в KV-путь:

hcl
consulKey "hub/${var.env}/config"

Это означает, что один файл задачи (hub.nomad.hcl) может деплоиться в любое окружение, просто изменяя переменную env.

Резервное копирование и восстановление

Данные Consul KV следует регулярно резервировать. Потеря KV-хранилища означает, что всю конфигурацию приложений придётся воссоздавать вручную.

bash
# Export all KV data as JSON
consul kv export hub/ > hub-kv-backup.json

# Import from backup
consul kv import @hub-kv-backup.json

TIP

Храните резервные копии KV в системе контроля версий или в безопасном месте для бэкапов. Это ваш источник истины для конфигурации приложений.

Дополнительное чтение

  • Nomad — где определяются блоки template, потребляющие Consul KV
  • Traefik — обратный прокси, маршрутизирующий трафик к сервисам, настроенным через Consul

Документация по инфраструктуре