保护集群

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

开始之前

  • 您需要拥有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具才能与您的集群通信。建议在至少有两个节点的集群上运行本教程,这些节点不充当控制平面主机。如果您还没有集群,可以使用 minikube 创建一个集群,或者可以使用以下 Kubernetes 游乐场之一

    要检查版本,请输入 kubectl version

控制对 Kubernetes API 的访问

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

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

Kubernetes 预期集群中的所有 API 通信默认情况下都使用 TLS 加密,大多数安装方法将允许创建必要的证书并将它们分发到集群组件。请注意,某些组件和安装方法可能会启用 HTTP 上的本地端口,管理员应熟悉每个组件的设置,以识别可能存在安全隐患的流量。

API 身份验证

选择 API 服务器要使用的身份验证机制,该机制与安装集群时的常用访问模式相匹配。例如,小型单用户集群可能希望使用简单的证书或静态承载令牌方法。较大的集群可能希望集成现有的 OIDC 或 LDAP 服务器,这些服务器允许将用户细分为组。

所有 API 客户端都必须经过身份验证,即使是基础设施的一部分,例如节点、代理、调度程序和卷插件。这些客户端通常是 服务帐户 或使用 x509 客户端证书,它们在集群启动时自动创建,或者在集群安装的一部分中进行设置。

有关更多信息,请参阅 身份验证参考文档

API 授权

经过身份验证后,每个 API 调用都应通过授权检查。Kubernetes 附带了集成的 基于角色的访问控制 (RBAC) 组件,该组件将传入的用户或组与捆绑在角色中的权限集进行匹配。这些权限将动词(get、create、delete)与资源(pod、服务、节点)结合起来,并且可以是命名空间范围的或集群范围的。提供了一组开箱即用的角色,这些角色根据客户端可能想要执行的操作,提供了合理的默认责任分离。建议您将 节点RBAC 授权者与 节点限制 准入插件一起使用。

与身份验证一样,简单而广泛的角色可能适合较小的集群,但随着更多用户与集群进行交互,可能需要将团队分离到具有更多限制角色的单独 命名空间 中。

对于授权,了解对一个对象的更新如何导致其他地方的操作非常重要。例如,用户可能无法直接创建 pod,但允许他们创建部署(代表他们创建 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 服务器可以访问的防火墙之后。

启用审计日志记录

审计记录器 是一个测试版功能,用于记录 API 所执行的操作,以便在发生安全漏洞时进行后续分析。建议启用审计日志记录并将审计文件存档到安全的服务器上。

限制对 alpha 或 beta 功能的访问

Alpha 和 beta Kubernetes 功能处于积极开发阶段,可能存在限制或错误,导致安全漏洞。始终评估 alpha 或 beta 功能可能提供的价值,并衡量其对安全态势的潜在风险。如有疑问,请禁用不使用的功能。

定期轮换基础设施凭据

秘密或凭据的生命周期越短,攻击者利用该凭据的难度就越大。为证书设置较短的生命周期,并将其轮换自动化。使用能够控制已发放令牌可用时间的身份验证提供程序,并尽可能使用较短的生命周期。如果在外部集成中使用服务帐户令牌,请计划定期轮换这些令牌。例如,在完成引导阶段后,应撤销用于设置节点的引导令牌或将其授权移除。

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

许多 Kubernetes 第三方集成可能会改变集群的安全配置文件。启用集成时,始终审查扩展请求的权限,然后再授予其访问权限。例如,许多安全集成可能请求访问集群上的所有秘密,这实际上会使该组件成为集群管理员。如有疑问,请尽可能将集成限制在单个命名空间内运行。

如果组件能够在 kube-system 等命名空间内创建 Pod,则这些组件可能意外地变得非常强大,因为这些 Pod 可以访问服务帐户秘密或使用提升的权限运行(如果这些服务帐户被授予对宽松的 PodSecurityPolicies 的访问权限)。

如果使用 Pod 安全准入 并允许任何组件在允许特权 Pod 的命名空间内创建 Pod,则这些 Pod 可能会逃脱其容器,并利用这种扩展的访问权限来提升其权限。

不应允许不受信任的组件在任何系统命名空间(名称以 kube- 开头的命名空间)中创建 Pod,也不应允许在任何授予访问权限的命名空间中创建 Pod,因为这些访问权限可能会导致权限提升。

加密静态秘密

通常,etcd 数据库将包含通过 Kubernetes API 可访问的任何信息,并且可能会向攻击者提供对集群状态的显著可见性。始终使用经过良好审查的备份和加密解决方案加密备份,并尽可能考虑使用全磁盘加密。

Kubernetes 支持可选的 静态加密,用于存储在 Kubernetes API 中的信息。这使您能够确保 Kubernetes 为对象(例如,SecretConfigMap 对象)存储数据时,API 服务器会写入对象的加密表示形式。该加密意味着即使是能够访问 etcd 备份数据的用户也无法查看这些对象的内容。在 Kubernetes 1.31 中,您还可以加密自定义资源;自定义资源定义中定义的扩展 API 的静态加密已作为 v1.26 版本的一部分添加到 Kubernetes 中。

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

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

下一步

上次修改时间:2023 年 4 月 30 日下午 10:20 PST:在保护集群和安全检查清单之间添加链接 (19a3dc0f6f)