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

  • 代理连接共享限制在极狐GitLab 17.0 中有 100 改为 500。

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

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

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

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

要使用极狐GitLab CI/CD 来和集群交互,您必须要注册极狐GitLab Runner。但是您不需要在具有代理的集群中拥有 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 的项目。 您可以授权代理访问单个项目,或授权一个群组或子组,以便其中的所有项目都具有访问权限。为了增加安全性,您还可以使用模拟

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

授权代理访问您的项目

  • 在极狐GitLab 15.6 中移除了层级限制。
  • 在极狐GitLab 15.7 中,允许在用户命名空间中授权项目。

要授权代理访问您保存 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 命令的上下文。

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

  • 在极狐GitLab 15.6 中移除了层级限制。

要授权代理访问群组或子组中的所有极狐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

使用 Auto DevOps 的环境

如果启用了 Auto DevOps,您必须定义 CI/CD 变量 KUBE_CONTEXT。将 KUBE_CONTEXT 的值设置为您希望 Auto DevOps 使用的代理上下文:

deploy:
  variables:
    KUBE_CONTEXT: path/to/agent/project:agent-name

您可以为单独的 Auto DevOps 作业指派不同的代理。比如,Auto DevOps 可以使用一个代理用于 staging 作业,另一个代理用于 production 作业。要使用多个代理,为每一个代理定义一个环境范围的 CI/CD 变量。比如:

  1. 定义两个名为 KUBE_CONTEXT 的变量。
  2. 对于第一个变量:
    1. 设置 environmentstaging
    2. 将值设置为您的 staging 代理上下文。
  3. 对于第二个变量:
    1. 设置 environmentproduction
    2. 将值设置为您的 production 代理上下文。

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

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

  • 基于证书的集群的上下文称为 gitlab-deploy。默认情况下始终选择此上下文。
  • 代理上下文包含在 KUBECONFIG 中。您可以使用 kubectl config use-context path/to/agent/repository:agent-name 来选择它们。

要在存在基于证书的连接时使用代理连接,您可以手动配置新的 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

具有使用自签名证书的 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 客户端。

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

  • 在极狐GitLab 15.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 官方文档

限制项目和群组访问指定环境

  • 引入于极狐GitLab 15.7。

默认情况下,如果您的代理授权给项目,则项目的所有 CI/CD 作业都可以使用该代理。

要限制代理仅能运行指定环境的作业,您需要在 ci_access.projectsci_access.groups 中添加 environments。比如:

  ci_access:
    projects:
      - id: path/to/project-1
      - id: path/to/project-2
        environments:
          - staging
          - review/*
    groups:
      - id: path/to/group-1
        environments:
          - production

在此示例中:

  • project-1 下的所有作业都可以访问代理。
  • project-2 下的 stagingreview/* 环境作业可以访问代理。
    • * 是通配符,所以 review/* 会匹配 review 环境下的所有环境。
  • group-1 下的 production 环境中的 CI/CD 作业可以访问代理。

限制代理对受保护分支的访问权限

  • 引入于极狐GitLab 17.3,使用名为 kubernetes_agent_protected_branches 的功能标志。默认禁用。
此功能的可用性受控于功能标志。更多详情,可查看历史。此功能仅为测试所用,并未生产就绪。

为了限制代理对于受保护分支的访问权限:

  • 添加 protected_branches_only: trueci_access.projectsci_access.groups。比如:

    ci_access:
      projects:
        - id: path/to/project-1
          protected_branches_only: true
      groups:
        - id: path/to/group-1
          protected_branches_only: true
          environments:
            - production
    

默认情况下,protected_branches_only 设置为 false,可以从非受保护和受保护分支访问代理。

为了安全,您可以将此功能和环境限制结合起来。

如果一个项目有多个配置,仅使用最近指定的配置。比如,如下配置在 example/my-project 中授予了访问未受保护分支的权限,即使 example 组配置了仅允许访问受保护分支:

# .gitlab/agents/my-agent/config.yaml
ci_access:
  project:
    - id: example/my-project # Project of the group below
      protected_branches_only: false # This configuration supercedes the group configuration
      environments:
        - dev
  groups:
    - id: example
      protected_branches_only: true
      environments:
        - dev

相关主题

故障排除

不支持 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