立起平台基线并往上抬
目标
在命名空间中明确规定平台要求的最低基线,确认它确实会拒绝违规对象,然后完整走一遍从影响调查到例外处理的升级流程。
为什么重要
如果基线只写在文档里,它什么也拒绝不了;无法实施的规则,半年后往往已有一半被破坏。反过来,如果一开始就全部阻止,昨天还能工作的部署今天就会被拦住,平台也会被视为故障原因。因此,实际工作通常遵循这样的顺序:“强制执行当前能够遵守的等级,用警告提前提示下一等级,升级前调查影响,并为暂时无法遵守的一方提供带到期日的例外。”本实验将让你亲手走完这一流程。之所以同时处理一致性(conformance),原因也相同:若保留废弃 API,某天升级集群时整个部署可能突然停止;提前识别这种信号是平台团队的基本功。
步骤
- 创建命名空间
platform-baseline并添加标签:pod-security.kubernetes.io/enforce=baseline、pod-security.kubernetes.io/enforce-version=v1.30、pod-security.kubernetes.io/warn=restricted、pod-security.kubernetes.io/warn-version=v1.30、platform.labhub.io/owner=platform-team。 - 在
/root/cnpa-base/bad-probe.yaml中编写位于platform-baseline命名空间的 Podbad-probe。设置spec.hostPID: true,容器名为probe,镜像为ghcr.io/labhub/probe:1.0.0。尝试应用,并把包括标准错误在内的失败输出保存到/root/cnpa-base/reject.txt。集群中不得残留 Podbad-probe。 - 在
/root/cnpa-base/legacy.yaml中编写使用apiVersion: extensions/v1beta1的 Ingressorders-legacy(命名空间platform-baseline)。尝试应用,并将失败输出保存到/root/cnpa-base/legacy-reject.txt。 - 在
/root/cnpa-base/app.yaml中编写并应用 apps/v1 Deploymentorders。要求:spec.replicas: 2;元数据标签为app.kubernetes.io/name: orders和app.kubernetes.io/part-of: cnpa-platform;容器名app;镜像ghcr.io/labhub/orders:1.4.0;两个容器端口分别为名为http的 8080 和名为metrics的 9102。在/root/cnpa-base/edge.yaml中编写并应用 Serviceorders(选择器app.kubernetes.io/name: orders,名为http的端口从 80 转发到 8080,名为metrics的端口从 9102 转发到 9102)以及 networking.k8s.io/v1 Ingressorders(主机orders.labhub.internal,路径/,pathType: Prefix,后端为服务orders的端口名http)。 - 在
/root/cnpa-base/servicemonitor.yaml中编写并应用 ServiceMonitororders(命名空间platform-baseline)。spec.selector.matchLabels为app.kubernetes.io/name: orders,spec.endpoints[0].port为metrics,interval为30s。 - 在
/root/cnpa-base/exception.yaml中编写并应用命名空间platform-legacy。标签为pod-security.kubernetes.io/enforce: baseline和pod-security.kubernetes.io/enforce-version: v1.30;注解为platform.labhub.io/exception-expires(YYYY-MM-DD 格式的到期日)和platform.labhub.io/exception-reason(原因)。在同一文件中也加入 Deploymentlegacy-batch(replicas 1、镜像ghcr.io/labhub/legacy-batch:0.9.0、不设安全配置)。然后以服务器端 dry-run 提交把该命名空间提升到restricted的标签变更,并把包括标准错误在内的输出保存到/root/cnpa-base/upgrade-check.txt。不要修改legacy-batch,保持原样。 - 让
orders的 Pod 模板符合 restricted 基线。在 Pod 级别加入runAsNonRoot: true、runAsUser: 10001、seccompProfile.type: RuntimeDefault,在容器级别加入allowPrivilegeEscalation: false和capabilities.drop: [ALL]。重新应用并等新 Pod 启动后,把platform-baseline的enforce标签提升为restricted。enforce-version仍保持v1.30。 - 在
/root/cnpa-base/baseline.json中记录现状。键为namespace、enforce、enforce_version、deployments(该命名空间的 Deployment 数量)、servicemonitor(名称)、exception_namespace、exception_expires。
参考
- 拒绝消息会写到标准错误而不是标准输出。请用
> 파일 2>&1一并保存。 - 可用
kubectl get svc -n platform-baseline -l <라벨>反查选择器选中了什么。 - 如果在第 6 步给
legacy-batch加入安全配置,升级警告会消失,导致评分失败。若误加,请用kubectl delete deploy legacy-batch -n platform-legacy删除后重新应用。 - 第 7 步的顺序很重要。若先提升等级,新 Pod 会被拒绝,发布将停滞。
基线命名空间
创建命名空间 platform-baseline 并添加标签:pod-security.kubernetes.io/enforce=baseline、pod-security.kubernetes.io/enforce-version=v1.30、pod-security.kubernetes.io/warn=restricted、pod-security.kubernetes.io/warn-version=v1.30、platform.labhub.io/owner=platform-team。
Pod Security Admission 仅通过命名空间标签工作。把当前要遵守的等级设为 enforce,把下一步要提升的等级设为 warn。还要为每个等级固定版本标签。
确认策略确实拒绝违规对象
在 /root/cnpa-base/bad-probe.yaml 中编写位于 platform-baseline 命名空间的 Pod bad-probe。设置 spec.hostPID: true,容器名为 probe,镜像为 ghcr.io/labhub/probe:1.0.0。尝试应用,并把包括标准错误在内的失败输出保存到 /root/cnpa-base/reject.txt。集群中不得残留 Pod bad-probe。
贴上标签并不等于策略一定在运行。创建一个要求主机命名空间的 Pod,并把由此产生的拒绝消息连同标准错误一起保存到文件。
为什么废弃 API 会被拒绝
在 /root/cnpa-base/legacy.yaml 中编写使用 apiVersion: extensions/v1beta1 的 Ingress orders-legacy(命名空间 platform-baseline)。尝试应用,并将失败输出保存到 /root/cnpa-base/legacy-reject.txt。
使用已废弃组编写的清单会因映射失败而不是语法错误而失败。原样保留该消息,并向集群确认该组确实未提供。
迁移到更高版本的 API 并应用
在 /root/cnpa-base/app.yaml 中编写并应用 apps/v1 Deployment orders。要求:spec.replicas: 2;元数据标签为 app.kubernetes.io/name: orders 和 app.kubernetes.io/part-of: cnpa-platform;容器名 app;镜像 ghcr.io/labhub/orders:1.4.0;两个容器端口分别为名为 http 的 8080 和名为 metrics 的 9102。在 /root/cnpa-base/edge.yaml 中编写并应用 Service orders(选择器 app.kubernetes.io/name: orders,名为 http 的端口从 80 转发到 8080,名为 metrics 的端口从 9102 转发到 9102)以及 networking.k8s.io/v1 Ingress orders(主机 orders.labhub.internal,路径 /,pathType: Prefix,后端为服务 orders 的端口名 http)。
Deployment 使用 apps/v1,Ingress 使用 networking.k8s.io/v1。v1 Ingress 的每条路径都需要 pathType,后端需分别指向服务名和端口。用端口名而不是编号引用,可避免与 Service 不一致。
建立抓取契约
在 /root/cnpa-base/servicemonitor.yaml 中编写并应用 ServiceMonitor orders(命名空间 platform-baseline)。spec.selector.matchLabels 为 app.kubernetes.io/name: orders,spec.endpoints[0].port 为 metrics,interval 为 30s。
ServiceMonitor 通过标签选择 Service,端口引用的是 Service 端口名而不是编号。创建后,用 kubectl 反查该选择器实际选中了什么。
调查例外与升级影响
在 /root/cnpa-base/exception.yaml 中编写并应用命名空间 platform-legacy。标签为 pod-security.kubernetes.io/enforce: baseline 和 pod-security.kubernetes.io/enforce-version: v1.30;注解为 platform.labhub.io/exception-expires(YYYY-MM-DD 格式的到期日)和 platform.labhub.io/exception-reason(原因)。在同一文件中也加入 Deployment legacy-batch(replicas 1、镜像 ghcr.io/labhub/legacy-batch:0.9.0、不设安全配置)。然后以服务器端 dry-run 提交把该命名空间提升到 restricted 的标签变更,并把包括标准错误在内的输出保存到 /root/cnpa-base/upgrade-check.txt。不要修改 legacy-batch,保持原样。
以服务器端 dry-run 提交标签变更,会返回按新等级评估现有 Pod 的警告。警告写入标准错误,请一并保存。例外命名空间中的工作负载要故意保持不变。
调整工作负载并提升等级
让 orders 的 Pod 模板符合 restricted 基线。在 Pod 级别加入 runAsNonRoot: true、runAsUser: 10001、seccompProfile.type: RuntimeDefault,在容器级别加入 allowPrivilegeEscalation: false 和 capabilities.drop: [ALL]。重新应用并等新 Pod 启动后,把 platform-baseline 的 enforce 标签提升为 restricted。enforce-version 仍保持 v1.30。
restricted 要求四项:不以 root 运行、使用默认 seccomp 配置文件、禁止权限提升、丢弃全部 capability。前两项写在 Pod 级别,后两项写在容器级别。先修正工作负载,再提升等级。
用数值记录基线现状
在 /root/cnpa-base/baseline.json 中记录现状。键为 namespace、enforce、enforce_version、deployments(该命名空间的 Deployment 数量)、servicemonitor(名称)、exception_namespace、exception_expires。
报告中的所有数字都应能从集群重新统计。分别查询命名空间标签、Deployment 数量、ServiceMonitor 名称和例外到期日后填写。