LabHub
学习 学习路径 课程

CKS — Kubernetes 安全专家

Pod Security Admission 与 securityContext

在 LabHub 中继续学习

目标

掌握仅通过命名空间标签设定工作负载安全底线的方法,并亲手完成能够真正通过 restricted 配置文件的 Pod 规范。

为什么重要

PodSecurityPolicy 已在 1.25 中移除。使用 PSP 时,必须向 ServiceAccount 授予“use 此 PSP”的权限,这一结构本身就可能成为权限提升路径,而且很难预测多个 PSP 中究竟会应用哪一个。替代方案 PSA 只需几行命名空间标签,并可分别启用 enforce、audit、warn 三种模式,从而实现渐进式引入。若在现有集群中立即启用 enforce,大量工作负载会被阻止,因此标准流程是先启用 warn 和 audit 进行观察。

restricted 配置文件要求的四项设置(runAsNonRoot、allowPrivilegeEscalation false、capabilities drop ALL、seccompProfile)是 CKS 中最常出现的组合。与其死记硬背,不如亲自逐一移除,观察会产生什么错误,更容易长期掌握。

此环境的 API 服务器已经启用 PodSecurity Admission,因此违规 Pod 会真正被拒绝。

步骤

  1. 创建命名空间 cks-psa,并添加标签 pod-security.kubernetes.io/enforce=baseline
  2. 创建命名空间 cks-psa-strict,将 enforce、audit、warn 三个标签全部设为 restricted, 并将 enforce-versionaudit-versionwarn-version 三个标签全部设为 latest
  3. cks-psa-strict 中创建 Pod hardened(容器名称 app,镜像 nginx:1.27-alpine)。 为通过 restricted,Pod 层级需要 runAsNonRoot: trueseccompProfile.type: RuntimeDefault,容器层级需要 allowPrivilegeEscalation: falsecapabilities.drop: [ALL]
  4. 尝试在 cks-psa-strict 中 apply 包含 privileged: true 容器的 Pod bad-pod。 将输出(包括标准错误)保存到 /root/cks-securitycontext/denied.txt。 Pod 不得创建成功。
  5. cks-psa 中创建 Pod nonroot-app(容器名称 app)。在 Pod 层级 securityContext 中 设置 runAsNonRoot: truerunAsUser: 10001runAsGroup: 10001fsGroup: 20001
  6. cks-psa-strict 中创建 Pod dropped(容器名称 app)。Pod 层级的 seccompProfile.typeRuntimeDefaultrunAsNonRoottrue; 容器层级设置 allowPrivilegeEscalation: falsecapabilities.drop: [ALL]readOnlyRootFilesystem: true
  7. 创建 RuntimeClass cks-sandboxhandlerrunscoverhead.podFixed 为 内存 160Mi 和 CPU 250m
  8. cks-psa-strict 中创建 Deployment payments。replicas 为 2,选择器和 Pod 标签为 app=payments,Pod 规范的 runtimeClassNamecks-sandbox;Pod 模板应具备 与第 3 步相同的四项条件,以通过 restricted。

参考

应用 baseline 配置文件

创建命名空间 cks-psa,并添加标签 pod-security.kubernetes.io/enforce=baseline

PSA 通过命名空间标签运行。标签键以 pod-security.kubernetes.io/ 开头。

设置全部三种模式与版本标签

创建命名空间 cks-psa-strict,将 enforce、audit、warn 三个标签全部设为 restricted, 并将 enforce-versionaudit-versionwarn-version 三个标签全部设为 latest

enforce、audit、warn 各自都有对应的 -version 标签。固定版本可以避免集群升级直接导致策略收紧。

通过 restricted 的 Pod

cks-psa-strict 中创建 Pod hardened(容器名称 app,镜像 nginx:1.27-alpine)。 为通过 restricted,Pod 层级需要 runAsNonRoot: trueseccompProfile.type: RuntimeDefault,容器层级需要 allowPrivilegeEscalation: falsecapabilities.drop: [ALL]

restricted 强制要求四项设置。缺少任何一项都会被拒绝,错误消息会指出触发了哪个字段。

还要注意一点:runAsNonRoot: true 不会替你指定 UID。它只表示“不得以 root 运行”;如果镜像未指定 UID,在真实节点上 kubelet 会无法启动 Pod,并报出 CreateContainerConfigError。真实集群中应同时设置 runAsUser,或使用按非 root 用户构建的镜像。本实验环境不会实际运行 Pod,因此不会显现这一差异。

确认违规 Pod 被拒绝

尝试在 cks-psa-strict 中 apply 包含 privileged: true 容器的 Pod bad-pod。 将输出(包括标准错误)保存到 /root/cks-securitycontext/denied.txt。 Pod 不得创建成功。

必须同时把 apply 的标准输出与标准错误保存到文件。请使用 2>&1 | tee。如果 Pod 被创建,说明策略并未生效。

指定运行用户与组

cks-psa 中创建 Pod nonroot-app(容器名称 app)。在 Pod 层级 securityContext 中 设置 runAsNonRoot: truerunAsUser: 10001runAsGroup: 10001fsGroup: 20001

runAsUser/runAsGroup/fsGroup 位于 Pod 层级 securityContext;runAsNonRoot 两个层级都可使用。fsGroup 会改变卷文件的组所有权。

组合 seccomp 与 capability

cks-psa-strict 中创建 Pod dropped(容器名称 app)。Pod 层级的 seccompProfile.typeRuntimeDefaultrunAsNonRoottrue; 容器层级设置 allowPrivilegeEscalation: falsecapabilities.drop: [ALL]readOnlyRootFilesystem: true

由于该命名空间使用 restricted,此 Pod 也必须满足全部四项必要条件才能创建。

RuntimeClass 对象

创建 RuntimeClass cks-sandboxhandlerrunscoverhead.podFixed 为 内存 160Mi 和 CPU 250m

RuntimeClass 是集群范围资源。handler 的值必须逐字符匹配节点容器运行时配置中的 Runtime 名称。

综合:使用沙箱 Runtime 部署

cks-psa-strict 中创建 Deployment payments。replicas 为 2,选择器和 Pod 标签为 app=payments,Pod 规范的 runtimeClassNamecks-sandbox;Pod 模板应具备 与第 3 步相同的四项条件,以通过 restricted。

Deployment 的 Pod 模板同样接受 PSA 检查。在 Pod 规范的 runtimeClassName 中填写前面创建的 RuntimeClass 名称。