Обзор
За последние несколько лет многие организации начали внедрять архитектуры 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-адресов