Как стать автором
Обновить
33.72
Gitorion
CI/CD Kubernetes-платформа

CI/CD Kubernetes платформа Gitorion. Непрерывная доставка CD на базе Jenkins

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров2.6K

Привет всем! В предыдущей статье мы подробно рассмотрели реализацию непрерывной интеграции CI на базе Gitea/Forgejo в платформе Gitorion. В данной статье предлагаем вашему вниманию подробнее познакомиться с внедрением непрерывной доставки CD в платформу Gitorion на базе Jenkins.

Jenkins Agents

Jenkins выполняет все команды пайплайнов в агентах, которые запускает как модули в кластере Kubernetes по Web-хуку из Gitea/Forgejo. Спецификацию модуля агента Jenkins задайте в Jenkinsfile:

pipeline {

  agent {
    kubernetes {
            yaml """
apiVersion: v1
kind: Pod
metadata:
  name: build-pod
  annotations:
    container.apparmor.security.beta.kubernetes.io/buildkitd: unconfined
  labels:
    app.kubernetes.io/component: jenkins-dind
    app.kubernetes.io/instance: jenkins
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - "dc1-worker1"
  containers:
    - name: jnlp
      resources: {}
    - name: docker-client
      image: docker:dind-rootless
      imagePullPolicy: IfNotPresent
      env:
      - name: DOCKER_HOST
        value: "unix:///run/user/1000/docker.sock"
      securityContext:
        privileged: true
    - name: buildkitd
      image: moby/buildkit:master-rootless
      imagePullPolicy: IfNotPresent
      args:
        - --oci-worker-no-process-sandbox
        - --addr
        - unix:///run/user/1000/buildkit/buildkitd.sock
        - --addr
        - tcp://0.0.0.0:1234
      readinessProbe:
        exec:
          command:
            - buildctl
            - debug
            - workers
        initialDelaySeconds: 5
        periodSeconds: 30
      livenessProbe:
        exec:
          command:
            - buildctl
            - debug
            - workers
        initialDelaySeconds: 5
        periodSeconds: 30
      securityContext:
        seccompProfile:
          type: Unconfined
        runAsUser: 1000
        runAsGroup: 1000
      volumeMounts:
        - mountPath: /home/user/.local/share/buildkit
          name: buildkitd
  volumes:
    - name: buildkitd
      emptyDir: {}
"""
        }
    }

    stage ('build') {
      steps {
	    container('docker-client') {
          script {
            ...
    	  }
	    }
      }
    }

    stage('staging') {
      steps {
	    script {
	      container('docker-client') {
            script {
              ...
            }
	      }
        }
      }
    }

   ...
}

Агент вытягивает Git-репозиторий микросервиса из Gitea/Forgejo по Web-хуку и выполняет стадии пайплана в Jenkinsfile, расположенном в корне git-репозитория.

Jenkins Agent вытягивает Git-репозиторий из Gitea/Forgejo
Jenkins Agent вытягивает Git-репозиторий из Gitea/Forgejo

Безопасная сборка Docker-образов в Kubernetes

Для сборки Docker-образов в кластере Kubernetes запустите в модуле агента Jenkins "build-pod" контейнер "docker-client" созданный из Docker-образа "image: docker:dind-rootless". В данном контейнере будет запущен Docker-сервер, который выполнит все команды docker из пайплайна. Сборку Docker-образов Docker-сервер отправляет на Buildkitd-сервер, запущенный в контейнере "buildkitd" из образа "image: moby/buildkit:master-rootless".

Из соображений безопасности настоятельно рекомендуем использовать только rootless образы dind и buildkit d в которых все процессы запускаются от имени пользователя не имеющего root-прав. В контейнерах, созданных из образов dind:latest и buildkit:latest процессы запускаются с root-правами, что дает возможность получить root-доступ к хосту кластера Kubernetes. Так же следует запретить на git-сервере вносить изменения в Jenkinsfile всем кроме доверенных лиц, чтобы лишить возможности переопределить модуль агента Jenkins. Как это сделать мы подробно рассказали в статье про непрерывную интеграцию CI в пункте "Защита веток".

Для ускорения сборки Docker-образов Buildkit задействует кэш сборки Docker, который хранит в приватном репозитории Docker-образов. Данный подход позволяет не собирать при каждой сборке слои, в которых не внесли изменения, а брать уже ранее собранные слои в предыдущих сборках из кэша:

+ docker buildx create --use '--driver=remote' tcp://127.0.0.1:1234
keen_hoover
[Pipeline] sh
+ docker buildx build --push -t registry.gitorion.kvm/gitorion/owneruser/frontend/master:d5a6fa44a1fafdcf89423096f7d2125702e85001 --cache-to 'type=registry,image-manifest=true,ref=registry.gitorion.kvm/gitorion/owneruser/frontend/master:latest,mode=min' --cache-from 'type=registry,image-manifest=true,ref=registry.gitorion.kvm/gitorion/owneruser/frontend/master:latest' --cache-from 'type=registry,image-manifest=true,ref=registry.gitorion.kvm/gitorion/nginx:1.27.3-alpine3.20' .doc

На рисунке ниже приведем пример сборки Docker-образа в пайплайне Jenkins

Jenkins Agent собирает Docker-образ приложения
Jenkins Agent собирает Docker-образ приложения

Приватный репозиторий Docker-образов

Для хранения собранных Docker-образов установили в кластер Kubernetes приватный репозиторий Docker-образов Harbor. Jenkins Agent выполняет команду docker push и отправляет Docker-образ, собранный на стадии Build, в приватный репозиторий Docker-образов. На стадии доставки микросервиса в кластер Kubernetes ресурсы Deployment или StatefulSet берут Docker-образы из приватного репозитория Docker-образов и используют для запуска Docker-контейнеров микросервисов в кластере Kubernetes.

Jenkins Agent отправляет Docker-образ в приватный репозиторий
Jenkins Agent отправляет Docker-образ в приватный репозиторий

Multibranch Pipeline

В предыдущей статье про непрерывную интеграцию CI на базе Gitea/Forgejo мы упоминали, что каждый программист вносит изменения в код только в пределах своей ветки. В Jenkins есть пайплайн типа Multibranch Pipeline, который автоматически обнаруживает новые ветки в Git-репозитории и для каждой из них запускает свой пайплайн. Программист создает новую ветку командами:

git checkout -b dev3
git push --set-upstream origin dev3

Gitea/Forgejo посылает Web-хук в Jenkins. Jenkins по Web-хуку автоматически находит новую ветку и запускает для нее пайплайн.

Multibranch Pipeline нашел новую ветку dev3 в Git-репозитории и запустил для нее пайплайн
Multibranch Pipeline нашел новую ветку dev3 в Git-репозитории и запустил для нее пайплайн

Cтадии пайплайна

Независимо от имени ветки, первой запускается стадия Build, в которой собирается Docker-образ микросервиса и помещается в приватный репозиторий Docker Registry. Далее, пайплайн извлекает из Web-хука имя ветки. Для ветки main запускает стадию Staging и доставляет микросервис в контур Staging.

Стадия Staging
Стадия Staging

Для всех остальных веток пайплайн запускает стадию Review и деплоит микросервис в контур Development.

Стадия Review
Стадия Review

Cтадии Staging и Review используют одни и те же шаблоны templates helm-чарта в Git-репозитории микросервиса, чтобы на Review доставлялось то же самое, что и на Staging и в Production. В helm-чарте содержится директория configs с конфигами микросервиса отдельно для каждого контура Development, Staging и Production.

Связь коммитов Gitea с ревизиями Helm

Jenkins Agent в момент деплоя микросервиса в Staging контур извлекает SHA1 коммита из Web-хука Gitea/Forgejo.

Коммиты в Gitea/Forgejo
Коммиты в Gitea/Forgejo

Каждый новый деплой микросервиса - это очередная ревизия helm. Мы добавили SHA1 коммита к именам ревизий helm, тем самым связав SHA1 коммитов с номерами ревизий helm.

Связь SHA1 коммитов Gitea/Forgejo c номерами ревизий helm
Связь SHA1 коммитов Gitea/Forgejo c номерами ревизий helm

Так же SHA1 коммитов мы использовали в качестве тэгов при именования Docker-образов:

image: docker-registry.jenkins.svc.cluster.local/owneruser/backend/main:bb7cfed40a

Промоушен Promote со Staging на Production

После демонстрации в окружении Staging наработок программистов заказчику, тимлид вручную запускает пайплайн промоушена Promote микросервиса со Staging на Production. Пайплайн выполняет команду:

helm history staging-owneruser-backend -n staging

Берет SHA1 коммита, соответствующего ревизии, у которой в столбце STATUS стоит "deployed" (см. скрин выше). Извлекает из приватного репозитория образов Docker Registry Docker-образ, тэг которого соответствует коммиту со статусом "deployed":

image: docker-registry.jenkins.svc.cluster.local/owneruser/backend/main:74e5cbd967

и доставляет в Production контур. Стадия Build игнорируется, поскольку сборка Docker-образа не нужна на стадии промоушена Promote.

Стадия промоушена Promote со Staging на Production
Стадия промоушена Promote со Staging на Production

Откат Rollback на предыдущие версии

На случай, если в продакшен будет доставлен микросервис с ошибкой, разработали пайплайн отката Rollback на предыдущие версии. Чтобы иметь возможность оперативно восстановить работу продакшена, пока программисты будут исправлять ошибку.

Для отката Rollback тимлиду нужно определиться, до какого коммита в Gitea/Forgejo он хочет откатиться, задать SHA1 коммита в параметрах пайплайна и вручную запустить пайплайн.

Список коммитов, до которых можно сделать откат Rollback
Список коммитов, до которых можно сделать откат Rollback

Jenkins Agent выполнит откат командой helm rollback до ревизии, соответствующей выбранному коммиту.

Откат Rollback до заданного коммита
Откат Rollback до заданного коммита

Canary-релизы

Чтобы не перегружать текущую статью, мы рассказали о способах безопасно протестировать новый релиз приложения на ограниченном количестве реальных пользователей в продакшене в отдельной статье по Canary-релизы.

Заключение

В следующей статье мы рассмотрим подробнее тонкости реализации единого входа Single Sign-On (SSO) во все сервисы платформы Gitorion при помощи Keycloak. Спасибо.

Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Публикации

Информация

Сайт
gitorion.ru
Дата регистрации
Численность
2–10 человек
Представитель
gitorion

Истории