# Настройка билда и деплоя (nelm + Jenkins + Bitbucket) в клиентской инфраструктуре Исходные условия у клиента: **уже есть** чистый Kubernetes/Deckhouse-кластер, **Jenkins** и **Bitbucket**. Ниже — только то, что нужно донастроить, чтобы нажатием кнопок в Jenkins собирать образы и выкатывать сервисы через `nelm` из актуальных репозиториев Bitbucket. ## 1. Идея схемы ``` Bitbucket (источник правды: код + .helm/) │ git clone на каждый job ▼ Jenkins agent (одна ВМ: docker build/push + nelm release install) │ kubeconfig сервисного аккаунта ▼ Кластер(ы) dev / preprod / prod ``` - **Не** хранить копию репозиториев вручную на агенте (`~/nelm-work/bitbucket` и т.п.). - На каждый build/deploy Jenkins **клонирует** нужные репозитории с ветки (обычно `main`). - Образы уходят во **внутренний registry**. - Манифесты применяет **`nelm release install`** (не werf, не helm из GitLab CI). - Секреты в чартах — в `secret-values.yaml`, ключ только на агенте / в credentials Jenkins. ## 2. Что подготовить один раз ### 2.1. Инструменты на Jenkins agent На той же машине, где крутится agent (или в контейнере agent с доступом к Docker socket): | Компонент | Зачем | |-----------|--------| | `git` | checkout репозиториев | | `docker` (+ доступ к socket / DinD) | build & push | | `nelm` | render/install релизов | | `kubectl` | namespaces, проверка подов, kubeconfig | | доступ к Bitbucket HTTP(S) | clone | | доступ к registry | push/pull | | доступ к API Kubernetes | deploy | Пример установки `nelm` (если есть выход в интернет на этапе подготовки; в закрытом контуре — положить бинарь вручную): ```bash # бинарь nelm → /usr/local/bin/nelm или ~/bin/nelm export PATH="$HOME/bin:/usr/local/bin:$PATH" nelm version ``` ### 2.2. Сервисный аккаунт для деплоя С админского kubeconfig (на master или с ноутбука с доступом): ```bash export KUBECONFIG=/path/to/admin.kubeconfig chmod +x create-deploy-sa.sh ./create-deploy-sa.sh # получите kube-deploy.config ``` Скрипт создаёт SA + `ClusterAuthorizationRule` (Deckhouse) и пишет kubeconfig. Дальше: 1. Скопируйте `kube-deploy.config` на Jenkins agent (например `/var/lib/jenkins/kube-deploy.config`, права только для пользователя agent). 2. Заведите **отдельный context на каждый контур**, если это разные кластеры: ```bash kubectl --kubeconfig=kube-deploy.config config rename-context lab-cluster-dev # аналогично lab-cluster-preprod, lab-cluster-prod # либо три разных kubeconfig + переключение в job ``` В job по умолчанию используется context `lab-cluster-${ENV}`. ### 2.3. Ключ секретов nelm Один общий ключ на контур (или на все контуры, если один vault-подход): ```bash nelm chart secret key create > /secure/nelm_secret_key chmod 600 /secure/nelm_secret_key ``` Все `secret-values.yaml` в репозиториях должны быть зашифрованы **этим** ключом. В Jenkins: credential типа **Secret text**, id = `nelm-secret-key`. ### 2.4. Доступ Jenkins → Bitbucket 1. В Bitbucket создайте technical user / HTTP access token с правом **read** на project со сервисами. 2. В Jenkins: credential **Username with password**, id = `bitbucket-git` (user + token). 3. Убедитесь, что agent резолвит URL Bitbucket (DNS / `/etc/hosts`) и доверяет TLS (корпоративный CA в trust store или внутренний HTTP). ### 2.5. Registry и pull secrets в кластере В каждом namespace (`dev` / `preprod` / `prod`) или на уровне SA чарта нужен `imagePullSecrets` (часто `registrysecret`), совпадающий с `.Values.imagePullSecrets` в чартах. Образы в `values.yaml` репозиториев должны указывать на **клиентский** registry, не на lab `192.168.10.68:5000` и не на docker.io. ### 2.6. StorageClass / ноды В чартах по умолчанию часто `localpath` и `nodeSelector: node-role.kubernetes.io/worker: ""`. Приведите values под клиентский StorageClass и лейблы нод **до** первого деплоя (или через `--set` в job, если так принято). ## 3. Репозитории в Bitbucket Минимальный состав project (имена можно сохранить): | Repo | Содержимое | |------|------------| | `postgres`, `seaweedfs`, `ollama`, `keycloak`, `vllm` | код + `Dockerfile` + каталог `.helm/` | | опционально `nelm-ci` | `Jenkinsfile`, `jenkins/*.groovy`, `jenkins/checkout-repos.sh` | В каждом сервисном репо обязательно: ```text .helm/Chart.yaml .helm/values.yaml # образы внутреннего registry .helm/secret-values.yaml # зашифрованные секреты (если есть) .helm/templates/... Dockerfile # если нужен build ``` `values-public.yaml` — только для стендов с доступом в интернет; **в закрытом контуре не использовать**. ## 4. Job в Jenkins ### Вариант A (предпочтительно): Pipeline from SCM 1. Создайте repo `nelm-ci` с `Jenkinsfile` и каталогом `jenkins/`. 2. New Item → Pipeline → Pipeline script from SCM → Bitbucket Git → этот repo. 3. Credentials: `bitbucket-git`, `nelm-secret-key`. 4. Параметры job (уже в `Jenkinsfile`): | Параметр | Смысл | |----------|--------| | `SERVICE` | один сервис или `all` | | `ENV` | `dev` / `preprod` / `prod` (= namespace) | | `ACTION` | `build` / `deploy` / `build-and-deploy` | | `USE_PUBLIC_IMAGES` | **false** у клиента | | `REGISTRY` | адрес внутреннего registry | | `GIT_BASE_URL` | `https://bitbucket.example.com/scm/PROJ` или `.../bbadmin` | | `GIT_BRANCH` | ветка | | `KUBE_CONTEXT` | пусто = `lab-cluster-$ENV` | Логика: 1. **Checkout from Bitbucket** — `jenkins/checkout-repos.sh` клонирует актуальные сервисы в `$WORKSPACE/repos/`. 2. **Build** — `docker build` / mirror → `REGISTRY/...`, `docker push`. 3. **Deploy** — `nelm release install -n $ENV -r ${service}-${ENV}` из `$WORKSPACE/repos//.helm`. ### Вариант B: Freestyle (как на lab) Shell build step вызывает тот же `checkout-repos.sh`, затем `nelm`/`docker`. Скрипты CI лежат на агенте или тоже подтягиваются из `nelm-ci` одним `git clone`. ## 5. Переменные окружения на agent / в job ```bash export PATH="/usr/local/bin:$HOME/bin:$PATH" export KUBECONFIG=/var/lib/jenkins/kube-deploy.config export NELM_SECRET_KEY=... # из Jenkins credentials export GIT_BASE_URL=https://bitbucket.client.local/bbadmin export GIT_BRANCH=main ``` ## 6. Первый прогон (чеклист) 1. В Bitbucket открывается repo, на `main` есть `.helm/`. 2. С agent: `git ls-remote $GIT_BASE_URL/postgres.git`. 3. `nelm chart render -n dev --set env=dev --set global.cluster=dev path/to/.helm` — без ошибок, секреты расшифровываются. 4. В нужном namespace есть `registrysecret` (если образы приватные). 5. Jenkins → Build with Parameters → `SERVICE=postgres`, `ENV=dev`, `ACTION=build-and-deploy`, `USE_PUBLIC_IMAGES=false`. 6. `kubectl -n dev get pods` — Ready; `nelm release list -n dev` — статус deployed. ## 7. Три контура - Namespace = имя env (`dev` / `preprod` / `prod`), либо своя политика — тогда поправьте job. - Разные кластеры → разные kube-context / kubeconfig. - Разные значения (replicas, resources, storage) — через overlays в `values.yaml` (`dig .Values.env ...`), не через копипасту манифестов. ## 8. Чего не делать - Не деплоить из «замороженной» папки на диске агента без `git fetch`. - Не коммитить `NELM_SECRET_KEY` и сырые пароли в Bitbucket. - Не оставлять в `values.yaml` адреса lab-registry / docker.io для боевого контура. - Не смешивать werf converge и nelm на одном релизе без миграции ownership аннотаций Helm. ## 9. Файлы из поставки lab (ориентир) | Файл | Назначение | |------|------------| | `create-deploy-sa.sh` | SA + kubeconfig для runner | | `Jenkinsfile` | pipeline с checkout → build → deploy | | `jenkins/checkout-repos.sh` | актуальный clone сервисов | | `jenkins/build.groovy` / `deploy.groovy` | стадии | | `DEPLOY.md` | краткий lab-ориентир | | `NELM-CLOSED-LOOP.ru.md` | правки репозиториев под закрытый контур |