Установка через Wizard¶
Wizard — официальный Go-инсталлер AppSec.AIGate, упакованный в Docker-образ. Управляет полным жизненным циклом установки: namespace, pull-secret, инфраструктура, продуктовые сервисы — в правильном порядке. Один и тот же бинарь обслуживает несколько продуктов; для AiGate образ собирается с PRODUCT=aigate.
Docker Compose
Установка пилот/демо на отдельном сервере через Docker Compose описана в разделе Установка и запуск. Этот раздел — про промышленное развёртывание в Kubernetes.
Способ доступа извне (exposure)¶
Wizard разделяет два независимых решения:
exposure— как внешний трафик попадает в сервисы. Единый источник правды:gateway|ingress|none.auth.enabled— включён ли OIDC (Keycloak + Envoy SecurityPolicy). Ортогонален и учитывается только приexposure: gateway.
Трафик идёт через Envoy Gateway (Gateway API). Только этот режим поддерживает OIDC.
auth: false— Gateway/HTTPRoute без аутентификации (dev/smoke).auth: true— Keycloak + OIDC SecurityPolicy, JWT во всех сервисах (production). Требует TLS-секрет и DNS на хосты.
Классический Ingress (ingress-nginx и т.п.). OIDC недоступен — сервисы открыты без логина.
Точка входа не создаётся. После установки вы сами создаёте Gateway/Ingress/HTTPRoute и аутентификацию. Доступ для проверки — через kubectl port-forward.
AiGate-специфика инфраструктуры
AiGate не использует NATS (в отличие от GenAI). PostgreSQL — в режиме databases (отдельная БД на группу сервисов), MinIO — только бакет policies. Realm Keycloak — llm-firewall с ролями admin/operator/viewer.
Быстрый старт: интерактивный Wizard¶
docker run --rm -it \
-v ~/.kube/config:/kubeconfig:ro \
-v $(pwd):/workspace \
registry.appsec.global/appsecaigate-release/wizard:<VERSION> \
wizard
OIDC / exec-based kubeconfig
Если ~/.kube/config использует OIDC (auth-provider: oidc) или exec-плагин (exec: command: ...) — wizard не подключится: внешние бинари недоступны в контейнере. Нужен kubeconfig со статическим Bearer-токеном.
Создайте ~/kube-wizard.yaml с полем user.token: <TOKEN> (токен из вашего OIDC-провайдера) и монтируйте его: -v ~/kube-wizard.yaml:/kubeconfig:ro. Токен обычно живёт ~1 час — при истечении пересоздать.
Wizard задаёт минимум вопросов и пишет values.yaml в текущую директорию:
AppSec AIGate — Setup Wizard
────────────────────────────
Domain: app.example.com
Namespace [aigate]:
How should services be exposed? (gateway/ingress/none) [gateway]: gateway
Enable auth (Keycloak + Envoy OIDC)? [y/N]: y
TLS secret name (kubectl create secret tls <name> ...) [aigate-tls]: aigate-tls
Gateway className [aigate-class]:
Gateway external IP (leave blank for cloud auto-assign):
Enable persistence (required for production)? [y/N]: y
StorageClass (leave blank for cluster default):
✓ values.yaml written
Run install now? [Y/n]: y
Куда пишется values.yaml
Внутри контейнера инсталлер обнаруживает /workspace и пишет файл туда — он появляется в текущей директории хоста благодаря -v $(pwd):/workspace.
По окончании wizard печатает endpoints и DNS-записи (при auth: true — также команду для пароля bootstrap-пользователя aigate-admin@appsec.global из секрета keycloak-auth).
Запуск как in-cluster Job¶
Альтернатива docker run с рабочей машины — запуск инсталлера внутри кластера через Kubernetes Job. Предпочтительно, когда:
- нет прямого доступа к kube-API с локальной машины (только in-cluster);
- хочется, чтобы wait-for зависимостей шёл по внутреннему DNS кластера;
- установка выполняется из CI/CD или bastion-пода.
Образ full-таргета уже несёт вшитые чарты и ENTRYPOINT ["/app/installer", "--local-charts", "/charts"]; команда (check/install/delete) добавляется через args.
1. ConfigMap с values¶
kubectl -n aigate create configmap wizard-values \
--from-file=values.yaml=values.yaml \
--dry-run=client -o yaml | kubectl apply -f -
2. ServiceAccount + RBAC¶
Wizard создаёт namespace, ставит helm-релизы инфры и сервисов, детектит CRD (Envoy Gateway) — нужны широкие права.
apiVersion: v1
kind: ServiceAccount
metadata: { name: wizard-installer, namespace: aigate }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: { name: wizard-installer-admin }
roleRef: { apiGroup: rbac.authorization.k8s.io, kind: ClusterRole, name: cluster-admin }
subjects:
- { kind: ServiceAccount, name: wizard-installer, namespace: aigate }
3. Job — сначала check (preflight, ничего не меняет)¶
apiVersion: batch/v1
kind: Job
metadata: { name: wizard-check, namespace: aigate }
spec:
backoffLimit: 0
template:
spec:
serviceAccountName: wizard-installer
restartPolicy: Never
imagePullSecrets: [{ name: harbor-cr }]
containers:
- name: wizard
image: registry.appsec.global/appsecaigate-release/wizard:<VERSION>
args: ["check", "-f", "/cfg/values.yaml"] # затем install / delete
env:
- { name: KUBECONFIG, value: "" } # форсит fallback на in-cluster SA
volumeMounts: [{ name: cfg, mountPath: /cfg }]
volumes:
- name: cfg
configMap: { name: wizard-values }
После зелёного check — пересоздать Job с args: ["install", "-f", "/cfg/values.yaml"].
kubectl -n aigate get pods -l job-name=wizard-check # Completed = exit 0
kubectl -n aigate logs job/wizard-check # таблица CHECK ... ✓ all checks passed
Грабли in-cluster Job
ImagePullBackOff: no basic auth credentials—harbor-crавторизует хостregistry.appsec.global. Вimage:использовать именно его, неharbor.prod.swordfishsecurity.com(один Harbor, но imagePullSecret матчится по хосту).loading kubeconfig— образ ставитENV KUBECONFIG=/kubeconfig, а в Job такого файла нет. Выставитьenv KUBECONFIG=""→ клиент фоллбэкнется на in-cluster SA.app-secret:tokenization-vault ... requiredна check — создать секрет до install (см. Секреты).
Установка из готового values.yaml¶
docker run --rm \
-v ~/.kube/config:/kubeconfig:ro \
-v ./values.yaml:/values.yaml \
-e HARBOR_PASS="<пароль>" \
registry.appsec.global/appsecaigate-release/wizard:<VERSION> \
install --harbor-user "<логин>" -f /values.yaml
Команды и флаги¶
| Команда | Описание |
|---|---|
wizard |
Интерактивный ввод → values.yaml → опциональный install |
install |
Полная установка всех компонентов |
update |
Умный апгрейд — пропускает релизы без изменений (по хешу values+версии) |
update --force |
Принудительный апгрейд всех релизов (hotfix под тот же semver) |
delete |
Удалить Helm-релизы (--wipe-pvc — также PVC, потеря данных) |
check |
Pre-flight проверки без изменений |
| Флаг | По умолчанию | Описание |
|---|---|---|
-f, --values <path> |
values.yaml |
Путь к конфигурации |
--dry-run |
false |
Отрендерить манифесты без применения |
--only <a,b> |
— | Только указанные фазы |
--skip <a,b> |
— | Пропустить фазы |
--set key=value |
— | Переопределить значение (повторяемый) |
--harbor-user |
— | Логин Harbor для pull-secret |
--harbor-pass |
$HARBOR_PASS |
Пароль Harbor (предпочтительно env) |
--harbor-server |
registry.appsec.global |
Хост Harbor |
--parallel N |
4 |
Параллельность Phase 2 |
--no-gpu |
false |
Пропустить GPU-сервисы (gpu: true в профиле) — кластер без GPU-нод |
--skip-services <a,b> |
— | Пропустить конкретные phase-2 сервисы |
--release-version |
вшита в образ | Переопределить версию чартов |
Пароль Harbor через env
Передавайте пароль через -e HARBOR_PASS="...", не через --harbor-pass — чтобы не светить в ps aux.
Фазы установки¶
| Фаза | Имя | Что делает | Пропускается |
|---|---|---|---|
| Pre-flight | preflight:secrets |
Наличие Secret'ов | при secrets.create: true |
| Pre-flight | preflight:gateway |
Envoy Gateway / Gateway API CRD | при exposure≠gateway → ok/warn |
| Pre-flight | preflight:gpu |
Нода с nvidia.com/gpu |
если нет GPU-сервисов к деплою или --no-gpu |
| Pre-flight | preflight:deps |
Непустота global.deps.*.existingSecret |
— |
| Pre-flight | preflight:appsecrets |
App-секреты продукта (для AiGate — tokenization-vault-secrets) |
если профиль их не требует |
| Phase 1 | phase1:infra |
postgres, redis, minio, keycloak, opa | — |
| Phase 1.1 | phase1.1:bootstrap |
БД, бакет policies, realm llm-firewall |
если *.bootstrap не задан |
| Phase 1.5 | phase1.5 |
aigate-gateway (GatewayClass + OIDC) | при exposure≠gateway |
| Phase 2 | phase2:product |
16 продуктовых сервисов | — |
| Phase 2.5 | phase2.5 |
Ingress для UI | при exposure≠ingress |
Частичный запуск¶
# Только продуктовые сервисы (после hotfix образа)
docker run --rm ... install --only phase2:product -f /values.yaml
# Пропустить инфраструктуру
docker run --rm ... install --skip phase1:infra,phase1.1:bootstrap -f /values.yaml
# Кластер без GPU — поднять всё, кроме ML-сервисов
docker run --rm ... install --no-gpu -f /values.yaml
preflight:gpu
AiGate несёт три GPU-сервиса (content-safety, threat-detector, translation-service). Если деплоятся они, но в кластере 0 nvidia.com/gpu — preflight:gpu завалит установку с подсказкой (добавить GPU-ноду или --no-gpu). Без GPU-сервисов фаза пропускается.
values.yaml — справочник¶
Обязательные параметры¶
| Параметр | Описание |
|---|---|
domain |
Базовый домен инсталляции (не app.customer.com) |
namespace |
Kubernetes namespace (default: aigate) |
Схема (AiGate)¶
# ─── Базовые ──────────────────────────────────────────────────────────────
domain: "app.example.com" # ОБЯЗАТЕЛЕН
namespace: "aigate"
# ─── Доступ извне ─────────────────────────────────────────────────────────
exposure: "gateway" # gateway | ingress | none
auth:
enabled: false # OIDC; учитывается только при exposure=gateway
gateway: # заполнять при exposure=gateway
publicScheme: "https" # http | https
externalIPs: [] # bare-metal: ["10.0.0.1"]; cloud: []
className: "aigate-class"
ingress:
className: "" # при exposure=ingress
ingressTlsSecretName: "" # при auth=true + https
imagePullSecretName: "harbor-cr"
# ─── Секреты ──────────────────────────────────────────────────────────────
secrets:
create: true # false = создать Secret'ы вручную до запуска
# ─── Инфра-компоненты (AiGate — без NATS) ─────────────────────────────────
postgres:
enabled: true
persistence: { enabled: false, size: "50Gi", storageClass: "" }
redis:
enabled: true
persistence: { enabled: false, size: "2Gi", storageClass: "" }
minio:
enabled: true
persistence: { enabled: false, size: "100Gi", storageClass: "" }
keycloak:
enabled: true # только при auth.enabled: true
persistence: { enabled: false, size: "1Gi", storageClass: "" }
# ─── Внешняя инфраструктура ───────────────────────────────────────────────
global:
image:
registry: "registry.appsec.global"
repositoryPrefix: "appsecaigate-release"
deps:
postgres:
host: postgres
port: 5432
existingSecret: postgres-auth
# bootstrap: true # создать БД admin_api_db / profiles_registry / vault_db
redis:
host: redis
port: 6379
existingSecret: redis-auth
minio:
host: minio
port: 9000
existingSecret: minio-auth
# scheme: https # если внешний MinIO за TLS (default: http)
# bootstrap: true # создать бакет policies
keycloak:
host: keycloak
port: 8080
# scheme: https # если внешний Keycloak за TLS
# bootstrap: true # создать realm llm-firewall
# ─── App-секреты продукта (создаёт клиент сам) ────────────────────────────
# tokenization-vault-secrets/VAULT_MASTER_KEY — см. Секреты
license:
centerPublicKey: "" # выдаёт SwordFish Security
bootstrap: идемпотентность
Операции bootstrap безопасны для повторного запуска (IF NOT EXISTS / 409 Conflict = пропуск). Нужны для внешних сервисов (enabled: false) при первом install; для встроенных (enabled: true) инициализацию делают Helm-хуки автоматически.
Pre-flight, обновление, проверка, удаление¶
# Pre-flight без изменений
docker run --rm -v ~/.kube/config:/kubeconfig:ro -v ./values.yaml:/values.yaml \
registry.appsec.global/appsecaigate-release/wizard:<VERSION> check -f /values.yaml
# Умный апгрейд (новый тег образа = новая версия чартов)
docker run --rm ... update -f /values.yaml
docker run --rm ... update --force -f /values.yaml # hotfix под тот же semver
# Проверка
kubectl get pods -n aigate
kubectl -n aigate get secret keycloak-auth \
-o jsonpath='{.data.KEYCLOAK_BOOTSTRAP_USER_PASSWORD}' | base64 -d # auth=true
# Удаление (PVC сохраняются)
docker run --rm ... delete -f /values.yaml
kubectl delete pvc -n aigate --all && kubectl delete ns aigate # полный снос
Версия инсталлера = версия продукта
Тег образа Wizard определяет версию всех Helm-чартов. Для апгрейда достаточно поменять тег — версия в values.yaml не указывается.
Разбор частых проблем — Устранение неполадок.