задний план
В настоящее время используется 5 серверов для сборкиKubernetesВ кластерной среде реализованы мониторинг и сбор журналов, а бизнес также вручную перенесен в кластер для бесперебойной работы, поэтому необходимоdockerПроцесс CICD среды перенесен вKubernetesв кластере
Преимущество
KubernetesКластеризация для реализации CICD имеет несколько существенных преимуществ.
-
DeploymentЕстественная поддержка непрерывного развертывания в сочетании с другимиKubernetesФункции также могут обеспечить сине-зеленое развертывание, канареечное развертывание и т. д. - новая версия
GitLabиGitLab Runnerестественная поддержкаKubernetesкластер, поддержкаrunnerАвтоматическое масштабирование для сокращения использования ресурсов
окрестности
KubernetesВерсия: 1.14
GitLabВерсия: 12.2.5
GitLab-RunnerВерсия: 12.1.0
DockerВерсия среды: 17.03.1
Развертывание GitLab-Runner
Введение в конфигурацию
исходная средаgitlab runnerВыполняя вручную команду регистрации и команду запуска, предоставленную на официальном веб-сайте, он делится на два развертывания, что требует большего количества ручных операций.Kubernetes, который поддерживает использованиеHelmРазвертывание в один клик, официальные документы следующие
На самом деле, рекомендации официальной документации не ясны, и многие конфигурации не представлены в документации.Рекомендуется перейти в репозиторий исходного кода, чтобы просмотреть подробную документацию по использованию параметров.
Введено несколько ключевых конфигураций, позже проект будет изменен.ciбудет использоваться файл конфигурации
Сборка с DinD больше не рекомендуется
официальная документациявводить
Use docker-in-docker workflow with Docker executor
The second approach is to use the special docker-in-docker (dind) Docker image with all tools installed (
docker) and run the job script in context of that image in privileged mode.Note:
docker-composeis not part of docker-in-docker (dind). To usedocker-composein your CI builds, follow thedocker-composeinstallation instructions.Danger: By enabling
--docker-privileged, you are effectively disabling all of the security mechanisms of containers and exposing your host to privilege escalation which can lead to container breakout. For more information, check out the official Docker documentation on Runtime privilege and Linux capabilities.Docker-in-Docker works well, and is the recommended configuration, but it is not without its own challenges:
- При использовании docker-in-docker каждое задание находится в чистой среде без прошлой истории. Параллельные задания работают нормально, потому что каждая сборка получает собственный экземпляр механизма Docker, поэтому они не будут конфликтовать друг с другом. Но это также означает, что задания могут быть медленнее, потому что нет кэширования слоев.
- By default, Docker 17.09 and higher uses
--storage-driver overlay2which is the recommended storage driver. See Using the overlayfs driver for details.- Since the
docker:19.03.1-dindконтейнер и контейнер Runner не используют общую корневую файловую систему, рабочий каталог задания можно использовать в качестве точки монтирования для дочерних контейнеров.Например, если у вас есть файлы, которыми вы хотите поделиться с дочерним контейнером, вы можете создать подкаталог в/builds/$CI_PROJECT_PATHand use it as your mount point (for a more thorough explanation, check issue #41227):
В любом случае используйтеDinDВыполнение сборки контейнеров возможно, но сталкивается со многими проблемами, такими как использованиеoverlay2Для работы в сети требуется версия Docker выше 17.09.
Using
docker:dindRunning the
docker:dindalso known as thedocker-in-dockerimage is also possible but sadly needs the containers to be run in privileged mode. If you're willing to take that risk other problems will arise that might not seem as straight forward at first glance. Because the docker daemon is started as aserviceusually in your.gitlab-ci.yamlit will be run as a separate container in your Pod. Basically containers in Pods only share volumes assigned to them and an IP address by which they can reach each other usinglocalhost./var/run/docker.sockis not shared by thedocker:dindcontainer and thedockerbinary tries to use it by default.To overwrite this and make the client use TCP to contact the Docker daemon, in the other container, be sure to include the environment variables of the build container:
DOCKER_HOST=tcp://localhost:2375for no TLS connection.DOCKER_HOST=tcp://localhost:2376for TLS connection.Make sure to configure those properly. As of Docker 19.03, TLS is enabled by default but it requires mapping certificates to your client. You can enable non-TLS connection for DIND or mount certificates as described in Use Docker In Docker Workflow wiht Docker executor
Включено по умолчанию после Docker 19.03.1TLSКонфигурация, ее необходимо объявить во встроенной переменной окружения, иначе сообщение о подключении невозможноdockerошибка и используйтеDinDсоздавать потребностиrunnerВключите привилегированный режим для доступа к ресурсам хоста, а так как привилегированный режим используется, вPodсредняя параrunnerОграничение ресурсов, которое необходимо использовать, будет недействительным.
Создание образов Docker с помощью Kaniko
В настоящее время официально предусмотрен другой метод вdockerСоздавайте и отправляйте образы в контейнер, который является более элегантным и может обеспечить плавную миграцию, т.е.kaniko
Building a Docker image with kaniko
Его преимущества описаны на официальном сайте следующим образом.
Другой способ создать образ Docker в кластере Kubernetes — использоватьkaniko. икоко
- Позволяет создавать образы без привилегированного доступа.
- Работает без демона Docker.
В следующей практике для сборки образов Docker будут использоваться два метода, которые можно выбрать в соответствии с реальной ситуацией.
Развертывание с помощью Helm
ВытащитьHelm Gitlab-RunnerСклад на локальный, изменить конфигурацию
поставь оригиналgitlab-runnerКонфигурация перенесена вHelm, после миграции следующим образом
image: alpine-v12.1.0
imagePullPolicy: IfNotPresent
gitlabUrl: https://gitlab.fjy8018.top/
runnerRegistrationToken: "ZXhpuj4Dxmx2tpxW9Kdr"
unregisterRunners: true
terminationGracePeriodSeconds: 3600
concurrent: 10
checkInterval: 30
rbac:
create: true
clusterWideAccess: false
metrics:
enabled: true
listenPort: 9090
runners:
image: ubuntu:16.04
imagePullSecrets:
- name: registry-secret
locked: false
tags: "k8s"
runUntagged: true
privileged: true
pollTimeout: 180
outputLimit: 4096
cache: {}
builds: {}
services: {}
helpers: {}
resources:
limits:
memory: 2048Mi
cpu: 1500m
requests:
memory: 128Mi
cpu: 200m
affinity: {}
nodeSelector: {}
tolerations: []
hostAliases:
- ip: "192.168.1.13"
hostnames:
- "gitlab.fjy8018.top"
- ip: "192.168.1.30"
hostnames:
- "harbor.fjy8018.top"
podAnnotations: {}
Который настроен с закрытым ключом, интранетharborадрес,harborИзвлечь закрытый ключ ресурса, политика ограничения ресурсов
Выбор GitLab-Runner может привести к ямам
выберитеrunnerзеркально какalpine-v12.1.0, только этот момент, последняя версия бегуна 12.5.0, но в ней много проблем,alpineНовая версия зеркала находится вKubernetesПроизошло прерывание, которое не удалось разрешитьDNSпроблема, отраженная вGitLab-Runnerв центреCould not resolve hostиserver misbehaving
Ознакомьтесь с решением
В ходе запроса выясняется, что на его официальном складе все еще есть много связанных проблем, которые не были закрыты.
Официальный гитлаб:Kubernetes runner: Could not resolve host
переполнение стека:Gitlab Runner is not able to resolve DNS of Gitlab Server
Приведенные решения без исключения относятся к переходу на alpine-v12.1.0.
We had same issue for couple of days. We tried change CoreDNS config, move runners to different k8s cluster and so on. Finally today i checked my personal runner and found that i'm using different version. Runners in cluster had
gitlab/gitlab-runner:alpine-v12.3.0, when mine hadgitlab/gitlab-runner:alpine-v12.0.1. We added lineimage: gitlab/gitlab-runner:alpine-v12.1.0in
values.yamland this solved problem for us
Корень проблемы должен быть в том, что у базового образа alpine проблема с поддержкой кластера Kubernetes.
ndots breaks DNS resolving #64924
docker-alpineИмеются также незакрытые соответствующие складыissue, в котором упоминается оDNSПроблемы с разбором тайм-аутов и исключений
Установить
Однострочная команда для установки
$ helm install /root/gitlab-runner/ --name k8s-gitlab-runner --namespace gitlab-runner
Вывод выглядит следующим образом
NAME: k8s-gitlab-runner
LAST DEPLOYED: Tue Nov 26 21:51:57 2019
NAMESPACE: gitlab-runner
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
k8s-gitlab-runner-gitlab-runner 5 0s
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
k8s-gitlab-runner-gitlab-runner 0/1 1 0 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
k8s-gitlab-runner-gitlab-runner-744d598997-xwh92 0/1 Pending 0 0s
==> v1/Role
NAME AGE
k8s-gitlab-runner-gitlab-runner 0s
==> v1/RoleBinding
NAME AGE
k8s-gitlab-runner-gitlab-runner 0s
==> v1/Secret
NAME TYPE DATA AGE
k8s-gitlab-runner-gitlab-runner Opaque 2 0s
==> v1/ServiceAccount
NAME SECRETS AGE
k8s-gitlab-runner-gitlab-runner 1 0s
NOTES:
Your GitLab Runner should now be registered against the GitLab instance reachable at: "https://gitlab.fjy8018.top/"
Проверьте страницу администратора gitlab и обнаружите, что бегун был успешно зарегистрирован.
Инженерная конфигурация
DinD способ сборки необходимой конфигурации
Если оригиналciфайл основан на19.03 DinDЗеркальные сборки должны быть добавленыTLSСвязанная конфигурация
image: docker:19.03
variables:
DOCKER_DRIVER: overlay
DOCKER_HOST: tcp://localhost:2375
DOCKER_TLS_CERTDIR: ""
...
Остальная конфигурация остается прежней, построена с помощью DinD.
Конфигурация разрешений Kubectl и Kubernetes
из-за использованияk8sкластер, а развертывание через кластер требует использованияkubectlклиент, поэтому вручную создалkubectl dockerзеркало, использоватьgitlabкурокdockerhubКонструкция, содержимое конструкции открыто и прозрачно, и его можно использовать с уверенностью.Если есть другие версии требований к конструкции, вы также можете отправить запрос на вытягивание, который будет добавлен позже.В настоящее время используется только 1.14.0.
имеютkubectlКлиент, также необходимо настроить подключениеTLSи связанные аккаунты
Для обеспечения безопасности создайте новый, который специально обращается к пространству имен проекта.ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: hmdt-gitlab-ci
namespace: hmdt
Используйте механизм RBAC, предоставляемый кластером, чтобы предоставить учетной записи права администратора для пространства имен.
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: hmdt-gitlab-role
namespace: hmdt
subjects:
- kind: ServiceAccount
name: hmdt-gitlab-ci
namespace: hmdt
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: admin
После создания запросите его уникальное имя, сгенерированное в кластере k8s, вотhmdt-gitlab-ci-token-86n89
$ kubectl describe sa hmdt-gitlab-ci -n hmdt
Name: hmdt-gitlab-ci
Namespace: hmdt
Labels: <none>
Annotations: kubectl.`Kubernetes`.io/last-applied-configuration:
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"hmdt-gitlab-ci","namespace":"hmdt"}}
Image pull secrets: <none>
Mountable secrets: hmdt-gitlab-ci-token-86n89
Tokens: hmdt-gitlab-ci-token-86n89
Events: <none>
Затем найдите сертификат ЦС в соответствии с приведенным выше секретом.
$ kubectl get secret hmdt-gitlab-ci-token-86n89 -n hmdt -o json | jq -r '.data["ca.crt"]' | base64 -d
Затем найдите соответствующий токен
$ kubectl get secret hmdt-gitlab-ci-token-86n89 -n hmdt -o json | jq -r '.data.token' | base64 -d
Конфигурация GitLab, связанная с Kubernetes
Войдите на страницу конфигурации кластера gitlab Kubernetes, заполните соответствующую информацию и разрешите gitlab автоматически подключаться к среде кластера.
Обратите внимание, что вам нужно снять этот флажок, иначе gitlab автоматически создаст новую учетную запись пользователя вместо использования уже созданной учетной записи пользователя и не сообщит об ошибке разрешения во время работы.
Ошибка, вызванная отказом от отмены, выглядит следующим образом: gitlab создал новую учетную запись пользователя.hmdt-prod-service-account, но не имеет разрешения на работу с указанным пространством имен
Конфигурация среды GitLab
Создайте среду
Имя и URL-адрес можно настроить по мере необходимости.
Конфигурация CI-скрипта
Окончательный файл конфигурации CI выглядит следующим образом, в котором используетсяDinDспособ построитьDockerfile
image: docker:19.03
variables:
MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode -Dmaven.test.skip=true"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
DOCKER_DRIVER: overlay
DOCKER_HOST: tcp://localhost:2375
DOCKER_TLS_CERTDIR: ""
SPRING_PROFILES_ACTIVE: docker
IMAGE_VERSION: "1.8.6"
DOCKER_REGISTRY_MIRROR: "https://XXX.mirror.aliyuncs.com"
stages:
- test
- package
- review
- deploy
maven-build:
image: maven:3-jdk-8
stage: test
retry: 2
script:
- mvn $MAVEN_CLI_OPTS clean package -U -B -T 2C
artifacts:
expire_in: 1 week
paths:
- target/*.jar
maven-scan:
stage: test
retry: 2
image: maven:3-jdk-8
script:
- mvn $MAVEN_CLI_OPTS verify sonar:sonar
maven-deploy:
stage: deploy
retry: 2
image: maven:3-jdk-8
script:
- mvn $MAVEN_CLI_OPTS deploy
docker-harbor-build:
image: docker:19.03
stage: package
retry: 2
services:
- name: docker:19.03-dind
alias: docker
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build --pull -t "$CI_REGISTRY_IMAGE:$IMAGE_VERSION" .
- docker push "$CI_REGISTRY_IMAGE:$IMAGE_VERSION"
- docker logout $CI_REGISTRY
deploy_live:
image: fjy8018/kubectl:v1.14.0
stage: deploy
retry: 2
environment:
name: prod
url: https://XXXX
script:
- kubectl version
- kubectl get pods -n hmdt
- cd manifests/
- sed -i "s/__IMAGE_VERSION_SLUG__/${IMAGE_VERSION}/" deployment.yaml
- kubectl apply -f deployment.yaml
- kubectl rollout status -f deployment.yaml
- kubectl get pods -n hmdt
Используйте при необходимостиKanikoПостроитьDockerfile, конфигурация следующая
Обратите внимание, что зеркала, которые зависят от нихgcr.io/kaniko-project/executor:debugОн принадлежит зеркальному складу Google и может быть недоступен.
image: docker:19.03
variables:
MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode -Dmaven.test.skip=true"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
DOCKER_DRIVER: overlay
DOCKER_HOST: tcp://localhost:2375
DOCKER_TLS_CERTDIR: ""
SPRING_PROFILES_ACTIVE: docker
IMAGE_VERSION: "1.8.6"
DOCKER_REGISTRY_MIRROR: "https://XXX.mirror.aliyuncs.com"
cache:
paths:
- target/
stages:
- test
- package
- review
- deploy
maven-build:
image: maven:3-jdk-8
stage: test
retry: 2
script:
- mvn $MAVEN_CLI_OPTS clean package -U -B -T 2C
artifacts:
expire_in: 1 week
paths:
- target/*.jar
maven-scan:
stage: test
retry: 2
image: maven:3-jdk-8
script:
- mvn $MAVEN_CLI_OPTS verify sonar:sonar
maven-deploy:
stage: deploy
retry: 2
image: maven:3-jdk-8
script:
- mvn $MAVEN_CLI_OPTS deploy
docker-harbor-build:
stage: package
retry: 2
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$IMAGE_VERSION
deploy_live:
image: fjy8018/kubectl:v1.14.0
stage: deploy
retry: 2
environment:
name: prod
url: https://XXXX
script:
- kubectl version
- kubectl get pods -n hmdt
- cd manifests/
- sed -i "s/__IMAGE_VERSION_SLUG__/${IMAGE_VERSION}/" deployment.yaml
- kubectl apply -f deployment.yaml
- kubectl rollout status -f deployment.yaml
- kubectl get pods -n hmdt
конвейер выполнения
бегун автоматически расширяется и сжимается
KubernetesБегун в раннере будет автоматически расширяться и сжиматься в зависимости от количества задач Текущее ограничение конфигурации — 10.
Grafana также может отслеживать использование ресурсов кластера в процессе сборки.
использоватьDinDПостроитьDockerfileрезультат
использоватьKanikoПостроитьDockerfileрезультат
Результат развертывания
При развертывании gitlab автоматически внедрит настроенную конфигурацию.kubectl config
построить результат
После завершения развертывания вы можете просмотреть результаты развертывания на странице конфигурации среды.Будут записаны только успешные развертывания.