强化集群的安全性

Kubernetes 的开发速度较快,经常会有新的安全功能供您使用。本页面将指导您完成当前指南中的操作,以加强 Google Kubernetes Engine (GKE) 集群的安全性。

本指南首先介绍重要安全措施,这些措施需要客户在创建集群时执行相关操作。文档较后的部分会提到不太重要的功能、默认安全设置以及可以在创建后启用的功能。如需大致了解安全主题,请阅读安全概览

您可以使用 Security Health Analytics 自动检查多项建议以及其他常见的错误配置。

如果以下建议与 CIS GKE 基准建议相关,则本指南会指明这一点。

及时(默认日期为 2019 年 11 月 11 日)升级您的 GKE 基础架构

CIS GKE 基准建议:6.5.3 - 确保为 GKE 节点启用节点自动升级

要提高安全性,最简单的方法是及时更新 Kubernetes。Kubernetes 经常引入新的安全功能并提供安全补丁程序。

如需了解安全补丁程序,请参阅 GKE 安全公告

在 Google Kubernetes Engine 中,系统会自动为您修补和升级主实例。 节点自动升级功能还会自动升级集群中的节点。

如果您选择停用节点自动升级,我们建议您按照自己的时间安排每月升级一次。旧版集群应选择启用节点自动升级,并严格按照重要补丁程序的 GKE 安全公告执行相关操作。

如需了解详情,请参阅自动升级节点

限制对控制层面和节点的网络访问

CIS GKE 基准建议:6.6.2 - 首选 VPC 原生集群;6.6.3 - 确保启用主授权网络;6.6.4 - 确保在启用专用端点并停用公共访问的情况下创建集群;6.6.5 - 确保使用专用节点创建集群

您应该限制集群控制层面和节点对互联网的公开程度。这些设置只能在创建集群时进行设定。

默认情况下,GKE 集群控制层面和节点具有互联网可路由地址,这些地址可以从任何 IP 地址进行访问。

请参阅创建专用集群,了解 GKE 集群控制层面。可以提供网络级保护的专用集群有三种不同的类型:

  • 停用公共端点访问权限:这是最安全的选项,它会阻止对主实例和节点的所有互联网访问。如果您已将本地网络配置为通过 Cloud InterconnectCloud VPN 连接到 Google Cloud,那么这是一个不错的选择。这些技术会将您的公司网络有效连接到您的云端 VPC。
  • 启用公共端点访问权限,并启用主授权网络(推荐):此选项可以限制您定义的来源 IP 地址对主实例的访问权限。如果您还没有 VPN 基础架构,或者您的远程用户或分支机构通过公共互联网(而不是公司 VPN 和 Cloud Interconnect 或 Cloud VPN)进行连接,这是一个不错的选择。
  • 启用公共端点访问权限,但停用主授权网络:这是默认选项,它允许互联网上的任何人与控制层面建立网络连接。

如需停用直接对节点的互联网访问权限,请在创建集群时指定 gcloud 工具选项 --enable-private-nodes。

此选项指示 GKE 使用 RFC 1918 专用 IP 地址预配节点,这意味着这些节点无法通过公共互联网直接进行访问。

我们建议集群至少启用主授权网络和专用节点功能。这样可以确保通过以下方式能够访问控制层面:

  • 主授权网络中已列入白名单的 CIDR。
  • 集群 VPC 中的节点。
  • 管理主实例的 Google 内部生产作业。

以上方式对应于创建集群时的以下 gcloud 标志:

  • --enable-ip-alias
  • --enable-private-nodes
  • --enable-master-authorized-networks

群组验证(Beta 版)

CIS GKE 基准建议:6.8.3 - 考虑使用 Google GKE 群组来管理 Kubernetes RBAC 用户

此设置只能在创建集群时启用。

您应该使用群组来管理您的用户。借助群组,您可以通过身份管理系统和身份管理员来控制身份。在群组中添加任何人或从群组中移除任何人时,您只需调整群组成员即可,无需更新 RBAC 配置。

如需使用 Google 群组管理用户权限,您必须在创建集群时启用 Google GKE 群组。这样,您可以轻松管理具有相同权限的用户,同时身份管理员也可以集中、一致地管理用户。

如需启用 Google GKE 群组,请创建一个用于管理用户访问权限的 Google 群组 gke-security-groups,并在创建集群时指定 gcloud 标志 --security-group

容器节点选项

以下各个部分将介绍安全节点配置选项。

启用安全强化型 GKE 节点

CIS GKE 基准建议:6.5.5 - 确保已启用安全强化型 GKE 节点

安全强化型 GKE 节点提供强大、可验证的节点身份和完整性,能够提高 GKE 节点的安全性,应在所有 GKE 集群上启用。

如需启用安全强化型 GKE 节点,请在创建或更新集群时指定 gcloud 选项 --enable-shielded-nodes安全强化型 GKE 节点应启用安全启动功能。如果您需要未签名的第三方内核模块,则不应使用安全启动功能。如需启用安全启动功能,请在创建集群时指定 gcloud 标志 --shielded-secure-boot

选择具有 containerd 运行时环境的安全强化节点映像

带有 Containerd (cos_containerd) 映像的 Container-Optimized OS 是 Container-Optimized OS 映像的变体,其中 containerd 是与 Kubernetes 直接集成的主容器运行时环境。

containerd 是 Docker 的核心运行时环境组件,旨在为 Kubernetes 容器运行时环境接口 (CRI) 提供核心容器功能。由于其复杂程度远远低于完整的 Docker 守护程序,因此它具有较小的攻击面。

如需在集群中使用 cos_containerd 映像,请在创建或升级集群时指定 gcloud 标志 --image-type=cos_containerd

cos_containerd 是 GKE 的首选映像,因为它已专门针对正在运行的容器进行了自定义构建、优化和强化

启用 Workload Identity

CIS GKE 基准建议:6.2.2 - 首选使用专用的 Google Cloud 服务帐号和 Workload Identity

建议使用 Workload Identity 来向 Google API 验证身份。它取代了之前使用节点服务帐号或将服务帐号密钥导出到 Secret 中的做法,如使用服务帐号向 Google Cloud 验证身份中所述。

Workload Identity 还取代了使用元数据隐藏的需要,因此这两种方法不兼容。由元数据隐藏保护的敏感元数据也受 Workload Identity 的保护。

利用 GKE Sandbox 强化工作负载隔离

CIS GKE 基准建议:6.10.4 - 考虑使用 GKE Sandbox 来强化工作负载隔离,尤其是对于不受信任的工作负载

GKE Sandbox 提供了一道额外的安全保障,可防止恶意代码影响集群节点上的主机内核。

请参阅利用 GKE Sandbox 强化工作负载隔离,了解如何使用 GKE Sandbox。

权限

使用最低权限的 Google 服务帐号

CIS GKE 基准建议:6.2.1 - 避免使用 Compute Engine 默认服务帐号运行 GKE 集群

每个 GKE 节点都有一个与其关联的 Cloud Identity and Access Management (Cloud IAM) 服务帐号。默认情况下,系统会为节点提供 Compute Engine 默认服务帐号,您可以导航到 Cloud Console 的 Cloud IAM 部分找到该帐号。默认情况下,此帐号具有广泛的访问权限,可用于各种应用,但它的权限超出了运行 Kubernetes Engine 集群的必需权限。您应该创建并使用具有最低权限的服务帐号来运行 GKE 集群,而不是使用 Compute Engine 默认服务帐号。

随着 Workload Identity 的发布,我们建议进一步减少使用节点服务帐号。我们希望负责日志记录、监控和类似任务的系统守护程序使用节点服务帐号。而 Pod 中的工作负载应通过 Workload Identity 来预配 Google 身份。

GKE 要求服务帐号至少具有 monitoring.viewermonitoring.metricWriterlogging.logWriter 角色。详细了解监控角色日志记录角色

以下命令会创建一个 Cloud IAM 服务帐号,该帐号具有操作 GKE 所需的最低权限:

gcloud

gcloud iam service-accounts create sa-name \
  --display-name=sa-name

gcloud projects add-iam-policy-binding project-id \
  --member "serviceAccount:sa-name@project-id.iam.gserviceaccount.com" \
  --role roles/logging.logWriter

gcloud projects add-iam-policy-binding project-id \
  --member "serviceAccount:sa-name@project-id.iam.gserviceaccount.com" \
  --role roles/monitoring.metricWriter

gcloud projects add-iam-policy-binding project-id \
  --member "serviceAccount:sa-name@project-id.iam.gserviceaccount.com" \
  --role roles/monitoring.viewer

配置连接器

注意:此步骤需要使用配置连接器。按照安装说明在您的集群上安装配置连接器。

  1. 如需创建服务帐号,请下载以下资源并将其保存为 service-account.yaml。将 [SA_NAME] 替换为您要用于服务帐号的名称。

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMServiceAccount
    metadata:
      name: [SA_NAME]
    spec:
      displayName: [SA_NAME]
    然后运行以下命令:
    kubectl apply -f service-account.yaml

  2. logging.logWriter 角色应用到服务帐号。下载以下资源并将其保存为 policy-logging.yaml。将 [SA_NAME][PROJECT_ID] 替换为您自己的信息。

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-logging
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/logging.logWriter
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-logging.yaml

  3. 应用 monitoring.metricWriter 角色。下载以下资源并将其保存为 policy-metrics-writer.yaml。将 [SA_NAME][PROJECT_ID] 替换为您自己的信息。

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-metrics-writer
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/monitoring.metricWriter
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-metrics-writer.yaml

  4. 应用 monitoring.viewer 角色。下载以下资源并将其保存为 policy-monitoring.yaml。将 [SA_NAME][PROJECT_ID] 替换为您自己的信息。

    apiVersion: iam.cnrm.cloud.google.com/v1beta1
    kind: IAMPolicyMember
    metadata:
      name: policy-monitoring
    spec:
      member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
      role: roles/monitoring.viewer
      resourceRef:
        kind: Project
        name: [PROJECT_ID]
    kubectl apply -f policy-monitoring.yaml

如果您在 Google Container Registry 中使用私有映像,还需要向以下服务帐号授予权限:

gcloud

gcloud projects add-iam-policy-binding project-id \
--member "serviceAccount:sa-name@project-id.iam.gserviceaccount.com" \
--role roles/storage.objectViewer

配置连接器

注意:此步骤需要使用配置连接器。按照安装说明在您的集群上安装配置连接器。

storage.objectViewer 角色应用到您的服务帐号。下载以下资源并将其保存为 policy-object-viewer.yaml。将 [SA_NAME][PROJECT_ID] 替换为您自己的信息。

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-object-viewer
spec:
  member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/storage.objectViewer
  resourceRef:
    kind: Project
    name: [PROJECT_ID]
kubectl apply -f policy-object-viewer.yaml

如果您希望其他真人用户能够使用此服务帐号创建新集群或节点池,则必须在此服务帐号上向该用户授予 Service Account User 角色:

gcloud

gcloud iam service-accounts add-iam-policy-binding \
sa-name@project-id.iam.gserviceaccount.com \
--member=user:user \
--role=roles/iam.serviceAccountUser

配置连接器

注意:此步骤需要使用配置连接器。按照安装说明在您的集群上安装配置连接器。

iam,serviceAccountUser 角色应用到您的服务帐号。下载以下资源并将其保存为 policy-service-account-user.yaml。将 [SA_NAME][PROJECT_ID] 替换为您自己的信息。

apiVersion: iam.cnrm.cloud.google.com/v1beta1
kind: IAMPolicyMember
metadata:
  name: policy-service-account-user
spec:
  member: serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com
  role: roles/iam.serviceAccountUser
  resourceRef:
    kind: Project
    name: [PROJECT_ID]
kubectl apply -f policy-service-account-user.yaml

如果集群已存在,则您现在可以使用这个新的服务帐号创建新节点池:

gcloud container node-pools create node-pool \
  --service-account=sa-name@project-id.iam.gserviceaccount.com \
  --cluster=cluster-name

如果您需要 GKE 集群具有其他 Google Cloud 服务的访问权限,则应另外创建一个服务帐号,并使用 Workload Identity 为该服务帐号授予您的工作负载访问权限。

限制集群发现 RBAC 权限

默认情况下,Kubernetes 使用一组宽松的发现 ClusterRoleBinding 引导集群,从而允许广泛访问包括 CustomResourceDefinition 信息在内的集群 API 信息。

用户应注意,system:discoverysystem:basic-user ClusterRoleBinding 的主体中包含的 system:authenticated 群组可以包括任何经过身份验证的用户(包括任何具有 Google 帐号的用户),它不代表 GKE 上集群的有意义的安全级别。

希望强化集群的发现 API 用户应考虑以下一项或多项措施:

  • 配置授权网络,限制对设定的 IP 地址范围的访问。
  • 设置专用集群,限制对 VPC 的访问。
  • 挑选默认 system:discoverysystem:basic-user ClusterRoleBinding 的主体,例如,考虑仅允许访问 system:serviceaccounts 群组及其他已知用户和群组,而不是使用 Kubernetes 的默认设置(即允许访问 system:(un)authenticated)。

使用命名空间和 RBAC 限制对集群资源的访问

CIS GKE 基准建议:5.6.1 - 使用命名空间在各资源之间创建管理边界

通过为每个团队和环境创建单独的命名空间或集群,为团队提供 Kubernetes 所需的最低访问权限。为每个命名空间分配成本中心和适当的标签,以实现责任的明晰化和退款。仅为开发者提供部署和管理应用(特别是在生产环境中)所需的访问权限级别,允许其对命名空间进行访问。制定用户需要对集群执行的任务,并定义他们执行每项任务所需的权限。

如需详细了解如何创建命名空间,请参阅 Kubernetes 文档

Cloud IAM基于角色的访问权限控制 (RBAC) 可以协同工作,而实体在任一级层必须具有足够权限,才能使用集群中的资源。

针对 GKE 向群组和用户分配适当的 Cloud IAM 角色以提供项目级层的权限,并使用 RBAC 授予集群和命名空间级层的权限。如需了解详情,请参阅访问权限控制

如需了解详情,请参阅为生产准备 Kubernetes Engine 环境

使用网络政策限制 Pod 之间的流量

CIS GKE 基准建议:6.6.7 - 确保已启用网络政策,并进行适当设置

默认情况下,集群中的所有 Pod 都可以相互通信。您应该根据工作负载的需要控制 Pod 之间的通信。

限制网络对服务的访问权限可以大大增加攻击者在集群中横向移动的难度,还可以保护服务免遭意外的或故意的拒绝服务攻击。控制流量的两种推荐方法如下:

  1. 使用 Istio。请参阅在 GKE 上安装 Istio。如果您对负载平衡、服务授权、节流、配额、指标等等感兴趣,请选择此方法。
  2. 使用 Kubernetes 网络政策。请参阅设置集群网络政策。如果您需要 Kubernetes 所提供的基本访问权限控制功能,请选择此方法。Kubernetes 文档很好地演示了简单的 nginx 部署。

如果需要,可以同时使用 Istio 和网络政策。

Secret 管理

CIS GKE 基准建议:6.3.1 - 考虑使用 Cloud KMS 中托管的密钥来加密 Kubernetes Secret

您应该为存储在 etcd 中的敏感数据(例如 Secret)提供额外保护。如需执行此操作,您需要配置与 GKE 集群集成的 Secret 管理器。某些解决方案可以同时用于 GKE 和 Anthos GKE On-Prem,因此,如果您在多个环境中运行工作负载,则可以选择这些解决方案。如果您选择使用 HashiCorp Vault 之类的外部 Secret 管理器,则需要在创建集群之前先设置该管理器。

您可以通过多种方式来管理 Secret。

  • 您可以在 GKE 本地使用 Kubernetes Secret。或者,您可以通过应用层 Secret 加密,使用您管理的密钥在应用层对这些 Secret 进行加密。
  • 您可以使用 HashiCorp Vault 等 Secret 管理器。在安全强化的 HA 模式下运行时,此管理器将提供一种适合生产环境且具有一致性的方法来管理 Secret。您可以使用 Kubernetes 服务帐号或 Google Cloud 服务帐号向 HashiCorp Vault 进行身份验证。如需详细了解如何将 GKE 与 Vault 搭配使用,请参阅在 Kubernetes 上运行和连接到 HashiCorp Vault

GKE 虚拟机默认在存储层加密,其中包括 etcd。

使用准入控制器强制执行政策

CIS GKE 基准建议:6.10.3 - 确保启用 Pod 安全政策并进行适当设置

准入控制器是负责管理和实施集群使用方式的插件。您必须启用它们才能使用 Kubernetes 的一些更高级的安全功能;它们是强化集群的深度防御方法的重要组成部分。

默认情况下,Kubernetes 中的 Pod 可以使用必需功能之外的功能。您应该将 Pod 的功能限制在工作负载必需的范围内。

Kubernetes 提供的控件可以限制 Pod 仅使用明确授予的功能来执行任务。Pod 安全政策允许您为 Pod 设置智能默认值,并强制执行您希望在整个机群中启用的控件。您定义的政策应特定于应用的需求。建议您首先使用 restricted-psp.yaml 示例政策。

如需详细了解 Pod 安全政策,请参阅使用 PodSecurityPolicy

如果您使用的是 NetworkPolicy 且有一个 Pod 受到 PodSecurityPolicy 的约束,请创建有权使用 PodSecurityPolicy 的 RBAC Role 或 ClusterRole。然后将 Role 或 ClusterRole 绑定到 Pod 的服务帐号。在这种情况下,仅为用户帐号授予权限是不够的。如需了解详情,请参阅进行政策授权

监控集群配置

您应该审核集群配置与您定义的设置之间是否存在差异。

您可以使用 Security Health Analytics 自动检查本安全强化指南中介绍的多项建议以及其他常见的错误配置。

安全默认设置

以下各个部分介绍了新集群中默认的安全配置选项。您应验证先前存在的集群采用了安全配置。

保护节点元数据(1.12 及更高版本的默认设置)

CIS GKE 基准建议:6.4.1 - 确保停用旧版 Compute Engine 实例元数据 API;6.4.2 - 确保启用 GKE 元数据服务器

Compute Engine 的实例元数据服务器提供旧版 /0.1//v1beta1/ 端点,这些端点不会强制执行元数据查询标头。对于 1.12 及更高版本的新集群,这些 API 已默认停用。如果您升级了旧版本的集群,则应手动停用这些旧版 API

针对 Kubernetes 的一些实际攻击需要通过访问虚拟机的元数据服务器来提取凭据。如果您使用 Workload Identity元数据隐藏,则系统会阻止这些攻击。

Compute Engine v1beta1 和 v0.1 元数据服务器端点已弃用,并将按计划关停。请务必确保将所有请求更新为使用 v1 端点。

如需了解详情,请参阅保护集群元数据

停用旧的客户端身份验证方法(1.12 及更高版本的默认设置)

CIS GKE 基准建议:6.8.1 - 确保停用“使用静态密码进行基本身份验证”;6.8.2 - 确保停用“使用客户端证书进行身份验证”

向 Kubernetes API 服务器进行身份验证的方法有多种。

在 GKE 中,受支持的方法包括服务帐号不记名令牌、OAuth 令牌、x509 客户端证书、静态密码。GKE 通过 gcloud 管理身份验证,让您能够使用 OAuth 令牌方法,设置 Kubernetes 配置,获取访问令牌并使其保持最新。

在 GKE 与 Google OAuth 集成之前,预配的 x509 证书或静态密码是唯一可用的身份验证方法,但现在不推荐使用,并且 1.12 及更高版本的新集群已默认停用上述证书或密码。

现有集群应移动到 OAuth。如果集群外部的系统需要使用长期凭据,我们建议您创建具有所需权限的 Google 服务帐号或 Kubernetes 服务帐号并导出密钥。

如需更新现有集群并移除静态密码,请运行以下命令:

gcloud container clusters update cluster-name \
  --no-enable-basic-auth

目前,无法从现有集群中移除以前颁发的客户端证书,但如果启用了 RBAC 且停用了 ABAC,则该证书将失去权限。

启用 Cloud Logging(默认)

CIS GKE 基准建议:6.7.1 - 确保已启用 Stackdriver Kubernetes Logging 和 Monitoring

为了减少运营开销并维护日志的统一视图,请在部署集群的任何位置实施一致的日志记录策略。Anthos 集群默认与 Cloud Logging 集成,应保持这种配置。

默认情况下,所有 GKE 集群会启用 Kubernetes 审核日志记录功能,该功能会按时间顺序记录对 Kubernetes API 服务器进行的调用。Kubernetes 审核日志条目适合用于调查可疑 API 请求、收集统计信息,或针对不当 API 调用创建监控提醒。

GKE 集群将 Kubernetes Audit Logging 与 Cloud Audit LogsCloud Logging 集成。如果需要,您可以将日志从 Cloud Logging 导出到自己的日志记录系统。

停用 Kubernetes 网页界面(信息中心)(1.10 及更高版本的默认设置)

CIS GKE 基准建议:6.10.1 - 确保已停用 Kubernetes 网页界面

在 GKE 上运行时,不应启用 Kubernetes 网页界面(信息中心)。

Kubernetes 网页界面(信息中心)由具有较高权限的 Kubernetes 服务帐号提供支持。由于 Cloud Console 提供了很多相同功能,因此您无需这些权限。

如需停用 Kubernetes 网页界面,请运行以下命令:

gcloud container clusters update cluster-name \
    --update-addons=KubernetesDashboard=DISABLED

停用 ABAC(1.10 及更高版本的默认设置)

CIS GKE 基准建议:6.8.4 - 确保已停用旧版授权 (ABAC)

您应该停用基于属性的访问权限控制 (ABAC),转而在 GKE 中使用基于角色的访问权限控制 (RBAC)。

在 Kubernetes 中,RBAC 用于在集群级层和命名空间级层授予对资源的权限。借助 RBAC,您可以使用包含一组权限的规则来定义角色。RBAC 拥有明显的安全优势,目前在 Kubernetes 中已非常稳定,因此您可以停用 ABAC。

如果您仍需使用 ABAC,请先查看使用 RBAC 的前提条件。如果您从旧版本升级集群并且使用的是 ABAC,则应该更新访问权限控制配置:

gcloud container clusters update cluster-name \
    --no-enable-legacy-authorization

如需按照上述建议创建新集群,请运行以下命令:

gcloud container clusters create cluster-name \
    --no-enable-legacy-authorization

后续步骤