03 · Платформа: DevOps, k8s, сеть, хранилище3.2 · CI с Jenkins3.2.4средний

Секреты в CI и типичные отказы пайплайна

Зачем это нужно

Пайплайн без секретов редок: пароль registry, API-ключ облака, токен Git. Одна строка password = "sk-123" в Jenkinsfile — инцидент безопасности и учебный провал. Второй навык — диагностика: Jenkins красный в половине случаев из-за окружения, а не из-за кода. Умение читать лог stage и чинить типовые сбои экономит часы всей команде.

Основные идеи

Credentials в Jenkins. Секреты хранят в Credentials Store (глобально или на folder). В pipeline — только ID, не значение:

withCredentials([ string(credentialsId: 'minio-access-key', variable: 'MINIO_KEY') ]) { sh 'python upload.py --key "$MINIO_KEY"' }

Типы: Username/Password, Secret text, SSH key, Secret file. Jenkins маскирует секреты в логах (но осторожно с set +x и echo).

Не секреты в Git. Запрещено: .env с паролями в repo, ARG REGISTRY_PASSWORD в Dockerfile, base64 «для obscurity». Правильно: .env.example без значений; runtime — Kubernetes Secret или Jenkins credentials.

Binding в Docker login. Пароль в stdin, не в командной строке (иначе виден в ps):

sh 'echo "$REG_PASS" | docker login registry -u "$REG_USER" --password-stdin'

Типичные отказы и что проверять

Симптом Частая причина
docker: not found Docker не установлен на agent или нет label
permission denied при docker User agent не в группе docker
unauthorized: authentication required Неверный credentialsId или истёк токен
pytest: command not found Зависимости не установлены в stage до test
Flaky test Гонка, зависимость от сети, время
Out of disk Нет cleanWs(), копятся слои Docker
Timeout Обучение модели в CI без GPU — вынести в nightly

Flaky builds. Нестабильный пайплайн подрывает доверие. Фиксируйте: seed для тестов, mock внешних API, retry только там, где оправдано (network blip), не для падающих assert.

Безопасность ML-артефактов. Registry credentials дают push; отдельные read-only credentials — для pull в k8s (imagePullSecrets). Модель не должна утекать через публичный лог (не печатайте содержимое Secret).

Отказоустойчивость процесса. CI упал — PR не мержим. CD (Helm/Argo) не обновляет prod, если новый образ не собран. Явная связь: нет зелёного CI → нет нового тега → нет деплоя.

Как это выглядит на практике

Сценарий 1: push падает с 401.

  1. Открыть лог stage Push.

  2. Проверить credentialsId в Jenkins (Manage Credentials).

  3. Перевыпустить token в registry, обновить secret в Jenkins.

  4. Rebuild без изменения кода.

Сценарий 2: «работало вчера».

  1. Compare: обновился ли базовый образ python:3.11-slim?

  2. Зафиксировать digest базового образа в Dockerfile или lockfile.

  3. Добавить --pull только по расписанию, не на каждый PR.

Сценарий 3: секрет попал в Git (учебный fire-drill).

  1. Немедленно rotate credential.

  2. Удалить из истории git (BFG / git filter-repo) — с помощью преподавателя.

  3. Включить pre-commit hook или scanning (gitleaks) — тема смежная.

Postmortem в Confluence: что сломалось, как обнаружили, как предотвратить — навык из блока 1.

Что сделать после занятия

  • Перенесите все секреты из скриптов в Jenkins Credentials; проверьте, что в логе они замаскированы.

  • Создайте таблицу «5 типовых ошибок CI» для вашего проекта с симптомом и fix.

  • Намеренно сломайте пайплайн (неверный credentialsId) и восстановите по логу — тренировка on-call.

Официальные материалы