Help us learn about your current experience with the documentation. Take the survey.

Kubernetes 集成开发指南

本文档提供了在为 GitLab Kubernetes 集成 开发时的各种指南。

开发

架构

某些 Kubernetes 操作,例如创建受限的项目命名空间,是在 GitLab Rails 应用程序上执行的。这些操作使用 客户端库 执行,并带有一定的风险。这些操作以运行 GitLab Rails 应用程序的相同用户身份运行。有关更多信息,请阅读下面的 安全 部分。

某些 Kubernetes 操作,例如安装集群应用程序,是在 Kubernetes 集群本身的一次性 Pod 上执行的。这些安装 Pod 命名为 install-<application_name>,并在 gitlab-managed-apps 命名空间内创建。

在代码组织方面,我们通常将在 lib/gitlab/kubernetes 中添加表示 Kubernetes 资源的对象。

客户端库

我们使用 kubeclient gem 来执行 Kubernetes API 调用。由于 kubeclient gem 不支持从单个客户端使用不同的 API 组(如 apis/rbac.authorization.k8s.io),我们创建了一个包装类,Gitlab::Kubernetes::KubeClient,使您能够实现这一点。

支持选定的 Kubernetes API 组。如果您需要使用新的 API 组或方法,请添加对它们的支持到 Gitlab::Kubernetes::KubeClient。新的 API 组或 API 组版本可以添加到 SUPPORTED_API_GROUPS - 在内部,这会为该组创建一个内部客户端。新方法可以作为对相关内部客户端的委托添加。

性能考虑

所有对 Kubernetes API 的调用必须在后台进程中执行。不要在 Web 请求中执行 Kubernetes API 调用。这会阻塞 Web 服务器,并且由于 Kubernetes 集群响应时间不在我们的控制范围内,可能导致 GitLab 遭受拒绝服务(DoS)攻击。

确保您的调用在后台进程中执行的最简单方法是委托任何此类工作在 Sidekiq worker 中执行。

您可能希望调用 Kubernetes 并返回响应,但后台工作者可能不太适合。考虑使用 reactive caching。例如:

  def calculate_reactive_cache!
    { pods: cluster.platform_kubernetes.kubeclient.get_pods }
  end

  def pods
    with_reactive_cache do |data|
      data[:pods]
    end
  end

测试

我们在 KubernetesHelpers 中有一些 WebMock 存根,可以帮助您在测试中模拟对 Kubernetes API 的调用。

Amazon EKS 集成

本节概述了允许 GitLab 实例创建 EKS 集群的过程。

需要满足以下先决条件:

一个 Customer AWS 账户。EKS 集群在此账户中创建。必须存在以下资源:

  • 一个具有创建集群和相关资源权限的预配置角色。它必须将 GitLab AWS 账户列为可信实体。
  • 一个供集群使用的 VPC、管理角色、安全组和子网。

一个 GitLab AWS 账户。这是执行预配置操作的账户。必须存在以下资源:

  • 一个具有权限来假定上述 Customer 账户中预配置角色的服务账户。
  • 通过 gitlab.ymlkubernetes 部分在 GitLab 中配置的此服务账户的凭据。

创建集群的过程如下:

  1. 使用 :provision_role_external_id,GitLab 假定由 :provision_role_arn 提供的角色,并在提供者记录上存储一组临时凭据。默认情况下,这些凭据有效期为 1 小时。

  2. 创建一个 CloudFormation 堆栈,基于 AWS CloudFormation EKS 模板。这将触发创建 EKS 集群所需的所有资源。

  3. GitLab 轮询堆栈状态,直到所有资源准备就绪,在大多数情况下,这需要 10 到 15 分钟。

  4. 当堆栈准备就绪时,GitLab 存储集群详细信息并生成另一组临时凭据,这次允许通过 kubeclient 连接到集群。这些凭据有效期为 1 分钟。

  5. GitLab 配置工作节点,使其能够对集群进行身份验证,并为自己创建一个服务账户以供将来操作。

  6. 删除不再需要的凭据。这将删除以下属性:

    • access_key_id
    • secret_access_key
    • session_token

安全

服务器端请求伪造(SSRF)攻击

由于 Kubernetes 集群的 URL 是用户控制的,因此很容易受到服务器端请求伪造(SSRF)攻击。如果您要向集群添加更多 API 调用,应该了解缓解策略。

缓解策略包括:

  1. 不允许重定向到攻击者控制资源:Kubeclient::KubeClient 可以通过传入 http_max_redirects: 0 作为选项来配置以防止任何重定向。

  2. 不暴露错误消息:通过这样做,我们防止攻击者触发错误来暴露来自攻击者控制请求的结果。例如,我们不暴露(或存储)原始错误消息:

    rescue Kubernetes::HttpError => e
      # 不好的做法
      # app.make_errored!("Kubernetes error: #{e.message}")
    
      # 好的做法
      app.make_errored!("Kubernetes error: #{e.error_code}")

调试 Kubernetes 集成

与 Kubernetes 集成相关的日志可以在 kubernetes.log 中找到。在本地 GDK 安装中,这些日志位于 log/kubernetes.log

您还可以关注安装日志来调试与安装相关的问题。一旦安装/升级开始,等待 Pod 创建。然后运行以下命令来获取写入的 Pod 日志:

kubectl logs <pod_name> --follow -n gitlab-managed-apps