- 工作流
- 连接到 Kubernetes API
- 配置设置
- 配置示例
- 准备步骤的资源检查
- 通过 Kubernetes 执行器使用缓存
- 配置卷类型
- 自定义卷挂载
- 为 Pod 设置安全策略
- 定义服务列表
- 设置拉取策略
- 指定执行构建的节点
- 定义节点亲和列表
- 添加额外的主机别名
- 配置容器生命周期钩子
- 配置 Pod DNS 设置
- 指定容器能力
- 设置 RuntimeClass
- 在构建中使用 Docker
- 作业执行
- 移除旧的 Runner Pod
-
故障排除
Job failed (system failure): timed out waiting for pod to start
context deadline exceeded
- 使用 Kubernetes API 试图通信时拒绝连接
Error cleaning up pod
和Job failed (system failure): prepare environment: waiting for pod running
request did not complete within requested timeout
fatal: unable to access 'https://gitlab-ci-token:token@example.com/repo/proj.git/': Could not resolve host: example.com
docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443
MountVolume.SetUp failed for volume "kube-api-access-xxxxx" : chown is not supported by windows
- 构建 Pod 被分配 Worker 节点的 IAM 角色而不是 Runner IAM 角色
Preparation failed: failed to pull image 'image-name:latest': pull_policy ([Always]) defined in GitLab pipeline config is not one of the allowed_pull_policies ([])
- 后台进程导致作业挂起和超时
- 限制对作业变量的访问
Kubernetes 执行器
使用 Kubernetes 执行器为您的构建使用 Kubernetes 集群。执行器调用 Kubernetes 集群 API 并为每个极狐GitLab CI 作业创建 Pod。
工作流
Kubernetes 执行器将构建分为以下步骤:
- 准备:创建与 Kubernetes 集群相关的 Pod。 创建运行构建和服务所需的容器。
- 构建前:克隆、还原缓存并从之前阶段下载产物。此步骤作为 Pod 的一部分在特殊容器上运行。
- 构建:用户构建。
- 构建后:创建缓存,向极狐GitLab 上传产物。此步骤也将特殊容器用作 Pod 的一部分。
Runner 如何创建 Kubernetes Pod
下图显示了极狐GitLab 实例与托管在 Kubernetes 集群上的 Runner 之间的交互。Runner 调用 Kubernetes API 在集群上创建 Pod。
对于在 .gitlab-ci.yml
或 config.toml
文件中定义的每个 service
,Pod 都由以下容器组成:
- 定义为
build
的构建容器。 - 定义为
helper
的 helper 容器。 - 定义为
svc-X
的服务容器,其中X
是[0-9]+
。
服务和容器运行在同一个 Kubernetes Pod 中并共享相同的本地主机地址。以下限制适用:
- 在极狐GitLab Runner 12.8 和 Kubernetes 1.7 及更高版本中,可以通过其 DNS 名称访问服务。如果您使用的是旧版本,则必须使用
localhost
。 - 您使用的服务不能使用同一端口。例如,您不能同时使用两个
mysql
服务。
图中的交互对任何 Kubernetes 集群都有效。例如,托管在主要公共云提供商或私有化部署的 Kubernetes 安装上的 turnkey 解决方案。
连接到 Kubernetes API
使用以下选项连接到 Kubernetes API。提供的用户帐户必须具有在指定命名空间中创建、列出和附加到 Pod 的权限。
选项 | 描述 |
---|---|
host
| 可选的 Kubernetes apiserver 主机 URL(如未指定,则尝试自动发现 |
cert_file
| 可选的 Kubernetes apiserver 用户授权证书 |
key_file
| 可选的 Kubernetes apiserver 用户授权私有 key |
ca_file
| 可选的 Kubernetes apiserver ca 证书 |
如果您在 Kubernetes 集群中运行极狐GitLab Runner,您应该省略所有这些字段,以便极狐GitLab Runner 自动发现 Kubernetes API。
如果您在集群外部运行极狐GitLab Runner,则必须设置每个设置并确保极狐GitLab Runner 可以在集群上访问 Kubernetes API。
配置设置
使用 config.toml
文件中的以下设置配置 Kubernetes 执行器。
CPU 请求和限制
设置 | 描述 |
---|---|
cpu_limit
| 构建容器所需的 CPU 分配。 |
cpu_limit_overwrite_max_allowed
| 为构建容器可写入的最大的 CPU 分配量。如果为空,则禁用了 CPU 限制覆盖功能。 |
cpu_request
| 构建容器所请求的 CPU 分配。 |
cpu_request_overwrite_max_allowed
| 为构建容器可写入的最大的 CPU 分配请求量。如果为空,则禁用了 CPU 请求覆盖功能。 |
helper_cpu_limit
| 给予构建 Helper 容器的 CPU 分配。 |
helper_cpu_limit_overwrite_max_allowed
| Helper 容器可写入的最大的 CPU 分配量。如果为空,则禁用了 CPU 限制覆盖功能。 |
helper_cpu_request
| 构建 Helper 容器所需的 CPU 分配。 |
helper_cpu_request_overwrite_max_allowed
| Helper 容器可写入的最大的 CPU 分配请求量。如果为空,则禁用了 CPU 请求覆盖功能。 |
service_cpu_limit
| 给予构建服务容器的 CPU 分配。 |
service_cpu_limit_overwrite_max_allowed
| 服务容器可写入的最大的 CPU 分配量。如果为空,则禁用了 CPU 限制覆盖功能。 |
service_cpu_request
| 构建服务容器所请求的 CPU 分配。 |
service_cpu_request_overwrite_max_allowed
| 服务容器可写入的最大的 CPU 分配请求量。如果为空,则禁用了 CPU 请求覆盖功能。 |
内存请求和限制
设置 | 描述 |
---|---|
memory_limit
| 分配给构建容器的内存量。 |
memory_limit_overwrite_max_allowed
| 构建容器可写入的最大的内存分配量。如果为空,则禁用了内存限制覆盖功能。 |
memory_request
| 从构建容器请求的内存量。 |
memory_request_overwrite_max_allowed
| 构建容器可写入的最大的内存分配请求量。如果为空,则禁用了内存请求覆盖功能。 |
helper_memory_limit
| 构建 Helper 容器所分配的内存量。 |
helper_memory_limit_overwrite_max_allowed
| Helper 容器可写入的最大的内存分配量。如果为空,则禁用了内存限制覆盖功能。 |
helper_memory_request
| 构建 Helper 容器所请求的内存量。 |
helper_memory_request_overwrite_max_allowed
| Helper 容器可写入的最大的内存分配请求量。如果为空,则禁用了内存请求覆盖功能。 |
service_memory_limit
| 构建服务容器所分配的内存量。 |
service_memory_limit_overwrite_max_allowed
| 服务容器可写入的最大的内存分配量。如果为空,则禁用了内存限制覆盖功能。 |
service_memory_request
| 构建服务容器所请求的内存量。 |
service_memory_request_overwrite_max_allowed
| 服务容器可写入的最大的内存分配请求量。如果为空,则禁用了内存请求覆盖功能。 |
存储请求和限制
设置 | 描述 |
---|---|
ephemeral_storage_limit
| 构建容器的临时存储限制。 |
ephemeral_storage_limit_overwrite_max_allowed
| 可以覆盖的构建容器的最大临时存储限制。如果为空,则禁用了临时存储限制覆盖功能。 |
ephemeral_storage_request
| 给予构建容器的临时存储请求。 |
ephemeral_storage_request_overwrite_max_allowed
| 构建容器可被覆盖的最大临时存储请求量。如果为空,则禁用了临时存储请求覆盖功能。 |
helper_ephemeral_storage_limit
| 给予构建容器的临时存储限制。 |
helper_ephemeral_storage_limit_overwrite_max_allowed
| Helper 容器可被覆盖的最大临时存储限制。如果为空,则禁用了临时存储请求覆盖功能。 |
helper_ephemeral_storage_request
| 给予 Helper 容器的临时存储请求。 |
helper_ephemeral_storage_request_overwrite_max_allowed
| Helper 容器可被覆盖的最大临时存储请求量。如果为空,则禁用了临时存储请求覆盖功能。 |
service_ephemeral_storage_limit
| 给予服务容器的临时存储限制。 |
service_ephemeral_storage_limit_overwrite_max_allowed
| 服务容器可被覆盖的最大临时存储限制。如果为空,则禁用了临时存储请求覆盖功能。 |
service_ephemeral_storage_request
| 给予服务容器的临时存储请求。 |
service_ephemeral_storage_request_overwrite_max_allowed
| 服务容器可被覆盖的最大临时存储请求量。如果为空,则禁用了临时存储请求覆盖功能。 |
其他 config.toml
设置
设置 | 描述 |
---|---|
affinity
| 指定运行构建的节点的亲和规则。阅读更多关于使用亲和的内容。 |
allow_privilege_escalation
| 启用 allowPrivilegeEscalation 标志,运行所有容器。如果为空,它不定义 SecurityContext 容器中的 allowPrivilegeEscalation 标志并且允许 Kubernetes 使用默认的特权升级行为。
|
allowed_images
|
.gitlab-ci.yml 中可指定的镜像的通配符列表。如果不存在,则允许所有镜像(等同于 ["*/*:*"] )。查看详情。
|
allowed_pull_policies
| 可以在 .gitlab-ci.yml 文件或 config.toml 文件中指定的拉取策略列表。
|
allowed_services
|
.gitlab-ci.yml 中可以指定的服务的通配符列表。如果不存在,则允许所有镜像(等同于 ["*/*:*"] )。查看详情。
|
bearer_token
| 用于发布构建 Pod 的默认承载令牌。 |
bearer_token_overwrite_allowed
| 允许项目指定用于创建构建 Pod 的持有者令牌的布尔。 |
cap_add
| 指定应该被添加到作业 Pod 容器的 Linux 能力。阅读更多关于 Kubernetes 执行器中的能力配置的内容。 |
cap_drop
| 指定应该从作业 Pod 容器 移除的 Linux 能力。阅读更多关于 Kubernetes 执行器中的能力配置的内容。 |
cleanup_grace_period_seconds
| 作业完成后,Pod 优雅关闭的时间(秒)。关闭时间之后,使用停止信号强制停止进程。如果指定了 terminationGracePeriodSeconds ,则忽略它。
|
helper_container_security_context
| 为 Helper 容器设置容器安全上下文。阅读更多安全上下文的内容。 |
helper_image
| (高级)覆盖默认 Helper 镜像,该镜像用于克隆仓库和上传产物。 |
helper_image_flavor
| 设置 Helper 镜像类型 (alpine 、alpine3.12 、alpine3.13 、alpine3.14 、alpine3.15 或 ubuntu )。默认为 alpine 。使用 alpine 与使用 alpine3.12 相同。
|
host_aliases
| 添加到所有容器的额外主机别名列表。阅读更多关于使用额外主机别名的内容。 |
image_pull_secrets
| 包含用于验证从私有镜像库拉取的 Docker 镜像的 Kubernetes docker-registry 秘密名称的项目阵列。
|
namespace
| 运行 Kubernetes Pod 的命名空间。 |
namespace_overwrite_allowed
| 验证命名空间覆盖环境变量内容的正则表达式(以下记录)。如果为空,则禁用了命名空间覆盖功能。 |
node_selector
|
string=string (环境变量的 string:string )形式的 key=value 对的 table 。对其进行设置限制了向匹配所有 key=value 对的 Kubernetes 节点的 Pod 创建。阅读更多使用节点选择器的内容。
|
node_tolerations
|
string=string:string 形式的 "key=value" = "Effect" 对的 table 。对其进行设置允许 Pod 使用所有或一子组的容忍污点。仅允许通过环境变量配置提供一个容忍。key 、value 和 effect 与 Kubernetes Pod 容忍配置中的对应字段名称相匹配。
|
pod_annotations
|
string=string 形式的 key=value 对的 table 。这是添加到 Runner 创建的每个构建 Pod 的标注列表。为进行扩展,这些的值可以包括环境变量。在每个构建中,Pod 标注可被覆盖。
|
pod_annotations_overwrite_allowed
| 验证 Pod 标注覆盖环境变量内容的正则表达式。如果为空,则禁用了 Pod 标注覆盖功能。 |
pod_labels
|
key=value 对的 table ,格式为 string=string 。是要添加到 Runner 创建的每个构建 pod 的标志列表。这些值可以包括用于扩展的环境变量。可以使用 pod_labels_overwrite_allowed 在每个构建中覆盖 Pod 标志。
|
pod_labels_overwrite_allowed
| 用于验证 Pod 标记内容覆盖环境变量的正则表达式。为空时,它会禁用 pod 标记覆盖功能。 |
pod_security_context
| 通过配置文件进行配置。为构建 Pod 设置了 Pod 安全上下文。阅读更多安全上下文的内容。 |
init_permissions_container_security_context
| 为 init-permissions 容器设置容器安全上下文。 阅读更多安全上下文的内容。 |
build_container_security_context
| 为构建容器设置容器安全上下文。阅读更多安全上下文的内容。 |
helper_container_security_context
| 为 Helper 容器设置容器安全上下文。 阅读更多安全上下文的内容。 |
service_container_security_context
| 为服务容器设置容器安全上下文。阅读更多安全上下文的内容。 |
pod_termination_grace_period_seconds
| Pod 级别的设置,决定 Pod 优雅关闭的时间(秒)。在这之后,使用停止信号强制停止进程。如果指定了 terminationGracePeriodSeconds ,则忽略。
|
poll_interval
| Runner 轮询它刚刚创建的 Kubernetes Pod 的频率(秒),以检查其状态(默认 = 3)。 |
poll_timeout
| Runner 试图连接它刚刚创建的容器的超时时间前需要传递的时间(秒)。在为超过集群一次可以处理的构建进行排队时有用。(默认 = 180)。 |
resource_availability_check_max_attempts
| 检查资源(服务账户和/或拉取密钥)组在放弃前是否可用所进行的尝试的最多次数。两次尝试中间间隔 5 秒(默认为 5 )。
|
privileged
| 使用特权标记运行容器。 |
runtime_class_name
| 为所有创建的 Pod 所使用的运行时类。如果集群不支持这个功能,作业会退出或失败。 |
pull_policy
| 指定镜像拉取策略:never 、if-not-present 或 always 。如果没有设置,会使用集群的镜像默认拉取策略。关于如何设置多种拉取策略,请参见使用拉取策略。您也可以参考if-not-present 、never 安全考虑。您也可以限制拉取策略。
|
scheduler_name
| 用于调度构建 pod 的调度器。 |
service_account
| Pod 使用的与 Kubernetes API 通信的默认服务账户作业/执行器。 |
service_account_overwrite_allowed
| 验证服务账户覆盖环境变量内容的正则表达式。如果为空,则禁用了服务账户覆盖功能。 |
services
| 自极狐GitLab Runner 12.5 起,使用边车 (https://learn.microsoft.com/en-us/azure/architecture/patterns/sidecar)模式附着到构建容器的服务列表。阅读更多关于使用服务的内容。 |
terminationGracePeriodSeconds
| 向运行在 Pod 中的进程发送结束信号之后的时长和使用停止信号强制停止进程的时间。 |
volumes
| 通过配置文件进行配置,将要挂载到构建容器的卷列表。阅读更多使用卷的内容。 |
dns_policy
| 指定构建 Pod 时应该使用的 DNS 策略:none 、default 、cluster-first 或 cluster-first-with-host-net 。如果没有设置,将使用 Kubernetes 默认的 (cluster-first )。
|
dns_config
| 指定构建 Pod 时应该使用的 DNS 配置。阅读更多使用 Pod DNS 配置的内容。 |
priority_class_name
| 指定要设置到 Pod 的优先级。如果未设置,将使用默认值。 |
pod_spec
| 此设置处于 Alpha 阶段。使用在用于运行 CI 作业的 Pod 上设置的配置列表覆盖 Runner Manager 生成的 Pod 规范。可以设置 Kubernetes Pod Specification 中列出的所有参数。有关详细信息,请参阅覆盖生成的 Pod 规范(Alpha)。
|
覆盖生成的 Pod 规范 (Alpha)
引入于极狐GitLab Runner 15.10。
此功能处于 Alpha 阶段。我们强烈建议您先在测试 Kubernetes 集群上使用此功能,然后再将其用于生产集群。要使用此功能,您必须启用 FF_USE_ADVANCED_POD_SPEC_CONFIGURATION
功能标志。
要修改 Runner Manager 生成的 PodSpec
,请使用 config.toml
文件中的 pod_spec
设置。
pod_spec
设置覆盖并完成生成的 Pod 规范的字段。您可以配置多个 pod_spec
设置。
设置 | 描述 |
---|---|
name
| 为自定义 pod_spec 指定的名称
|
patch_path
| 定义在生成前应用于最终 PodSpec 对象的更改的文件路径。该文件必须是 JSON 或 YAML 文件
|
patch
| JSON 或 YAML 格式字符串,描述在生成前必需应用到最终的 PodSpec 对象的更改
|
patch_type
| Runner 用于将指定更改应用于极狐GitLab Runner 生成的 PodSpec 对象的策略。可接受的值为 merge 、json 和 strategic
|
不能在同一个 pod_spec
配置中设置 patch_path
和 patch
,否则会报错。
config.toml
中的多个 pod_spec
配置示例:
[[runners]]
[runners.kubernetes]
[[runners.kubernetes.pod_spec]]
name = "hostname"
patch = '''
hostname: "custom-pod-hostname"
'''
patch_type = "merge"
[[runners.kubernetes.pod_spec]]
name = "subdomain"
patch = '''
subdomain: "subdomain"
'''
patch_type = "strategic"
[[runners.kubernetes.pod_spec]]
name = "terminationGracePeriodSeconds"
patch = '''
[{"op": "replace", "path": "/terminationGracePeriodSeconds", "value": 60}]
'''
patch_type = "json"
合并补丁策略
merge
补丁策略在现有的 PodSpec
上应用键值替换。
如果您使用此策略,则 config.toml
中的 pod_spec
配置会在生成之前覆盖最终 PodSpec
对象中的值。因为值被完全覆盖,所以您应该谨慎使用此补丁策略。
以下是使用 merge
补丁策略的 pod_spec
配置示例:
concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = ""
url = "https://gitlab.example.com"
id = 0
token = "__REDACTED__"
token_obtained_at = 0001-01-01T00:00:00Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "kubernetes"
shell = "bash"
environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
[runners.kubernetes]
image = "alpine"
...
[[runners.kubernetes.pod_spec]]
name = "build envvars"
patch = '''
containers:
- env:
- name: env1
value: "value1"
- name: env2
value: "value2"
name: build
'''
patch_type = "merge"
通过此配置,最终的 PodSpec
只有一个名为 build
的容器,且带有两个环境变量 env1
和 env2
。上面的示例会让相关的 CI 作业失败,因为:
- 删除了
helper
容器规范。 -
build
容器规范丢失了极狐GitLab Runner 设置的所有必要配置。
为了防止作业失败,在此示例中,pod_spec
必须包含极狐GitLab Runner 生成的未修改的参数。
JSON 补丁策略
json
补丁策略使用 JSON 补丁规范来控制要更新的 PodSpec
对象和数组。您不能在 array
参数上使用此策略。
以下是使用 json
补丁策略的 pod_spec
配置示例。在此配置中,一个新的 key: value pair
被添加到现有的 nodeSelector
中。现有值不会被覆盖。
concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = ""
url = "https://gitlab.example.com"
id = 0
token = "__REDACTED__"
token_obtained_at = 0001-01-01T00:00:00Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "kubernetes"
shell = "bash"
environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
[runners.kubernetes]
image = "alpine"
...
[[runners.kubernetes.pod_spec]]
name = "val1 node"
patch = '''
{ "op": "add", "path": "/nodeSelector", "value": { key1: "val1" } }
'''
patch_type = "json"
Strategic 补丁策略
strategic
补丁策略使用应用于 PodSpec
对象的每个字段的现有 patchStrategy
。
以下是使用 json
补丁策略的 pod_spec
配置示例。在此配置中,构建容器上设置了 resource request
。
concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = ""
url = "https://gitlab.example.com"
id = 0
token = "__REDACTED__"
token_obtained_at = 0001-01-01T00:00:00Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "kubernetes"
shell = "bash"
environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
[runners.kubernetes]
image = "alpine"
...
[[runners.kubernetes.pod_spec]]
name = "cpu request 500m"
patch = '''
containers:
- name: build
resources:
requests:
cpu: "500m"
'''
patch_type = "strategic"
使用此配置,在构建容器上设置了 resource request
。
最佳实践
- 在生产环境中部署之前,需要在测试环境中测试添加的
pod_spec
。 - 确保
pod_spec
配置不会对极狐GitLab Runner 生成的规范产生负面影响。 - 不要对复杂的 Pod 规范更新使用
merge
补丁策略。 - 如果可能,在配置可用时使用
config.toml
。例如,以下配置将极狐GitLab Runner 设置的第一个环境变量替换为自定义pod_spec
中设置的环境变量,而不是将环境变量集添加到现有列表中。
concurrent = 1
check_interval = 1
log_level = "debug"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = ""
url = "https://gitlab.example.com"
id = 0
token = "__REDACTED__"
token_obtained_at = 0001-01-01T00:00:00Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "kubernetes"
shell = "bash"
environment = ["FF_USE_ADVANCED_POD_SPEC_CONFIGURATION=true", "CUSTOM_VAR=value"]
[runners.kubernetes]
image = "alpine"
...
[[runners.kubernetes.pod_spec]]
name = "build envvars"
patch = '''
containers:
- env:
- name: env1
value: "value1"
name: build
'''
patch_type = "strategic"
Pod 生命周期
Pod 的生命周期可能会受到以下因素的影响:
- 在
TOML
配置文件中设置pod_termination_grace_period_seconds
参数。 在发送TERM
信号后,在 Pod 上运行的进程可以运行给定时间。 如果 Pod 在此时间段后未成功终止,则会发送终止信号。 - 启用
FF_USE_POD_ACTIVE_DEADLINE_SECONDS
功能标志。 当启用并且作业超时后,运行 CI/CD 作业的 Pod 会被标记为失败并且所有关联的容器都被终止。如果想先让极狐GitLab 中的作业超时,请将activeDeadlineSeconds
设置为configured timeout + 1 second
。
FF_USE_POD_ACTIVE_DEADLINE_SECONDS
功能标志并且
pod_termination_grace_period_seconds
设置为非零值,作业超时的时候,CI 作业 Pod 不会立即终止。
Pod terminationGracePeriods
确保 Pod 仅在其过期时终止。作业 Pod 的默认注释
引入于极狐GitLab Runner 15.9。
默认情况下,在运行作业的 Pod 上添加以下注释:
Key | 说明 |
---|---|
job.runner.gitlab.com/id
| 作业 ID,在极狐GitLab 实例的所有作业中是唯一的。 |
job.runner.gitlab.com/url
| 作业详细信息的 URL。 |
job.runner.gitlab.com/sha
| 构建项目的提交修订。 |
job.runner.gitlab.com/before_sha
| 分支或标签上的最后一次提交。 |
job.runner.gitlab.com/ref
| 构建项目的分支或标签名称。 |
job.runner.gitlab.com/name
| 作业名称。 |
project.runner.gitlab.com/id
| 作业的项目 ID。 |
要覆盖默认注释,请在极狐GitLab Runner 配置中使用 pod_annotations
。
您还可以在 .gitlab-ci.yml
文件中覆盖每个 CI/CD 作业的注释。
配置执行器服务账户
您可以设置 KUBERNETES_SERVICE_ACCOUNT
环境变量或者使用 --kubernetes-service-account
标记。
覆盖 Kubernetes 命名空间
先决条件:
- 在极狐GitLab Runner Helm Chart 的
values.yml
文件中,rbac.clusterWideAccess
设置为true
。 - Runner 在核心 API 群组中配置了权限。
您可以覆盖 Kubernetes 命名空间以指定用于 CI 目的的命名空间,并向其部署自定义的 Pod 组。 Runner 生成的 Pod 位于被覆盖的命名空间中,以在 CI 阶段启用容器之间的访问。
要覆盖每个 CI/CD 作业的 Kubernetes 命名空间,请在 .gitlab-ci.yml
文件中设置 KUBERNETES_NAMESPACE_OVERWRITE
参数。
variables:
KUBERNETES_NAMESPACE_OVERWRITE: ci-${CI_COMMIT_REF_SLUG}
要在 CI 运行期间仅使用指定的命名空间,请在 config.toml
文件中为 namespace_overwrite_allowed
定义一个正则表达式:
[runners.kubernetes]
...
namespace_overwrite_allowed = "ci-.*"
配置 Runner API 权限
要为核心 API 群组配置权限,请更新极狐GitLab Runner Helm Chart 的 values.yml
文件。
您可以:
- 将
rbac.create
设置为true
。 -
在
values.yml
文件中指定具有以下权限的服务帐户rbac.serviceAccountName: <service_account_name>
。-
对于
exec strategy
:资源 权限 pods/exec 创建、打补丁、删除 pods 获取、列出、查看、创建、打补丁、删除 services 获取、列出、查看、创建、打补丁、删除 secrets 获取、列出、查看、创建、更新、打补丁、删除 serviceAccounts 获取(1) -
对于
attach strategy
:资源 权限 pods/attach 创建、打补丁、删除 pods/exec 创建、打补丁、删除 pods 获取、查看、创建、删除 services 获取、查看、创建、删除 configmaps 获取、创建、更新、删除 secrets 获取、创建、更新、删除 serviceAccounts 获取(1)
-
(1) 仅在以下情况需要 serviceAccount
权限:
- 15.0 和 15.1 版本中
- 15.0.1、15.1.1 和 15.2 中,当
resource_availability_check_max_attempts
的值大于 0
覆盖 Kubernetes 默认服务账户
要覆盖 .gitlab-ci.yml
文件中每个 CI/CD 作业的 Kubernetes 服务帐户,请设置变量 KUBERNETES_SERVICE_ACCOUNT_OVERWRITE
。
您可以使用此变量指定附加到命名空间的服务帐户,复杂的 RBAC 配置可能需要使用。
variables:
KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: ci-service-account
为确保在 CI 运行期间仅使用指定的服务帐户,为以下任意一项定义一个正则表达式:
-
service_account_overwrite_allowed
设置。 -
KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED
环境变量。
如果您都不设置,则覆盖将被禁用。
为 Kubernetes API 调用设置承载令牌
要为创建 Pod 的 API 调用设置承载令牌,请使用 KUBERNETES_BEARER_TOKEN
变量。
这允许项目所有者使用项目 secret 变量来指定承载令牌。
指定承载令牌时,您必须设置 Host
配置设置。
variables:
KUBERNETES_BEARER_TOKEN: thebearertokenfromanothernamespace
覆盖 Pod 标记
为每个 CI/CD 作业覆盖 Kubernetes Pod 标记:
- 在
.config.yaml
文件中,为pod_labels_overwrite_allowed
定义一个正则表达式。 -
在
.gitlab-ci.yml
文件中,将KUBERNETES_POD_LABELS_*
变量赋值为key=value
。 Pod 标记被覆盖为key=value
。您可以应用多个值:variables: KUBERNETES_POD_LABELS_1: "Key1=Val1" KUBERNETES_POD_LABELS_2: "Key2=Val2" KUBERNETES_POD_LABELS_3: "Key3=Val3"
覆盖 Pod 注释
要为每个 CI/CD 作业覆盖 Kubernetes Pod 注释:
- 在
.config.yaml
文件中,为pod_annotations_overwrite_allowed
定义一个正则表达式。 - 在
.gitlab-ci.yml
文件中,设置KUBERNETES_POD_ANNOTATIONS_*
变量并使用key=value
作为值。 Pod 注释被覆盖到key=value
。您可以指定多个注释:
variables:
KUBERNETES_POD_ANNOTATIONS_1: "Key1=Val1"
KUBERNETES_POD_ANNOTATIONS_2: "Key2=Val2"
KUBERNETES_POD_ANNOTATIONS_3: "Key3=Val3"
覆盖容器资源
您可以为每个 CI/CD 作业覆盖 Kubernetes CPU 和内存分配。您可以为构建、Helper 和服务容器应用请求和限制设置。
要覆盖容器资源,请在 .gitlab-ci.yml
文件中使用以下变量。
变量的值仅限于该资源的最大覆盖设置。如果没有为资源设置最大覆盖,则不使用该变量。
variables:
KUBERNETES_CPU_REQUEST: "3"
KUBERNETES_CPU_LIMIT: "5"
KUBERNETES_MEMORY_REQUEST: "2Gi"
KUBERNETES_MEMORY_LIMIT: "4Gi"
KUBERNETES_EPHEMERAL_STORAGE_REQUEST: "512Mi"
KUBERNETES_EPHEMERAL_STORAGE_LIMIT: "1Gi"
KUBERNETES_HELPER_CPU_REQUEST: "3"
KUBERNETES_HELPER_CPU_LIMIT: "5"
KUBERNETES_HELPER_MEMORY_REQUEST: "2Gi"
KUBERNETES_HELPER_MEMORY_LIMIT: "4Gi"
KUBERNETES_HELPER_EPHEMERAL_STORAGE_REQUEST: "512Mi"
KUBERNETES_HELPER_EPHEMERAL_STORAGE_LIMIT: "1Gi"
KUBERNETES_SERVICE_CPU_REQUEST: "3"
KUBERNETES_SERVICE_CPU_LIMIT: "5"
KUBERNETES_SERVICE_MEMORY_REQUEST: "2Gi"
KUBERNETES_SERVICE_MEMORY_LIMIT: "4Gi"
KUBERNETES_SERVICE_EPHEMERAL_STORAGE_REQUEST: "512Mi"
KUBERNETES_SERVICE_EPHEMERAL_STORAGE_LIMIT: "1Gi"
配置示例
以下是 Kubernetes 执行器的 config.toml
文件的示例配置。
concurrent = 4
[[runners]]
name = "myRunner"
url = "https://gitlab.com/ci"
token = "......"
executor = "kubernetes"
[runners.kubernetes]
host = "https://45.67.34.123:4892"
cert_file = "/etc/ssl/kubernetes/api.crt"
key_file = "/etc/ssl/kubernetes/api.key"
ca_file = "/etc/ssl/kubernetes/ca.crt"
namespace = "gitlab"
namespace_overwrite_allowed = "ci-.*"
bearer_token_overwrite_allowed = true
privileged = true
cpu_limit = "1"
memory_limit = "1Gi"
service_cpu_limit = "1"
service_memory_limit = "1Gi"
helper_cpu_limit = "500m"
helper_memory_limit = "100Mi"
poll_interval = 5
poll_timeout = 3600
dns_policy = "cluster-first"
[runners.kubernetes.node_selector]
gitlab = "true"
[runners.kubernetes.node_tolerations]
"node-role.kubernetes.io/master" = "NoSchedule"
"custom.toleration=value" = "NoSchedule"
"empty.value=" = "PreferNoSchedule"
"onlyKey" = ""
准备步骤的资源检查
- 引入于极狐GitLab 15.0。
- 更新于极狐GitLab 15.2。
先决条件:
- 设置
image_pull_secrets
或service_account
。 - 将
resource_availability_check_max_attempts
设置为大于零的数字。 - Kubernetes
serviceAccount
与get
和list
权限一起使用。
极狐GitLab Runner 每 5 秒钟检查一次新的服务账户或密钥是否可用。
- 在 15.0 和 15.1 中,您无法禁用此功能,当设置负值时它默认为
5
。 - 在 15.0.1、15.1.1、15.2 及更高版本中,此功能默认处于禁用状态。要启用此功能,请将
resource_availability_check_max_attempts
设置为0
以外的任何值。 您设置的值定义 Runner 检查服务帐户或 secret 的次数。
通过 Kubernetes 执行器使用缓存
当缓存与 Kubernetes 执行器一起使用时,一个名为 /cache
的卷会挂载在 Pod 上。在作业执行期间,如果需要缓存数据,Runner 会检查缓存数据是否可用。如果压缩文件在缓存卷上可用,则缓存数据可用。
要设置缓存卷,请使用 config.toml
文件中的 cache_dir
设置。
- 如果可用,压缩文件会被提取到构建文件夹,并且可以用在作业中。
- 如果不可用,从配置存储下载缓存数据并作为压缩文件保存到
cache dir
中。 然后压缩文件被提取到build
文件夹中。
配置卷类型
您可以挂载以下类型的卷:
hostPath
persistentVolumeClaim
configMap
secret
emptyDir
csi
具有多种卷类型的配置示例:
concurrent = 4
[[runners]]
# usual configuration
executor = "kubernetes"
[runners.kubernetes]
[[runners.kubernetes.volumes.host_path]]
name = "hostpath-1"
mount_path = "/path/to/mount/point"
read_only = true
host_path = "/path/on/host"
[[runners.kubernetes.volumes.host_path]]
name = "hostpath-2"
mount_path = "/path/to/mount/point_2"
read_only = true
[[runners.kubernetes.volumes.pvc]]
name = "pvc-1"
mount_path = "/path/to/mount/point1"
[[runners.kubernetes.volumes.config_map]]
name = "config-map-1"
mount_path = "/path/to/directory"
[runners.kubernetes.volumes.config_map.items]
"key_1" = "relative/path/to/key_1_file"
"key_2" = "key_2"
[[runners.kubernetes.volumes.secret]]
name = "secrets"
mount_path = "/path/to/directory1"
read_only = true
[runners.kubernetes.volumes.secret.items]
"secret_1" = "relative/path/to/secret_1_file"
[[runners.kubernetes.volumes.empty_dir]]
name = "empty-dir"
mount_path = "/path/to/empty_dir"
medium = "Memory"
[[runners.kubernetes.volumes.csi]]
name = "csi-volume"
mount_path = "/path/to/csi/volume"
driver = "my-csi-driver"
[runners.kubernetes.volumes.csi.volume_attributes]
size = "2Gi"
hostPath
卷
配置 hostPath
卷以指导 Kubernetes 在容器中挂载指定的主机路径。
在 config.toml
文件中使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 卷的名称。 |
mount_path
| 字符串 | 是 | 卷应该挂载的容器内部的路径。 |
sub_path
| 字符串 | 否 | 在卷而不是根的内部挂载子路径。 |
host_path
| 字符串 | 否 | 挂载为卷的主机路径。如果未指定,则将其设置为与 mount_path 相同的路径。
|
read_only
| 布尔 | 否 | 以只读模式设置卷(默认为 False)。 |
persistentVolumeClaim
卷
配置 persistentVolumeClaim
卷以指导 Kubernetes 使用 Kubernetes 集群中定义的 persistentVolumeClaim
并将其挂载到容器中。
在 config.toml
文件中使用以下选项::
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 卷的名称,同时也是应该使用的 PersistentVolumeClaim 的名称。 |
mount_path
| 字符串 | 是 | 挂载卷的容器内部的路径。 |
read_only
| 布尔 | 否 | 将卷设置为只读模式(默认为 False。 |
sub_path
| 字符串 | 否 | 在卷而不是根内部挂载子路径。 |
configMap
卷
配置 configMap
卷以指导 Kubernetes 使用 Kubernetes 集群中定义的 configMap
并将其挂载到容器中。
在 config.toml
中使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 卷的名称,同时也是应该使用的configMap的名称。 |
mount_path
| 字符串 | 是 | 挂载卷的容器内部的路径。 |
read_only
| 布尔 | 否 | 以只读模式设置卷(默认为 False)。 |
sub_path
| 字符串 | 否 | 在卷而不是根内部挂载子路径。 |
items
| map[string]string
| 否 | 从应该使用的 configMap 进行密钥 Key-to-Path 映射。 |
configMap
中的每个 key 都被更改为一个文件并存储在挂载路径中。默认情况下:
- 包括所有 key。
-
configMap
key 用作文件名。 - 该值存储在文件内容中。
要更改默认 key 和值存储,请使用 items
选项。如果您使用 items
选项,只有指定的 key会被添加到卷中,所有其他 key 都会被跳过。
secret
卷
配置一个 secret
卷 以指导 Kubernetes 使用 Kubernetes 集群中定义的 secret
并将其挂载到容器中。
在 config.toml
文件中使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 卷的名称,同时也是应该使用的 Secret 的名称。 |
mount_path
| 字符串 | 是 | 应该挂载卷的容器内部的路径。 |
read_only
| 布尔 | 否 | 以只读模式设置卷(默认为 False)。 |
sub_path
| 字符串 | 否 | 在卷而不是根内部挂载子路径。 |
items
| map[string]string
| 否 | 从应该使用的 configMap 进行密钥 Key-to-Path 映射。 |
secret
中的每个 key 都被更改为一个文件并存储在选中的挂载路径中。默认情况下:
- 包括所有 key。
-
configMap
key 用作文件名。 - 该值存储在文件内容中。
要更改默认 key 和值存储,请使用 items
选项。如果您使用 items
选项,只有指定的 key会被添加到卷中,所有其他 key 都会被跳过。
emptyDir
卷
配置一个 emptyDir
卷以指导 Kubernetes 在容器中挂载一个空目录。
在 config.toml
文件中使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 卷的名称。 |
mount_path
| 字符串 | 是 | 应该挂载卷的容器内部的路径。 |
sub_path
| 字符串 | 否 | 在卷而不是根内部挂载子路径。 |
medium
| 字符串 | 否 | “内存”会提供 tmpfs,否则默认为节点磁盘存储(默认为 ““)。 |
csi
卷
配置容器存储接口 (csi
) 卷以指导 Kubernetes 使用自定义的 csi
驱动程序挂载容器中的任意存储系统。
在 config.toml
中使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 卷的名称。 |
mount_path
| 字符串 | 是 | 应该挂载卷的容器内部的路径。 |
driver
| 字符串 | 是 | 指定使用的卷驱动名称的字符串值。 |
fs_type
| 字符串 | 否 | 指定文件系统类型名称的字符串值(例如,”ext4”、”xfs”、”ntfs”)。 |
volume_attributes
| map[string]string
| 否 | CSI 卷的属性的键值对映射 |
sub_path
| 字符串 | 否 | 在卷而不是根内部挂载子路径。 |
read_only
| 布尔 | 否 | 以只读模式设置卷(默认为 False)。 |
在服务容器上挂载卷
为构建容器定义的卷同样也为所有服务容器进行自动挂载。您可以使用此功能作为 services_tmpfs
(仅适用于 Docker 执行器)的替代方法,在 RAM 中挂载数据库存储以加速测试。
以下是 config.toml
文件中的配置示例:
[[runners]]
# usual configuration
executor = "kubernetes"
[runners.kubernetes]
[[runners.kubernetes.volumes.empty_dir]]
name = "mysql-tmpfs"
mount_path = "/var/lib/mysql"
medium = "Memory"
自定义卷挂载
引入于极狐 GitLab Runner 13.12。
为了为作业存储构建目录,向配置的 builds_dir
(默认为 /builds
)定义自定义卷挂载。
如果您使用 PVC卷,基于访问模式,您可能仅限于在一个节点上运行作业。
以下是 config.toml
文件中的配置示例:
concurrent = 4
[[runners]]
# usual configuration
executor = "kubernetes"
builds_dir = "/builds"
[runners.kubernetes]
[[runners.kubernetes.volumes.empty_dir]]
name = "repo"
mount_path = "/builds"
medium = "Memory"
为 Pod 设置安全策略
在 config.toml
中配置安全上下文,为构建 Pod 设置安全策略。
使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
fs_group
| int
| 否 | 应用到 Pod 中所有容器的特殊补充组。 |
run_as_group
| int
| 否 | 运行容器进程的入口点的 GID。 |
run_as_non_root
| 布尔 | 否 | 表明容器必须以非根用户的身份运行。 |
run_as_user
| int
| 否 | 运行容器进程的入口点的 UID。 |
supplemental_groups
|
int 列表
| 否 | 应用到每个容器第一个运行的进程和容器的主 GID 的组列表。 |
selinux_type
| string
| 否 | 适用于 Pod 中所有容器的 SELinux 类型标记。 |
以下为 config.toml
中的 Pod 安全上下文示例:
concurrent = %(concurrent)s
check_interval = 30
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
helper_image = "gitlab-registry.example.com/helper:latest"
[runners.kubernetes.pod_security_context]
run_as_non_root = true
run_as_user = 59417
run_as_group = 59417
fs_group = 59417
使用 Helper 镜像
设置安全策略后,Helper 镜像必须符合该策略。 该镜像不会从根群组中获得权限,因此您必须确保用户 ID 是根群组的一部分。
nonroot
环境,您可以使用极狐GitLab Runner UBI
和极狐GitLab Runner Helper UBI
OpenShift (OCP) 镜像,而不是 Helper 镜像。以下示例创建一个名为 nonroot
的用户和群组,并将 Helper 镜像设置为以该用户身份运行。
ARG tag
FROM registry.gitlab.com/gitlab-org/ci-cd/gitlab-runner-ubi-images/gitlab-runner-helper-ocp:${tag}
USER root
RUN groupadd -g 59417 nonroot && \
useradd -u 59417 nonroot -g nonroot
WORKDIR /home/nonroot
USER 59417:59417
为容器设置安全策略
引入于极狐GitLab Runner 14.5。
在 config.toml
执行器中配置容器安全上下文,为构建、Helper 或服务 Pod 设置容器安全策略。
使用以下选项:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
run_as_group
| 整数 | 否 | 运行容器进程的入口点的 GID。 |
run_as_non_root
| 布尔 | 否 | 表明容器必须以非根用户的身份运行。 |
run_as_user
| 整数 | 否 | 运行容器进程的入口点的 UID。 |
capabilities.add
| 字符串列表 | 否 | 运行容器时的添加能力。 |
capabilities.drop
| 字符串列表 | 否 | 运行容器时的丢弃能力。 |
selinux_type
| 字符串 | 否 | 与容器进程关联的 SELinux 类型标记。 |
在 config.toml
中的以下示例中,安全上下文配置:
- 设置 Pod 安全上下文。
- 为构建和 Helper 容器覆盖
run_as_user
和run_as_group
。 - 指定所有服务容器从 Pod 安全上下文继承
run_as_user
和run_as_group
。
concurrent = 4
check_interval = 30
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
helper_image = "gitlab-registry.example.com/helper:latest"
[runners.kubernetes.pod_security_context]
run_as_non_root = true
run_as_user = 59417
run_as_group = 59417
fs_group = 59417
[runners.kubernetes.build_container_security_context]
run_as_user = 65534
run_as_group = 65534
[runners.kubernetes.build_container_security_context.capabilities]
add = ["NET_ADMIN"]
[runners.kubernetes.helper_container_security_context]
run_as_user = 1000
run_as_group = 1000
[runners.kubernetes.service_container_security_context]
run_as_user = 1000
run_as_group = 1000
定义服务列表
引入于极狐GitLab Runner 12.5。
引入于极狐GitLab Runner 12.9。
引入于极狐GitLab Runner 13.6。
在 config.toml
中定义服务列表。
concurrent = 1
check_interval = 30
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
helper_image = "gitlab-registy.example.com/helper:latest"
[[runners.kubernetes.services]]
name = "postgres:12-alpine"
alias = "db1"
[[runners.kubernetes.services]]
name = "registry.example.com/svc1"
alias = "svc1"
entrypoint = ["entrypoint.sh"]
command = ["executable","param1","param2"]
设置拉取策略
支持多个引入于极狐GitLab 13.11 的拉取策略。
使用 config.toml
文件中的 pull_policy
参数来指定单个或多个拉取策略。
该策略控制镜像的获取和更新方式,并应用于构建镜像、Helper 镜像和任何服务。
要确定使用的策略,请参阅有关拉取策略的 Kubernetes 文档。
对于单个拉取策略:
[runners.kubernetes]
pull_policy = "never"
对于多个拉取策略:
[runners.kubernetes]
# use multiple pull policies
pull_policy = ["always", "if-not-present"]
当您定义多个策略时,每个策略都会使用,直到成功获取镜像。
例如,当您使用 [ always, if-not-present ]
时,如果 always
策略因临时注册表问题而失败,则使用 if-not-present
策略。
重试失败的拉取:
[runners.kubernetes]
pull_policy = ["always", "always"]
极狐GitLab 和 Kubernetes 在命名规范方面不同。
Runner 拉取策略 | Kubernetes 拉取策略 | 描述 |
---|---|---|
空 | 空 | 使用 Kubernetes 指定的默认策略。 |
if-not-present
| IfNotPresent
| 只有在执行作业的节点上不存在时才能拉取镜像。详情请参见安全考虑。 |
always
| Always
| 每次执行作业时都拉取镜像。 |
never
| Never
| 永不拉取镜像,并且要求节点已经拥有镜像。 |
指定执行构建的节点
使用 node_selector
选项指定要在 Kubernetes 集群中的哪个节点上执行构建。
它是一个 key=value
对的表,格式为 string=string
(在环境变量的情况下为 string=string
)。
Runner 使用提供的信息来确定构建的操作系统和体系结构。这确保使用了正确的 Helper 镜像。
默认情况下,操作系统和体系结构假定为 linux/amd64
。
您可以使用特定的标签来调度具有不同操作系统和架构的节点。
linux/arm64
示例
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes.node_selector]
"kubernetes.io/arch" = "arm64"
"kubernetes.io/os" = "linux"
windows/amd64
示例
Windows Kubernetes 拥有特定限制,所以如果使用了进程隔离,您必须使用 node.kubernetes.io/windows-build
标记提供特定 Windows 构建版本。
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
# The FF_USE_POWERSHELL_PATH_RESOLVER feature flag has to be enabled for PowerShell
# to resolve paths for Windows correctly when Runner is operating in a Linux environment
# but targeting Windows nodes.
environment = ["FF_USE_POWERSHELL_PATH_RESOLVER=1"]
[runners.kubernetes.node_selector]
"kubernetes.io/arch" = "amd64"
"kubernetes.io/os" = "windows"
"node.kubernetes.io/windows-build" = "10.0.19041"
定义节点亲和列表
节点亲和
引入于极狐GitLab Runner 13.4。
定义在构建时间添加到 Pod 规格的节点亲和列表。
以下是 config.toml
中的配置示例:
concurrent = 1
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
[runners.kubernetes.affinity]
[runners.kubernetes.affinity.node_affinity]
[[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution]]
weight = 100
[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference]
[[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_expressions]]
key = "cpu_speed"
operator = "In"
values = ["fast"]
[[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_expressions]]
key = "mem_speed"
operator = "In"
values = ["fast"]
[[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution]]
weight = 50
[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference]
[[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_expressions]]
key = "core_count"
operator = "In"
values = ["high", "32"]
[[runners.kubernetes.affinity.node_affinity.preferred_during_scheduling_ignored_during_execution.preference.match_fields]]
key = "cpu_type"
operator = "In"
values = ["arm64"]
[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution]
[[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution.node_selector_terms]]
[[runners.kubernetes.affinity.node_affinity.required_during_scheduling_ignored_during_execution.node_selector_terms.match_expressions]]
key = "kubernetes.io/e2e-az-name"
operator = "In"
values = [
"e2e-az1",
"e2e-az2"
]
定义计划 Pod 的节点
引入于极狐GitLab Runner 14.3。
使用 Pod 亲和与反亲和来约束基于其他 Pod 上的标记,您的 Pod 可以在上面计划的节点。
config.toml
中的示例配置:
concurrent = 1
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
[runners.kubernetes.affinity]
[runners.kubernetes.affinity.pod_affinity]
[[runners.kubernetes.affinity.pod_affinity.required_during_scheduling_ignored_during_execution]]
topology_key = "failure-domain.beta.kubernetes.io/zone"
namespaces = ["namespace_1", "namespace_2"]
[runners.kubernetes.affinity.pod_affinity.required_during_scheduling_ignored_during_execution.label_selector]
[[runners.kubernetes.affinity.pod_affinity.required_during_scheduling_ignored_during_execution.label_selector.match_expressions]]
key = "security"
operator = "In"
values = ["S1"]
[[runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution]]
weight = 100
[runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term]
topology_key = "failure-domain.beta.kubernetes.io/zone"
[runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector]
[[runners.kubernetes.affinity.pod_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector.match_expressions]]
key = "security_2"
operator = "In"
values = ["S2"]
[runners.kubernetes.affinity.pod_anti_affinity]
[[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution]]
topology_key = "failure-domain.beta.kubernetes.io/zone"
namespaces = ["namespace_1", "namespace_2"]
[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.label_selector]
[[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.label_selector.match_expressions]]
key = "security"
operator = "In"
values = ["S1"]
[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.namespace_selector]
[[runners.kubernetes.affinity.pod_anti_affinity.required_during_scheduling_ignored_during_execution.namespace_selector.match_expressions]]
key = "security"
operator = "In"
values = ["S1"]
[[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution]]
weight = 100
[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term]
topology_key = "failure-domain.beta.kubernetes.io/zone"
[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector]
[[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.label_selector.match_expressions]]
key = "security_2"
operator = "In"
values = ["S2"]
[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.namespace_selector]
[[runners.kubernetes.affinity.pod_anti_affinity.preferred_during_scheduling_ignored_during_execution.pod_affinity_term.namespace_selector.match_expressions]]
key = "security_2"
operator = "In"
values = ["S2"]
添加额外的主机别名
引入于极狐GitLab Runner 13.7。
此功能可用于 Kubernetes 1.7 及更高版本。
配置主机别名以指导 Kubernetes 在容器中向 /etc/hosts
文件添加条目。
使用以下选项:
选项 | 类型 | 是否必需 | 描述 |
---|---|---|---|
IP
| string | Yes | 您想将主机添加到的 IP 地址 |
Hostnames
|
string list
| Yes | 将要添加到 IP 到主机别名列表 |
config.toml
文件中的配置示例:
concurrent = 4
[[runners]]
# usual configuration
executor = "kubernetes"
[runners.kubernetes]
[[runners.kubernetes.host_aliases]]
ip = "127.0.0.1"
hostnames = ["web1", "web2"]
[[runners.kubernetes.host_aliases]]
ip = "192.168.1.1"
hostnames = ["web14", "web15"]
配置容器生命周期钩子
引入于极狐GitLab Runner 14.2。
当执行对应的生命周期钩子时,使用容器生命周期钩子运行为处理器所配置的代码。
您可以配置两种钩子:PreStop
和 PostStart
。每个都只允许设置一种处理器。
以下 config.toml
文件中到配置示例:
[[runners]]
name = "kubernetes"
url = "https://gitlab.example.com/"
executor = "kubernetes"
token = "yrnZW46BrtBFqM7xDzE7dddd"
[runners.kubernetes]
image = "alpine:3.11"
privileged = true
namespace = "default"
[runners.kubernetes.container_lifecycle.post_start.exec]
command = ["touch", "/builds/postStart.txt"]
[runners.kubernetes.container_lifecycle.pre_stop.http_get]
port = 8080
host = "localhost"
path = "/test"
[[runners.kubernetes.container_lifecycle.pre_stop.http_get.http_headers]]
name = "header_name_1"
value = "header_value_1"
[[runners.kubernetes.container_lifecycle.pre_stop.http_get.http_headers]]
name = "header_name_2"
value = "header_value_2"
通过以下设置配置每个生命周期钩子:
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
exec
| KubernetesLifecycleExecAction
| 否 |
Exec 指定采取的措施。
|
http_get
| KubernetesLifecycleHTTPGet
| 否 |
HTTPGet 指定执行的 HTTP 请求。
|
tcp_socket
| KubernetesLifecycleTcpSocket
| 否 |
TCPsocket 指定有关 TCP 端口的行动。
|
KubernetesLifecycleExecAction
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
command
|
string list
| 是 | 容器内执行的命令行。 |
KubernetesLifecycleHTTPGet
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
port
| int
| 是 | 容器上访问的端口数量。 |
host
| 字符串 | 否 | 连接的主机名称,默认为 Pod IP(可选)。 |
path
| 字符串 | 否 | HTTP 服务器上访问的路径(可选)。 |
scheme
| 字符串 | 否 | 连接主机的 Scheme,默认为 HTTP(可选)。 |
http_headers
|
KubernetesLifecycleHTTPGetHeader 列表
| 否 | 请求中设置的自定义 Header(可选)。 |
KubernetesLifecycleHTTPGetHeader
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | HTTP Header 名称。 |
value
| 字符串 | 是 | HTTP Header 值。 |
KubernetesLifecycleTcpSocket
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
port
| int
| 是 | 容器上访问的端口数量。 |
host
| 字符串 | 否 | 连接的主机名称,默认为 Pod IP(可选)。 |
配置 Pod DNS 设置
引入于极狐GitLab Runner 13.7。
使用以下选项配置 Pod 的 DNS 设置。
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
nameservers
|
string 列表
| 否 | 将用作 Pod 的 DNS 服务器的 IP 地址列表 |
options
| KubernetesDNSConfigOption
| 否 | 一个可选的对象列表,其中每个对象可能有一个名称参数(必需)和一个值参数(可选) |
searches
|
string 列表
| 否 | 用于在 Pod 中查找主机名的 DNS 搜索域列表 |
config.toml
文件中的配置示例:
concurrent = 1
check_interval = 30
[[runners]]
name = "myRunner"
url = "https://gitlab.example.com"
token = "__REDACTED__"
executor = "kubernetes"
[runners.kubernetes]
image = "alpine:latest"
[runners.kubernetes.dns_config]
nameservers = [
"1.2.3.4",
]
searches = [
"ns1.svc.cluster-domain.example",
"my.dns.search.suffix",
]
[[runners.kubernetes.dns_config.options]]
name = "ndots"
value = "2"
[[runners.kubernetes.dns_config.options]]
name = "edns0"
KubernetesDNSConfigOption
选项 | 类型 | 必须 | 描述 |
---|---|---|---|
name
| 字符串 | 是 | 配置选项名称。 |
value
| *string
| 否 | 配置选项值。 |
指定容器能力
您可以指定在容器中使用的 Kubernetes 能力。
要指定容器能力,请使用 config.toml
中的 cap_add
和 cap_drop
选项。容器运行时也可以定义默认能力列表,如 Docker
或 容器中的那些能力。
这是 Runner 默认丢弃的能力列表。
您在 cap_add
选项中列出的功能不会被丢弃。
config.toml
文件中的配置示例:
concurrent = 1
check_interval = 30
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
# ...
cap_add = ["SYS_TIME", "IPC_LOCK"]
cap_drop = ["SYS_ADMIN"]
# ...
当您指定能力:
-
用户定义的
cap_drop
优先于用户定义的cap_add
。如果您在两个设置中定义相同的能力,则只有来自cap_drop
的能力会传递给容器。 -
从传递给容器配置的能力标识符中删除
CAP_
前缀。 例如,如果要添加或删除CAP_SYS_TIME
功能,请在配置文件中输入字符串SYS_TIME
。 -
Kubernetes 集群的所有者可以定义一个 PodSecurityPolicy,其中默认允许、限制或添加特定能力。这些规则优先于任何用户定义的配置。
默认丢弃能力列表
极狐GitLab Runner 默认丢弃以下能力。
用户定义的 cap_add
优先于默认的已丢弃的能力列表。
如果要添加默认丢弃的功能,请将其添加到 cap_add
。
NET_RAW
设置 RuntimeClass
引入于极狐GitLab Runner 14.9。
使用 runtime_class_name
为每个作业容器设置RuntimeClass。
如果您指定一个 RuntimeClass 名称,并且它未在您的集群中进行配置或者不支持这个功能,执行器会创建作业失败。
concurrent = 1
check_interval = 30
[[runners]]
name = "myRunner"
url = "gitlab.example.com"
executor = "kubernetes"
[runners.kubernetes]
runtime_class_name = "myclass"
在构建中使用 Docker
在构建中使用 Docker 时,您应该注意以下事项。
暴露的 /var/run/docker.sock
如果您使用 runners.kubernetes.volumes.host_path
选项将主机的 /var/run/docker.sock
暴露到您的构建容器中,则存在一定的风险。
可以从构建容器访问节点的容器,并且取决于您是否在与生产容器相同的集群中运行构建,这样做可能并不明智。
使用 docker:dind
如果运行 docker:dind
,也称为 docker-in-docker
镜像,容器必须以特权模式运行。这可能有潜在的风险并导致其他问题。
Docker Daemon 在 Pod 中作为单独的容器运行,因为它以 service
的形式启动,通常在 .gitlab-ci.yml
中。Pod 中的容器仅共享分配给它们的卷和 IP 地址,它们使用 localhost
相互通信。docker:dind
容器不共享 /var/run/docker.sock
并且 docker
二进制文件尝试对其进行默认使用。
要配置客户端使用 TCP 联系 Docker Daemon,在另一个容器中包括构建容器的以下环境变量:
- 非 TLS 连接:
DOCKER_HOST=tcp://<hostname>:2375
- TLS 连接:
DOCKER_HOST=tcp://<hostname>:2376
对于 hostname
,将值设置为:
- 极狐GitLab Runner 12.7 及更早版本,以及 Kubernetes 1.6 及更早版本:
localhost
- 极狐GitLab Runner 12.8 及更高版本和 Kubernetes 1.7 及更高版本:
docker
在 Docker 19.03 及更高版本中,TLS 默认开启,但您必须将证书映射到您的客户端。 您可以为 DIND 或安装证书启用非 TLS 连接。有关详细信息,请参阅在带有 Docker 执行器的 Docker 工作流中使用 Docker。
防止主机内核暴露
如果您使用 docker:dind
或 /var/run/docker.sock
,Docker Daemon 可以访问主机的底层内核。这意味着在构建 Docker 镜像时,在 Pod 中设置的任何 limits
都不起作用。
Docker Daemon 报告节点的全部容量,而不管 Kubernetes 生成的 Docker 构建容器上的限制。
如果您以特权模式运行构建容器,或者暴露了 /var/run/docker.sock
,则主机内核可能会暴露给构建容器。为了尽量减少曝光,请在 node_selector
选项中指定一个标记。这确保在任何容器可以部署到节点之前,节点匹配标记。
例如,如果您指定标记 role=ci
,构建容器仅在标记为 role=ci
的节点上运行,所有其他生产服务在其他节点上运行。
要进一步分离构建容器,您可以使用 taints 节点。 Taints 可防止其他 Pod 调度到与构建 Pod 相同的节点上,而无需为其他 Pod 进行额外配置。
使用 kaniko 构建 Docker 镜像
您可以使用 kaniko 在 Kubernetes 集群中构建 Docker 镜像。
Kaniko 在没有 Docker Daemon 的情况下工作,并且在没有特权访问的情况下构建镜像。
有关详细信息,请参阅使用 kaniko 和极狐GitLab CI/CD 构建镜像。
限制 Docker 镜像和服务
为 Kubernetes 执行器添加于极狐GitLab Runner 14.2。
您可以限制运行作业的 Docker 镜像。为此,您需要指定通配符类型。例如,为了仅允许您的私有 Docker 镜像库中的镜像:
[[runners]]
(...)
executor = "kubernetes"
[runners.kubernetes]
(...)
allowed_images = ["my.registry.tld:5000/*:*"]
allowed_services = ["my.registry.tld:5000/*:*"]
或者限定为镜像库中的特定镜像列表:
[[runners]]
(...)
executor = "kubernetes"
[runners.kubernetes]
(...)
allowed_images = ["my.registry.tld:5000/ruby:*", "my.registry.tld:5000/node:*"]
allowed_services = ["postgres:9.4", "postgres:latest"]
限制 Docker 拉取策略
引入于极狐GitLab 15.1。
在 .gitlab-ci.yml
文件中,您可以指定拉取策略。该策略决定 CI/CD 作业应该如何获取镜像。
要限制可以在 .gitlab-ci.yml
文件中使用的拉取策略,可以使用 allowed_pull_policies
。
例如,只允许 always
和 if-not-present
拉取策略:
[[runners]]
(...)
executor = "kubernetes"
[runners.kubernetes]
(...)
allowed_pull_policies = ["always", "if-not-present"]
- 如果未指定
allowed_pull_policies
,则默认为pull_policy
关键字中的值。 - 如果未指定
pull_policy
,则使用集群的镜像默认拉取策略。 - 现有的
pull_policy
关键字 不得包含未在allowed_pull_policies
中指定的拉取策略。如果包含,则作业将会返回错误。
作业执行
- 引入于极狐GitLab Runner 12.9。
- 在
FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY
功能标志后,默认启用。
极狐GitLab Runner 默认使用 kube attach
而不是 kube exec
。这会避免作业因网络不稳定而导致的中途被标记为成功的问题。
如果您在升级到极狐GitLab Runner 14.0 后遇到问题,将 FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY
功能标志设置为 true
。
容器入口点已知问题
- 引入于极狐GitLab Runner 14.5。
- 更新于极狐GitLab Runner 15.1。
kube attach
的 Kubernetes 执行器一起使用时,使用 Docker 镜像中定义的入口点。
在 15.1 及更高版本中,当设置了 FF_KUBERNETES_HONOR_ENTRYPOINT
时,Docker 镜像中定义的入口点将与 Kubernetes 执行器一起使用。容器入口点存在以下已知问题:
- 如果在 Dockerfile 中为镜像定义了入口点,则它必须打开一个有效的 Shell。否则,作业会挂起。
- 执行入口点时,文件类型 CI/CD 变量尚未写入磁盘。该文件只能在脚本执行期间在作业中访问。
- 以下 CI/CD 变量在入口点中不可访问。您可以使用
before_script
在运行脚本命令之前进行设置更改:
移除旧的 Runner Pod
引入于极狐GitLab Runner 14.6。
有时,在 Runner Manager 不正确关闭时,会出现旧的 Runner Pod 没有被清理的情况。
为解决这个问题,您可以使用极狐GitLab Runner Pod Cleanup 应用调度旧的 Pod 清理。详情请参见:
- 极狐GitLab Runner Pod 清理项目自述文件。
- 极狐GitLab Runner Pod 清理文档。
故障排除
以下是使用 Kubernetes 执行器时经常遇到的错误。
Job failed (system failure): timed out waiting for pod to start
如果集群无法在 poll_timeout
定义的超时时间到达之前调度构建 Pod,构建 Pod 就会返回错误。Kubernetes 调度器 应该能够删除它。
为解决这个问题,在您的 config.toml
文件夹中增加 poll_timeout
的值。
context deadline exceeded
作业日志中的 context deadline exceeded
错误通常表明 Kubernetes API 客户端达到了给定的集群 API 请求的超时时间。
检查 kube-apiserver
集群组件的指标,寻找以下内容的标志:
- 增加的响应时延。
- 对 Pod、密钥、ConfigMaps 和其他核心(v1)资源进行正常创建或删除操作时的错误率。
来自 kube-apiserver
操作的超时时间驱动的错误日志可能会显示为:
Job failed (system failure): prepare environment: context deadline exceeded
Job failed (system failure): prepare environment: setting up build pod: context deadline exceeded
在某些情况下,kube-apiserver
错误响应或许会提供子组件失败(例如 Kubernetes 集群的 etcdserver
)的额外信息:
Job failed (system failure): prepare environment: etcdserver: request timed out
Job failed (system failure): prepare environment: etcdserver: leader changed
Job failed (system failure): prepare environment: Internal error occurred: resource quota evaluates timeout
在创建构建 Pod 和完成后进行清理时可能会发生 kube-apiserver
服务失败的情况:
Error cleaning up secrets: etcdserver: request timed out
Error cleaning up secrets: etcdserver: leader changed
Error cleaning up pod: etcdserver: request timed out, possibly due to previous leader failure
Error cleaning up pod: etcdserver: request timed out
Error cleaning up pod: context deadline exceeded
使用 Kubernetes API 试图通信时拒绝连接
当极狐GitLab Runner 向 Kubernetes API 发送请求并失败时,很可能因为
kube-apiserver
已经超载且不能接受或处理 API 请求。
Error cleaning up pod
和 Job failed (system failure): prepare environment: waiting for pod running
当 Kubernetes 未能及时调度作业 Pod 时会发生以下错误。 极狐GitLab Runner 等待 Pod 准备好,但是失败了,又试图清理 Pod,也可能会失败。
Error: Error cleaning up pod: Delete "https://xx.xx.xx.x:443/api/v1/namespaces/gitlab-runner/runner-0001": dial tcp xx.xx.xx.x:443 connect: connection refused
Error: Job failed (system failure): prepare environment: waiting for pod running: Get "https://xx.xx.xx.x:443/api/v1/namespaces/gitlab-runner/runner-0001": dial tcp xx.xx.xx.x:443 connect: connection refused
为解决这个问题,检查 Kubernetes 主要节点和运行
kube-apiserver
实例的所有节点。确保他们拥有管理目标数量的您希望在集群上增加的 Pod 所需的所有资源。
如果您想更改极狐GitLab Runner 等待 Pod 达到 Ready
状态的时间,请使用
poll_timeout
设置。
为了更好地了解如何调度 Pod 或者他们没有被及时调度的原因,请阅读 Kubernetes 调度器。
request did not complete within requested timeout
构建 Pod 创建过程中的 request did not complete within requested timeout
消息表明 Kubernetes 集群上配置的准入控制网络钩子超时了。
准入控制网络钩子是所有 API 请求的集群级别的管理控制拦截,如果没有及时执行会失败。
准入控制网络钩子支持可以精准控制其拦截的 API 请求和命名空间源的过滤器。如果极狐GitLab Runner 的 Kubernetes API 调用不需要通过准入控制网络钩子进行传递,那么您可以更改网络钩子的选择器/过滤配置,忽略极狐GitLab Runner 命名空间,或者通过配置极狐GitLab Runner Helm Chart values.yaml
中的 podAnnotations
或 podLabels
,将排除标记/标注应用到极狐GitLab Runner Pod。
例如,为了避免数据狗准入控制器网络钩子拦截极狐GitLab Runner Manager Pod 的 API 请求,可以添加以下内容:
podLabels:
admission.datadoghq.com/enabled: false
如果您想列出 Kubernetes 集群的准入控制网络钩子,请运行:
kubectl get validatingwebhookconfiguration -o yaml
kubectl get mutatingwebhookconfiguration -o yaml
如果准入控制网络钩子超时,可以查看到以下格式的日志:
Job failed (system failure): prepare environment: Timeout: request did not complete within requested timeout
Job failed (system failure): prepare environment: setting up credentials: Timeout: request did not complete within requested timeout
准入控制网络钩子失败可能会显示为:
Job failed (system failure): prepare environment: setting up credentials: Internal error occurred: failed calling webhook "example.webhook.service"
fatal: unable to access 'https://gitlab-ci-token:token@example.com/repo/proj.git/': Could not resolve host: example.com
如果使用 Helper 镜像的 alpine
类型,
可能会引发有关 Alpine 的 musl
的 DNS 解析器的 DNS 问题。
使用 helper_image_flavor = "ubuntu"
选项应该能解决这个问题。
docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?
如果使用 Docker-in-Docker,在没有时间完全启动时试图访问 DIND 服务会发生这个错误。
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443
使用 Docker-in-Docker 时,如果 DIND 最大传输单元(MTU)大于 Kubernetes 交叉网络,会发生这个错误。DIND 使用默认的 1500 MTU,这对于路由到默认交叉网络来说过大。可以在服务定义中更改 DIND MTU:
services:
- name: docker:dind
command: ["--mtu=1450"]
MountVolume.SetUp failed for volume "kube-api-access-xxxxx" : chown is not supported by windows
当运行 CI/CD 作业时,您或许会收到类似以下内容的错误:
MountVolume.SetUp failed for volume "kube-api-access-xxxxx" : chown c:\var\lib\kubelet\pods\xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\volumes\kubernetes.io~projected\kube-api-access-xxxxx\..2022_07_07_20_52_19.102630072\token: not supported by windows
当您使用节点选择器在具有不同操作系统和架构的节点上运行构建时,会出现此问题。
要解决此问题,请配置 nodeSelector
,以便始终将 Runner Manager Pod 安排在 Linux 节点上。例如,您的 values.yaml
文件 应包含以下内容:
nodeSelector:
kubernetes.io/os: linux
构建 Pod 被分配 Worker 节点的 IAM 角色而不是 Runner IAM 角色
当 Worker 节点 IAM 角色没有承担正确角色的权限时,会发生此问题。要解决此问题,请将 sts:AssumeRole
权限添加到 Worker 节点的 IAM 角色的信任关系中:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AWS_ACCOUNT_NUMBER>:role/<IAM_ROLE_NAME>"
},
"Action": "sts:AssumeRole"
}
Preparation failed: failed to pull image 'image-name:latest': pull_policy ([Always]) defined in GitLab pipeline config is not one of the allowed_pull_policies ([])
如果您在 .gitlab-ci.yml
中指定了 pull_policy
但在 Runner 的配置文件中没有配置任何策略,则会发生此问题。要解决此问题,请根据限制 Docker 拉取策略将 allowed_pull_policies
添加到您的配置中。
后台进程导致作业挂起和超时
在作业执行期间启动的后台进程可以阻止构建作业退出。为避免这种情况,您可以:
- 双分叉进程。例如,
command_to_run < /dev/null &> /dev/null &
。 - 在退出作业脚本之前终止进程。
限制对作业变量的访问
使用 Kubernetes 执行器时,有权访问 Kubernetes 集群的用户可以读取作业中使用的变量。默认情况下,作业变量存储在:
- ConfigMap
- Pod 的环境部分
要限制对作业变量数据的访问,您应该使用基于角色的访问控制 (RBAC),以便只有极狐GitLab 管理员才能访问极狐GitLab Runner 使用的命名空间。
如果您需要其他用户访问极狐GitLab Runner 命名空间,请设置以下 verbs
来限制用户在极狐GitLab Runner 命名空间中的访问类型:
- 对于
pods
和configmaps
:get
watch
list
- 对于
pods/exec
和pods/attach
,使用create
。
授权用户的示例 RBAC 定义:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: gitlab-runner-authorized-users
rules:
- apiGroups: [""]
resources: ["configmaps", "pods"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["pods/exec", "pods/attach"]
verbs: ["create"]