使用部署安全措施在 Azure Kubernetes 服务(AKS)中强制实施最佳做法

本文介绍如何使用部署安全措施在 Azure Kubernetes 服务 (AKS) 群集上强制实施最佳做法。

概述

注意事项

默认情况下,在 AKS 自动中启用部署安全措施。

在整个开发生命周期中,如果 Kubernetes 资源的初始部署存在配置错误,则常会出现漏洞和其他问题。 为了减轻 Kubernetes 开发的负担,Azure Kubernetes 服务 (AKS) 提供部署保障。 部署安全措施通过 Azure Policy 控制在 AKS 群集中强制实施 Kubernetes 最佳做法。

部署保障提供两个级别的配置:

  • Warn:在代码终端中显示警告消息,提醒你有不合规的群集配置,但仍允许请求通过。
  • Enforce:如果部署不遵循最佳做法,则通过拒绝和变更部署来强制实施合规配置。

为“警告”或“强制”配置部署安全措施后,部署安全措施会在创建或更新时以编程方式评估 Kubernetes 资源,以满足合规性要求。 部署保障还通过 Azure 门户 或 CLI 或终端中的 Azure Policy 合规性仪表板在每个资源级别显示跨工作负荷的聚合符合性信息。 运行不符合的工作负荷表示群集未遵循最佳做法,并且群集上的工作负荷面临群集配置导致的问题的风险。

先决条件

注意事项

群集管理员不需要 Azure Policy 权限来启用或禁用部署保护。 但是,需要安装 Azure Policy 加载项。

  • 你需要为 AKS 启用 Azure Policy 加载项。 有关详细信息,请参阅启用 AKS 群集上的 Azure Policy。 这包括在订阅中注册 Microsoft.PolicyInsights 资源供应商。

部署保障策略

下表列出了启用部署保护时,哪些策略会生效,以及它们所针对的 Kubernetes 资源。 可以在 Azure 门户中将 当前可用的部署安全措施 作为 Azure Policy 定义或在 Azure Kubernetes 服务的 Azure Policy 内置定义中查看。 此集合背后的意图是创建适用于大多数用户和用例的常见和通用最佳做法列表。

部署安全措施策略 变更后的结果(如果有)
无法编辑单个节点 空值
必须定义 Kubernetes 群集容器 CPU 和内存资源请求 设置默认 CPU 和内存请求并强制实施最小值。 有关详细信息,请参阅 资源请求可变器
必须具有反关联规则或 topologySpreadConstraintsSet 添加 Pod 反关联规则和拓扑分布约束,以提高工作负荷分布。 有关详细信息,请参阅 反相关性和拓扑分散变异器
无特定于 AKS 的标签 空值
Kubernetes 群集容器应只使用允许的映像 空值
保留的系统池标记 如果未设置,则从用户节点池中删除 CriticalAddonsOnly 污点。 AKS 使用 CriticalAddonsOnly 污点让客户 Pod 远离系统池。 此配置可确保 AKS 组件与客户 Pod 之间的明确分离,并防止驱逐不能容忍 CriticalAddonsOnly 污点的客户 Pod。
确保群集容器已配置就绪情况或运行情况探测 空值
Kubernetes 群集应使用容器存储接口 (CSI) 驱动程序 StorageClass 空值
Kubernetes 群集服务应使用唯一选择器 空值
Kubernetes 群集容器映像不应包含最新的映像标记 空值

如果要提交有关部署保障的想法或请求,请在 AKS GitHub 存储库 中打开一个问题,并在标题的开头添加 [Deployment Safeguards request]

资源请求可变器

将部署保护措施设置为 Enforce 级别时,资源请求可变器会自动设置 CPU 和内存请求以及未定义这些请求的容器的限制,或者其值低于最低阈值。

默认值

如果未指定任何资源,则 mutator 将设置以下默认值:

资源 请求 限度
CPU 500m 500m
内存 2048Mi (2Gi) 2048Mi (2Gi)

最低强制措施

指定资源但低于阈值时,可变器将强制实施以下最小值:

资源 最小值
CPU 100米
内存 100Mi

了解资源单位

CPU 单位

  • m = millicores (1m = CPU 核心的千分之一)
  • 1000m = 1 个完整 CPU 核心
  • 500m = 0.5 CPU 核心(半核)
  • 100m = 0.1 个 CPU 核心(核心的 10%)

内存单位

  • Mi = Mebibytes (binary: 1 Mi = 1,024 × 1,024 字节)
  • Gi = Gibibytes (binary: 1 Gi = 1,024 Mi)
  • 2048Mi = 2Gi
  • 100Mi ≈ 105 MB

CPU 变异规则

可变器对 CPU 资源应用以下逻辑:

Scenario Action
CPU 请求和限制都缺失 将这两者都设置为 500m (默认值)
CPU 请求存在,但小于 100m 将请求设置为 100m (最小值)
CPU 限制存在,但小于 100m 将限制设置为 100m (最小值)
仅存在 CPU 请求 将请求设置为与限制相等
仅存在 CPU 限制 将请求设置为与限制相等

内存突变规则

可变器对内存资源应用以下逻辑:

Scenario Action
内存请求和限制都缺失 将这两者都设置为 2048Mi (默认值)
内存请求存在,但小于 100Mi 将请求设置为 100Mi (最小值)
内存限制存在,但小于 100Mi 将限制设置为 100Mi (最小值)
仅存在内存请求 保持现状(不添加限制)
仅存在内存限制 保持原样(未添加请求)

Kubernetes 服务质量(QoS)类修正

应用 CPU 和内存突变后,如果请求值超出同一资源类型的限制,则可变器会限制请求以匹配限制。 此修补程序维护有效的 Kubernetes 服务质量(QoS)类配置。

已经变异的案例

资源请求变换器在以下情况下应用更改:

  • 空资源:没有 CPU 或内存请求或限制的容器接收默认值(500m CPU、 2048Mi 内存)。
  • 低于最低阈值:将 CPU 请求或以下 100m 限制增加到 100m。 内存请求或以下 100Mi 限制将增加到 100Mi
  • QoS 方案无效:当请求超出限制时,请求会降低以匹配限制。
  • 部分资源规范:仅有请求或仅有限制的容器(但不包括两者)在指定时强制实施最小值。
  • 多个容器:Pod 中的所有容器都经过适当处理和变更。
  • 已启用的命名空间:只有启用了保护的命名空间中的工作负荷才会被改变。

未改变的案例

资源请求可变器在以下方案中不应用更改:

  • 排除的命名空间:排除安全措施的命名空间中的工作负荷保持不变。
  • 已符合要求的资源:已具有超过最低阈值的请求和限制的容器保持不变。
  • 有效的 QoS 配置:当请求小于或等于限制且两个值都高于最小值时,不会发生任何更改。

反相关性和拓扑分散变异器

将部署保护措施设置为 Enforce 级别时,反关联和拓扑分布可变器会自动添加 Pod 反关联规则和拓扑分布约束,以提高节点之间的工作负荷分布。

当变量器运行时

仅当满足以下所有条件时,才会运行变异器:

  • Pod 反相关性和拓扑分布约束在工作负荷上都不存在。
  • 命名空间不会从部署安全措施中排除。
  • 部署保障机制处于 Enforce 模式。
  • 工作负荷没有 kubernetes.azure.com/managedby=aks 标签。

突变器添加的内容

标签标识:变异器使用以下标签优先级标识 Pod:

  • app 标签(第一优先级)
  • app.kubernetes.io/name 标签(次优先级)
  • 创建 default-antiaffinity-applabel=<workload-name> 标签(回退)

Pod 反亲和性:添加一个权重为 100 的优先 Pod 反亲和性规则,该规则更倾向于在不同节点上调度具有匹配标签的 Pod。 使用拓扑密钥 kubernetes.io/hostname

拓扑分布约束:添加具有以下设置的约束:

设置 价值
MaxSkew 1(允许每个节点的 Pod 数量最多差异 1 个)
当无法满足时 ScheduleAnyway (尽最大努力,不阻止计划)
拓扑密钥 kubernetes.io/hostname

已经变异的案例

反相关性和拓扑分布变异器在以下方案中应用更改:

  • 具有 app 标签的工作负荷:将 app 标签值用于反相关性和拓扑分布选择器。
  • 带有app.kubernetes.io/name标签的工作负荷:如果没有app标签,使用该标签作为选择器。
  • 没有应用标签的工作负荷:使用工作负荷名称创建默认标签,并添加反相关性和拓扑分散规则。
  • 清理工作负荷:没有现有相关性或拓扑分布约束的工作负荷接收这两种配置。
  • 部分关联:具有现有节点相关性(但无 Pod 反关联)的工作负荷接收 Pod 反相关性和拓扑分布规则。
  • 已启用的命名空间:突变仅发生在启用了保护的命名空间中。

未改变的案例

反相关性和拓扑分布变异器在以下方案中不应用更改:

  • 现有的拓扑分布约束:完全跳过已具有任何拓扑分布约束的工作负荷。
  • 现有的 Pod 反关联:会完全跳过那些具有现有必需或首选 Pod 反关联规则的工作负载。
  • 排除的命名空间:排除安全措施的命名空间中的工作负荷保持不变。
  • 没有可识别名称或标签的工作负载:可以正常跳过无法确定应用名称的边缘情况。

部署安全措施错误消息

本节介绍在部署保护措施检测到您可能会遇到的不合规配置时的错误消息,并提供建议的修复措施。

常规安全防护错误消息

下表列出了常规部署保障策略的错误消息:

Policy 错误消息 修复
强制实施探测 Container <container_name> in your Pod <pod_name> has no livenessProbe. Required probes: readinessProbe, livenessProbe 将实时性和就绪情况探测添加到每个容器。
无“最新”图像 Please specify an explicit, versioned image tag such as '1.0' for container %v. Using explicit version tags is a best practice to ensure reproducibility, prevent unintended updates, and facilitate easier debugging and rollbacks. Avoid using the 'latest' tag because it can change over time without notice. 使用非空且不同于 latest 的显式图像标记。 例如, nginx 不允许,但 nginx:v1.0.0 允许。
强制实施 CSI 驱动程序 Storage class <class_name> use intree provisioner kubernetes.io/azure-file is not allowedStorage class <class_name> use intree provisioner kubernetes.io/azure-disk is not allowed 请改用 disk.csi.azure.comfile.csi.azure.com。 有关详细信息,请参阅 AKS 中的 CSI 驱动程序
资源请求 container <container_name> has no resource requests 将 CPU 和内存请求添加到容器。
AntiAffinity 规则 Deployment with 2 replicas should have either podAntiAffinity or topologySpreadConstraints set to avoid disruptions due to nodes crashing 定义 podAntiAffinitytopologySpreadConstraints 在工作负载上。
受限标签 Label kubernetes.azure.com is reserved for AKS use only 从工作负荷中删除标签。
受限节点编辑 Tainting or labeling individual nodes is not recommended. Please use Azure CLI to taint/label node pools instead 使用 Azure CLI 来排斥或标记节点池,而不是单个节点。
受限污点 Taint with key CriticalAddonsOnly is reserved for the system pool only 不要用CriticalAddonsOnly污染用户节点池。

Pod 安全标准错误消息

注意事项

AKS 自动中已默认启用基线 Pod 安全标准。 无法停用 AKS 自动化中的基线 Pod 安全标准。

部署安全措施还支持启用基线、受限和特权 Pod 安全标准。 若要确保工作负载成功部署,请确保每个清单符合基线或受限 Pod 安全要求。 默认情况下,Azure Kubernetes 服务使用 Privileged Pod 安全标准。

Policy 错误消息 修复
AppArmor AppArmor annotation values must be undefined/nil, runtime/default, or localhost/*AppArmor profile type must be one of: undefined/nil, RuntimeDefault, or Localhost 删除 AppArmor 的任何规范。 Kubernetes 默认应用 AppArmor 设置。 在受支持的主机上,默认情况下应用 RuntimeDefault AppArmor 配置文件。
主机命名空间 Host network namespaces are disallowed: spec.hostNetwork is set to trueHost PID namespaces are disallowed: spec.hostPID is set to trueHost IPC namespaces are disallowed: spec.hostIPC is set to true 将这些值设置为 false或删除指定字段。
特权容器 Privileged [ephemeral\|init\|N/A] containers are disallowed: spec.containers[*].securityContext.privileged is set to true 将相应的 securityContext.privileged 字段设置为 false或删除该字段。
能力 消息开头为 Disallowed capabilities detected 从容器清单中删除显示的功能。
HostPath 卷 HostPath volumes are forbidden under restricted security policy unless containers mounting them are from allowed images 移除 HostPath 卷和卷装载。
主机端口 HostPorts are forbidden under baseline security policy 从有问题的容器中删除主机端口规范。
SELinux SELinux type must be one of: undefined/empty, container_t, container_init_t, container_kvm_t, or container_engine_t 将容器的 securityContext.seLinuxOptions.type 字段设置为允许的值之一。
/proc 装载类型 ProcMount must be undefined/nil or 'Default' in spec.containers[*].securityContext.procMount spec.containers[*].securityContext.procMount设置为Default或保留其未定义。
Seccomp Seccomp profile must not be explicitly set to Unconfined. Allowed values are: undefined/nil, RuntimeDefault, or Localhost 请将securityContext.seccompProfile.type设置为 pod 或容器的允许值之一。
Sysctls Disallowed sysctl detected. Only baseline Kubernetes pod security standard sysctls are permitted 删除不允许的 sysctls。 有关特定列表,请参阅 Kubernetes Pod 安全标准规范
卷类型(仅限于 PSS 受限模式) Only the following volume types are allowed under restricted policy: configMap, csi, downwardAPI, emptyDir, ephemeral, persistentVolumeClaim, projected, secret 删除不属于允许类型之一的任何卷。
特权升级 (仅限 PSS 受限) Privilege escalation must be set to false under restricted policy 将每个容器、initContainer 和临时容器设置为spec.containers[*].securityContext.allowPrivilegeEscalationfalse
以非管理员身份运行(仅限 PSS 受限环境) Containers must not run as root user in spec.containers[*].securityContext.runAsNonRoot 将每个容器、initContainer 和临时容器设置为spec.containers[*].securityContext.runAsNonRoottrue
以非根用户身份运行(仅 PSS 受限) Containers must not run as root user: spec.securityContext.runAsUser is set to 0 设置 securityContext.runAsUser 为非零值,或者在 Pod 级别及每个容器、初始化容器和临时容器中保持未定义。
Seccomp(仅限于 PSS 受限模式) Seccomp profile must be "RuntimeDefault" or "Localhost" under restricted policy 请将securityContext.seccompProfile.type设置为 pod 或容器的允许值之一。 这不同于基线,因为受限策略不允许未定义值。
功能(受限于 PSS) All containers must drop ALL capabilities under restricted policyOnly NET_BIND_SERVICE may be added to capabilities under restricted policy 所有容器必须删除 ALL 功能,并且只允许添加 NET_BIND_SERVICE

启用部署安全措施

注意事项

使用部署保障 Enforce 级别意味着你选择加入被阻止和改变的部署。 在启用 Enforce之前,请考虑这些策略如何与 AKS 群集配合使用。

在现有群集上启用部署安全措施

在启用了 Azure Policy 插件的现有集群上,使用带有 az aks safeguard create 标志的 --level 命令启用部署保护措施。 如果要接收不合规的警告,请将 --level 设置为 Warn。 如果要拒绝或变更所有不合规的部署,请将其设置为 Enforce

az aks safeguards create --resource-group <resource-group-name> --name <cluster-name> --level Enforce 

还可以使用 --cluster 标志和指定群集资源 ID 来启用部署安全措施。

az aks safeguards create --cluster <ID> --level Enforce

如果要更新现有群集的部署保障级别,请使用新值 --level运行以下命令。

az aks safeguards update --resource-group <resource-group-name> --name <cluster-name> --level Warn 

排除命名空间

还可以从部署安全措施中排除某些命名空间。 排除命名空间时,该命名空间中的活动不受 Deployment Safeguards 警告或强制措施影响。

例如,若要排除命名空间 ns1ns2,可以使用带 --excluded-ns 标志的命名空间列表,列表中的命名空间用空格分隔,如以下示例所示:

az aks safeguards update --resource-group <resource-group-name> --name <cluster-name> --level Warn --excluded-ns ns1 ns2 

启用 Pod 安全标准

注意事项

默认情况下,Azure Kubernetes 服务(AKS)使用 Privileged Pod 安全标准。 如果要还原到默认配置,请将 --pss-level 标志设置为 Privileged

若要在部署安全措施中启用 Pod 安全标准,请使用--pss-level标志选择以下级别之一:BaselineRestrictedPrivileged

az aks safeguards update --resource-group <resource-group-name> --name <cluster-name> --level Warn --pss-level <Baseline|Restricted|Privileged>

更新部署防护版本

部署安全措施遵循 AKS 加载项版本控制方案。 部署保护的每个新版本都将作为 AKS 中的新次要版本发布。 这些更新将通过 AKS GitHub 发行说明 传达,并反映在文档中的“部署保障策略”表中。

若要了解有关 AKS 版本控制和加载项的详细信息,请参阅以下文档: aks-component-versionsaks-versioning-for-addons

验证群集之间的合规性

部署 Kubernetes 清单后,如果群集不符合部署保障措施,CLI 或终端中会显示警告或潜在拒绝消息,如以下示例所示:

警告

$ kubectl apply -f deployment.yaml
Warning: [azurepolicy-k8sazurev1antiaffinityrules-ceffa082711831ebffd1] Deployment with 2 replicas should have either podAntiAffinity or topologySpreadConstraints set to avoid disruptions due to nodes crashing
deployment.apps/simple-web created

强制执行

使用部署保护突变时, Enforce 级别会改变 Kubernetes 资源(如果适用)。 但是,Kubernetes 资源仍需要通过所有安全措施才能成功部署。 如果任何安全措施策略失败,资源将被拒绝,不会进行部署。

$ kubectl apply -f deployment.yaml 
Error from server (Forbidden): error when creating "deployment.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [azurepolicy-k8sazurev1antiaffinityrules-ceffa082711831ebffd1] Deployment with 2 replicas should have either podAntiAffinity or topologySpreadConstraints set to avoid disruptions due to nodes crashing

如果 Kubernetes 资源符合适用的突变安全措施并满足所有其他保护要求,则会成功部署它们,如以下示例所示:

$ kubectl apply -f deployment.yaml
deployment.apps/simple-web created

使用 Azure Policy 仪表板验证群集之间的合规性

若要验证是否已应用部署安全措施并检查群集的符合性,请导航到群集的 Azure 门户页,然后选择“ 策略”,然后选择 “Azure Policy”。

从策略和计划列表中,选择与部署安全措施关联的计划。 你会看到一个仪表板,其中显示了 AKS 群集中的合规性状态。

注意事项

若要正确评估 AKS 群集的合规性,Azure Policy 计划的范围必须限定为群集的资源组。

禁用部署安全措施

若要在群集上禁用部署安全措施,请使用 delete 命令。

az aks safeguards delete --resource-group <resource-group-name> --name <cluster-name>

FAQ

我可以创建自己的突变吗?

否。 如果你有安全措施方面的想法,请在 AKS GitHub 存储库中提出问题,并将 [Deployment Safeguards request] 添加到标题开头。

在“Enforcement”中,我可以挑选需要的变更吗?

否。 部署安全措施要么全有,要么全无。 启用警告或强制实施后,所有安全措施都处于活动状态。

为什么即使部署资源未遵循最佳做法,还是得到接纳?

部署安全措施通过 Azure Policy 控件强制实施最佳做法标准,并具有针对 Kubernetes 资源进行验证的策略。 为了评估和强制实施群集组件,Azure Policy 扩展 Gatekeeper。 Gatekeeper 强制目前也在 fail-open 模型中运行。 由于无法保证 Gatekeeper 响应我们发起的网络请求,因此,在这种情况下,我们确保跳过验证,以便拒绝操作不会阻止您的部署。

若要了解详细信息,请参阅 Gatekeeper 中的工作负荷验证

后续步骤