安全清单

确保 Kubernetes 集群安全性的基准检查清单。

本清单旨在提供一份基础指南列表,并链接到每个主题更全面的文档。它不求面面俱到,并会随时间不断演进。

关于如何阅读和使用本文档

  • 主题的顺序并不代表优先级。
  • 部分检查项在每个章节列表下方的段落中有详细说明。

注意

仅凭检查清单本身不足以获得良好的安全态势。良好的安全态势需要持续的关注和改进,但清单可以是通往安全备战这一永无止境旅程的第一步。本清单中的某些建议对于您的具体安全需求来说可能过于严格或过于宽松。由于 Kubernetes 安全并非“一刀切”,因此每一类检查项都应根据其实际价值进行评估。

认证与授权

  • 引导启动(bootstrapping)后,不再使用 system:masters 组进行用户或组件认证。
  • kube-controller-manager 运行时启用了 --use-service-account-credentials
  • 根证书受到保护(使用离线 CA,或带有有效访问控制的受管在线 CA)。
  • 中间证书和叶证书的过期时间不超过未来 3 年。
  • 存在定期访问审查流程,且审查间隔不超过 24 个月。
  • 遵循 基于角色的访问控制 (RBAC) 最佳实践 以获取有关认证和授权的指导。

引导启动后,用户和组件都不应以 system:masters 身份向 Kubernetes API 进行身份验证。同样,应避免以 system:masters 身份运行整个 kube-controller-manager。事实上,system:masters 仅应作为紧急访问机制(break-glass mechanism)使用,而非作为管理员用户使用。

网络安全

  • 所使用的 CNI 插件支持网络策略。
  • 集群中的所有工作负载都应用了入站和出站网络策略。
  • 在每个命名空间内设置了默认网络策略,选择所有 Pod,拒绝所有通信。
  • 如果合适,使用服务网格(Service Mesh)对集群内部的所有通信进行加密。
  • Kubernetes API、kubelet API 和 etcd 未公开暴露在互联网上。
  • 过滤了工作负载对云元数据 API 的访问。
  • 限制了 LoadBalancer 和 ExternalIPs 的使用。

许多 容器网络接口 (CNI) 插件 提供了限制 Pod 可通信网络资源的功能。这通常通过 网络策略 (Network Policies) 来实现,它提供了一种命名空间作用域的资源来定义规则。在每个命名空间中,通过选择所有 Pod 并阻止所有出站和入站流量的默认网络策略,可以有效地采用“允许列表”方法,以确保没有遗漏任何工作负载。

并非所有 CNI 插件都提供传输加密。如果所选插件缺少此功能,可以使用服务网格作为替代方案来实现该功能。

控制平面的 etcd 数据存储应具备访问限制,且不应在互联网上公开暴露。此外,应使用双向 TLS (mTLS) 与其进行安全通信。为此所使用的证书颁发机构应当是 etcd 专用的。

对 Kubernetes API 服务器的外部互联网访问应受到限制,不得公开暴露 API。请注意,许多托管 Kubernetes 发行版默认会公开暴露 API 服务器。此时,您可以使用堡垒机(Bastion host)来访问服务器。

应当限制 kubelet API 的访问,且不得公开暴露。当未通过 --config 标志指定配置文件时,默认的认证和授权设置过于宽松。

如果使用云服务商托管 Kubernetes,则还应限制或阻止 Pod 对云元数据 API 169.254.169.254 的访问(如果不需要),因为它可能泄露信息。

关于限制 LoadBalancer 和 ExternalIPs 的使用,请参阅 CVE-2020-8554: 使用 LoadBalancer 或 ExternalIPs 的中间人攻击 以及 DenyServiceExternalIPs 准入控制器 获取更多信息。

Pod 安全

  • 仅在必要时授予对工作负载进行 createupdatepatchdelete 的 RBAC 权限。
  • 所有命名空间都应用并强制执行了适当的 Pod 安全标准策略。
  • 为工作负载设置了内存限制,且限制值等于或小于请求值。
  • 可能对敏感工作负载设置了 CPU 限制。
  • 对于支持的节点,启用了 Seccomp 并为程序配置了适当的系统调用配置文件。
  • 对于支持的节点,启用了 AppArmor 或 SELinux 并为程序配置了适当的配置文件。

RBAC 授权至关重要,但 无法精细到对 Pod 资源(或任何管理 Pod 的资源)进行授权。唯一的细粒度限制是资源本身的 API 动词,例如 Pod 的 create。如果没有额外的准入控制,创建这些资源的授权将允许直接且不受限制地访问集群中可调度的节点。

Pod 安全标准 定义了三种不同的策略:特权(privileged)、基准(baseline)和受限(restricted),限制了 PodSpec 中安全相关字段的设置方式。这些标准可以通过默认启用的 Pod 安全准入 在命名空间级别强制执行,也可以通过第三方准入 Webhook 强制执行。请注意,与它所取代的已移除的 PodSecurityPolicy 准入不同,Pod 安全 准入可以轻松地与准入 Webhook 和外部服务结合使用。

Pod 安全准入的 restricted 策略是 Pod 安全标准 中限制最严的策略,它 可以在多种模式下运行,包括 warn(警告)、audit(审计)或 enforce(强制执行),从而根据安全最佳实践逐步应用最合适的 安全上下文。尽管如此,仍应针对特定用例单独研究 Pod 的 安全上下文,以限制 Pod 在预定义安全标准之上的额外特权和访问权限。

有关 Pod 安全 的实践教程,请参阅博客文章 Kubernetes 1.23:Pod 安全准入进入 Beta 阶段

应设置 内存和 CPU 限制,以限制 Pod 在节点上可消耗的资源,从而防止来自恶意或被入侵工作负载的潜在 DoS 攻击。此类策略可由准入控制器强制执行。请注意,CPU 限制将限制使用率,因此可能会对自动伸缩功能或效率产生意外影响,例如在可用 CPU 资源下以“尽力而为(best effort)”方式运行进程。

注意

内存限制高于请求值可能会使整个节点面临 OOM(内存溢出)问题。

启用 Seccomp

Seccomp 代表安全计算模式(secure computing mode),自 Linux 内核版本 2.6.12 起已成为其功能的一部分。它可用于沙盒化进程的特权,限制其从用户空间对内核进行的系统调用。Kubernetes 允许您自动将节点上加载的 seccomp 配置文件应用于 Pod 和容器。

Seccomp 可以通过减少容器内可用的 Linux 内核系统调用攻击面来提高工作负载的安全性。Seccomp 过滤器模式利用 BPF 创建特定系统调用的允许或拒绝列表,即配置文件。

自 Kubernetes 1.27 起,您可以启用 RuntimeDefault 作为所有工作负载的默认 seccomp 配置文件。该主题有一个 安全教程。此外,Kubernetes 安全配置文件操作符 (Security Profiles Operator) 项目旨在简化集群中 seccomp 的管理和使用。

说明

Seccomp 仅在 Linux 节点上可用。

启用 AppArmor 或 SELinux

AppArmor

AppArmor 是一个 Linux 内核安全模块,可以提供一种简单的方法来实现强制访问控制 (MAC),并通过系统日志实现更好的审计。在支持的节点上强制执行默认 AppArmor 配置文件,也可以配置自定义配置文件。与 seccomp 一样,AppArmor 也是通过配置文件进行配置的,每个配置文件要么在强制模式(enforcing mode)下运行(阻止对不允许资源的访问),要么在抱怨模式(complain mode)下运行(仅报告违规)。AppArmor 配置文件通过注释以容器为单位进行强制执行,允许进程仅获得所需的权限。

说明

AppArmor 仅在 Linux 节点上可用,并且在 某些 Linux 发行版 中启用。

SELinux

SELinux 同样是一个 Linux 内核安全模块,可提供支持访问控制安全策略的机制,包括强制访问控制 (MAC)。SELinux 标签可以通过其 securityContext 部分 分配给容器或 Pod。

说明

SELinux 仅在 Linux 节点上可用,并且在 某些 Linux 发行版 中启用。

日志与审计

  • 如果启用了审计日志,则会对其进行保护,防止一般访问。

Pod 放置

  • Pod 的放置是根据应用程序的敏感程度分层进行的。
  • 敏感应用程序在隔离的节点上运行,或使用特定的沙盒运行时。

属于不同敏感级别的 Pod(例如应用程序 Pod 和 Kubernetes API 服务器)应部署到不同的节点上。节点隔离的目的是防止应用程序容器逃逸后,直接获得对敏感级别更高的应用程序的访问权限,从而在集群内轻松横向移动。应强制执行这种分离,以防止 Pod 被意外部署到同一节点上。这可以通过以下功能来强制执行:

节点选择器 (Node Selectors)
作为 Pod 规范的一部分,键值对指定了要部署到的节点。这些可以通过 PodNodeSelector 准入控制器在命名空间和集群级别进行强制执行。
Pod 容忍度限制 (PodTolerationRestriction)
一种准入控制器,允许管理员限制命名空间内允许的 容忍度 (Tolerations)。命名空间内的 Pod 只能使用命名空间对象注释键中指定的容忍度,该键提供了一组默认和允许的容忍度。
RuntimeClass
RuntimeClass 是用于选择容器运行时配置的功能。容器运行时配置用于运行 Pod 的容器,可以在性能开销的代价下提供相对于主机的更多或更少隔离。

Secrets

  • ConfigMap 不用于保存机密数据。
  • Secret API 配置了静态加密(Encryption at rest)。
  • 如果合适,部署了可用的第三方存储机密注入机制。
  • 不需要的服务账户令牌不会挂载到 Pod 中。
  • 正在使用 绑定服务账户令牌卷 (Bound service account token volume),而非不过期的令牌。

Pod 所需的机密应存储在 Kubernetes Secrets 中,而不是 ConfigMap 等替代方案中。存储在 etcd 中的 Secret 资源应 在静态时加密

需要机密的 Pod 应通过卷自动挂载这些机密,最好存储在内存中,例如使用 emptyDir.medium 选项。也可以使用诸如 Secrets Store CSI Driver 之类的机制将第三方存储中的机密作为卷注入。这比赋予 Pod 服务账户 RBAC 访问机密的权限更为优先。这样可以将机密作为环境变量或文件添加到 Pod 中。请注意,环境变量方法更容易因日志中的崩溃转储而导致泄露,且在 Linux 中环境变量不具备机密性,这与文件的权限机制不同。

服务账户令牌不应挂载到不需要它们的 Pod 中。这可以通过在服务账户内设置 automountServiceAccountTokenfalse(以在整个命名空间应用)或专门为某个 Pod 设置来配置。对于 Kubernetes v1.22 及更高版本,请使用 绑定服务账户 (Bound Service Accounts) 获取限时的服务账户凭据。

镜像

  • 最小化容器镜像中不必要的内容。
  • 容器镜像配置为以非特权用户身份运行。
  • 对容器镜像的引用采用 sha256 摘要(而非标签),或通过在部署时 通过准入控制 验证镜像的数字签名来验证其来源。
  • 在创建和部署期间定期扫描容器镜像,并修复已知的易受攻击软件。

容器镜像应包含打包程序所需的最少量内容。最好只包含程序及其依赖项,并从尽可能小的基础镜像构建。特别是,生产环境中使用的镜像不应包含 Shell 或调试工具,因为可以使用 临时调试容器 (Ephemeral debug container) 进行故障排除。

使用 Dockerfile 中的 USER 指令 构建镜像,使其直接以非特权用户身份启动。即使未在镜像清单中指定,安全上下文 (Security Context) 也允许通过 runAsUserrunAsGroup 以特定的用户和组启动容器镜像。但是,镜像层中的文件权限可能会导致在不修改镜像的情况下,无法以新非特权用户身份直接启动进程。

避免使用镜像标签来引用镜像,尤其是 latest 标签,因为标签背后的镜像可以在注册表中轻松修改。建议使用镜像清单独有的完整 sha256 摘要。此策略可通过 ImagePolicyWebhook 强制执行。镜像签名也可以在部署时通过准入控制器自动 验证,以确认其真实性和完整性。

扫描容器镜像可以防止关键漏洞随容器镜像一起部署到集群中。镜像扫描应在将容器镜像部署到集群之前完成,并且通常作为 CI/CD 流水线中部署过程的一部分执行。镜像扫描的目的是获取有关容器镜像中可能存在的漏洞及其预防措施的信息,例如 通用漏洞评分系统 (CVSS) 分数。如果将镜像扫描结果与流水线合规规则相结合,则只有经过适当补丁修复的容器镜像才会进入生产环境。

准入控制器

  • 启用了适当的准入控制器选择。
  • Pod 安全策略由 Pod 安全准入或/和 Webhook 准入控制器强制执行。
  • 准入链插件和 Webhook 已安全配置。

准入控制器有助于提高集群的安全性。然而,它们本身也可能带来风险,因为它们扩展了 API 服务器,并且 应妥善保护它们

以下列表介绍了可以考虑增强集群和应用程序安全态势的若干准入控制器。它包括本文档其他部分可能引用的控制器。

第一组准入控制器包括 默认启用 的插件,除非您明确知道自己在做什么,否则请考虑保持启用状态:

CertificateApproval
执行额外的授权检查,以确保审批用户有权批准证书请求。
CertificateSigning
执行额外的授权检查,以确保签名用户有权签署证书请求。
CertificateSubjectRestriction
拒绝任何指定 system:masters 组(或“组织属性”)的证书请求。
LimitRanger
强制执行 LimitRange API 约束。
MutatingAdmissionWebhook
允许通过 Webhook 使用自定义控制器,这些控制器可能会修改其审查的请求。
PodSecurity(Pod 安全)
作为 Pod 安全策略的替代品,限制已部署 Pod 的安全上下文。
ResourceQuota
强制执行资源配额以防止资源过度使用。
ValidatingAdmissionWebhook
允许通过 Webhook 使用自定义控制器,这些控制器不会修改其审查的请求。

第二组包括默认未启用但处于通用可用(GA)状态的插件,建议用于提高您的安全态势:

DenyServiceExternalIPs
拒绝所有对 Service.spec.externalIPs 字段的新增使用。这是对 CVE-2020-8554: 使用 LoadBalancer 或 ExternalIPs 的中间人攻击 的缓解措施。
NodeRestriction
限制 kubelet 的权限,使其只能修改其拥有的 Pod API 资源或代表其自身的 Node API 资源。它还防止 kubelet 使用 node-restriction.kubernetes.io/ 注释,该注释可能会被攻击者利用访问 kubelet 凭据来影响 Pod 到受控节点的放置。

第三组包括默认未启用但可在特定用例中考虑的插件:

AlwaysPullImages
强制使用带标签镜像的最新版本,并确保部署者有权使用该镜像。
ImagePolicyWebhook
允许通过 Webhook 对镜像强制执行额外的控制。

接下来


最后修改于 2025 年 2 月 28 日下午 6:03(太平洋标准时间):更新 security-checklist.md (7adba34538)