保护集群
本文档涵盖了保护集群免受意外或恶意访问的相关主题,并提供了关于整体安全性的建议。
开始之前
您需要一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与您的集群通信。建议在至少有两个节点(不充当控制平面主机)的集群上运行本教程。如果您还没有集群,可以使用 minikube 创建一个,或者可以使用以下 Kubernetes 游乐场
要检查版本,请输入
kubectl version。
控制对 Kubernetes API 的访问
由于 Kubernetes 完全由 API 驱动,因此控制和限制谁可以访问集群以及允许他们执行哪些操作是第一道防线。
对所有 API 流量使用传输层安全 (TLS)
Kubernetes 期望集群中的所有 API 通信默认情况下都通过 TLS 加密,并且大多数安装方法都允许创建必要的证书并分发到集群组件。请注意,某些组件和安装方法可能会启用通过 HTTP 进行本地端口访问,管理员应熟悉每个组件的设置,以识别潜在的不安全流量。
API 身份验证
选择 API 服务器使用的身份验证机制,该机制与您安装集群时的常见访问模式相匹配。例如,小型、单用户集群可能希望使用简单的证书或静态 Bearer Token 方法。大型集群可能希望集成现有的 OIDC 或 LDAP 服务器,允许用户细分为组。
所有 API 客户端必须经过身份验证,即使它们是基础设施的一部分,例如节点、代理、调度器和卷插件。这些客户端通常是 服务帐户 或使用 x509 客户端证书,并在集群启动时自动创建或作为集群安装的一部分进行设置。
请参阅 身份验证参考文档,了解更多信息。
API 授权
身份验证后,预计每个 API 调用也需要通过授权检查。Kubernetes 附带了一个集成的 基于角色的访问控制 (RBAC) 组件,该组件将传入的用户或组与捆绑到角色中的一组权限进行匹配。这些权限将动词(get、create、delete)与资源(pod、服务、节点)结合起来,并且可以是命名空间范围的或集群范围的。提供了一组开箱即用的角色,这些角色根据客户端可能想要执行的操作提供合理的默认职责分离。建议使用 节点 和 RBAC 授权器,以及 NodeRestriction 准入插件。
与身份验证一样,简单且广泛的角色可能适合较小的集群,但随着越来越多的用户与集群交互,可能需要将团队分成单独的 命名空间,并具有更有限的角色。
在授权方面,重要的是要了解对一个对象的更新可能会导致其他地方的操作。例如,用户可能无法直接创建 Pod,但允许他们创建 Deployment,后者代表他们创建 Pod,这将让他们间接创建这些 Pod。同样,从 API 删除节点将导致计划到该节点的 Pod 被终止并在其他节点上重新创建。开箱即用的角色代表了灵活性和常见用例之间的平衡,但应仔细审查更有限的角色,以防止意外升级。如果默认角色不满足您的需求,您可以创建特定于您用例的角色。
请参阅 授权参考部分,了解更多信息。
控制对 Kubelet 的访问
Kubelet 暴露 HTTPS 端点,这些端点授予对节点和容器的强大控制。默认情况下,Kubelet 允许对该 API 进行未经身份验证的访问。
生产集群应启用 Kubelet 身份验证和授权。
请参阅 Kubelet 身份验证/授权参考,了解更多信息。
控制工作负载或用户在运行时拥有的功能
Kubernetes 中的授权有意是高级别的,侧重于对资源执行粗粒度的操作。更强大的控制措施存在于策略中,用于根据用例限制这些对象在集群中、自身和其他资源上的行为。
限制集群上的资源使用量
资源配额限制授予命名空间的资源数量或容量。这最常用于限制命名空间可以分配的 CPU、内存或持久磁盘的量,但也可以控制每个命名空间中存在的 Pod、服务或卷的数量。
限制范围限制上述某些资源的上限或下限,以防止用户请求通常保留的资源(如内存)的不合理的高或低值,或者在未指定时提供默认限制。
控制容器运行的权限
Pod 定义包含一个 安全上下文,允许它请求以特定 Linux 用户在节点上运行(如 root)、访问以特权运行或访问主机网络,以及其他允许它在托管节点上不受限制运行的控制。
您可以配置 Pod 安全准入 以强制在 命名空间中使用特定的 Pod 安全标准,或检测违规行为。
通常,大多数应用程序工作负载只需要有限的访问主机资源,因此它们可以成功地以 root 进程(uid 0)运行,而无需访问主机信息。但是,考虑到与 root 用户相关的权限,您应该编写应用程序容器以非 root 用户运行。同样,管理员如果希望防止客户端应用程序逃逸其容器,应应用 Baseline 或 Restricted Pod 安全标准。
防止容器加载不需要的内核模块
Linux 内核会自动从磁盘加载内核模块,如果某些情况下需要,例如连接硬件或挂载文件系统时。对于 Kubernetes 而言,即使非特权进程也可以通过创建适当类型的套接字来导致某些与网络协议相关的内核模块被加载。这可能允许攻击者利用管理员认为未使用的内核模块中的安全漏洞。
要防止加载特定的模块,您可以从节点卸载它们,或添加规则来阻止它们。在大多数 Linux 发行版上,您可以通过创建诸如 /etc/modprobe.d/kubernetes-blacklist.conf 的文件来实现,内容如下:
# DCCP is unlikely to be needed, has had multiple serious
# vulnerabilities, and is not well-maintained.
blacklist dccp
# SCTP is not used in most Kubernetes clusters, and has also had
# vulnerabilities in the past.
blacklist sctp
要更通用地阻止模块加载,您可以使用 Linux 安全模块(如 SELinux)完全拒绝容器的 module_request 权限,从而防止内核为容器加载任何情况下的模块。(Pod 仍然可以使用手动加载的模块,或内核代表更特权进程加载的模块。)
限制网络访问
命名空间的 网络策略 允许应用程序作者限制其他命名空间中的 Pod 可以访问其命名空间中的 Pod 和端口。许多受支持的 Kubernetes 网络提供程序 现在都尊重网络策略。
配额和限制范围也可以用于控制用户是否可以请求节点端口或负载均衡服务,这在许多集群中可以控制这些用户应用程序是否在集群外部可见。
可能还存在其他保护措施,可以控制特定插件或环境的网络规则,例如每节点防火墙、物理隔离集群节点以防止交叉干扰,或高级网络策略。
限制云元数据 API 访问
云平台(AWS、Azure、GCE 等)通常在实例上本地公开元数据服务。默认情况下,这些 API 可供在实例上运行的 Pod 访问,并且可能包含该节点的云凭据或配置数据,例如 kubelet 凭据。这些凭据可用于在集群或同一帐户下的其他云服务中升级权限。
在云平台上运行 Kubernetes 时,请限制分配给实例凭据的权限,使用 网络策略 限制 Pod 对元数据 API 的访问,并避免使用配置数据来传递密钥。
控制 Pod 可以访问哪些节点
默认情况下,没有限制 Pod 可以运行在哪些节点上。Kubernetes 提供了 丰富的策略来控制 Pod 放置到节点上,以及 基于污点的 Pod 放置和驱逐,这些策略可供用户使用。对于许多集群,使用这些策略来分离工作负载可以成为作者采用或通过工具强制执行的约定。
作为管理员,可以使用 beta 准入插件 PodNodeSelector 来强制命名空间内的 Pod 默认或需要特定的节点选择器,如果最终用户无法更改命名空间,这可以强烈限制特定工作负载中所有 Pod 的放置。
保护集群组件免受破坏
本节描述了一些保护集群免受破坏的常见模式。
限制对 etcd 的访问
对 API 的 etcd 后端进行写入相当于获得整个集群的 root 权限,读取权限可以被快速利用来提升权限。管理员应始终使用来自 API 服务器到 etcd 服务器的强凭据,例如通过 TLS 客户端证书进行双向认证,并且通常建议将 etcd 服务器置于防火墙之后,只有 API 服务器才能访问。
注意
允许集群内的其他组件以读或写权限访问主 etcd 实例,相当于授予集群管理员权限。强烈建议使用单独的 etcd 实例来存储非主组件的数据,或者使用 etcd ACL 来限制对密钥空间子集的读写访问。启用审计日志
审计日志记录器 是一个 beta 功能,用于记录 API 执行的操作,以便在发生破坏时进行后续分析。建议启用审计日志并将其存档到安全服务器上。
限制对 alpha 或 beta 功能的访问
Alpha 和 beta Kubernetes 功能正在积极开发中,可能存在安全漏洞导致的安全限制或错误。始终评估 alpha 或 beta 功能可能提供的价值与对安全态势的潜在风险。如有疑问,请禁用您不使用的功能。
频繁轮换基础设施凭据
密钥或凭据的生命周期越短,攻击者就越难利用该凭据。为证书设置较短的生命周期并自动轮换它们。使用可以控制已颁发令牌可用时间长度的身份验证提供程序,并在可能的情况下使用较短的生命周期。如果您在外部集成中使用服务帐户令牌,请计划定期轮换这些令牌。例如,在引导阶段完成后,用于设置节点的引导令牌应被撤销或其授权被删除。
在启用第三方集成之前对其进行审查
许多 Kubernetes 的第三方集成可能会改变集群的安全状况。在启用集成时,始终在授予其访问权限之前审查扩展请求的权限。例如,许多安全集成可能会请求访问集群上的所有密钥的权限,这实际上使该组件成为集群管理员。如有疑问,尽可能将集成限制为在单个命名空间中运行。
如果它们可以在像 kube-system 命名空间这样的命名空间内执行,则可以创建 Pod 的组件也可能意外地变得非常强大,因为这些 Pod 可以访问服务帐户密钥或以提升的权限运行,如果这些服务帐户被授予访问宽松的 PodSecurityPolicies。
如果您使用 Pod 安全准入 并允许任何组件在允许特权 Pod 的命名空间内创建 Pod,则这些 Pod 可能能够逃脱其容器并使用此扩展的访问权限来提升其权限。
您不应允许不受信任的组件在任何系统命名空间(名称以 kube- 开头的命名空间)或任何允许授予访问权限可能导致权限提升的命名空间中创建 Pod。
加密静态密钥
通常,etcd 数据库将包含可通过 Kubernetes API 访问的任何信息,并且可能使攻击者能够显著了解集群的状态。始终使用经过良好审查的备份和加密解决方案来加密您的备份,并在可能的情况下考虑使用全盘加密。
Kubernetes 支持 Kubernetes API 中信息的可选 静态加密。这使您可以确保 Kubernetes 存储对象数据(例如 Secret 或 ConfigMap 对象)时,API 服务器会写入该对象的加密表示形式。这种加密意味着即使有人访问 etcd 备份数据也无法查看这些对象的内容。在 Kubernetes 1.35 中,您还可以加密自定义资源;作为 v1.26 版本的一部分,对在 CustomResourceDefinitions 中定义的扩展 API 进行静态加密已添加到 Kubernetes 中。
接收安全更新警报和报告漏洞
加入 kubernetes-announce 群组,以获取有关安全公告的电子邮件。有关如何报告漏洞的更多信息,请参阅 安全报告 页面。
接下来
- 安全检查清单,获取有关 Kubernetes 安全指南的更多信息。
- Seccomp 节点参考