Для чего компании внедрять CI/CD
- Сокращает время на тестирование. Автоматизация позволяет быстро и эффективно запускать тесты, избегая ручных проверок, что ускоряет цикл обратной связи.
- Минимизирует ошибки на этапе интеграции. Частые небольшие изменения проще тестировать и обнаруживать ошибки, чем большие обновления, которые могут быть более сложными для тестирования.
- Ускоряет вывод продукта на рынок. Благодаря автоматизированным процессам внедрения новых функций или исправлений программного обеспечения, разработчики могут выпускать обновления гораздо быстрее, снижая время вывода на рынок.
- Упрощает управление версиями ПО. Каждое изменение кода может быть упаковано в отдельный релиз, что упрощает отслеживание и управление версиями программного обеспечения.
Best practices CI/CD
1. Multi-stage сборка Docker-образаОдной из ключевых рекомендаций является использование multi-stage сборки Docker-образа. Этот подход позволяет значительно уменьшить размер итогового образа, так как в конечный образ попадает только необходимый код и библиотеки, а временные и вспомогательные файлы остаются на стадии сборки.
Преимущества multi-stage сборки:
- Минимизация размера финального Docker-образа.
- Упрощение управления зависимостями.
- Снижение рисков уязвимостей благодаря уменьшению ненужных библиотек.
Основные бенефиты Kaniko:
- Безопасность. Kaniko не требует выполнения привилегированных операций, в отличие от Docker-in-Docker (DinD), который может представлять угрозу для безопасности кластера.
- Легкость интеграции с Kubernetes. Kaniko легко интегрируется с Kubernetes-платформами, что упрощает процесс автоматизации.
- Ускорение повторных сборок. Когда части образа остаются неизменными между сборками, Kaniko использует закэшированные слои, что значительно сокращает время сборки. Это особенно важно при частых запусках пайплайнов.
- Простота интеграции с Kubernetes. Kaniko был разработан специально для Kubernetes, поэтому он легко интегрируется с различными системами CI/CD, работающими в Kubernetes-кластерах. Он упрощает автоматизацию процессов сборки образов и их деплоя, минимизируя сложность настройки.
- DinD требует привилегированных контейнеров, что делает его менее безопасным в сравнении с Kaniko.
- При использовании DinD могут возникать проблемы с производительностью из-за сложностей с запуском Docker внутри Docker.
- Тегирование. Все релизы должны сопровождаться уникальными тегами, что позволяет легко отслеживать версионность и фиксировать конкретные состояния приложения.
- Protected branches. Защищенные ветки позволяют ограничить доступ к изменению важнейших веток, например, master или production. Это помогает избежать случайных изменений и ошибок в ключевых ветках.
- Быстро разворачивать новые проекты на базе готовых пайплайнов.
- Обеспечить консистентность процессов сборки и деплоя во всех проектах.
- Уменьшить время на настройку CI/CD для новых команд.
Однако, если у вас только один проект, лучше использовать один пайплайн без child или downstream пайплайнов, так как это упростит поддержку и отладку процессов, а так же позволит более гибко управлять его логикой.
5. Использование гибких правил для триггера пайплайнов
Часто нет необходимости запускать полный пайплайн на каждое изменение в кодовой базе. Поэтому важно использовать гибкие правила для триггеров:
- Триггерить пайплайн только при изменениях в определённых директориях или файлах (например, для деплоя на production запускать пайплайн только при изменениях в папке с конфигурациями).
- Ограничение запуска пайплайнов по событиям (например, запускать пайплайн только при слиянии в защищённые ветки).
В рамках этой статьи мы будем использовать следующие инструменты:
- Gitlab CI для организации процессов сборки, включая сборку Docker-образа;
- ArgoCD для деплоя приложений;
- Vault для безопасного хранения и использования секретов, интегрированного на уровне Gitlab CI.
Лучшие практики CI/CD: билд приложение через GitLab CI
Для начала создадим multi-stage Dockerfile, который позволяет собрать минимальный и оптимизированный образ для нашего приложения. В качестве примера используем PHP-приложение:
## common_artifact
FROM registry.examle.ru/infra/ubuntu-base:common AS common_artifact
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN su app -c 'wget --quiet https://repo1.maven.org/maven2/com/google/javascript/closure-compiler/v.../closure-compiler-v....jar -O /opt/closure-tools/compiler.jar --no-check-certificate'
COPY --chown=app:app . /app
ARG db_string
ARG db_user_name
ARG db_password
ARG db_host
ARG db_port
ARG db_name
RUN echo "${db_host} pgsql.db" >> /etc/hosts && \
/usr/bin/php some commads
COPY --chown=app:app ./.infra/files/js_min.sh /app/js_min.sh
RUN su app -c '/bin/bash /app/js_min.sh'
WORKDIR /app/somedir/protected
RUN su app -c '/bin/bash gulpc'
### frontend
FROM registry.examle.ru/infra/nginx-upstream-limit:nginx-gc AS frontend
COPY ./.infra/files/frontend/nginx.conf /etc/nginx/nginx.conf
COPY ./.infra/files/frontend/content /app/somedir/content
COPY . /app
RUN rm -rf /app/somedir/protected/modules \
/app/somedir/protected/resource \
/app/somedir/js \
/app/_sql/sqlLocalizationUpdate*
COPY --from=common_artifact /app/somedir/protected/modules /app/somedir/protected/modules
COPY --from=common_artifact /app/somedir/protected/resource /app/somedir/protected/resource
COPY --from=common_artifact /app/somedir/js /app/somedir/js
COPY --from=common_artifact /app/_sql/sqlLocalizationUpdate* /app/_sql/
## backend
FROM registry.examle.ru/infra/ubuntu-base:backend AS backend
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV LC_ALL=ru_RU.UTF-8
ENV LANG=ru_RU.UTF-8
COPY --chown=app:app ./.infra/files/backend/fonts /usr/share/fonts/TTF
RUN chown -R app:app /usr/share/fonts/TTF && chmod -R 0755 /usr/share/fonts/TTF
COPY ./.infra/files/frontend/wp_content /app/somedir/wp-content
COPY --chown=app:app ./.infra/files/somedir/cron.d /etc/cron.d
COPY --chown=app:app ./.infra/files/somedir/somedir /etc/somedir
COPY --chown=app:app ./.infra/files/somedir/d /etc/service/d
COPY --chown=app:app ./.infra/files/somedir/supercronic_run /etc/service/supercronic/run
COPY --chown=app:app ./.infra/files/backend/php-fpm.conf /etc/php/7.4/fpm/php-fpm.conf
COPY --chown=app:app ./.infra/files/backend/php.ini /etc/php/7.4/cli/php.ini
COPY --chown=app:app ./.infra/files/backend/php-fpm.ini /etc/php/7.4/fpm/php.ini
COPY --chown=app:app . /app
WORKDIR /app
RUN rm -rf /app/somedir/protected/modules \
/app/somedir/protected/resource \
/app/somedir/js \
/app/_sql/sqlLocalizationUpdate* && \
mkdir -p /app/somedir/protected/runtime && \
chown -R app:app /app/somedir/protected/runtime
COPY --from=common_artifact --chown=app:app /app/somedir/protected/modules /app/somedir/protected/modules
COPY --from=common_artifact --chown=app:app /app/somedir/protected/resource /app/somedir/protected/resource
COPY --from=common_artifact --chown=app:app /app/somedir/js /app/somedir/js
COPY --from=common_artifact --chown=app:app /app/_sql/sqlLocalizationUpdate* /app/_sql/
- common_artifact stage: установка зависимостей, вписывание аргументов для сборки приложения и его подготовка.
- frontend stage: копирование финального приложения в образ, замена и оптимизация кода, минимизируя размер Docker-образа.
- backend stage: копирование финального приложения в образ, замена и оптимизация кода, минимизируя размер Docker-образа.
2. Пример шаблона для GitLab CI с Kaniko
Для более гибкого и масштабируемого процесса, мы можем создать отдельный репозиторий с шаблонами для CI/CD. Этот подход особенно полезен для организаций с большим количеством проектов, где требуется унифицированный подход к сборке, тестированию и деплою. В данном случае мы создадим репозиторий, который будет содержать директории для различных этапов CI/CD — сборки, тестирования, деплоя и других шагов.
ci-templates/
├── build/
│ └── kaniko-build-template.yml
├── test/
│ └── test-template.yml
├── deploy/
│ └── argo-deploy-template.yml
└── .gitlab-ci.yml
Описание директорий:- build/ — содержит шаблоны для сборки Docker-образов, в том числе Kaniko для различных окружений.
- test/ — включает шаблоны для автоматизированного тестирования приложений (юнит-тесты, интеграционные тесты).
- deploy/ — содержит шаблоны для деплоя, например, с использованием ArgoCD для различных сред (production, staging, development).
- .gitlab-ci.yml — основной файл, который инклюдит шаблоны из других директорий и определяет общие правила.
Шаблон для Kaniko-сборки
Описание задачи для сборки:stages:
- build
include:
- local: stage-ci.yml
.build:
stage: build
image:
name: registry-url/infra/kaniko-executor:v1.16.0-debug
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- cat ${CR_CONFIG} > /kaniko/.docker/config.json
- touch new-test
- echo "test" >> new-test
- >
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${DOCKERFILE}"
--destination "registry-url/${REGISTRY}/${IMAGE}"
--cache=true
--cache-repo "registry-url/${REGISTRY}/${CI_PROJECT_NAME}-cache"
build_dev:
extends:
- .build
variables:
REGISTRY: $CR_AGENCY_DEV_ID
CR_CONFIG: $CR_AGENCY_DEV_CONFIG
IMAGE: ${CI_PROJECT_NAME}:${CI_COMMIT_SHORT_SHA}
rules:
- if: $CI_COMMIT_BRANCH =~ /^feature\/.*/
- if: $CI_COMMIT_BRANCH == "develop"
cache:
policy: push
build_prod:
extends:
- .build
variables:
REGISTRY: $CR_AGENCY_PROD_ID
CR_CONFIG: $CR_AGENCY_PROD_CONFIG
IMAGE: ${CI_PROJECT_NAME}:${CI_COMMIT_TAG}
rules:
- if: $CI_COMMIT_TAG != null
build_stage:
extends:
- .build
variables:
REGISTRY: $CR_AGENCY_PROD_ID
CR_CONFIG: $CR_AGENCY_PROD_CONFIG
IMAGE: ${CI_PROJECT_NAME}:${CI_COMMIT_TAG}
rules:
- if: '$CI_COMMIT_REF_NAME == "staging"'
- build_template — шаблон, который содержит основные настройки для всех задач сборки, таких как образ Kaniko, кэширование, и авторизация в Docker Registry.
- отдельные задачи для окружений (build.prod, build.dev) — каждая задача предназначена для определённого окружения. Например, для продакшена будет собираться образ с тегом prod, для staging — с тегом stage, и так далее.
Каждое окружение имеет свои правила для триггеров пайплайна:
- Сборка для продакшена запускается если коммит происходит с тегом.
- Сборка для dev окружения — при коммите в ветку содержащую в название feature, при коммите в ветку develop.
include:
- project: 'ci-templates'
file: 'build/kaniko-build-template.yml'
# Определение триггеров для сборки
workflow:
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
- if: '$CI_COMMIT_REF_NAME == "staging"'
- if: '$CI_COMMIT_REF_NAME == "develop"
Здесь:
include — подключает шаблон kaniko-build-template.yml из репозитория ci-templates, который содержит всю логику для сборки Docker-образов.
workflow — задает условия для запуска пайплайнов: сборка запускается только при работе с ветками main, staging или develop.
- 1. Унификация процессов. Использование шаблонов позволяет обеспечить единообразие процессов CI/CD для всех проектов. Это особенно важно для крупных организаций с большим количеством проектов.
- 2. Повторное использование. Шаблоны могут быть использованы в разных проектах, что сокращает время на настройку CI/CD и минимизирует вероятность ошибок.
- 3. Гибкость. При необходимости шаблоны можно модифицировать для определённых проектов, сохраняя при этом общую структуру.4. Облегчение управления изменениями. Все изменения в пайплайнах можно вносить централизованно, в репозитории с шаблонами. Это упрощает поддержку и обновление CI/CD процессов для всех проектов одновременно.
Преимущества ArgoCD и почему его стоит использовать
ArgoCD: перейдём к деплою. ArgoCD — это мощный инструмент для автоматизации процессов деплоя в Kubernetes с использованием методологии GitOps, что делает его важным элементом CI/CD пайплайнов.
Преимущества ArgoCD:
- GitOps-ориентированный деплой. ArgoCD автоматически синхронизирует состояние приложения в кластере с его состоянием в репозитории Git. Это делает деплой полностью управляемым через Git, улучшая контроль версий и прозрачность процессов.
- Автоматическая синхронизация. ArgoCD непрерывно следит за изменениями в репозитории и автоматически обновляет Kubernetes-кластер, когда изменения происходят.
- Гибкость и поддержка различных инструментов. ArgoCD поддерживает деплой из Helm-чартов, Kustomize, Jsonnet и других методов описания инфраструктуры.
- Простота визуализации и управления. Встроенная панель управления (Web UI) позволяет легко следить за состоянием всех приложений, их версиями и статусами синхронизации.
1. Параметр: UI
ArgoCD: Имеет удобный веб-интерфейс для управления приложениями и отслеживания состояния синхронизации.
FluxCD: Веб-интерфейс отсутствует, управление осуществляется через CLI.
2. Параметр: Поддержка Helm
ArgoCD: Полноценная поддержка Helm-чартов и управление релизами через UI.
FluxCD: Поддержка Helm через дополнительный компонент helm-controller.
3. Параметр: Установка и настройка
ArgoCD: Более сложная установка и настройка, но более удобное управление после внедрения.
FluxCD: Простая установка, но управление требует использования сторонних инструментов.
4. Параметр: Синхронизация
ArgoCD: Поддерживает как ручную, так и автоматическую синхронизацию с возможностью отката изменений.
FluxCD: Основной упор на автоматическую синхронизацию без встроенной поддержки ручных операций.
В целом, ArgoCD более удобен для команд, которые хотят гибкости в управлении деплоем и удобный интерфейс, в то время как FluxCD больше подходит для сценариев, требующих минимальной инфраструктуры и полной автоматизации.
5. Установка ArgoCD через Helm
Для того чтобы установить ArgoCD через Helm и настроить его под свои нужды, включая настройку Ingress с хостом argo.example.com, необходимо отредактировать файл values.yaml. Этот файл позволяет кастомизировать установку ArgoCD, включая конфигурацию Ingress, ресурсы, безопасность и другие параметры.
# Общие настройки для ArgoCD
global:
image:
repository: argoproj/argocd
tag: v2.9.0 # Укажите актуальную версию ArgoCD
installCRDs: true
# Настройки для сервера ArgoCD
server:
service:
type: ClusterIP
port: 80
# Настройка Ingress для доступа к UI ArgoCD
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: "letsencrypt-prod" # Опционально, если вы используете cert-manager для TLS
hosts:
- host: argo.example.com
paths:
- /
tls:
- secretName: argocd-tls
hosts:
- argo.example.com
# Настройки безопасности
# Определение ресурсов для ArgoCD серверов
controller:
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
repoServer:
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
# Настройка синхронизации проектов
applicationSet:
enabled: true
# Опции RBAC для пользователей
rbacConfig:
policy.default: role:readonly
scopes: "[groups]"
# Автоматическое создание пользователя admin с паролем
initialAdminPassword: "supersecretpassword"Описание ключевых параметров:
1. global.image — определяет репозиторий и тег (версию) для образа ArgoCD. Важно указывать актуальную версию.
2. server.service — указывает тип сервиса для ArgoCD. Мы используем тип ClusterIP, чтобы сервис был доступен только внутри кластера. Если требуется внешний доступ, можно заменить на LoadBalancer.
3. server.ingress — настройка Ingress контроллера для доступа к веб-интерфейсу ArgoCD:
- enabled — включает Ingress.
- annotations — опционально добавляем аннотации для интеграции с cert-manager, если требуется автоматическая настройка TLS сертификатов.
- hosts — задаёт доменное имя (в данном случае argo.example.com), по которому будет доступен ArgoCD.
- tls — настройка для автоматического получения TLS-сертификатов, указав secretName для хранения сертификатов.
4. controller.resources и repoServer.resources — задают ресурсы для компонентов ArgoCD (ограничения по CPU и памяти).
5. rbacConfig — позволяет настроить права доступа по умолчанию для пользователей, задавая роль readonly для базовых пользователей.
6. initialAdminPassword — задаёт начальный пароль для пользователя admin, который будет создан при установке ArgoCD.
После редактирования файла values.yaml можно установить ArgoCD с помощью Helm:
1. Сначала добавим репозиторий Helm для ArgoCD:
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
2. Выполним установку ArgoCD с использованием нашего файла values.yaml:
helm install argo-cd argo/argo-cd --namespace argocd --create-namespace -f values.yaml
После завершения установки ArgoCD будет доступен по адресу https://argo.example.com, если настроен правильный DNS и сертификаты для Ingress.
Helm-чарт для приложения будет основан на nxs-universal-chart, который предоставляет универсальные шаблоны для управления различными типами приложений. Пример значений для web-приложения можно взять из образца.
Пример файла values.yml для вашего приложения:
app:
name: "my-app"
version: "1.0.0"
image:
repository: "my-registry/my-app"
tag: "latest"
pullPolicy: "IfNotPresent"
replicaCount: 2
service:
type: "ClusterIP"
port: 80
ingress:
enabled: true
annotations: {}
hosts:
- host: "my-app.example.com"
paths:
- "/"
tls: []
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
Интеграция ArgoCD с GitLab CIТеперь мы создадим GitLab CI файл для деплоя через ArgoCD в три разных окружения: prod, stage и dev.
1. Шаблон деплоя с ArgoCD — создадим файл argo-deploy-template.yml:
stages:
- deploy
.deploy_template: &deploy_template
image: bitnami/kubectl:latest
script:
- kubectl config set-cluster $K8S_CLUSTER --server=$K8S_SERVER --insecure-skip-tls-verify=true
- kubectl config set-credentials $K8S_USER --token=$K8S_TOKEN
- kubectl config set-context $K8S_CONTEXT --cluster=$K8S_CLUSTER --user=$K8S_USER
- kubectl config use-context $K8S_CONTEXT
- argocd app sync my-app --prune --timeout 300
# Деплой на production
deploy_prod:
<<: *deploy_template
stage: deploy
environment:
name: production
script:
- argocd app sync my-app-prod --prune --timeout 300
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
# Деплой на staging
deploy_stage:
<<: *deploy_template
stage: deploy
environment:
name: staging
script:
- argocd app sync my-app-stage --prune --timeout 300
rules:
- if: '$CI_COMMIT_REF_NAME == "staging"'
# Деплой на development
deploy_dev:
<<: *deploy_template
stage: deploy
environment:
name: development
script:
- argocd app sync my-app-dev --prune --timeout 300
rules:
- if: '$CI_COMMIT_REF_NAME == "develop"'
Этот шаблон:
- Настраивает kubectl для работы с Kubernetes-кластером через предоставленные переменные (сервер, токен, контекст).
- Использует команду argocd app sync для синхронизации приложений в разных окружениях (prod, stage, dev).
include:
- local: 'argo-deploy-template.yml'
workflow:
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
- if: '$CI_COMMIT_REF_NAME == "staging"'
- if: '$CI_COMMIT_REF_NAME == "develop"'
ArgoCD предлагает мощные инструменты для GitOps-ориентированного деплоя приложений, с поддержкой автоматической синхронизации и удобного управления через UI. Мы рассмотрели его установку через Helm, создание Helm-чарта на базе nxs-universal-chart, а также интеграцию с GitLab CI для деплоя в разные окружения.
Преимущества использования Vault
HashiCorp Vault — это инструмент для безопасного управления секретами и доступом к ним в приложениях и инфраструктуре. Он поддерживает шифрование данных, динамическое управление доступом и аудит использования секретов, что делает его важным элементом в CI/CD пайплайнах.
1. Централизованное управление секретами. Vault предоставляет единое место для безопасного хранения секретов (пароли, токены, API-ключи и другие конфиденциальные данные), что упрощает управление ими.
2. Динамическая генерация секретов. Vault может динамически генерировать временные доступы, такие как креды для баз данных или облачных сервисов, которые автоматически истекают через определенное время.
3. Гибкие политики доступа. Политики позволяют настроить гибкий контроль над доступом к секретам на основе ролей и сервисов.
4. Аудит и безопасность. Vault ведёт полный аудит использования секретов, что помогает отслеживать и контролировать доступ к конфиденциальным данным.
5. Шифрование данных в движении и покое. Все секреты в Vault хранятся в зашифрованном виде, что обеспечивает высокий уровень безопасности.
1. Параметр: Управление секретами
HashiCorp Vault: Централизованное управление секретами с поддержкой динамических секретов.
FluxCD Secret Management: Ограничено Kubernetes Secret и интеграцией с SOPS.
2. Параметр: Шифрование
HashiCorp Vault: Полноценное шифрование секретов в хранилище и при передаче.
FluxCD Secret Management: Шифрование секретов через внешние инструменты.
3. Параметр: Политики и доступ
HashiCorp Vault: Гибкое управление доступом через политики и роли.
FluxCD Secret Management: Доступ на основе ролей Kubernetes и RBAC.
4. Параметр: Поддержка облаков и баз данных
HashiCorp Vault: Поддерживает динамическое создание временных учётных данных для облаков и баз данных.
FluxCD Secret Management: Отсутствует встроенная поддержка динамических секретов.
Vault обеспечивает более мощное и гибкое управление секретами, в то время как FluxCD ограничен базовой работой с Kubernetes Secret и интеграцией с инструментами шифрования, такими как SOPS.
Установка Vault через Helm
Чтобы развернуть HashiCorp Vault в Kubernetes-кластере, можно использовать Helm для установки. Установка включает редактирование файла values.yaml для кастомизации конфигурации под ваши нужды.
Добавим репозиторий Helm для Vault:
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
Создадим файл values.yaml, чтобы кастомизировать установку Vault, включая настройку Ingress.
Пример файла values.yaml для Vault с поддержкой Ingress:
server:
# Включение режима HA (High Availability) для Vault
ha:
enabled: true
replicas: 3
# Настройка сервиса для Vault
service:
type: ClusterIP
# Включение и настройка Ingress для доступа к Vault UI
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: "letsencrypt-prod" # Опционально, если вы используете cert-manager
hosts:
- host: vault.example.com
paths:
- /
tls:
- hosts:
- vault.example.com
secretName: vault-tls
# Политики и начальные настройки
extraConfig: |
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
storage "file" {
path = "/vault/data"
}
ui = true
# Задание ресурсов для Vault
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256MiОписание параметров:
- ha.enabled — включает режим High Availability (HA) для повышения отказоустойчивости, с тремя репликами Vault.
- ingress — настраивает Ingress для доступа к Vault через домен vault.example.com. TLS поддерживается через cert-manager.
- extraConfig — конфигурация для работы Vault. Включаем интерфейс UI и определяем хранилище данных.
- resources — определение лимитов и запросов по ресурсам для оптимального использования кластера.
Установка Vault с нашим values.yaml:
helm install vault hashicorp/vault --namespace vault --create-namespace -f values.yaml
После установки Vault будет доступен через Ingress по адресу https://vault.example.com.
Теперь рассмотрим, как интегрировать Vault с GitLab CI для безопасного доступа к секретам во время сборки и деплоя приложения.
Создадим файл vault-secrets-template.yml, который будет использоваться для извлечения секретов из Vault в процессе сборки.
stages:
- build
# Шаблон для использования Vault
.vault_template: &vault_template
image: hashicorp/vault:latest
script:
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/db-creds)
- echo "Database password retrieved from Vault: $DB_PASSWORD"
# Билд для production
build_prod:
<<: *vault_template
stage: build
environment:
name: production
script:
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/prod/db-creds)
- ./build.sh
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
# Билд для staging
build_stage:
<<: *vault_template
stage: build
environment:
name: staging
script:
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/staging/db-creds)
- ./build.sh
rules:
- if: '$CI_COMMIT_REF_NAME == "staging"'
# Билд для development
build_dev:
<<: *vault_template
stage: build
environment:
name: development
script:
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/dev/db-creds)
- ./build.sh
rules:
- if: '$CI_COMMIT_REF_NAME == "develop"'Описание пайплайна:
- vault login — логин в Vault с использованием токена, который передаётся в переменной окружения $VAULT_TOKEN.
- vault kv get — команда для извлечения секретов из Vault. В этом примере мы извлекаем пароль базы данных.
- build_prod, build_stage, build_dev — задачи для каждого окружения (production, staging, development), где мы получаем секреты, специфичные для окружения, и запускаем процесс сборки.
2. Основной .gitlab-ci.yml файл
Основной .gitlab-ci.yml файл должен инклюдить шаблон для использования Vault и настроить пайплайн для трёх окружений:
include:
- local: 'vault-secrets-template.yml'
workflow:
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
- if: '$CI_COMMIT_REF_NAME == "staging"'
- if: '$CI_COMMIT_REF_NAME == "develop"'
Интеграция HashiCorp Vault с GitLab CI позволяет безопасно управлять секретами в процессе сборки и деплоя приложений. Мы рассмотрели процесс установки Vault через Helm, настройку Ingress, использование Vault для управления секретами через GitLab CI и создание пайплайнов для разных окружений. Этот подход улучшает безопасность и удобство работы с секретами в CI/CD процессах.После рассмотрения всех шагов, включая интеграцию HashiCorp Vault и использование ArgoCD, мы можем объединить все настройки в один итоговый .gitlab-ci.yml файл. Этот файл будет включать три основных этапа: сборку образов с использованием Kaniko, деплой с помощью ArgoCD и использование Vault для управления секретами. Пайплайн будет разделён на три окружения: production, staging, и development.
Итоговый .gitlab-ci.yml файл
# Включение шаблонов для сборки, деплоя и работы с секретами Vault
include:
- local: 'kaniko-build-template.yml'
- local: 'argo-deploy-template.yml'
- local: 'vault-secrets-template.yml'
# Определение этапов пайплайна
stages:
- build
- deploy
# Определение триггеров для пайплайнов на основе веток
workflow:
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
- if: '$CI_COMMIT_REF_NAME == "staging"'
- if: '$CI_COMMIT_REF_NAME == "develop"'
# Билд для production с Kaniko и Vault
build_prod:
stage: build
image: gcr.io/kaniko-project/executor:latest
environment:
name: production
script:
# Вход в Vault и получение секретов для продакшена
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/prod/db-creds)
# Билд Docker-образа через Kaniko
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:prod --cache=true
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
# Билд для staging с Kaniko и Vault
build_stage:
stage: build
image: gcr.io/kaniko-project/executor:latest
environment:
name: staging
script:
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/staging/db-creds)
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:stage --cache=true
rules:
- if: '$CI_COMMIT_REF_NAME == "staging"'
# Билд для development с Kaniko и Vault
build_dev:
stage: build
image: gcr.io/kaniko-project/executor:latest
environment:
name: development
script:
- vault login $VAULT_TOKEN
- export DB_PASSWORD=$(vault kv get -field=password secret/dev/db-creds)
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:dev --cache=true
rules:
- if: '$CI_COMMIT_REF_NAME == "develop"'
# Деплой на production через ArgoCD
deploy_prod:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: production
script:
- kubectl config set-cluster $K8S_CLUSTER --server=$K8S_SERVER --insecure-skip-tls-verify=true
- kubectl config set-credentials $K8S_USER --token=$K8S_TOKEN
- kubectl config set-context $K8S_CONTEXT --cluster=$K8S_CLUSTER --user=$K8S_USER
- kubectl config use-context $K8S_CONTEXT
- argocd app sync my-app-prod --prune --timeout 300
rules:
- if: '$CI_COMMIT_REF_NAME == "main"'
# Деплой на staging через ArgoCD
deploy_stage:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: staging
script:
- kubectl config set-cluster $K8S_CLUSTER --server=$K8S_SERVER --insecure-skip-tls-verify=true
- kubectl config set-credentials $K8S_USER --token=$K8S_TOKEN
- kubectl config set-context $K8S_CONTEXT --cluster=$K8S_CLUSTER --user=$K8S_USER
- kubectl config use-context $K8S_CONTEXT
# Синхронизация приложения через ArgoCD
- argocd app sync my-app-stage --prune --timeout 300
rules:
- if: '$CI_COMMIT_REF_NAME == "staging"'
# Деплой на development через ArgoCD
deploy_dev:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: development
script:
- kubectl config set-cluster $K8S_CLUSTER --server=$K8S_SERVER --insecure-skip-tls-verify=true
- kubectl config set-credentials $K8S_USER --token=$K8S_TOKEN
- kubectl config set-context $K8S_CONTEXT --cluster=$K8S_CLUSTER --user=$K8S_USER
- kubectl config use-context $K8S_CONTEXT
- argocd app sync my-app-dev --prune --timeout 300
rules:
- if: '$CI_COMMIT_REF_NAME == "develop"'
Обзор итогового пайплайна:
1. Сборка:
- Используется Kaniko для сборки Docker-образов для каждого окружения (prod, staging, dev).
- В процессе сборки, перед запуском Kaniko, из Vault извлекаются секреты для каждого окружения (например, пароли для баз данных).
2. Деплой:
- После успешной сборки происходит деплой через ArgoCD.
- Для каждого окружения используется отдельное приложение в ArgoCD (my-app-prod, my-app-stage, my-app-dev).
3. Workflow:
Пайплайн запускается только при работе с ветками main (production), staging, и develop.
Заключение
Эффективный CI/CD-процесс сегодня — это не просто автоматизация сборки и деплоя, а комплексная система, которая включает управление секретами, безопасное окружение для сборки, гибкость конфигураций и контроль на каждом этапе. Интеграция инструментов, таких как GitLab CI, Kaniko, ArgoCD и HashiCorp Vault, позволяет создавать мощные и безопасные пайплайны, которые обеспечивают стабильность и предсказуемость процесса разработки.
Оставьте заявку, чтобы обсудить проект
Спасибо за обращение
Мы свяжемся с вами в ближайшее время.