Настроить выполнение заданий CI/CD SourceCraft в кластере Kubernetes
В пользовательском воркере self-hosted-processor поддерживается режим, в котором задания CI/CD выполняются в кластере Kubernetes. Каждое задание выполняется в отдельном поде. Поды создаются воркером заранее и поддерживаются в пуле. Когда появляется новое задание, воркер выбирает доступный под из пула и передает задание агенту, который запущен в поде. После выполнения задания под автоматически удаляется.
Примечание
Поддержка Kubernetes-режима доступна начиная с версии воркера 0.14.1.
Обзор
Воркер может быть запущен:
-
вне кластера Kubernetes, например на компьютере пользователя. В таком случае в параметры воркера передается
kubeconfigдля работы с кластером Kubernetes. Для передачи задания агенту используется проброс портаport forward.Конфигурация
kubeconfigдолжна содержать единственный контекст, и этот контекст должен быть выбран текущим. -
внутри кластера Kubernetes. Для передачи задания агенту используется IP-адрес пода
podIP.Пространство имен, в котором запущен воркер, должно отличаться от пространства имен, выделенного под пул подов.
Работа воркера состоит из следующих этапов:
Старт воркера
При старте воркер в пространстве имен Kubernetes, выделенном под пул подов, удаляет и создает заново секрет agent-secrets. Секрет содержит конфигурацию агента и сертификат удостоверяющего центра (certificate authority, CA), необходимые для запуска агента. Сертификат удостоверяющего центра используется для авторизации запросов воркера к агенту по протоколу mTLS.
Обслуживание пула подов
Воркер периодически запускает процедуру обслуживания пула подов:
-
Внутренние состояния подов синхронизируются с состояниями в кластере Kubernetes.
-
Обрабатываются переходы подов между состояниями.
-
Создаются новые поды.
-
Неизвестные поды удаляются, в том числе поды, оставшиеся от предыдущего запуска воркера, или поды, созданные другим воркером.
Важно
Не запускайте несколько экземпляров воркера с пулом подов в одном пространстве имен. Воркеры будут удалять поды друг друга.
В пуле поддерживается количество доступных подов, равное минимальному размеру пула, заданному в конфигурации воркера. Общее количество подов в пуле не может превышать максимальный размер пула, также заданный в конфигурации воркера.
Выполнение задания
После получения задания воркер ищет в пуле доступный под и передает задание агенту, который запущен в этом поде.
Процесс отправки задания агенту отличается в зависимости от того, где размещен воркер:
Воркер пробрасывает порт агента на свой локальный порт (port forward), отправляет задание агенту через локальный порт и закрывает соединение, использованное для проброса порта.
Воркер отправляет задание на порт агента по IP-адресу пода.
Важно
Разрешите взаимодействие воркера с подом в пространстве имен пула — такое взаимодействие может быть ограничено сетевыми политиками или другими инструментами.
При передаче задания агенту воркер авторизует свой запрос с помощью клиентского сертификата и ключа. Агент проверяет авторизацию с помощью сертификата удостоверяющего центра. Соединение воркера и агента защищено по протоколу mTLS.
Далее агент выполняет задание самостоятельно. После завершения выполнения задания воркер удаляет под.
Процесс настройки
Чтобы настроить выполнение заданий CI/CD в кластере Kubernetes:
- Подготовьте кластер Kubernetes
- Создайте конфигурационный файл воркера
- Создайте шаблон пода
- Запустите воркер
Подготовьте кластер Kubernetes
Совет
Для выполнения заданий CI/CD SourceCraft вы можете использовать кластер Yandex Managed Service for Kubernetes.
-
Установите
kubectlи подключитесь к кластеру Kubernetes. -
Создайте пространство имен для пула подов воркера:
kubectl create namespace pods-namespace -
Создайте файл
role.yamlс описанием роли пользователя, от имени которого воркер будет взаимодействовать с кластером Kubernetes. Пользователь должен иметь права на управление секретами и подами в пространстве имен пула подов. Если воркер запущен вне кластера Kubernetes, дополнительно требуются права на проброс портов.Воркер вне кластераВоркер в кластере--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: processor-role rules: - apiGroups: [""] resources: ["secrets", "pods"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - apiGroups: [""] resources: ["pods/portforward"] verbs: ["create"]--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: processor-role rules: - apiGroups: [""] resources: ["secrets", "pods"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] -
Примените манифест для пространства имен, созданного ранее:
kubectl apply -f role.yaml -n pods-namespace
Создайте конфигурационный файл воркера
Создайте файл config.yaml со следующей конфигурацией:
kubernetes:
kubeconfig_path: /path/to/.kube/config
namespace: <пространство_имен_пула>
pod_template_path: /path/to/pod-template.yaml
agent:
port: 8693
ca_cert_path: /path/to/ca.crt
client_cert_path: /path/to/client.crt
client_key_path: /path/to/client.key
pool_max_size: 10
pool_min_size: 3
pool_maintenance_period: 10s
secret_updating_timeout: 20s
pods_listing_timeout: 10s
pod_creation_timeout: 1m
pod_startup_timeout: 2m
pod_deletion_timeout: 30s
endpoint_resolving_timeout: 10s
endpoint:
host: ci.sourcecraft.tech
port: 443
ssl_no_verify: false
executor_type: kubernetes
logger_type: json
logger_level: info
tags: ["my-tag", "+my-required-tag"]
auth:
pat: <персональный_токен>
Где:
kubernetes— раздел с параметрами, специфичными для режима Kubernetes:kubeconfig_path— путь до файлаkubeconfig. Также можно задать через переменную окруженияKUBECONFIG. Если параметр не задан, используется внутрикластерная конфигурация.namespace— пространство имен, выделенное под пул подов. Обязательный параметр.pod_template— шаблон пода в формате YAML. Также можно задать через переменную окруженияKUBERNETES_POD_TEMPLATE. Должен быть задан либоpod_template, либоpod_template_path. Указывать одновременно оба параметра нельзя.pod_template_path— путь до файла с шаблоном пода. Должен быть задан либоpod_template, либоpod_template_path. Указывать одновременно оба параметра нельзя.agent— подраздел с параметрами для взаимодействия с агентом:port— порт агента. Значение по умолчанию —8693. Порт должен отличаться от всех других портов пода. Попадает в конфигурацию агента.ca_cert— сертификат удостоверяющего центра. Также можно задать через переменную окруженияKUBERNETES_AGENT_CA_CERT. Должен быть задан либоca_cert, либоca_cert_path. Указывать оба параметра одновременно нельзя. Попадает в конфигурацию агента.ca_cert_path— путь до файла с сертификатом удостоверяющего центра. Должен быть задан либоca_cert, либоca_cert_path. Указывать одновременно оба параметра нельзя. Попадает в конфигурацию агента.client_cert— клиентский сертификат. Также можно задать через переменную окруженияKUBERNETES_AGENT_CLIENT_CERT. Должен быть задан либоclient_cert, либоclient_cert_path. Указывать одновременно оба параметра нельзя.client_cert_path— путь до файла с клиентским сертификатом. Должен быть задан либоclient_cert, либоclient_cert_path. Указывать одновременно оба параметра нельзя.client_key— клиентский ключ. Также можно задать через переменную окруженияKUBERNETES_AGENT_CLIENT_KEY. Должен быть задан либоclient_key, либоclient_key_path. Указывать одновременно оба параметра нельзя.client_key_path— путь до файла с клиентским ключом. Должен быть задан либоclient_key, либоclient_key_path. Указывать одновременно оба параметра нельзя.
pool_max_size— максимальный размер пула подов. Обязательный параметр. Должен быть не меньше значенияpool_min_size.pool_min_size— минимальный размер пула подов. Обязательный параметр. Должен быть больше0.pool_maintenance_period— периодичность обслуживания пула подов. Значение по умолчанию —10s.secret_updating_timeout— таймаут обновления секрета. Значение по умолчанию —20s.pods_listing_timeout— таймаут запроса для получения списка подов. Значение по умолчанию —10s.pod_creation_timeout— таймаут запроса создания пода. Значение по умолчанию —1m.pod_startup_timeout— таймаут ожидания запуска пода. Значение по умолчанию —2m. Включает время ожидания запуска пода со всеми его контейнерами.pod_deletion_timeout— таймаут запроса удаления пода. Значение по умолчанию —30s.endpoint_resolving_timeout— таймаут разрешения конечной точки. Значение по умолчанию —10s. Включает время ожидания проброса порта агента.
endpoint— раздел с параметрами для взаимодействия с сервисом SourceCraft. Раздел полностью попадает в конфигурацию агента:host— хост сервиса SourceCraft. Обязательный параметр.port— порт сервиса SourceCraft. Обязательный параметр.ssl_no_verify— флаг отключения проверки серверного сертификата сервиса SourceCraft. Значение по умолчанию —false.
executor_type— тип воркера. Для режима Kubernetes должно быть указано значениеkubernetes.logger_type— формат логирования. Допустимые значения:jsonилиconsole.logger_level— уровень логирования. Допустимые значения:debug,info,warn,error. Необязательный параметр.tags— список меток воркера. Необязательный параметр.auth— раздел с параметрами аутентификации воркера в сервисе SourceCraft:pat— персональный токен доступа (PAT). Также можно задать через переменную окруженияPAT_CREDENTIALS. Обязательный параметр.
Создайте шаблон пода
Шаблон пода задает конфигурацию, по которой воркер создает поды в пространстве имен пула.
Важно
В шаблоне обязательно должен быть контейнер с именем cicd-worker. В этом контейнере запускается агент, который выполняет задание. Ресурсы для контейнера cicd-worker выбирайте с учетом предполагаемой нагрузки при выполнении заданий.
Создайте файл pod-template.yaml с шаблоном пода, например:
---
apiVersion: v1
kind: Pod
metadata:
name: pod-template
spec:
containers:
- name: cicd-worker
image: cr.yandex/sourcecraft/ci/self-hosted-processor:latest
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
При создании пода воркер автоматически дополняет шаблон следующими параметрами:
- В контейнер
cicd-workerдобавляются переменные окружения из секретаagent-secrets, контейнерный портagent-portдля порта агента и проба запуска. - Имя пода меняется на
cicd-worker-<уникальный_идентификатор>. - Пространство имен меняется на пространство имен пула подов.
- Запрещается перезапуск пода.
Пример дополненной конфигурации
---
apiVersion: v1
kind: Pod
metadata:
name: cicd-worker-<уникальный_идентификатор>
namespace: <пространство_имен_пула>
spec:
containers:
- name: cicd-worker
image: cr.yandex/sourcecraft/ci/self-hosted-processor:latest
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
envFrom:
- secretRef:
name: agent-secrets
ports:
- name: agent-port
containerPort: 8693
protocol: TCP
startupProbe:
exec:
command: ["nc", "-z", "localhost", "8693"]
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 10
restartPolicy: Never
Docker-образ агента
В качестве Docker-образа агента рекомендуется использовать базовый образ контейнера воркера cr.yandex/sourcecraft/ci/self-hosted-processor:latest. Если для выполнения заданий требуется собственный образ, при его создании учитывайте следующие требования:
-
Воркер должен запускаться без указания пути к файлу конфигурации в командной строке — конфигурация передается через переменную окружения
PROCESSOR_CONFIG:ENTRYPOINT ["/self-hosted-processor", "run"] -
В образе должна быть создана директория
/home/sourcecraft-ci-runner. Пользователь, от имени которого работает контейнер, должен иметь полный доступ к этой директории. -
В образе должны быть установлены и доступны для запуска следующие исполняемые файлы:
bash,sh,git,git-lfs,docker,nc.
Использование Docker в задании
Если для выполнения заданий нужен Docker, добавьте в шаблон пода контейнер с Docker-in-Docker.
Пример шаблона пода с Docker-in-Docker
---
apiVersion: v1
kind: Pod
metadata:
name: pod-template
spec:
containers:
- name: cicd-worker
image: cr.yandex/sourcecraft/ci/self-hosted-processor:latest
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
env:
- name: DOCKER_HOST
value: "tcp://localhost:2376"
- name: DOCKER_TLS_VERIFY
value: "1"
- name: DOCKER_CERT_PATH
value: "/.docker-certs/client"
volumeMounts:
- name: docker-certs
mountPath: /.docker-certs
- name: dind
image: docker:dind
securityContext:
privileged: true
startupProbe:
exec:
command: ["docker", "info"]
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 30
env:
- name: DOCKER_TLS_CERTDIR
value: "/.docker-certs"
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
volumeMounts:
- name: docker-certs
mountPath: /.docker-certs
volumes:
- name: docker-certs
emptyDir: {}
Ресурсы для контейнера с Docker-in-Docker выбирайте с учетом предполагаемой нагрузки. Проба запуска для контейнера с Docker-in-Docker обязательна — она позволяет избежать ошибок выполнения заданий из-за неготовности Docker-in-Docker к работе при высокой нагрузке.
Также можно использовать более безопасный образ docker:dind-rootless. В этом случае на узлы кластера Kubernetes необходимо установить дополнительный компонент sysbox.
Запустите воркер
-
Подготовьте окружение.
-
Запустите воркер с конфигурацией, созданной ранее, одним из способов:
-
Передать путь до файла конфигурации в командной строке:
self-hosted-processor run --config-path <путь_к_config.yaml> -
Передать содержимое конфигурации через переменную окружения
PROCESSOR_CONFIG:PROCESSOR_CONFIG="<содержимое_конфигурации>" self-hosted-processor run
Важно
Без передачи конфигурации воркер не запустится. Одновременно использовать оба способа передачи конфигурации нельзя — в этом случае воркер также не запустится.
-
В реестре доступен базовый Docker-образ контейнера воркера cr.yandex/sourcecraft/ci/self-hosted-processor:latest, а также теги конкретных версий.
В этом образе воркер запускается без указания пути к файлу конфигурации:
ENTRYPOINT ["/self-hosted-processor", "run"]
Поэтому при запуске контейнера передайте конфигурацию через переменную окружения PROCESSOR_CONFIG:
docker run --rm -e "PROCESSOR_CONFIG=<содержимое_конфигурации>" cr.yandex/sourcecraft/ci/self-hosted-processor:latest
Пример манифеста для запуска воркера внутри кластера Kubernetes приведен в подразделе Запуск воркера внутри кластера Kubernetes.
Примеры конфигураций
Запуск воркера вне кластера Kubernetes
Файл конфигурации config.yaml:
kubernetes:
kubeconfig_path: /path/to/.kube/config
namespace: pods-namespace
pod_template_path: /path/to/pod-template.yaml
agent:
port: 8693
ca_cert_path: /path/to/ca.crt
client_cert_path: /path/to/client.crt
client_key_path: /path/to/client.key
pool_max_size: 10
pool_min_size: 3
endpoint:
host: ci.sourcecraft.tech
port: 443
executor_type: kubernetes
logger_type: json
tags: ["my-tag", "+my-required-tag"]
auth:
pat: <персональный_токен>
Команда запуска:
self-hosted-processor run --config-path /path/to/config.yaml
Запуск воркера внутри кластера Kubernetes
Манифест с сервисным аккаунтом, ролью, секретом и развертыванием воркера:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: processor-sa
namespace: processor-namespace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: processor-role
namespace: pods-namespace
rules:
- apiGroups: [""]
resources: ["secrets", "pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: processor-role-binding
namespace: pods-namespace
subjects:
- kind: ServiceAccount
name: processor-sa
namespace: processor-namespace
roleRef:
kind: Role
name: processor-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Secret
metadata:
name: processor-secrets
namespace: processor-namespace
type: Opaque
stringData:
PROCESSOR_CONFIG: |
---
kubernetes:
namespace: pods-namespace
agent:
port: 8693
pool_max_size: 10
pool_min_size: 3
endpoint:
host: ci.sourcecraft.tech
port: 443
executor_type: kubernetes
logger_type: json
tags: ["my-tag", "+my-required-tag"]
KUBERNETES_POD_TEMPLATE: |
---
apiVersion: v1
kind: Pod
metadata:
name: pod-template
spec:
containers:
- name: cicd-worker
image: cr.yandex/sourcecraft/ci/self-hosted-processor:latest
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
env:
- name: DOCKER_HOST
value: "tcp://localhost:2376"
- name: DOCKER_TLS_VERIFY
value: "1"
- name: DOCKER_CERT_PATH
value: "/.docker-certs/client"
volumeMounts:
- name: docker-certs
mountPath: /.docker-certs
- name: dind
image: docker:dind
securityContext:
privileged: true
startupProbe:
exec:
command: ["docker", "info"]
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 30
env:
- name: DOCKER_TLS_CERTDIR
value: "/.docker-certs"
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
volumeMounts:
- name: docker-certs
mountPath: /.docker-certs
volumes:
- name: docker-certs
emptyDir: {}
KUBERNETES_AGENT_CA_CERT: |
-----BEGIN CERTIFICATE-----
certificate content
-----END CERTIFICATE-----
KUBERNETES_AGENT_CLIENT_CERT: |
-----BEGIN CERTIFICATE-----
certificate content
-----END CERTIFICATE-----
KUBERNETES_AGENT_CLIENT_KEY: |
-----BEGIN PRIVATE KEY-----
key content
-----END PRIVATE KEY-----
PAT_CREDENTIALS: <персональный_токен>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubernetes-processor
namespace: processor-namespace
spec:
replicas: 1
selector:
matchLabels:
app: kubernetes-processor
template:
metadata:
labels:
app: kubernetes-processor
spec:
serviceAccountName: processor-sa
containers:
- name: kubernetes-processor
image: cr.yandex/sourcecraft/ci/self-hosted-processor:latest
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
envFrom:
- secretRef:
name: processor-secrets