保护集群
本文档涵盖了与保护集群免受意外或恶意访问相关的主题,并提供了关于整体安全性的建议。
准备工作
你需要拥有一个 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)与资源(pods、services、nodes)结合起来,并且可以是命名空间范围或集群范围的。提供了一组开箱即用的角色,这些角色根据客户端可能希望执行的操作,提供了合理的默认职责分离。建议你结合使用节点和RBAC授权器,以及NodeRestriction准入插件。
与认证一样,简单而广泛的角色可能适用于小型集群,但随着更多用户与集群交互,可能需要将团队分成不同的命名空间,并使用更受限制的角色。
在授权方面,了解一个对象的更新如何导致其他地方的操作非常重要。例如,用户可能无法直接创建 Pod,但允许他们创建代表他们创建 Pod 的 Deployment 将允许他们间接创建这些 Pod。同样,从 API 中删除一个节点将导致调度到该节点的 Pod 被终止并在其他节点上重新创建。开箱即用的角色在灵活性和常见用例之间取得了平衡,但应仔细审查更受限制的角色,以防止意外的权限提升。如果开箱即用的角色不满足你的需求,你可以为你的用例定制角色。
请查阅授权参考部分获取更多信息。
控制对 Kubelet 的访问
Kubelet 暴露 HTTPS 端点,这些端点对节点和容器拥有强大的控制权。默认情况下,Kubelet 允许对该 API 进行未认证访问。
生产集群应启用 Kubelet 认证和授权。
请查阅Kubelet 认证/授权参考获取更多信息。
在运行时控制工作负载或用户的能力
Kubernetes 中的授权有意地保持高级别,侧重于资源的粗粒度操作。更强大的控制措施以策略的形式存在,通过用例来限制这些对象如何作用于集群本身和其他资源。
限制集群上的资源使用
资源配额限制了分配给命名空间的资源数量或容量。这通常用于限制命名空间可以分配的 CPU、内存或持久磁盘量,但也可以控制每个命名空间中存在的 Pod、Service 或 Volume 的数量。
限制范围限制了上述某些资源的最大或最小大小,以防止用户请求内存等常用保留资源的不合理高或低值,或者在未指定默认值时提供默认限制。
控制容器以哪些权限运行
Pod 定义包含一个安全上下文,它允许 Pod 请求以特定 Linux 用户身份(如 root)在节点上运行的访问权限,请求运行特权或访问主机网络的访问权限,以及其他控制措施,否则这些控制措施将允许 Pod 在托管节点上不受限制地运行。
你可以配置Pod 安全准入,以在命名空间中强制使用特定的Pod 安全标准,或检测违规行为。
通常,大多数应用程序工作负载需要对主机资源进行有限的访问,以便它们可以作为 root 进程(uid 0)成功运行,而无需访问主机信息。但是,考虑到与 root 用户相关的特权,你应该编写应用程序容器以非 root 用户身份运行。同样,希望防止客户端应用程序逃离其容器的管理员应应用基线或受限Pod 安全标准。
阻止容器加载不需要的内核模块
在某些情况下,例如当连接了硬件或挂载了文件系统时,Linux 内核会自动从磁盘加载内核模块。对于 Kubernetes 来说,即使是非特权进程也可以通过创建适当类型的 socket 导致某些与网络协议相关的内核模块被加载。这可能允许攻击者利用管理员认为未使用的内核模块中的安全漏洞。
要防止特定模块自动加载,你可以将其从节点中卸载,或添加规则来阻止它们。在大多数 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 的访问,并避免使用预置数据来传递 Secret。
控制 Pod 可以访问哪些节点
默认情况下,对 Pod 可以在哪些节点上运行没有限制。Kubernetes 为最终用户提供了一套丰富的策略来控制 Pod 在节点上的放置以及基于污点的 Pod 放置和驱逐。对于许多集群来说,使用这些策略来分离工作负载可以是一种作者采用或通过工具强制执行的约定。
作为管理员,可以使用 Beta 版准入插件 PodNodeSelector
来强制命名空间中的 Pod 默认或要求特定的节点选择器,如果最终用户无法修改命名空间,这可以强烈限制特定工作负载中所有 Pod 的放置位置。
保护集群组件免受入侵
本节介绍了一些用于保护集群免受入侵的常见模式。
限制对 etcd 的访问
对 API 的 etcd 后端的写入权限等同于获得整个集群的 root 权限,而读取权限可以快速用于权限提升。管理员应该始终使用从 API 服务器到 etcd 服务器的强凭据,例如通过 TLS 客户端证书进行相互认证,并且通常建议将 etcd 服务器隔离在防火墙后面,只有 API 服务器才能访问。
注意
允许集群中的其他组件以读写访问整个键空间的方式访问主 etcd 实例,等同于授予 cluster-admin 权限。强烈建议为非主组件使用单独的 etcd 实例,或者使用 etcd ACLs 限制对键空间子集的读写访问。启用审计日志
审计日志是一个 Beta 功能,它记录 API 执行的操作,以便在发生入侵时进行后续分析。建议启用审计日志并将审计文件存档到安全服务器上。
限制对 Alpha 或 Beta 功能的访问
Alpha 和 Beta Kubernetes 功能处于积极开发中,可能存在导致安全漏洞的限制或错误。在评估 Alpha 或 Beta 功能可能提供的价值时,始终要权衡其对安全状况的潜在风险。如有疑问,请禁用你不使用的功能。
频繁轮换基础设施凭证
秘密或凭证的生命周期越短,攻击者利用该凭证就越困难。设置较短的证书生命周期并自动化其轮换。使用可以控制颁发令牌可用时长的认证提供商,并在可能的情况下使用较短的生命周期。如果你在外部集成中使用服务账号令牌,请计划频繁轮换这些令牌。例如,一旦引导阶段完成,用于设置节点的引导令牌应该被撤销或移除其授权。
在启用第三方集成之前进行审查
许多 Kubernetes 第三方集成可能会改变集群的安全配置文件。在启用集成时,始终在授予其访问权限之前审查扩展请求的权限。例如,许多安全集成可能会请求查看集群中所有 Secret 的权限,这实际上使该组件成为集群管理员。如有疑问,请尽可能将集成限制为在单个命名空间中运行。
如果创建 Pod 的组件能够在像 kube-system
这样的命名空间中创建 Pod,它们也可能拥有意想不到的强大能力,因为这些 Pod 可以获得服务账号 Secret 的访问权限,或者在这些服务账号被授予宽松的PodSecurityPolicies访问权限时以提升的权限运行。
如果你使用Pod 安全准入并允许任何组件在允许特权 Pod 的命名空间中创建 Pod,这些 Pod 可能会逃离其容器并使用这种扩大的访问权限来提升其特权。
你不应允许不受信任的组件在任何系统命名空间(名称以 kube-
开头的命名空间)或任何允许权限提升的命名空间中创建 Pod。
对静态数据进行加密
通常,etcd 数据库将包含通过 Kubernetes API 可访问的任何信息,并可能使攻击者对集群的状态获得重要可见性。始终使用经过充分审查的备份和加密解决方案来加密备份,并考虑在可能的情况下使用全盘加密。
Kubernetes 支持可选的静态加密,用于 Kubernetes API 中的信息。这可以确保当 Kubernetes 存储对象数据(例如,Secret
或 ConfigMap
对象)时,API 服务器会写入对象的加密表示。这种加密意味着即使有人访问了 etcd 备份数据也无法查看这些对象的内容。在 Kubernetes 1.34 中,你还可以加密自定义资源;CustomResourceDefinitions 中定义的扩展 API 的静态加密是作为 v1.26 版本的一部分添加到 Kubernetes 中的。
接收安全更新警报和报告漏洞
加入 kubernetes-announce 组以获取安全公告的电子邮件。有关如何报告漏洞的更多信息,请参阅安全报告页面。
下一步
- 有关 Kubernetes 安全指南的更多信息,请参阅安全清单。
- Seccomp 节点参考