Kubernetes 执行器 Enterprise
使用 Kubernetes 执行器时,运行器在命名空间中为每个任务创建一个 Pod,将其日志流式 传输 到 Semaphore,并在任务结束时删除该 Pod。运行器可以运行在集群内(推荐),也可以 运行在集群外并使用 kubeconfig。
容器任务如何运行、容器内有什么以及哪些功能不受支持,请参见 执行器。本页介绍 Kubernetes 的设置。
开始之前
- 拥有 Enterprise 许可证的 Semaphore 服务器。
- 部署在集群中的运行器,参见在 Kubernetes 上安装运行器。
以下步骤使用其命名空间
semaphore和 Deploymentsemaphore-runner。集群外的运行器参见 集群外的运行器。 - 有权在该命名空间中创建服务账号和 RBAC 对象的
kubectl。 - 集群可以拉取
semaphoreui/job和semaphoreui/helper(或你自己的镜像)。
运行器创建的对象
对于 ID 为 42 的任务,运行器在其命名空间中创建:
| 对象 | 名称 | 内容 |
|---|---|---|
| Pod | semaphore-job-42-<random> | 初始化容器 git-clone(辅助镜像)和容器 build(构建镜像),restartPolicy: Never。 |
| Secret | <pod>-ssh-<key id> | 每个 SSH 密钥一个,挂载在 /secrets/ssh/<key id>/。 |
| Secret | <pod>-vault | Ansible vault 密码。 |
| Secret | <pod>-extra-vars | 包含额外变量的 values.json。 |
| Secret | <pod>-env | 类型为 Environment variable 的变量组机密以及 SEMAPHORE_JWT,通过 envFrom 注入。 |
| ConfigMap | <pod>-inventory | 静态清单。 |
只创建任务需要的对象。它们都带有 semaphoreui.com/runner=semaphore 标签;Pod 还带有
semaphoreui.com/task-id=42。任务结束时运行器会将它们全部删除,失败或 Stop 之后
也是如此。
设置
步骤 1. 创建服务账号
运行器需要一个服务账号来创建任务 Pod。任务 Pod 使用第二个账号,它没有任何权限,也没有 API 令牌,因此 playbook 无法使用运行器的权限。
apiVersion: v1
kind: ServiceAccount
metadata:
name: semaphore-runner
namespace: semaphore
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: semaphore-job
namespace: semaphore
automountServiceAccountToken: false
步骤 2. 为运行器授予权限
以下是执行器发出的全部 API 调用:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: semaphore-runner
namespace: semaphore
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "delete"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: [""]
resources: ["secrets", "configmaps"]
verbs: ["create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: semaphore-runner
namespace: semaphore
subjects:
- kind: ServiceAccount
name: semaphore-runner
namespace: semaphore
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: semaphore-runner
使用 Role 而不是 ClusterRole:运行器只能操作自己的命名空间。
步骤 3. 将运行器切换到 Kubernetes 执行器
任务 Pod 不设置 securityContext,因此强制执行 restricted Pod Security 级别的命名空间会拒绝它们。
请允许 baseline:
kubectl label namespace semaphore pod-security.kubernetes.io/enforce=baseline --overwrite
为运行器 Pod 指定其服务账号和执行器设置。在运行器 Deployment 的 spec.template.spec 中添加:
spec:
serviceAccountName: semaphore-runner
containers:
- name: runner
env:
# ...SEMAPHORE_WEB_ROOT and SEMAPHORE_RUNNER_TOKEN as before
- name: SEMAPHORE_RUNNER_EXECUTOR_TYPE
value: k8s
- name: SEMAPHORE_RUNNER_K8S_NAMESPACE
value: semaphore
- name: SEMAPHORE_RUNNER_K8S_SERVICE_ACCOUNT
value: semaphore-job
- name: SEMAPHORE_RUNNER_K8S_IMAGE
value: semaphoreui/job:latest
kubectl apply -f semaphore-serviceaccounts.yaml -f semaphore-rbac.yaml -f semaphore-runner.yaml
kubectl -n semaphore rollout status deploy/semaphore-runner
未设置 kubeconfig 时,运行器使用 semaphore-runner 的集群内凭据。任务不再在运行器 Pod 中运行,
因此可以降低其 resources(例如 CPU 100m、内存 256Mi)。
步骤 4. 运行任务
将模板路由到该运行器并启动任务。观察其 Pod 出现并消失:
kubectl -n semaphore get pods -l semaphoreui.com/runner=semaphore -w
任务日志显示:
k8s: created pod semaphore/semaphore-job-42-a1b2c3 (1 ssh keys installed)
=== git-clone (init) ===
Cloning into '/workspace/repo'...
=== build (build) ===
semaphore: container executor: task 42, template 7
...
k8s: deleted pod semaphore/semaphore-job-42-a1b2c3
示例
集群外的运行器
运行器运行在虚拟机或 Docker 中,通过 kubeconfig 访问 API 服务器。只为该 kubeconfig 授予步骤 2 中的 Role,不要更多:
{
"web_host": "https://semaphore.example.com",
"runner": {
"token_file": "/var/lib/semaphore/runner_token.txt",
"executor": {
"type": "k8s",
"k8s": {
"kubeconfig": "/etc/semaphore/kubeconfig",
"namespace": "semaphore",
"service_account": "semaphore-job"
}
}
}
}
使用 kubeconfig 的当前上下文。
来自私有镜像仓库的镜像
在命名空间中创建拉取密钥并在 pull_secrets 中列出;多个名称用逗号分隔:
kubectl -n semaphore create secret docker-registry registry-example \
--docker-server=registry.example.com \
--docker-username=<user> --docker-password=<password>
- name: SEMAPHORE_RUNNER_K8S_IMAGE
value: registry.example.com/semaphore/job-aws:1.0
- name: SEMAPHORE_RUNNER_K8S_PULL_SECRETS
value: registry-example
这些密钥会附加到每个任务 Pod,同样适用于构建镜像、辅助镜像和模板的 Executor image。
任务 Pod 的 CPU 和内存
执行器不会为任务 Pod 设置 requests 或 limits。请使用 LimitRange 为命名空间设置
默认值;它适用于 git-clone 和 build 容器:
apiVersion: v1
kind: LimitRange
metadata:
name: semaphore-task-defaults
namespace: semaphore
spec:
limits:
- type: Container
defaultRequest:
cpu: 250m
memory: 256Mi
default:
cpu: "2"
memory: 2Gi
添加 ResourceQuota 以限制该命名空间中所有并行任务可使用的总量。