极狐GitLab CI/CD 与 Kubernetes 集群一起使用

  • 引入于 14.1 版本。
  • 预配置的 KUBECONFIG 引入于 14.2 版本。
  • ci_access 属性引入于 14.3 版本。
  • 授权群组的能力引入于 14.3 版本。
  • 移动到基础版于 14.5 版本。
  • 对 Omnibus 安装实例的支持引入于 14.5 版本。
  • 在基于证书的集群和代理之间切换的能力引入于 14.9 版本。基于证书的集群上下文始终称为 gitlab-deploy

您可以使用极狐GitLab CI/CD 工作流安全地部署到和更新您的 Kubernetes 集群。

为此,您必须首先在集群中安装代理。完成后,您将拥有 Kubernetes 上下文,并且可以在极狐GitLab CI/CD 流水线中运行 Kubernetes API 命令。

为确保对集群的访问安全:

  • 每个代理都有一个单独的上下文(kubecontext)。
  • 只有配置了代理的项目,以及您授权的任何其它项目,才能访问集群中的代理。

您不需要在具有代理的集群中拥有 runner。

极狐GitLab CI/CD 工作流步骤

要使用极狐GitLab CI/CD 更新 Kubernetes 集群,请完成以下步骤。

  1. 确保您有一个正常工作的 Kubernetes 集群,并且 manifests 位于极狐GitLab 项目中。
  2. 在同一个极狐GitLab 项目中,注册并安装极狐GitLab 代理
  3. 更新您的 .gitlab-ci.yml 文件,选择代理的 Kubernetes 上下文并运行 Kubernetes API 命令。
  4. 运行您的流水线,部署或更新集群。

如果您有多个包含 Kubernetes manifests 的极狐GitLab 项目:

  1. 在其自己的项目中安装极狐GitLab 代理,或在您保留 Kubernetes manifests 的项目之一中。
  2. 授权代理访问您的极狐GitLab 项目。
  3. 可选。为了增加安全性,使用模拟
  4. 更新您的 .gitlab-ci.yml 文件,选择代理的 Kubernetes 上下文并运行 Kubernetes API 命令。
  5. 运行您的流水线,部署或更新集群。

授权代理

如果您有多个极狐GitLab 项目,您必须授权代理访问您保存 Kubernetes manifests 的项目。 您可以授权代理访问单个项目,或授权一个群组或子组,以便其中的所有项目都具有访问权限。为了增加安全性,您还可以使用模拟

授权配置可能需要一到两分钟才能传播。

授权代理访问您的项目

引入于 14.4 版本。

要授权代理访问您保存 Kubernetes manifests 的极狐GitLab 项目:

  1. 在左侧边栏中,选择 搜索或转到 并找到包含代理配置文件(config.yaml)的项目。
  2. 编辑 config.yaml 文件。 在 ci_access 关键字下,添加 projects 属性。
  3. 对于 id,添加路径:

    ci_access:
      projects:
        - id: path/to/project
    
    • Kubernetes 项目必须与代理配置所在的项目位于同一群组层次结构中。
    • 您可以将其它代理安装到同一集群中,来适应其它层次结构。
    • 您最多可以授权 100 个项目。

现在,所有 CI/CD 作业都包含一个 kubeconfig 文件,其中包含每个共享代理连接的上下文。 kubeconfig 路径在环境变量 $KUBECONFIG 中可用。 从 CI/CD 脚本中选择运行 kubectl 命令的上下文。

授权代理访问您群组中的项目

引入于 14.3 版本。

要授权代理访问群组或子组中的所有极狐GitLab 项目:

  1. 在左侧边栏中,选择 搜索或转到 并找到包含代理配置文件(config.yaml)的项目。
  2. 编辑 config.yaml 文件。在 ci_access 关键字下,添加 groups 属性。
  3. 对于 id,添加路径:

    ci_access:
      groups:
        - id: path/to/group/subgroup
    
    • Kubernetes 项目必须与代理配置所在的项目位于同一群组层次结构中。
    • 您可以将其它代理安装到同一集群中,来适应其它层次结构。
    • 授权群组的所有子组也可以访问同一代理(无需单独指定)。
    • 您最多可以授权 100 个群组。

属于该群组及其子组的所有项目现在都有权访问该代理。 现在,所有 CI/CD 作业都包含一个 kubeconfig 文件,其中包含每个共享代理连接的上下文。 kubeconfig 路径在环境变量 $KUBECONFIG 中可用。 从 CI/CD 脚本中选择运行 kubectl 命令的上下文。

更新 .gitlab-ci.yml 文件以运行 kubectl 命令

在要运行 Kubernetes 命令的项目中,编辑项目的 .gitlab-ci.yml 文件。

script 关键字下的第一个命令中,设置代理的上下文。 使用 path/to/agent/repository:agent-name 格式。例如:

deploy:
  image:
    name: bitnami/kubectl:latest
    entrypoint: ['']
  script:
    - kubectl config get-contexts
    - kubectl config use-context path/to/agent/repository:agent-name
    - kubectl get pods

如果您不确定代理的上下文是什么,请打开一个终端并连接到您的集群。 运行 kubectl config get-contexts

具有基于证书和基于代理的连接的环境

当您部署到同时具有基于证书的集群(已弃用)和代理连接的环境时:

  • 基于证书的集群的上下文称为 gitlab-deploy。默认情况下始终选择此上下文。
  • 在 14.9 及更高版本中,代理上下文包含在 KUBECONFIG 中。您可以使用 kubectl config use-context path/to/agent/repository:agent-name 来选择它们。
  • 在 14.8 及更早版本中,您仍然可以使用代理连接,但对于已经具有基于证书的集群的环境,代理连接不包含在 KUBECONFIG 中。

要在存在基于证书的连接时使用代理连接,您可以手动配置新的 kubectl 配置上下文。例如:

deploy:
  variables:
    KUBE_CONTEXT: my-context # The name to use for the new context
    AGENT_ID: 1234 # replace with your agent's numeric ID
    K8S_PROXY_URL: https://<KAS_DOMAIN>/k8s-proxy/ # For agent server (KAS) deployed in Kubernetes cluster (for gitlab.com use kas.gitlab.com); replace with your URL
    # K8S_PROXY_URL: https://<GITLAB_DOMAIN>/-/kubernetes-agent/k8s-proxy/ # For agent server (KAS) in Omnibus
    # ... any other variables you have configured
  before_script:
    - kubectl config set-credentials agent:$AGENT_ID --token="ci:${AGENT_ID}:${CI_JOB_TOKEN}"
    - kubectl config set-cluster gitlab --server="${K8S_PROXY_URL}"
    - kubectl config set-context "$KUBE_CONTEXT" --cluster=gitlab --user="agent:${AGENT_ID}"
    - kubectl config use-context "$KUBE_CONTEXT"
  # ... rest of your job configuration

将代理与 Auto DevOps 结合使用

如果启用了 Auto DevOps,则必须定义 KUBE_CONTEXT CI/CD 变量。将 KUBE_CONTEXT 的值设置为您要在 Auto DevOps 流水线作业中使用的代理的上下文 (<PATH_TO_AGENT_CONFIG_REPOSITORY>:<AGENT_NAME>)。

您还可以为不同的 Auto DevOps 作业使用不同的代理。例如,您可以将一个代理用于 staging 作业,而将另一个代理用于 production 作业。要使用多个代理,请为每个代理定义一个唯一的 CI/CD 变量。

例如:

  1. 添加两个环境范围的 CI/CD 变量,并将两者命名为 KUBE_CONTEXT
  2. 将第一个变量的 environment 设置为 staging。将变量的值设置为 <PATH_TO_AGENT_CONFIGURATION_PROJECT>:<STAGING_AGENT_NAME>
  3. 将第二个变量的 environment 设置为 production。将变量的值设置为 <PATH_TO_AGENT_CONFIGURATION_PROJECT>:<PRODUCTION_AGENT_NAME>

staging 作业运行时,它将通过名为 <STAGING_AGENT_NAME> 的代理连接到集群,当 production 作业运行时,它将通过名为 <PRODUCTION_AGENT_NAME> 的代理连接到集群。

具有使用自签名证书的 KAS 的环境

如果您使用具有 KAS 和自签名证书的环境,则必须将 Kubernetes 客户端配置为信任为您的证书签名的证书颁发机构 (CA)。

要配置您的客户端,请执行以下操作之一:

  • 使用 PEM 格式的 KAS 证书设置 CI/CD 变量 SSL_CERT_FILE
  • 使用 --certificate-authority=$KAS_CERTIFICATE 配置 Kubernetes 客户端,其中 KAS_CERTIFICATE 是带有 KAS CA 证书的 CI/CD 变量。
  • 通过更新容器镜像或通过 runner 安装,将证书放置在作业容器中的适当位置。
  • (不建议)使用 --insecure-skip-tls-verify=true 配置 Kubernetes 客户端。

使用模拟限制项目和群组访问

引入于 14.5 版本。

默认情况下,您的 CI/CD 作业从用于在集群中安装代理的服务账户继承所有权限。 要限制对集群的访问,您可以使用模拟

要指定模拟,请使用代理配置文件中的 access_as 属性并使用 Kubernetes RBAC 规则来管理模拟账户权限。

您可以模拟:

  • 代理本身(默认)。
  • 访问集群的 CI/CD 作业。
  • 在集群中定义的特定用户或系统账户。

授权配置可能需要一到两分钟才能传播。

模拟代理

默认情况下模拟代理,不需要做任何事情来模拟它。

模拟访问集群的 CI/CD 作业

要模拟访问集群的 CI/CD 作业,请在 access_as 键下,添加 ci_job: {} 键值。

当代理向实际的 Kubernetes API 发出请求时,它会通过以下方式设置模拟凭据:

  • UserName 设置为 gitlab:ci_job:<job id>。示例:gitlab:ci_job:1074499489
  • Groups 设置为:

    • gitlab:ci_job 来识别来自 CI 作业的所有请求。
    • 项目所在群组的 ID 列表。
    • 项目 ID。
    • 作业所属的环境的 slug 和级别。

    示例:对于 group 1/group 1-1/project 1 中的 CI 作业,其中:

    • 群组 group1 的 ID 为 23。
    • 群组 group1/group1-1 ID 为 25。
    • 项目 group1/group1-1/project1 的 ID 为 150。
    • prod 环境中运行的作业,该环境具有 production 环境级别。

    群组列表将是 [gitlab:ci_job, gitlab:group:23, gitlab:group_env_tier:23:production, gitlab:group:25, gitlab:group_env_tier:25:production, gitlab:project:150, gitlab:project_env:150:prod, gitlab:project_env_tier:150:production]

  • Extra 携带有关请求的额外信息。在模拟身份上设置以下属性:
属性 描述
agent.gitlab.com/id 包含代理的 ID。
agent.gitlab.com/config_project_id 包含代理的配置项目 ID。
agent.gitlab.com/project_id 包含 CI 项目 ID。
agent.gitlab.com/ci_pipeline_id 包含 CI 流水线 ID。
agent.gitlab.com/ci_job_id 包含 CI 作业 ID。
agent.gitlab.com/username 包含运行 CI 作业的用户的用户名。
agent.gitlab.com/environment_slug 包含环境的别名。只有在环境中运行时才设置。
agent.gitlab.com/environment_tier 包含环境级别。只有在环境中运行时才设置。

通过 CI/CD 作业的身份限制访问的示例 config.yaml

ci_access:
  projects:
    - id: path/to/project
      access_as:
        ci_job: {}

限制 CI/CD 作业的 RBAC 示例

以下 RoleBinding 资源将所有 CI/CD 作业限制为仅查看权限。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ci-job-view
roleRef:
  name: view
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
subjects:
  - name: gitlab:ci_job
    kind: Group

模拟静态身份

对于给定的连接,您可以使用静态身份进行模拟。

access_as 键下,添加 impersonate 键,使用提供的身份发出请求。

可以使用以下键指定身份:

  • username(必需)
  • uid
  • groups
  • extra

详见 Kubernetes 官方文档

故障排除

不支持 kubectl 命令

不支持命令 kubectl execkubectl cpkubectl attachkubectl run --attach=truekubectl port-forward。 任何使用了这些 API 端点的都不起作用,因为它们使用了已弃用的 SPDY 协议。

授予对 ~/.kube/cache 的写入权限

kubectl、Helm、kptkustomize 等工具会在 ~/.kube/cache 中缓存有关集群的信息。如果此目录不可写,则该工具会在每次调用时获取信息,从而使交互变慢并在集群上产生不必要的负载。为了获得最佳体验,在您在 .gitlab-ci.yml 文件中使用的镜像中,确保该目录是可写的。

启用 TLS

如果您使用的是私有化部署的极狐GitLab 实例,请确保您的实例配置了 TLS。

如果您尝试在没有 TLS 的情况下使用 kubectl,您可能会收到如下错误:

$ kubectl get pods
error: You must be logged in to the server (the server has asked for the client to provide credentials)

无法连接到服务器:由未知授权机构签署的证书

如果您使用带有 KAS 和自签名证书的环境,您的 kubectl 调用可能会返回此错误:

kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority

出现此错误是因为该作业不信任签署 KAS 证书的证书颁发机构 (CA)。

要解决此问题,配置 kubectl 信任 CA

验证错误

如果您使用 kubectl 版本 v1.27.0 或 v.1.27.1,您可能会收到以下错误:

error: error validating "file.yml": error validating data: the server responded with the status code 426 but did not return more information; if you choose to ignore these errors, turn validation off with --validate=false

此问题是由 kubectl 和其他使用共享 Kubernetes 库的工具的 bug 引起的。

要解决此问题,请使用另一个版本的 kubectl