Deckhouse Code поставляет два образа раннера: registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner и registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner-helper.
Развёртывание и эксплуатацию раннеров (серверы, манифесты, Helm-чарты, обновление, мониторинг) выполняет администратор.
Раннер — процесс GitLab Runner, который получает задания CI/CD от Deckhouse Code и выполняет их в контейнерах, подах Kubernetes или виртуальных машинах в зависимости от своего executor.
Образы раннера
Тег образа — версия GitLab Runner, например v19.3.1. Оба образа собраны только для linux/amd64.
| Образ | Содержимое |
|---|---|
runner | GitLab Runner, плагин fleeting-plugin-dvp в /usr/local/bin. Процесс работает от пользователя gitlab-runner (UID и GID 1001) и читает конфигурацию из /etc/gitlab-runner/config.toml |
runner-helper | Вспомогательный процесс, который Docker executor и Kubernetes executor запускают рядом с каждым заданием, чтобы клонировать репозиторий и загрузить артефакты и кеш; содержит git, git-lfs и bash |
Docker executor и Kubernetes executor берут вспомогательный образ из параметра helper_image. В примерах ниже в нём указан образ runner-helper той же версии, что и раннер.
Создание раннера
Раннер подключается к Deckhouse Code с токеном аутентификации. Чтобы создать раннер инстанса и получить его токен:
- Откройте «Admin» → «CI/CD» → «Раннеры» и нажмите «Создать раннер инстанса».
- В поле «Теги» перечислите теги заданий, которые выполняет раннер, или выберите «Запуск заданий без тегов».
- Нажмите «Создать раннер».
- Скопируйте токен аутентификации раннера (начинается с
glrt-) на открывшейся странице.
В примерах ниже <TOKEN> — этот токен, <VERSION> — тег образа, https://code.example.com — адрес Deckhouse Code.
Автомасштабирование на Deckhouse Virtualization Platform
Плагин fleeting-plugin-dvp позволяет executor instance выполнять задания на виртуальных машинах из VirtualMachinePool в Deckhouse Virtualization Platform. Раннер задаёт число виртуальных машин в пуле (spec.replicas): по одной на задание плюс резерв простаивающих. Он подключается к виртуальной машине по SSH и выполняет задание в её оболочке. Ненужную виртуальную машину плагин удаляет и уменьшает spec.replicas.
Плагин не создаёт пул и пользователя на виртуальных машинах: пул и доступ по SSH подготавливаются заранее. В примере ниже раннер работает как Deployment в кластере Deckhouse Virtualization Platform, в неймспейсе code-runner-dvp вместе с пулом.
Неймспейс и SSH-ключ
Создайте неймспейс, пару ключей и Secret с закрытым ключом:
d8 k create namespace code-runner-dvp
ssh-keygen -t ed25519 -N "" -f code-runner-ssh
d8 k -n code-runner-dvp create secret generic code-runner-ssh --from-file=id_ed25519=code-runner-sshОткрытый ключ code-runner-ssh.pub указывается в манифесте пула.
Пул виртуальных машин
Пул создаётся пустым и удаляет виртуальные машины по имени (scaleDownPolicy: Explicit), как это делает плагин при уменьшении пула. В образе диска нужны SSH-сервер, bash и git; cloud-init создаёт пользователя, от которого подключается раннер. Сохраните манифест в файл code-runner-pool.yaml:
apiVersion: virtualization.deckhouse.io/v1alpha2
kind: VirtualMachinePool
metadata:
name: code-runner
namespace: code-runner-dvp
spec:
replicas: 0
scaleDownPolicy: Explicit
virtualMachineTemplate:
spec:
virtualMachineClassName: generic
runPolicy: AlwaysOn
cpu:
cores: 2
memory:
size: 2Gi
blockDeviceRefs:
- kind: VirtualDisk
name: disk
provisioning:
type: UserData
userData: |
#cloud-config
package_update: true
packages:
- git
users:
- name: gitlab-runner
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
lock_passwd: false
ssh_authorized_keys:
- <PUBLIC_KEY>
virtualDiskTemplates:
- name: disk
spec:
dataSource:
type: ObjectRef
objectRef:
kind: VirtualImage
name: ubuntu-2204
persistentVolumeClaim:
size: 20Gi
storageClassName: <STORAGE_CLASS_NAME><PUBLIC_KEY> — содержимое code-runner-ssh.pub; ubuntu-2204 — VirtualImage в том же неймспейсе. Задания записывают на диск рабочие копии и кеш, поэтому размер диска ограничивает размер задания.
Создайте пул:
d8 k apply -f code-runner-pool.yamlРазвёртывание раннера
Сохраните следующий манифест в файл
code-runner-dvp.yaml. Он содержит конфигурацию раннера, сервисный аккаунт с правами на пул и Deployment раннера со смонтированным закрытым ключом:apiVersion: v1 kind: Secret metadata: name: code-runner-config namespace: code-runner-dvp stringData: config.toml: | concurrent = 4 [[runners]] name = "dvp" url = "https://code.example.com" token = "<TOKEN>" executor = "instance" shell = "bash" [runners.autoscaler] plugin = "fleeting-plugin-dvp" max_instances = 5 [runners.autoscaler.plugin_config] namespace = "code-runner-dvp" name = "code-runner" [runners.autoscaler.connector_config] username = "gitlab-runner" key_path = "/ssh/id_ed25519" use_static_credentials = true use_external_addr = false [[runners.autoscaler.policy]] idle_count = 1 idle_time = "20m" --- apiVersion: v1 kind: ServiceAccount metadata: name: code-runner namespace: code-runner-dvp --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: code-runner namespace: code-runner-dvp rules: - apiGroups: ["virtualization.deckhouse.io"] resources: ["virtualmachinepools"] verbs: ["get", "patch"] - apiGroups: ["virtualization.deckhouse.io"] resources: ["virtualmachines"] verbs: ["get", "list", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: code-runner namespace: code-runner-dvp roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: code-runner subjects: - kind: ServiceAccount name: code-runner namespace: code-runner-dvp --- apiVersion: apps/v1 kind: Deployment metadata: name: code-runner namespace: code-runner-dvp spec: replicas: 1 selector: matchLabels: app: code-runner template: metadata: labels: app: code-runner spec: serviceAccountName: code-runner securityContext: runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 initContainers: - name: config image: registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner:<VERSION> command: ["cp", "/config-secret/config.toml", "/etc/gitlab-runner/config.toml"] volumeMounts: - name: config-secret mountPath: /config-secret - name: config mountPath: /etc/gitlab-runner containers: - name: runner image: registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner:<VERSION> volumeMounts: - name: config mountPath: /etc/gitlab-runner - name: ssh mountPath: /ssh volumes: - name: config-secret secret: secretName: code-runner-config - name: config emptyDir: {} - name: ssh secret: secretName: code-runner-ssh defaultMode: 0440Параметры, которые связывают раннер с пулом:
plugin_config.namespaceиplugin_config.name— неймспейс и имя VirtualMachinePool; безkubeconfig_pathплагин использует сервисный аккаунт пода;connector_config.username— пользователь, которого создаёт cloud-init;connector_config.key_path— закрытый ключ, открытая часть которого указана вssh_authorized_keys;use_external_addr = false— раннер подключается к внутреннему адресу виртуальной машины (status.ipAddress);shell = "bash"— в Debian и Ubuntu/bin/sh— этоdash, и скрипт подготовки задания в нём завершается с ошибкой;max_instances— верхний предел числа виртуальных машин в пуле;idle_countиidle_timeзадают, сколько свободных виртуальных машин держать и как долго.
Role разрешает плагину читать и изменять пул, читать и удалять его виртуальные машины. Init-контейнер копирует
config.tomlиз Secret в доступную для записи директорию, где раннер хранит и свой системный идентификатор.defaultMode: 0440разрешает чтение ключа группеgitlab-runner, которуюfsGroupназначает файлу ключа.Примените манифест:
d8 k apply -f code-runner-dvp.yamlПроверьте подключение к Deckhouse Code:
d8 k -n code-runner-dvp exec deploy/code-runner -- gitlab-runner verify
Раннер вне кластера обращается к пулу через файл kubeconfig, указанный в kubeconfig_path; его пользователю нужны права из Role выше.
Перезапущенный раннер заменяет виртуальные машины пула новыми. Чтобы он подхватывал работающие виртуальные машины, включите хранилище состояния автомасштабирования в директории на постоянном томе, смонтированном в контейнер раннера:
[runners.autoscaler.state_storage]
enabled = true
dir = "/home/gitlab-runner/state"
keep_instance_with_acquisitions = trueDocker executor
Docker executor выполняет каждое задание в контейнере Docker-демона на сервере раннера. Сам раннер работает в контейнере и обращается к демону через его сокет.
Создайте том для конфигурации раннера:
docker volume create code-runner-configЗарегистрируйте раннер. Команда записывает
config.tomlв том:docker run --rm -v code-runner-config:/etc/gitlab-runner \ registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner:<VERSION> \ register --non-interactive \ --url https://code.example.com \ --token <TOKEN> \ --executor docker \ --docker-image alpine:3 \ --docker-helper-image registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner-helper:<VERSION>--docker-image— образ для заданий, в.gitlab-ci.ymlкоторых не указанimage.Запустите раннер:
docker run -d --name code-runner --restart always \ --group-add "$(stat -c %g /var/run/docker.sock)" \ -v code-runner-config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner:<VERSION>Раннер работает от пользователя
gitlab-runner;--group-addдобавляет его в группу — владельца сокета Docker.Проверьте подключение к Deckhouse Code:
docker exec code-runner gitlab-runner verify
Kubernetes executor
Kubernetes executor выполняет каждое задание в отдельном поде. Сам раннер работает как Deployment в том же кластере и создаёт поды заданий в неймспейсе, указанном в config.toml.
Создайте неймспейс:
d8 k create namespace code-runnerСохраните следующий манифест в файл
code-runner.yaml. Он содержит конфигурацию раннера, сервисный аккаунт с правами на управление подами заданий и Deployment раннера:apiVersion: v1 kind: Secret metadata: name: code-runner-config namespace: code-runner stringData: config.toml: | concurrent = 4 [[runners]] name = "kubernetes" url = "https://code.example.com" token = "<TOKEN>" executor = "kubernetes" [runners.kubernetes] namespace = "code-runner" image = "alpine:3" helper_image = "registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner-helper:<VERSION>" --- apiVersion: v1 kind: ServiceAccount metadata: name: code-runner namespace: code-runner --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: code-runner namespace: code-runner rules: - apiGroups: [""] resources: ["pods", "pods/exec", "pods/attach", "pods/log", "secrets", "configmaps", "services", "events"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: code-runner namespace: code-runner roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: code-runner subjects: - kind: ServiceAccount name: code-runner namespace: code-runner --- apiVersion: apps/v1 kind: Deployment metadata: name: code-runner namespace: code-runner spec: replicas: 1 selector: matchLabels: app: code-runner template: metadata: labels: app: code-runner spec: serviceAccountName: code-runner securityContext: runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 initContainers: - name: config image: registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner:<VERSION> command: ["cp", "/config-secret/config.toml", "/etc/gitlab-runner/config.toml"] volumeMounts: - name: config-secret mountPath: /config-secret - name: config mountPath: /etc/gitlab-runner containers: - name: runner image: registry.deckhouse.ru/deckhouse/ee/packages/code/images/runner:<VERSION> volumeMounts: - name: config mountPath: /etc/gitlab-runner volumes: - name: config-secret secret: secretName: code-runner-config - name: config emptyDir: {}Init-контейнер копирует
config.tomlиз Secret в доступную для записи директорию, где раннер хранит и свой системный идентификатор.Примените манифест:
d8 k apply -f code-runner.yamlПроверьте подключение к Deckhouse Code:
d8 k -n code-runner exec deploy/code-runner -- gitlab-runner verify