nelm-ci/NELM-CLOSED-LOOP.ru.md

199 lines
10 KiB
Markdown
Raw Normal View History

# Особенности билда/деплоя через nelm и правки репозиториев `bitbucket/` под закрытый контур
## 1. Чем nelm отличается от привычного werf/helm в CI
| Тема | Как было (werf / common-ci) | Как делаем (nelm + Jenkins) |
|------|-----------------------------|-----------------------------|
| Источник манифестов | `werf.yaml` + `.helm`, converge | только chart в `.helm/`, `nelm release install` |
| Секреты | werf secret / тот же формат ключа | `secret-values.yaml` + `NELM_SECRET_KEY` (`nelm chart secret …`) |
| Сборка образа | часто встроенный werf build | отдельный этап: `docker build` + `docker push` в Jenkins |
| Откуда код | GitLab CI clone | Jenkins сам клонирует Bitbucket на каждый job |
| Релиз | имя/лейблы werf | release name = `<service>-<env>`, namespace = env |
| Три контура | разные values / stages | `--set env=… --set global.cluster=…`, overlays через `dig` |
Практические следствия:
1. **`werf.yaml` в закрытом контуре не нужен для деплоя.** Его можно оставить для совместимости, но pipeline на него не опирается. Деплой идёт из `.helm/`.
2. Ресурсы в кластере получают Helm-аннотации `meta.helm.sh/release-name` / `release-namespace`. Если объект уже создан руками или другим релизом — `nelm` откажется без `--force-adoption` (лучше удалить чужой объект или один раз осознанно adopt).
3. Расшифровка секретов происходит **на agent в момент install**. Без `NELM_SECRET_KEY` job упадёт или зальёт ciphertext в Secret (если включить `--no-decrypt-secrets` — так делать нельзя).
4. `nelm` ждёт Ready у workloads в пределах `--timeout`. В закрытом контуре таймауты чаще связаны с **ImagePullBackOff** (нет образа / нет pull secret), а не с самим nelm.
Типовые команды:
```bash
export NELM_SECRET_KEY=$(cat /secure/nelm_secret_key)
# проверка шаблонов без кластера
nelm chart render -n dev --set env=dev --set global.cluster=dev .helm
# деплой
nelm release install -n dev -r postgres-dev \
--set env=dev --set global.cluster=dev \
--timeout 5m \
.helm
nelm release list -n dev
nelm release history -n dev -r postgres-dev
```
Шифрование значений:
```bash
# показать plaintext (только на защищённой машине)
nelm chart secret values-file decrypt .helm/secret-values.yaml
# зашифровать новый файл тем же ключом
nelm chart secret values-file encrypt plaintext-values.yaml > .helm/secret-values.yaml
```
## 2. Что поправить в репозиториях из папки `bitbucket/`
Ниже — конкретный чеклист по текущим сервисам (`postgres`, `seaweedfs`, `ollama`, `keycloak`, `vllm`).
### 2.1. Образы: только внутренний registry
Сейчас в `values.yaml` часто:
```yaml
image:
postgresql: 192.168.10.68:5000/library/postgres:16-alpine
```
У клиента заменить host на **их** registry, например:
```yaml
image:
postgresql: registry.client.local/library/postgres:16-alpine
```
То же для всех ключей `image.*` во всех пяти чартах.
`values-public.yaml` (ghcr/docker.io/quay) — **не подключать** в job (`USE_PUBLIC_IMAGES=false`). Файл можно оставить в repo как reference для открытых стендов или удалить, чтобы никто случайно не выкатил публичные теги.
### 2.2. Dockerfile `FROM` — без интернета
Сейчас:
```dockerfile
FROM docker.io/library/postgres:16-alpine
FROM quay.io/keycloak/keycloak:26.4.0
```
В закрытом контуре:
```dockerfile
FROM registry.client.local/library/postgres:16-alpine
FROM registry.client.local/keycloak/keycloak:26.4.0
```
Либо на этапе build в Jenkins делать `docker pull` уже с зеркала (если base заранее завезли), а в Dockerfile всё равно писать внутренний путь — иначе `docker build` на agent без интернета упадёт.
Заранее завезти в registry: postgres, postgres-exporter, seaweedfs, ollama, keycloak, vllm (и зависимости keycloak plugins, если тянутся с сети на build).
### 2.3. `imagePullSecrets`
В values:
```yaml
imagePullSecrets:
- name: registrysecret
```
В каждом namespace деплоя должен существовать Secret этого имени (тип `kubernetes.io/dockerconfigjson`) **до** первого install, либо чарт должен его создавать из зашифрованных данных (сейчас обычно ожидается снаружи).
Иначе: `ErrImagePull` / `ImagePullBackOff`.
### 2.4. Секреты приложения
Файлы:
- `postgres/.helm/secret-values.yaml` — пароль БД
- `keycloak/.helm/secret-values.yaml` — admin / DB
- `seaweedfs/.helm/secret-values.yaml` — S3 keys
Действия у клиента:
1. Сгенерировать **свой** `NELM_SECRET_KEY` (не lab-ключ).
2. Перешифровать все `secret-values.yaml` новым ключом (`nelm chart secret key rotate` или encrypt заново).
3. Положить ключ только в Jenkins credentials / vault агента.
4. Заменить lab-пароли (`admin123`) на боевые **до** шифрования.
Репозитории без secret-values (`ollama`, частично `vllm`) — проверить, нет ли plaintext секретов в обычном `values.yaml` / TLS файлах.
### 2.5. TLS и вложенные секреты в git (`vllm`)
В `vllm/.helm/secret/{dev,preprod,prod}/` лежат `tls.crt` / `tls.key`.
Для клиента:
- либо заменить на клиентские сертификаты;
- либо убрать из git и монтировать из внешнего Secret / cert-manager;
- не коммитить боевые private key в публичные зеркала.
### 2.6. StorageClass и scheduling
В чартах lab:
- `storageClassName: localpath` (или аналог)
- `nodeSelector: node-role.kubernetes.io/worker: ""`
У клиента:
- имя StorageClass из их кластера (`ceph-rbd`, `nfs-client`, …);
- nodeSelector/tolerations под GPU-ноды для `ollama` / `vllm` (`gpu.enabled` уже есть флагом — выставить true и нужные taints только если ноды готовы);
- ресурсы (CPU/memory) под квоты namespace.
### 2.7. Ingress / DNS
У `keycloak`, `ollama`, `vllm` есть Ingress. Поправить:
- hosts под клиентскую зону;
- TLS (cert-manager annotations или уже существующие секреты);
- класс Ingress (`ingressClassName`), если не default.
В закрытом контуре без внешнего DNS — либо внутренние имена, либо временно ClusterIP + port-forward для приёмки.
### 2.8. Убрать/игнорировать зависимости от GitLab CI и werf
В репозиториях могут остаться:
- `werf.yaml`
- `.gitlab-ci.yml` / include на `common-ci`
Для клиентского Bitbucket+Jenkins:
- pipeline из Bitbucket **не** должен вызывать `werf converge`;
- достаточно `.helm/` + Dockerfile;
- CI logic — в Jenkins (`Jenkinsfile` / freestyle), см. `CLIENT-SETUP.ru.md`.
### 2.9. Имена release и namespace
Соглашение lab/клиента:
- namespace = `dev` | `preprod` | `prod`
- release = `<chartName>-<env>` (например `postgres-dev`)
Шаблоны используют `.Values.env` для overlays. Не хардкодить namespace в templates.
### 2.10. Экспортёры и sidecar-образы
У postgres отдельный образ `postgresqlExporter`. Его тоже нужно завезти во внутренний registry и прописать в `values.yaml`.
Нельзя подставлять образ postgres как exporter (так ломается readiness).
## 3. Рекомендуемый порядок миграции репо под клиента
1. Завести project в Bitbucket, запушить пять сервисов.
2. Заменить registry host + Dockerfile `FROM`.
3. Создать `registrysecret` в `dev`.
4. Сгенерировать клиентский `NELM_SECRET_KEY`, перешифровать `secret-values.yaml`, обновить пароли.
5. Поправить StorageClass / Ingress / nodeSelector.
6. Прогнать `nelm chart render` локально.
7. Подключить Jenkins job с **checkout из Bitbucket**, `USE_PUBLIC_IMAGES=false`.
8. `build-and-deploy` для `postgres` на `dev`, затем остальные сервисы.
## 4. Критерий «готово для закрытого контура»
- Job клонирует **актуальный** commit из Bitbucket (в логе виден `HEAD=…` после checkout).
- `docker build` не ходит в интернет (все `FROM` и base — внутренние).
- `nelm release install` без `values-public.yaml`.
- Секреты в кластере — расшифрованный plaintext, ключ не в git.
- Поды Running/Ready, образы с клиентского registry.