Непрерывная интеграция с помощью Drone на Kubernetes


Обзор

За последние несколько лет многие организации начали внедрять архитектуры Cloud Native. Несмотря на внедрение архитектуры Cloud Native, многие компании не достигли оптимальных результатов. Интересно, почему? Одной из причин является наша приверженность традиционным способам создания и развертывания приложений Cloud Native.

Kubernetes стала де-факто платформой развертывания Cloud Native, решив одну из основных проблем Cloud Native: «развертывание» приложений быстро, эффективно и надежно. Она предлагает радикально простое масштабирование и отказоустойчивость. Несмотря на это, не многие системы непрерывной интеграции (CI) используют преимущества Kubernetes. Ни одна из существующих систем сборки не предлагает возможности, присущие Kubernetes, такие как сборка в кластере, определение ресурсов сборки с помощью CRD, использование базовых средств безопасности и контроля доступа и т.д. Эти недостающие возможности Kubernetes сделали архитектуры Cloud Native менее эффективными и более сложными.

Позвольте мне представить Open Source проект Drone — облачную платформу самообслуживания Continuous Integration. 10 лет назад Drone был первым инструментом CI, который использовал контейнеры для запуска независимых друг от друга этапов конвейера. Сегодня, имея более 100M+ Docker pulls и наибольшее количество звезд на GitHub среди всех решений непрерывной интеграции, Drone предлагает зрелую систему CI на базе Kubernetes, использующую масштабирование и отказоустойчивость архитектуры Cloud Native. Drone помогает решить следующую часть головоломки, запуская встроенные в Kubernetes сборки в кластере.

В этом блоге мы рассмотрим, как мы установили kind и Drone вместе на наших ноутбуках для создания нативных конвейеров Kubernetes, которые затем могут быть перенесены на облачные платформы, такие как Harness CI, для более широкой командной разработки.

Этот блог представляет собой учебник, в котором я объясняю шаги, необходимые для использования KinD и Drone для настройки CI с Kubernetes на вашей локальной машине. По завершении этих шагов у вас будет полностью функциональная настройка Kubernetes + CI, которая поможет вам создавать и развертывать Cloud Native приложения на Kubernetes на вашем ноутбуке.

Необходимые инструменты

Для успешного завершения этой настройки нам понадобятся следующие инструменты на вашем ноутбуке,

  • Docker Desktop или Docker в Linux
  • вид
  • Helm
  • Kustomize
  • Kubectl
  • envsusbst

Все дистрибутивы linux добавляют envsubst через пакет gettext. На macOS он может быть установлен с помощью Homebrew, например brew install gettext.

Исходники демонстрации

Сопроводительный код для этого блога, т.е. демонстрационные исходники, доступен на моем репозитории GitHub. Давайте клонируем их на нашу машину,

git clone https://github.com/kameshsampath/drone-on-k8s && 
  cd "$(basename "$_" .git)"
export PROJECT_HOME="${PWD}"
Войдите в полноэкранный режим Выходим из полноэкранного режима

ПРИМЕЧАНИЕ: В этом блоге мы будем использовать имя $PROJECT_HOME для ссылки на папку с демо-исходниками, которую мы клонировали выше.

Итак, мы готовы приступить к работе!!!

## Настройка кластера Kubernetes

Как было сказано ранее, мы будем использовать kind в качестве нашего локального кластера Kubernetes. Но для этого блога мы сделаем следующие настройки,

  • Настроим локальный реестр контейнеров, куда мы сможем заталкивать и вытаскивать образы контейнеров, которые будут использоваться в нашем Kubernetes. Более подробную информацию можно найти в документации.
  • Сделайте дополнительные сопоставления портов, чтобы мы могли получить доступ к серверу Drone и git-репозиторию Gitea.

Чтобы упростить работу, все вышеупомянутые настройки были собраны в утилитный скрипт $PROJECT_HOME/bin/kind.sh. Чтобы запустить кластер KinD с этими настройками, просто сделайте следующее,

$PROJECT_HOME/bin/kind.sh
Войти в полноэкранный режим Выйти из полноэкранного режима

Система контроля версий

Без системы контроля версий (VCS) CI не имеет смысла. Одна из основных целей этого блога — показать, как запустить локальную VCS, чтобы вы могли создавать свои приложения без необходимости использования внешних VCS, таких как GitHub, Gitlab и т.д. Для нашей установки мы будем использовать Gitea — безболезненный, самостоятельно размещаемый сервис Git -. Gitea очень прост в настройке и предоставляет диаграммы Helm для установки на базе Kubernetes.

Значения Helm

Содержимое файла helm values, который будет использоваться для настройки Gitea, показано ниже. Настройки не требуют пояснений, более подробную информацию можно найти в шпаргалке.

service:
  http:
    # the Kubernetes service gitea-http'  service type
    type: NodePort 
    # the gitea-http service port
    port: 3000
    # this port will be used in KinD extra port mappings to allow accessing the 
    # Gitea server from our laptops
    nodePort: 30950
gitea:
  # the admin credentials to access Gitea typically push/pull operations
  admin:
    # DON'T use username admin as its reserved and gitea will 
    # fail to start
    username: demo
    password: demo@123
    email: admin@example.com
  config:
    server:
      # for this demo we will use http protocol to access Git repos
      PROTOCOL: http
      # the port gitea will listen on
      HTTP_PORT: 3000
      # the Git domain - all the repositories will be using this domain
      DOMAIN: gitea-127.0.0.1.sslip.io
      # The clone base url e.g. if repo is demo/foo the clone url will be 
      # http://gitea-127.0.0.1.sslip.io:3000/demo/foo
      ROOT_URL: http://gitea-127.0.0.1.sslip.io:3000/
    webhook:
      # since we will deploy to local network we will allow all hosts
      ALLOWED_HOST_LIST: "*"
      # since we are in http mode disable TLS
      SKIP_TLS_VERIFY: true
Войти в полноэкранный режим Выйти из полноэкранного режима

Добавьте репозиторий gitea helm,

helm repo add gitea-charts https://dl.gitea.io/charts/
helm repo update
Войти в полноэкранный режим Выйдите из полноэкранного режима

Выполните следующую команду для развертывания Gitea,

helm upgrade 
  --install gitea gitea-charts/gitea 
  --values $PROJECT_HOME/helm_vars/gitea/values.yaml 
  --wait
Войти в полноэкранный режим Выйдите из полноэкранного режима

Успешное развертывание gitea должно показать следующие службы в пространстве имен по умолчанию при выполнении команды,

kubectl get pods,svc -lapp.kubernetes.io/instance=gitea

Войти в полноэкранный режим Выйти из полноэкранного режима
NAME                                  READY   STATUS    RESTARTS   AGE
pod/gitea-0                           1/1     Running   0          4m32s
pod/gitea-memcached-b87476455-4kqvp   1/1     Running   0          4m32s
pod/gitea-postgresql-0                1/1     Running   0          4m32s

NAME                                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/gitea-http                  NodePort    10.96.55.25     <none>        3000:30950/TCP   4m32s
service/gitea-memcached             ClusterIP   10.96.176.235   <none>        11211/TCP        4m32s
service/gitea-postgresql            ClusterIP   10.96.59.23     <none>        5432/TCP         4m32s
service/gitea-postgresql-headless   ClusterIP   None            <none>        5432/TCP         4m32s
service/gitea-ssh                   ClusterIP   None            <none>        22/TCP           4m32s
Войти в полноэкранный режим Выйти из полноэкранного режима

Переменные окружения

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

Gitea

# Gitea domain
export GITEA_DOMAIN="gitea-127.0.0.1.sslip.io"
# Gitea URL
export GITEA_URL="http://${GITEA_DOMAIN}:3000"
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы можете получить доступ к Gitea в браузере, например, открыв ${GITEA_URL}. Учетные данные по умолчанию demo/demo@123.

Дрон

# the drone server host
export DRONE_SERVER_HOST="drone-127.0.0.1.sslip.io:8080"
# the drone server web console
export DRONE_SERVER_URL="http://${DRONE_SERVER_HOST}"
Войдите в полноэкранный режим Выход из полноэкранного режима

Приложение Drone Gitea oAuth

Drone будет использовать Gitea для получения/отправки исходного кода и добавления веб-крючков для запуска сборок при изменении исходного кода. Для выполнения этих действий необходимо настроить на Gitea приложение oAuth.

В демонстрационных исходниках есть небольшая утилита gitea-config, которая помогает создать приложение oAuth в Gitea, а также клонировать и создать на Gitea репозиторий quickstart под названием drone-quickstart. Мы будем использовать репозиторий drone-quickstart* для проверки нашей установки.

$PROJECT_HOME/bin/gitea-config-darwin-arm64 
  -g "${GITEA_URL}" -dh "${DRONE_SERVER_URL}"
Вход в полноэкранный режим Выйдите из полноэкранного режима

ПРИМЕЧАНИЕ: Используйте двоичный файл gitea-config, соответствующий вашей операционной системе и архитектуре. В приведенной выше команде мы использовали двоичный файл macOS arm64.

Утилита gitea-config создает файл .env в $PROJECT_HOME/k8s, который содержит несколько переменных окружения Drone, которые будут использоваться при развертывании сервера Drone в последующих шагах,

Развертывание Drone

Для нашего демо сервер Drone будет развернут в пространстве имен drone,

kubectl create ns drone
Войдите в полноэкранный режим Выйдите из полноэкранного режима

Добавьте репо штурвала дрона,

helm repo add drone https://charts.drone.io
helm repo update
Войти в полноэкранный режим Выйдите из полноэкранного режима

Следующее содержимое будет использоваться в качестве файла значений helm для развертывания сервера Drone,

service:
  # the Drone Kubernetes service type
  type: NodePort
  port: 8080
  # this port will be used in KinD extra port mappings to allow accessing the 
  # drone server from our laptops
  nodePort: 30980

extraSecretNamesForEnvFrom:
   # all the other as $PROJECT_HOME/k8s/.env variables are loaded via this secret
   # https://docs.drone.io/server/reference/
  - drone-demos-secret

env:
  # the Drone server host typically what the drone runners will use to 
  # communicate with the server
  DRONE_SERVER_HOST: drone-127.0.0.1.sslip.io:8080
  # Since we run Gitea in http mode we will skip TLS verification
  DRONE_GITEA_SKIP_VERIFY: true
  # The url where Gitea could be reached, typically used while 
  # cloning the sources
  # https://docs.drone.io/server/provider/gitea/
  DRONE_GITEA_SERVER: http://gitea-127.0.0.1.sslip.io:3000/
  # For this local setup and demo we wil run Drone in http mode
  DRONE_SERVER_PROTO: http

Войти в полноэкранный режим Выйти из полноэкранного режима

Выполните следующую команду helm для развертывания сервера Drone,

helm upgrade --install drone drone/drone 
  --values $PROJECT_HOME/helm_vars/drone/values.yaml 
  --namespace=drone 
  --post-renderer  k8s/kustomize 
  --wait
Войти в полноэкранный режим Выйти из полноэкранного режима

Успешное развертывание Drone должно показать следующие ресурсы в пространстве имен drone,

kubectl get pods,svc,secrets -n drone
Войти в полноэкранный режим Выйти из полноэкранного режима
NAME                         READY   STATUS    RESTARTS   AGE
pod/drone-5bb66b9d97-hbpl5   1/1     Running   0          9s

NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/drone   NodePort   10.96.184.123   <none>        8080:30980/TCP   9s

NAME                                 TYPE                 DATA   AGE
secret/drone-demos-secret            Opaque               3      9s
Войти в полноэкранный режим Выход из полноэкранного режима

Псевдонимы хостов

Как вы заметили, мы используем Magic DNS для Gitea и Drone. Это вызовет проблемы с разрешением имен внутри капсул Drone и Gitea, потому что url gitea-127.0.0.1.sslip.io разрешается в 127.0.0.1 на капсуле сервера Drone. Но чтобы наша установка работала, нам нужно, чтобы gitea-127.0.0.1.sslip.io был разрешен в службу gitea-http Kubernetes на нашем кластере.

Для этого мы используем псевдонимы хостов Kubernetes, чтобы добавить дополнительные записи хостов (/etc/hosts) в капсулы Drone, которые будут разрешать gitea-127.0.0.1.sslip.io в ClusterIP сервиса gitea-http.

Существует несколько техник, позволяющих нам добавлять хост-соединения в развертывания Kubernetes. Первая из них, которую мы использовали в предыдущей команде helm для развертывания сервера Drone, называется helm post renderer. Пост-рендерер позволил нам исправить развертывание Drone из диаграммы helm с hostAliases для gitea-127.0.0.1.sslip.io, разрешающимся в ClusterIP-адрес gitea-http.

Как мы делали с развертыванием Drone для разрешения Gitea, нам также нужно, чтобы капсулы Gitea разрешили сервер Drone при попытке отправить полезную нагрузку webhook для запуска сборки.

На этот раз давайте воспользуемся техникой исправления kubectl для обновления Gitea statefuleset deployments для разрешения drone-127.0.0.1.sslip.io на ClusterIP сервиса drone.

Ниже показан патч, который будет применен к Gitea statefulset.

{
  "spec": {
    "template": {
      "spec": {
        "hostAliases": [
          {
            "ip": "${DRONE_SERVICE_IP}",
            "hostnames": ["drone-127.0.0.1.sslip.io"]
          }
        ]
      }
    }
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Выполните следующую команду для исправления и обновления развертывания gitea statefulset,

export DRONE_SERVICE_IP="$(kubectl get svc -n drone drone -ojsonpath='{.spec.clusterIP}')"
kubectl patch statefulset gitea -n default --patch "$(envsubst<$PROJECT_HOME/k8s/patch.json)" 
Войти в полноэкранный режим Выйти из полноэкранного режима

СОВЕТ: Для замены переменных окружения в патче мы используем envsubst.

Подождите, пока капсулы Gitea будут обновлены и перезапущены,

kubectl rollout status statefulset gitea --timeout 30s
Войдите в полноэкранный режим Выход из полноэкранного режима

Вы можете проверить обновления файла /etc/hosts для капсулы gitea, выполнив команду,

kubectl exec -it gitea-0 -n default cat /etc/hosts
Войти в полноэкранный режим Выйти из полноэкранного режима

Должна появиться запись вида,

# Entries added by HostAliases.
10.96.184.123   drone-127.0.0.1.sslip.io
Войти в полноэкранный режим Выйти из полноэкранного режима

Где 10.96.184.123 — это ClusterIP службы дронов на моей установке, выполните следующую команду, чтобы проверить это,

kubectl get svc -n drone drone
Войти в полноэкранный режим Выйти из полноэкранного режима
NAME    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
drone   NodePort   10.96.184.123   <none>        8080:30980/TCP   6m14s
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы можете провести аналогичную проверку с дроновыми капсулами и убедиться, что в Drone pods /etc/hosts есть запись для gitea-127.0.0.1.sslip.io, сопоставляющая gitea-http ClusterIP.

Что мы сделали на данный момент,

  • Развернули настроенный кластер Kubernetes с помощью kind
  • Развернули Gitea на нашем кластере Kubernetes
  • Развернули сервер Drone на нашем кластере Kubernetes
  • Создали приложение oAuth на Gitea для авторизации сервера Drone
  • Создайте репозиторий на Gitea, который будет использоваться для тестирования нашего шага

Развертывание Drone Kubernetes Runner

Для запуска конвейеров Drone на Kubernetes нам необходимо развернуть Drone Kubernetes Runner.

Разверните drone-runner-kube со следующими значениями,

extraSecretNamesForEnvFrom:
   # all the other as env variables are loaded via this secret
  - drone-demos-secret
env:
  # the url to reach the Drone server
  # we point it to the local drone Kubernetes service drone on port 8080
  DRONE_RPC_HOST: "drone:8080"
Войти в полноэкранный режим Выйти из полноэкранного режима

Запустите helm install для развертывания drone-runner-kube,

helm upgrade --install drone-runner-kube drone/drone-runner-kube 
  --namespace=drone 
  --values $PROJECT_HOME/helm_vars/drone-runner-kube/values.yaml  
  --wait
Войти в полноэкранный режим Выйдите из полноэкранного режима

Запрос ресурсов Kubernetes на пространстве имен drone теперь должен вернуть drone-runner-kube pod и сервис,

kubectl get pods,svc -n drone -lapp.kubernetes.io/name=drone-runner-kube
Войдите в полноэкранный режим Выход из полноэкранного режима
NAME                                     READY   STATUS    RESTARTS   AGE
pod/drone-runner-kube-59f98956b4-mbr9c   1/1     Running   0          41s

NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/drone-runner-kube   ClusterIP   10.96.196.54   <none>        3000/TCP   41s
Войти в полноэкранный режим Выйдите из полноэкранного режима

Откройте веб-консоль сервера Drone в браузере, используя URL ${DRONE_SERVER_URL} следуйте инструкциям на экране для завершения регистрации и активации нашего репозитория drone-quickstart.

Запустим наш первый конвейер

Давайте клонируем репозиторий quickstart в выбранную нами папку на локальной машине,

git clone http://gitea-127.0.0.1.sslip.io:3000/demo/drone-quickstart
Войдите в полноэкранный режим Выход из полноэкранного режима

ПРИМЕЧАНИЕ: Учетные данные git по умолчанию для push — demo/demo@123.

Откройте проект drone-quickstart в вашем любимом редакторе, попробуйте внести некоторые изменения, например, добавьте фиктивный текст README для запуска сборки. Ваша сборка завершится неудачей, как показано ниже,

Не волнуйтесь, именно это мы сейчас и будем исправлять. Нам нужно сделать то же самое, добавив hostAliases в наши стручки трубопровода drone, а также обновить .drone.yml с ClusterIP gitea-http и hostnames с записью для gitea-127.0.0.1.sslip.io, чтобы наши стручки трубопровода Drone могли клонировать исходники из нашего репозитория Gitea.

Следующий фрагмент показывает обновленный .drone.yml с записями для псевдонимов хостов,

ПРИМЕЧАНИЕ: Кластерный IP gitea-http* может отличаться, чтобы получить кластерный IP службы **gitea-http, выполните команду kubectl get svc gitea-http -ojsonpath='{.spec.clusterIP}'.

---
kind: pipeline
type: kubernetes
name: default

steps:
- name: say hello
  image: busybox
  commands:
  - echo hello world
- name: good bye hello
  image: busybox
  commands:
  - echo good bye

# updates to match your local setup
host_aliases:
  # kubectl get svc gitea-http -ojsonpath='{.spec.clusterIP}'
  - ip: 10.96.240.234
    hostnames:
      - "gitea-127.0.0.1.sslip.io"

trigger:
  branch:
  - main
Вход в полноэкранный режим Выход из полноэкранного режима

Зафиксируйте и запустите код для запуска новой сборки конвейера Drone, и вы увидите, что она прошла успешно.

Очистка

Когда вы закончите экспериментировать, вы можете очистить установку, выполнив следующую команду

kind delete cluster --name=drone-demo
Войти в полноэкранный режим Выйти из полноэкранного режима

Резюме

Теперь у нас есть полностью функциональный CI с Drone на Kubernetes. Вам больше не нужно создавать нативные приложения для облака (Kubernetes), а можно осуществлять непрерывную интеграцию с большой легкостью и мощью.

Просто подытожим, что мы сделали в этом блоге,

  • Развернули настроенный кластер Kubernetes с помощью kind
  • Развернули Gitea на нашем кластере Kubernetes
  • Развернули Drone Server на нашем кластере Kubernetes.
  • Создали приложение oAuth на Gitea для авторизации дрона
  • Создали репозиторий на Gitea, который будет использоваться для тестирования нашего шага
  • Развернули Drone Kubernetes runner для запуска конвейеров на кластере Kubernetes
  • Создали наше приложение для быстрого запуска с использованием конвейеров Drone на Kubernetes
  • Использование псевдонимов хостов Kubernetes для добавления записей хостов в наши развертывания для разрешения локальных URL-адресов

Оцените статью
devanswers.ru
Добавить комментарий