保护集群

本文档涵盖了保护集群免受意外或恶意访问的相关主题,并提供了整体安全建议。

准备工作

  • 你需要拥有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以便与集群通信。建议在至少有两个非控制平面主机的节点集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用以下 Kubernetes 演练场之一:

    要检查版本,请输入 kubectl version

控制对 Kubernetes API 的访问

由于 Kubernetes 完全由 API 驱动,控制和限制谁可以访问集群以及他们被允许执行哪些操作是第一道防线。

对所有 API 流量使用传输层安全性 (TLS)

Kubernetes 要求集群中的所有 API 通信默认使用 TLS 加密,并且大多数安装方法将允许创建必要的证书并分发给集群组件。请注意,某些组件和安装方法可能通过 HTTP 启用本地端口,管理员应熟悉每个组件的设置以识别潜在的不安全流量。

API 认证

在安装集群时,选择与常见访问模式相匹配的 API 服务器认证机制。例如,小型单用户集群可能希望使用简单的证书或静态不记名令牌方法。大型集群可能希望集成现有的 OIDC 或 LDAP 服务器,以便将用户细分为组。

所有 API 客户端都必须经过认证,即使是构成基础设施一部分的客户端(例如节点、代理、调度器和卷插件)也是如此。这些客户端通常是服务账号(service accounts) 或使用 x509 客户端证书,它们在集群启动时自动创建,或作为集群安装的一部分进行设置。

有关更多信息,请查阅认证参考文档

API 鉴权

认证后,每个 API 调用也需要通过鉴权检查。Kubernetes 内置了集成的基于角色的访问控制 (RBAC) 组件,该组件将传入的用户或组与捆绑到角色中的一组权限进行匹配。这些权限将动词(get、create、delete)与资源(pod、service、node)结合起来,并且可以是命名空间级别或集群级别的。提供了一组开箱即用的角色,根据客户端可能要执行的操作,提供合理的默认职责分离。建议将NodeRBAC 鉴权器结合使用,并与 NodeRestriction 准入插件结合使用。

与认证类似,对于较小的集群,简单而宽泛的角色可能适用,但随着更多用户与集群交互,可能需要将团队分离到独立的命名空间中,并采用更受限的角色。

进行鉴权时,重要的是理解一个对象的更新如何可能导致其他地方的操作。例如,用户可能无法直接创建 pod,但如果允许他们创建一个代表他们创建 pod 的 Deployment,他们就可以间接创建这些 pod。同样,从 API 中删除节点将导致调度到该节点的 pod 被终止并在其他节点上重新创建。开箱即用的角色代表了灵活性和常见用例之间的平衡,但应仔细审查更受限的角色,以防止意外的权限升级。如果开箱即用的角色不满足你的需求,你可以根据你的用例创建特定角色。

有关更多信息,请查阅鉴权参考部分

控制对 Kubelet 的访问

Kubelet 暴露 HTTPS 端点,这些端点授予对节点和容器的强大控制权。默认情况下,Kubelet 允许未经认证的访问该 API。

生产集群应启用 Kubelet 认证和鉴权。

有关更多信息,请查阅Kubelet 认证/鉴权参考

在运行时控制工作负载或用户的能力

Kubernetes 中的鉴权级别较高,侧重于对资源进行粗粒度操作。更强大的控制存在于策略(policies)中,通过用例限制这些对象如何作用于集群本身和其他资源。

限制集群上的资源使用

资源配额(Resource quota)限制授予命名空间的资源数量或容量。这最常用于限制命名空间可以分配的 CPU、内存或持久盘的数量,但也可以控制每个命名空间中存在的 pod、service 或 volume 的数量。

限制范围(Limit ranges)限制上述某些资源的最大或最小大小,以防止用户请求常用保留资源(如内存)的不合理高或低值,或在未指定时提供默认限制。

控制容器运行所需的特权

Pod 定义包含一个安全上下文(security context),允许其请求以节点上的特定 Linux 用户(如 root)身份运行、访问特权或访问主机网络,以及其他控制,否则这些控制将允许它在主机节点上不受限制地运行。

你可以配置Pod 安全准入(Pod security admission)来强制在命名空间中使用特定的Pod 安全标准(Pod Security Standard),或检测违规行为。

通常,大多数应用工作负载需要对主机资源的有限访问权限,以便它们可以成功地作为 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 仍然可以使用手动加载的模块,或者由内核代表某些更高特权进程加载的模块。)

限制网络访问

命名空间的网络策略(network policies)允许应用开发者限制其他命名空间中的哪些 pod 可以访问其命名空间中的 pod 和端口。许多受支持的Kubernetes 网络提供商现在都遵守网络策略。

配额和限制范围也可以用于控制用户是否可以请求 node port 或 load-balanced service,这在许多集群上可以控制这些用户的应用是否在集群外部可见。

可能还存在额外的保护措施,可以根据插件或环境控制网络规则,例如每个节点的防火墙、物理隔离集群节点以防止交叉通信或高级网络策略。

限制云元数据 API 访问

云平台(AWS、Azure、GCE 等)通常会向实例本地暴露元数据服务。默认情况下,运行在实例上的 pod 可以访问这些 API,并且这些 API 可能包含该节点的云凭证或 kubelet 凭证等配置数据。这些凭证可用于在集群内或同一账户下的其他云服务中进行权限提升。

在云平台上运行 Kubernetes 时,请限制授予实例凭证的权限,使用网络策略限制 pod 对元数据 API 的访问,并避免使用配置数据传递 Secret。

控制 Pod 可以访问哪些节点

默认情况下,对于可以在哪些节点上运行 pod 没有限制。Kubernetes 提供了一组丰富的策略来控制 Pod 在节点上的调度以及最终用户可以使用的基于污点(taint)的 pod 调度和驱逐。对于许多集群,使用这些策略来分离工作负载可以成为开发者采用或通过工具强制执行的约定。

作为管理员,可以使用 Beta 版准入插件 PodNodeSelector 来强制命名空间中的 pod 默认或要求特定的节点选择器,如果最终用户无法修改命名空间,这可以极大地限制特定工作负载中所有 pod 的调度位置。

保护集群组件免受威胁

本节介绍了一些保护集群免受威胁的常见模式。

限制对 etcd 的访问

对 API 的 etcd 后端具有写访问权限等同于在整个集群上获得 root 权限,读访问权限也可用于快速提升权限。管理员应始终使用从 API 服务器到其 etcd 服务器的强凭证,例如通过 TLS 客户端证书进行相互认证,并且通常建议将 etcd 服务器隔离在只有 API 服务器可以访问的防火墙后面。

启用审计日志记录

审计日志记录器(audit logger)是一个 Beta 功能,它记录 API 执行的操作,以便在发生威胁时进行后续分析。建议启用审计日志记录并将审计文件归档到安全的服务器上。

限制对 Alpha 或 Beta 特性的访问

Alpha 和 Beta 版 Kubernetes 特性处于积极开发中,可能存在导致安全漏洞的限制或 bug。始终要权衡 Alpha 或 Beta 特性可能带来的价值与对你的安全状况可能造成的风险。如有疑问,请禁用不使用的特性。

频繁轮换基础设施凭证

Secret 或凭证的生命周期越短,攻击者就越难利用该凭证。设置证书的短生命周期并自动化其轮换。使用可以控制已颁发令牌可用时长的认证提供商,并尽可能使用短生命周期。如果在外部集成中使用服务账号令牌,请计划频繁轮换这些令牌。例如,一旦启动阶段完成,用于设置节点的引导令牌应被撤销或移除其鉴权。

启用第三方集成前进行审查

许多第三方 Kubernetes 集成可能会改变你的集群的安全配置。启用集成时,在授予访问权限之前,务必审查扩展请求的权限。例如,许多安全集成可能会请求查看你集群上所有 Secret 的权限,这实际上使该组件成为 cluster admin。如有疑问,如果可能的话,将集成限制在单个命名空间中运行。

如果可以创建 pod 的组件能在诸如 kube-system 命名空间之类的命名空间中创建 pod,它们也可能会出乎意料地强大,因为这些 pod 可以访问服务账号 Secret,或者如果这些服务账号被授予访问许可的PodSecurityPolicies的权限,它们就可以以更高的权限运行。

如果你使用Pod 安全准入并允许任何组件在允许特权 Pod 的命名空间中创建 Pod,这些 Pod 可能能够逃逸其容器并利用此扩大的访问权限提升其特权。

你不应允许不受信任的组件在任何系统命名空间(名称以 kube- 开头的命名空间)或任何允许权限提升的命名空间中创建 Pod。

加密静态 Secret

通常,etcd 数据库将包含可通过 Kubernetes API 访问的所有信息,并可能让攻击者对你的集群状态有重要可见性。务必使用经过充分审查的备份和加密解决方案来加密你的备份,并考虑在可能的情况下使用全盘加密。

Kubernetes 支持对 Kubernetes API 中的信息进行可选的静态加密(encryption at rest)。这使你能够确保当 Kubernetes 存储对象(例如,SecretConfigMap 对象)的数据时,API 服务器会写入对象的加密表示。这种加密意味着即使有权访问 etcd 备份数据的人也无法查看这些对象的内容。在 Kubernetes 1.33 中,你还可以加密自定义资源;作为 v1.26 版本的一部分,Kubernetes 添加了对 CustomResourceDefinitions 中定义的扩展 API 的静态加密。

接收安全更新警报和报告漏洞

加入 kubernetes-announce 组以接收关于安全公告的电子邮件。有关如何报告漏洞的更多信息,请参阅安全报告页面。

下一步

上次修改时间:太平洋标准时间 2024 年 9 月 17 日上午 10:57:添加专用的 seccomp 节点参考 (c2b49fee37)