Google Kubernetes Engine (GKE) 提供许多帮助保护工作负载的方法。在 GKE 中保护工作负载涉及堆栈的多个层,包括容器映像的内容、容器运行时环境、集群网络以及对集群 API 服务器的访问权限。
最好采用分层方法来保护集群和工作负载。您可以针对提供给用户及应用的访问权限级别,应用最小权限原则。在每一层中,您可能必须做出不同的取舍,以提供适当的灵活性和安全性级别,让组织能够安全地部署和维护其工作负载。例如,一些安全设置对于某些类型的应用或使用场景而言约束性太强,若不进行重大重构,则将无法正常工作。
本文档概述了基础架构的每一层,并介绍如何配置每一层的安全功能才最符合您的需求。
身份验证和授权
Kubernetes 支持两种类型的身份验证:
- 用户账号是 Kubernetes 已知的账号,但不由 Kubernetes 管理,例如,您无法使用
kubectl
创建或删除它们。 - 服务账号是由 Kubernetes 创建和管理的账号,但只能由 Kubernetes 创建的实体(如 Pod)使用。
在 GKE 集群中,Kubernetes 用户账号由 Google Cloud 管理,可以是以下两种类型之一:
通过身份验证后,您需要授权这些身份以创建、读取、更新或删除 Kubernetes 资源。
尽管名称相似,但 Kubernetes 服务账号和 Google Cloud 服务账号是不同的实体。Kubernetes 服务账号是定义它们的集群的一部分,通常在该集群中使用。相比之下,Google Cloud 服务账号是 Google Cloud 项目的一部分,可以轻松地在集群和 Google Cloud 项目集群本身以及使用 Identity and Access Management (IAM) 的任何 Google Cloud 资源中授予权限。这使得 Google Cloud 服务账号比 Kubernetes 服务账号更强大;为了遵循最小权限的安全原则,您应该考虑仅在需要其功能时使用 Google Cloud 服务账号。
要在集群级层或 Kubernetes 命名空间内配置对 Kubernetes 资源的更精细的访问权限,您可以使用基于角色的访问控制 (RBAC)。 通过 RBAC,您可以制定详细的政策,以定义您允许用户及服务账号访问的操作和资源。您可以使用 RBAC 来控制 Google 账号、Google Cloud 服务账号和 Kubernetes 服务账号的访问权限。如需进一步简化和精简 GKE 的身份验证和授权策略,您应该确保旧版基于特性的访问权限控制处于停用状态,以使 Kubernetes RBAC 和 Cloud IAM 成为可靠来源。
如需了解详情,请参阅:
- 阅读 GKE RBAC 文档。
- 在向 Kubernetes API 服务器进行身份验证中了解连接到 Kubernetes API 服务器时受支持的身份验证方法。
控制平面安全
在 GKE 中,Kubernetes 控制层面组件由 Google 管理和维护。控制层面组件托管用于运行 Kubernetes 控制层面的软件,包括 API 服务器、调度器、控制器管理器和 Kubernetes 配置持久保存所在的 etcd 数据库。
默认情况下,控制层面组件使用公共 IP 地址。要保护 Kubernetes API 服务器,您可以使用授权网络和专用集群,以允许您将专用 IP 地址分配给控制层面并停用对公共 IP 地址的访问权限。
您可以使用 IAM 作为身份提供商,在 Google Kubernetes Engine 中处理集群身份验证。如需了解身份验证,请参阅向 Kubernetes API 服务器进行身份验证。
帮助保护控制层面的另一个方法是确保定期执行凭据轮替。启动凭据轮替后,SSL 证书和集群证书授权机构会轮替。此过程由 GKE 自动执行,并且还确保您的控制层面 IP 地址会轮替。
如需了解详情,请参阅:
- 详细了解控制平面安全。
- 阅读基于角色的访问控制文档。
- 遵循凭据轮替指南。
节点安全
GKE 将工作负载部署到 Google Cloud 项目中运行的 Compute Engine 实例上。这些实例会作为节点关联到 GKE 集群。以下各个部分介绍如何利用 Google Cloud 中提供给您的节点级层安全功能。
Container-Optimized OS
默认情况下,GKE 节点使用 Google 的 Container-Optimized OS 作为运行 Kubernetes 及其组件的操作系统。Container-Optimized OS 实现了多项高级功能来增强 GKE 集群的安全性,其中包括:
- 锁定防火墙
- 只读文件系统(如果可能)
- 受限用户账号和停用 root 登录
GKE Autopilot 节点始终使用 Container-Optimized OS 作为操作系统。
节点升级
最佳做法是定期修补您的操作系统。容器运行时、Kubernetes 本身或节点操作系统中的安全问题可能会不时地要求您升级节点,而且更加迫切。升级节点时,节点的软件会升级到最新版本。
GKE 集群支持自动升级。在 Autopilot 集群中,始终启用自动升级。您还可以手动升级 Standard 集群中的节点。
保护节点以免受到不受信任的工作负载影响
对于运行未知或不可信工作负载的集群,良好的做法是保护节点上的操作系统,使其免受 Pod 中不受信任的工作负载的影响。
例如,软件即服务 (SaaS) 提供商等多租户集群通常会执行其用户提交的未知代码。安全研究则是工作负载可能需要比节点默认设置更强力的隔离的另一种应用。
您可以在集群上启用 GKE Sandbox,在节点上将不受信任的工作负载隔离到沙盒中。 GKE Sandbox 是通过开源项目 gVisor 构建的。
保护实例元数据
GKE 使用底层 Compute Engine 实例的实例元数据为节点提供凭据和配置,以用于引导节点并连接到节点控制层面。此元数据包含节点上的 Pod 不需要访问的敏感信息,例如节点的服务账号密钥。
您可以使用适用于 GKE 的工作负载身份联合封锁敏感实例元数据路径。适用于 GKE 的工作负载身份联合会启用集群中的 GKE 元数据服务器,以过滤对敏感字段(例如 kube-env
)的请求。
Autopilot 集群中会始终启用适用于 GKE 的工作负载身份联合。在 Standard 集群中,除非您手动启用适用于 GKE 的工作负载身份联合,否则 Pod 可以访问实例元数据。
网络安全
在 GKE 中运行的大多数工作负载需要与其他服务通信,这些服务可能在集群内部运行,也可能在集群外部运行。您可以使用多种不同方法来控制允许流经集群及其 Pod 的流量。
限制 Pod 到 Pod 的通信
默认情况下,您可以通过网络藉由 Pod IP 地址访问集群中的所有 Pod。同样,默认情况下,只要地址可在部署集群所在的 VPC 中进行访问,出站流量就允许建立连到该地址的出站连接。
创建进出 Pod 的入站和出站连接后,集群管理员和用户可以使用网络政策在命名空间中锁定这些连接。 默认情况下,如果未定义网络政策,则允许所有入站和出站流量流入和流出所有 Pod。网络政策允许您使用标签来定义流经 Pod 的流量。
在命名空间中应用了网络政策后,进出 Pod 的流量如果与所配置标签不相符,则全都删除。作为创建集群和/或命名空间的一部分,您可以对每个 Pod 应用默认拒绝入站和出站流量,以确保添加到集群的所有新工作负载必须向它们所需的流量明确授权。
如需了解详情,请执行以下操作:
过滤负载均衡的流量
要通过网络负载均衡器对您的 Kubernetes Pod 进行负载均衡,您需要创建类型为 LoadBalancer
且与 Pod 标签匹配的 Service。创建 Service 后,您将获得面向外部的 IP,该 IP 映射到 Kubernetes Pod 上的端口。您可以使用 kube-proxy 在节点级别上根据 IP 地址过滤经过授权的流量。
要配置此过滤条件,您可以使用 Service 对象的 loadBalancerSourceRanges
配置。借助此配置参数,您可以提供一份想要允许访问 Service 的 CIDR 范围列表。如果您未配置 loadBalancerSourceRanges
,则系统允许所有地址通过其外部 IP 访问 Service。
如果不需要从外部访问 Service,请考虑使用内部负载均衡器。如果需过滤掉 VPC 内部的流量,则内部负载均衡器也遵循 loadBalancerSourceRanges
。
如需了解详情,请参阅内部负载均衡教程。
保护工作负载
Kubernetes 可让用户快速预配、扩缩和更新基于容器的工作负载。本部分介绍的策略可供管理员和用户用来限制正在运行的容器对同一集群中的其他容器、容器在其中运行的节点,以及用户项目中启用的 Google Cloud 服务产生的影响。
限制 Pod 容器进程权限
限制容器化进程的权限对于集群的总体安全性十分重要。GKE Autopilot 集群始终限制特定权限,如 Autopilot 安全功能中所述。
GKE 还允许您通过安全上下文对 Pod 和容器设置安全相关选项。通过这些设置,您可以更改进程的安全设置,例如:
- 以其身份运行的用户和组
- 可用的 Linux 功能
- 提升权限的能力
如需在集群级层(而非 Pod 或容器级层)强制执行这些限制,请使用 PodSecurityAdmission 控制器。集群管理员可以使用 PodSecurityAdmission 来确保集群或命名空间中的所有 Pod 都遵循 Pod 安全标准中的预定义政策。您还可以使用 Gatekeeper 在集群级层设置自定义 Pod 安全政策。
GKE 节点操作系统(Container-Optimized OS 和 Ubuntu)会针对 Kubernetes 启动的所有容器应用默认的 Docker AppArmor 安全政策。您可以在 GitHub 上查看配置文件的模板。除此之外,配置文件会拒绝向容器提供以下能力:
- 直接将文件写入
/proc/
- 写入至不在进程 ID 目录 (
/proc/<number>
) 中的文件 - 写入至
/proc/sys
中的文件(/proc/sys/kernel/shm*
除外) - 装载文件系统
如需了解详情,请参阅:
- 阅读 Pod 安全上下文文档。
- 在 Container-Optimized OS AppArmor 文档中详细了解现有保护措施。
向 Pod 授予访问 Google Cloud 资源的权限
您的容器和 Pod 可能需要访问 Google Cloud 中的其他资源。您可以通过三种方法实现此目的。
适用于 GKE 的工作负载身份联合(推荐)
如需授权 Pod 访问 Google Cloud 资源,最安全的方法是使用适用于 GKE 的工作负载身份联合。适用于 GKE 的工作负载身份联合允许 Kubernetes 服务账号作为 IAM 服务账号运行。以 Kubernetes 服务账号运行的 Pod 拥有 IAM 服务账号的权限。
适用于 GKE 的工作负载身份联合可与 GKE Sandbox 搭配使用。
节点服务账号
在 Standard 集群中,您的 Pod 还可以使用节点的 Compute Engine 虚拟机 (VM) 使用的服务账号的凭据向 Google Cloud 进行身份验证。
这种方法与 GKE Sandbox 不兼容,因为 GKE Sandbox 会阻止对 Compute Engine 元数据服务器的访问。
服务账号 JSON 密钥(不推荐)
您可以使用服务账号密钥向应用授予 Google Cloud 资源的凭据。这种方法会造成您很难安全管理账号密钥,因此强烈不建议使用。
如果选择此方法,请为每个应用使用自定义 IAM 服务账号,以使应用具有最小的必要权限。系统会为每个服务账号授予配对应用成功运行所需的最低权限 IAM 角色。通过使服务账号成为应用专用的服务账号,您可以在服务账号被盗用时轻松撤消其访问权限,而不影响其他应用。为您的服务账号分配了正确的 IAM 角色后,您可以创建 JSON 服务账号密钥,然后使用 Kubernetes Secret 将该密钥装载到您的 Pod。
使用 Binary Authorization
Binary Authorization 是 Google Cloud 中的一项服务,为在云端运行的应用提供软件供应链安全性。Binary Authorization 适用于从 Artifact Registry 或其他容器映像注册表部署到 GKE 的映像。
通过强制执行 Binary Authorization,您可以确保在将应用部署到生产环境之前,已成功完成保护软件质量和完整性的内部过程。如需了解如何创建启用了 Binary Authorization 的集群,请参阅 Binary Authorization 文档中的创建集群。
借助 Binary Authorization 持续验证 (CV),您可以确保定期监控与 Pod 关联的容器映像,确保它们符合不断发展的内部过程。
审核日志记录
通过审核日志记录,管理员可以针对 GKE 环境中发生的事件进行保留、查询、处理和提醒。管理员可以使用日志中记录的信息执行取证分析、实时提醒,或者对一组 GKE 集群的使用方式和用户进行编目。
默认情况下,GKE 会记录管理员活动日志。您还可以选择记录数据访问事件,具体取决于您有兴趣检查的操作类型。
如需了解详情,请参阅:
- 参阅 GKE 审核日志记录教程。
- 详细了解 Cloud Audit Logs。
内置安全措施
GKE 对可以针对集群中的系统对象执行的操作施加了特定的限制。当您执行修补工作负载之类的操作时,名为 GKE Warden 的准入网络钩子会针对一组受限操作验证您的请求,并决定是否允许该请求。
Autopilot 集群安全措施
Autopilot 集群会根据我们的专业知识和行业最佳实践应用多项安全设置。如需了解详情,请参阅 Autopilot 中的安全措施。
标准集群安全措施
默认情况下,标准集群比 Autopilot 集群更宽松。GKE Standard 集群具有以下安全设置:
- 您无法更新 GKE 管理的系统工作负载(例如
kube-system
命名空间中的工作负载)使用的 ServiceAccount。 - 您无法将
cluster-admin
默认 ClusterRole 绑定到system:anonymous
、system:unauthenticated
或system:authenticated
群组。