Развёртывание Woodpecker в Kubernetes
История про установку CI/CD инструмента Woodpecker в Kubernetes для платформы управления исходным кодом Gitea.
Схема
Развернём следующую конфигурацию: один сервер CI/CD, один агент. Будем использовать Kubernetes-бэкенд.
Архитектура Woodpecker в Kubernetes
Предположим, в пространстве scm уже развернуты Gitea и Postgres. Агент и сервер Woodpecker развернём там же, а контейнеры пайплайнов агент будет разворачивать в пространстве wp-runtime.
Также допустим, что сервер Gitea располагается на домене git.example.com, а Woodpecker — на домене wp.example.com. Разворачивать будем версию Next (конкретно next-c40a6d884f), т. к. в версии 0.15 нет поддержки Kebernetes.
Подготовка БД
Подключаемся к Postgres:
PS C:\> kubectl -n scm exec --stdin --tty postgres-0 -- /bin/sh
/ $ psql
Создаём пользователя и БД:
CREATE ROLE woodpecker WITH LOGIN PASSWORD 'wp-passwd';
CREATE DATABASE woodpeckerdb WITH OWNER woodpecker TEMPLATE template0 ENCODING UTF8 LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8';
Подготовка Gitea
Нужно создать OAuth приложение.
- Заходим под администратором в Menu -> Site Administration -> Applications;
- Заполняем Application Name —
Woodpecker, Redirect URI —https://wp.example.com/authorize; - Запоминаем Client ID и Client Secret.
Установка сервера Woodpecker
Конфигурация сервиса
В WOODPECKER_ADMIN пишем имя администратора Gitea, заполняем адреса серверов и выбираем БД:
# config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: woodpecker-server-config
data:
WOODPECKER_HOST: https://wp.example.com
WOODPECKER_OPEN: "true"
WOODPECKER_ADMIN: admin
WOODPECKER_GITEA: "true"
WOODPECKER_GITEA_URL: https://git.example.com
WOODPECKER_DATABASE_DRIVER: postgres
Секреты
Общий секрет сервера и агента, WOODPECKER_AGENT_SECRET генерируем командой openssl rand -hex 32:
# secrets.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: woodpecker-secrets
stringData:
WOODPECKER_AGENT_SECRET:
Секрет с данными OAuth-приложения, созданного в Gitea:
# secrets.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: woodpecker-gitea-secrets
stringData:
WOODPECKER_GITEA_CLIENT:
WOODPECKER_GITEA_SECRET:
Секрет с данными подключения к БД:
# secrets.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: woodpecker-db-secrets
stringData:
WOODPECKER_DATABASE_DATASOURCE: postgres://woodpecker:wp-passwd@postgres:5432/woodpeckerdb?sslmode=disable
Конфигурация развертывания
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: woodpecker-server
spec:
replicas: 1
template:
spec:
containers:
- name: woodpecker-server
image: docker.io/woodpeckerci/woodpecker-server
envFrom:
- configMapRef:
name: woodpecker-server-config
- secretRef:
name: woodpecker-secrets
- secretRef:
name: woodpecker-gitea-secrets
- secretRef:
name: woodpecker-db-secrets
ports:
- name: http
containerPort: 8000
livenessProbe:
httpGet:
path: /healthz
port: 8000
readinessProbe:
httpGet:
path: /healthz
port: 8000
resources:
requests:
memory: "32Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "300m"
Сервис
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: woodpecker-server
spec:
type: NodePort
ports:
- name: http
nodePort: 31012
port: 8000
targetPort: 8000
- name: grpc
nodePort: 31013
port: 9000
targetPort: 9000
Развёртывание
Создадим Kustomize-модификацию:
# kustomization.yaml
resources:
- config.yaml
- deployment.yaml
- secrets.yaml
- service.yaml
namespace: scm
commonLabels:
app.kubernetes.io/name: woodpecker-server
images:
- name: docker.io/woodpeckerci/woodpecker-server
newTag: next-c40a6d884f
Развернём сервис:
kubectl apply -k <kustomization directory>/
Установка агента Woodpecker
Конфигурация сервиса
В WOODPECKER_SERVER указываем адрес сервера, в WOODPECKER_BACKEND_K8S_NAMESPACE указываем пространство для запуска пайплайнов:
# config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: woodpecker-agent-config
data:
WOODPECKER_SERVER: woodpecker-server:9000
WOODPECKER_BACKEND: kubernetes
WOODPECKER_BACKEND_K8S_NAMESPACE: wp-runtime
WOODPECKER_BACKEND_K8S_VOLUME_SIZE: 1G
WOODPECKER_BACKEND_K8S_STORAGE_RWX: "false"
Конфигурация развертывания
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: woodpecker-agent
spec:
replicas: 1
template:
spec:
serviceAccountName: woodpecker-agent
containers:
- name: woodpecker-agent
image: woodpeckerci/woodpecker-agent
envFrom:
- configMapRef:
name: woodpecker-agent-config
- secretRef:
name: woodpecker-secrets
ports:
- name: http
containerPort: 3000
resources:
requests:
memory: 32Mi
cpu: 100m
limits:
memory: 128Mi
cpu: 300m
Сервисная учётная запись
# serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: woodpecker-agent
Роль
Внимательно указываем пространства, т. к. роль развёртываем вручную, не через Kustomize:
# role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: woodpecker-agent
namespace: wp-runtime
rules:
- apiGroups: [""]
resources:
- persistentvolumeclaims
- pods
- pods/log
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: woodpecker-agent
namespace: wp-runtime
subjects:
- kind: ServiceAccount
name: woodpecker-agent
namespace: scm
roleRef:
kind: Role
name: woodpecker-agent
apiGroup: rbac.authorization.k8s.io
Развёртывание
Создадим Kustomize-модификацию:
# kustomization.yaml
resources:
- config.yaml
- deployment.yaml
- serviceaccount.yaml
namespace: scm
commonLabels:
app.kubernetes.io/name: woodpecker-agent
images:
- name: woodpeckerci/woodpecker-agent
newTag: next-c40a6d884f
Развернём сервис:
kubectl apply -k <kustomization directory>/
Отдельно добавим роль:
kubectl apply <kustomization directory>/role.yaml
Донастройка Gitea
Исправление Webhook
Чтобы Gitea обращалась напрямую к Woodpecker внутри кластера, нужно изменить адрес Woodpecker сервера в Webhook:
- В Gitea открываем репозиторий, переходим в Settings -> Webhooks, редактирование;
- Заменяем
https://wp.example.comнаhttp://woodpecker-server.scm.svc.cluster.local:8000.
Webhook автоматически добавляется при активации репозитория в Woodpecker.
Исправление разрешённых адресов для Webhook
В конфигурации _Gitea в файле app.ini добавляем секцию webhook и настраиваем разрешённые адреса:
[webhook]
ALLOWED_HOST_LIST = private
Замечания
- Если агент не цепляется к серверу, можно вручную его добавить в админке.
- В текущей реализации поды создаются с лимитами
2 G,2 CPUи требуемыми значениями1 G,1 CPU.