强化集群的安全性

以 Kubernetes 的开发速度,通常会有新的安全功能供您使用。本页面将指导您完成当前指南中的操作,以加强 Google Kubernetes Engine 集群的安全性。如需大致了解安全主题,请阅读安全概览

停用 Kubernetes 网页界面(信息中心)

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

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

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

gcloud container clusters update [CLUSTER_NAME] \
    --update-addons=KubernetesDashboard=DISABLED

停用 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

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

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

您可以使用 Kubernetes 的网络政策大大增加攻击者在集群中横向移动的难度。您还可以使用 Kubernetes Network Policy API 创建 Pod 级层的防火墙规则。这些防火墙规则可以决定哪些 Pod 和服务可以在集群内相互访问。

要在创建新集群时执行网络政策,请指定 --enable-network-policy 标志:

gcloud container clusters create [CLUSTER_NAME] \
    --zone=[COMPUTE_ZONE] \
    --enable-network-policy

启用网络政策后,您必须实际定义一个政策。由于它特定于实际的拓扑,因此我们无法提供具体建议。不过,Kubernetes 文档很好地演示了简单的 nginx 部署。

要详细了解 GKE 中的网络政策,请参阅设置集群网络政策

结合使用 NetworkPolicy 和 PodSecurityPolicy

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

为节点使用最小权限服务帐号

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

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

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

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

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

gcloud projects add-iam-policy-binding [PROJECT_ID] \
  --member "serviceAccount:[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com" \
  --role roles/storage.objectViewer

如果您希望其他用户能够使用此服务帐号创建新集群或节点池,则必须授予他们此服务帐号的“服务帐号用户”角色:

gcloud iam service-accounts add-iam-policy-binding \
  [SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com \
  --member=user:[USER] \
  --role=roles/iam.serviceAccountUser

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

gcloud container node-pools create [NODE_POOL] \
  --service-account=[SA_NAME]@[PROJECT_ID].iam.gserviceaccount.com" \
  --cluster=[CLUSTER_NAME]

如果您需要 GKE 集群具有其他 Google Cloud 服务的访问权限,则应该另外创建一个服务帐号并将其私钥存储在 Kubernetes Secret 中,为该服务帐号授予您的工作负载访问权限。如需了解详情,请参阅使用服务帐号向 Google Cloud Platform 进行身份验证

缩减节点服务帐号范围

如果您不想使用自定义服务帐号,则建议您缩减默认节点服务帐号的权限。

默认情况下,节点服务帐号具有访问权限范围。访问权限范围是为实例指定权限的传统方法。在 IAM 角色出现之前,访问权限范围是向服务帐号授予权限的唯一机制。

如果您没有为节点创建单独的服务帐号,则应该限制节点服务帐号的范围,以降低攻击中提升权限的可能性。 这样可以确保默认服务帐号的权限不超过运行集群的必需权限。虽然默认范围受到限制,但它们包含的范围可能会超出运行集群所需的最小必需范围。

在 GKE 中,节点的默认范围为 devstorage.read_onlylogging.writemonitoringservice.management.readonlyservicecontroltrace.append。设置范围时,它们均被指定为 gke-default。如果您要访问 Google Container Registry 中的私有映像,则最小必需范围仅为 logging.writemonitoringdevstorage.read_only

要创建具有自定义范围的集群,请使用 --scopes 选项:

gcloud container clusters create [CLUSTER_NAME] \
    --scopes=[CUSTOM_SCOPES]

如果未指定范围或自定义服务帐号,请使用 gke-default。如果指定自定义服务帐号,请使用 cloud-platformuserinfo.email

如果您的 gcloud 配置包含 container/new_scopes_behavior true,则系统已为所有 Kubernetes 版本启用了此行为。要为您的环境设置默认值,请运行以下命令:

gcloud config set container/new_scopes_behavior true

要详细了解所有范围的权限,请参阅 Google 范围

限制客户端身份验证方法

向 Kubernetes API 服务器进行身份验证的方法有多种。在 GKE 中,支持的方法包括 OpenID 连接令牌、x509 客户端证书和静态密码。GKE 通过 gcloud 为您管理身份验证,让您使用 OpenID 连接令牌方法,设置 Kubernetes 配置,获取访问令牌并使其保持最新。

其他身份验证方法(x509 证书和静态密码)具有更大的危害集群安全的攻击面。如果使用其他这些方法,当您创建新集群时,系统会为您生成凭据。除非您的应用正在使用这些身份验证方法,否则应该停用它们。您应该使用 OpenID 身份验证方法,并停用集群的客户端证书和静态密码身份验证方法。

只有具有 container.clusters.getCredentials 权限的用户才能检索客户端证书和静态密码。注意,由于 roles/container.adminroles/ownerroles/editor 角色都具有此权限,因此请慎用这些角色。详细了解 GKE IAM 角色

停用客户端证书身份验证

使用证书身份验证时,客户端提供一份 API 服务器可向指定的证书颁发机构验证的证书。在 GKE 中,客户端证书由集群根证书授权机构签署。

使用 ABAC 时,客户端证书可以默认向 API 服务器进行身份验证。但是在启用 RBAC 的情况下,必须为客户端证书授予权限。启用了 RBAC 并停用了 ABAC 的集群仍具有这些证书,但它们实际上毫无用处。

要在不生成客户端证书的情况下创建集群,请使用 --no-issue-client-certificate 标志:

gcloud container clusters create [CLUSTER_NAME] \
    --no-issue-client-certificate

目前,无法从现有集群中移除客户端证书。

停用静态密码身份验证

静态密码是 API 服务器验证的用户名和密码组合。在 GKE 中,系统会默认为用户名“admin”生成这些内容。

要在不生成静态密码的情况下创建集群,请使用 --no-enable-basic-auth 选项:

gcloud container clusters create [CLUSTER_NAME] \
    --no-enable-basic-auth

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

gcloud container clusters update [CLUSTER_NAME] \
    --no-enable-basic-auth

保护节点元数据

对 Kubernetes 的一些实际攻击依靠虚拟机元数据服务器的访问权限来提取节点的凭据。

如上所述,使用具有最低权限的服务帐号是缓解这些攻击的第一步。下一步是防止工作负载冒充节点。您应该停用旧版元数据服务器 API,并使用元数据隐藏来帮助保护系统的潜在敏感元数据,使其免受集群上运行的工作负载的影响。

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

自动升级节点

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

在 Google Kubernetes Engine 中,主实例会自动进行修补和升级,但您仍需要负责修补和升级节点。您应该启用节点自动升级,以自动接收节点池的升级程序和安全修补程序。

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

如果您不想启用节点自动升级,请务必仔细查看 Kubernetes Engine 安全公告,以获取安全修补程序信息。

使用 Pod 安全政策(测试版)限制 Pod 权限

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

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

要详细了解 Pod 安全政策,请参阅使用 PodSecurityPolicies

如果您在集群中同时使用网络政策和 Pod 安全政策,请参阅结合使用网络政策和 Pod 安全政策

限制集群发现 RBAC 权限

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

用户应注意,system:discoverysystem:basic-user ClusterRoleBinding 的主题中包含的 system:authenticated 组可以包括任何具有有效 Google 凭据的人(例如 Gmail 用户),因此不代表 GKE 上集群的有意义的安全级别。

希望对其集群的发现 API 进行安全强化的用户应考虑以下一项或多项操作:

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

后续步骤