Содержание

Развёртывание Woodpecker в Kubernetes

История про установку CI/CD инструмента Woodpecker в Kubernetes для платформы управления исходным кодом Gitea.

Развернём следующую конфигурацию: один сервер CI/CD, один агент. Будем использовать Kubernetes-бэкенд.

Woodpecker architecture in Kubernetes

Архитектура Woodpecker в Kubernetes

Предположим, в пространстве scm уже развернуты Gitea и Postgres. Агент и сервер Woodpecker развернём там же, а контейнеры пайплайнов агент будет разворачивать в пространстве wp-runtime.

Также допустим, что сервер Gitea располагается на домене git.example.com, а Woodpecker — на домене wp.example.com. Разворачивать будем версию Next (конкретно next-c40a6d884f), т. к. в версии 0.15 нет поддержки Kebernetes.

Подключаемся к Postgres:

shell-session

PS C:\> kubectl -n scm exec --stdin --tty postgres-0 -- /bin/sh
/ $ psql

Создаём пользователя и БД:

sql

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';

Нужно создать OAuth приложение.

  • Заходим под администратором в Menu -> Site Administration -> Applications;
  • Заполняем Application NameWoodpecker, Redirect URIhttps://wp.example.com/authorize;
  • Запоминаем Client ID и Client Secret.

В WOODPECKER_ADMIN пишем имя администратора Gitea, заполняем адреса серверов и выбираем БД:

yaml

# 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:

yaml

# secrets.yaml

---
apiVersion: v1
kind: Secret
metadata:
  name: woodpecker-secrets
stringData:
  WOODPECKER_AGENT_SECRET: 

Секрет с данными OAuth-приложения, созданного в Gitea:

yaml

# secrets.yaml

---
apiVersion: v1
kind: Secret
metadata:
  name: woodpecker-gitea-secrets
stringData:
  WOODPECKER_GITEA_CLIENT: 
  WOODPECKER_GITEA_SECRET: 

Секрет с данными подключения к БД:

yaml

# secrets.yaml

---
apiVersion: v1
kind: Secret
metadata:
  name: woodpecker-db-secrets
stringData:
  WOODPECKER_DATABASE_DATASOURCE: postgres://woodpecker:wp-passwd@postgres:5432/woodpeckerdb?sslmode=disable

yaml

# 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"

yaml

# 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-модификацию:

yaml

# 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

Развернём сервис:

shell-session

kubectl apply -k <kustomization directory>/

В WOODPECKER_SERVER указываем адрес сервера, в WOODPECKER_BACKEND_K8S_NAMESPACE указываем пространство для запуска пайплайнов:

yaml

# 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"

yaml

# 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

yaml

# serviceaccount.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: woodpecker-agent

Внимательно указываем пространства, т. к. роль развёртываем вручную, не через Kustomize:

yaml

# 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-модификацию:

yaml

# 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

Развернём сервис:

shell-session

kubectl apply -k <kustomization directory>/

Отдельно добавим роль:

shell-session

kubectl apply <kustomization directory>/role.yaml

Чтобы Gitea обращалась напрямую к Woodpecker внутри кластера, нужно изменить адрес Woodpecker сервера в Webhook:

  • В Gitea открываем репозиторий, переходим в Settings -> Webhooks, редактирование;
  • Заменяем https://wp.example.com на http://woodpecker-server.scm.svc.cluster.local:8000.

Webhook автоматически добавляется при активации репозитория в Woodpecker.

В конфигурации _Gitea в файле app.ini добавляем секцию webhook и настраиваем разрешённые адреса:

ini

[webhook]
ALLOWED_HOST_LIST = private
  1. Если агент не цепляется к серверу, можно вручную его добавить в админке.
  2. В текущей реализации поды создаются с лимитами 2 G, 2 CPU и требуемыми значениями 1 G, 1 CPU.
  1. Woodpecker Setup
  2. Woodpecker Gitea
  3. Woodpecker DB
  4. Woodpecker Server
  5. Woodpecker Agent
  6. Woodpecker Kubernetes
  7. Gitea Webhook config
  8. Woodpecker cmd flags
  9. Woodpecker pod limits