LabHub
学习 学习路径 课程

CNPA — 云原生平台工程助理

立起平台基线并往上抬

在 LabHub 中继续学习

目标

在命名空间中明确规定平台要求的最低基线,确认它确实会拒绝违规对象,然后完整走一遍从影响调查到例外处理的升级流程。

为什么重要

如果基线只写在文档里,它什么也拒绝不了;无法实施的规则,半年后往往已有一半被破坏。反过来,如果一开始就全部阻止,昨天还能工作的部署今天就会被拦住,平台也会被视为故障原因。因此,实际工作通常遵循这样的顺序:“强制执行当前能够遵守的等级,用警告提前提示下一等级,升级前调查影响,并为暂时无法遵守的一方提供带到期日的例外。”本实验将让你亲手走完这一流程。之所以同时处理一致性(conformance),原因也相同:若保留废弃 API,某天升级集群时整个部署可能突然停止;提前识别这种信号是平台团队的基本功。

步骤

  1. 创建命名空间 platform-baseline 并添加标签:pod-security.kubernetes.io/enforce=baselinepod-security.kubernetes.io/enforce-version=v1.30pod-security.kubernetes.io/warn=restrictedpod-security.kubernetes.io/warn-version=v1.30platform.labhub.io/owner=platform-team
  2. /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
  3. /root/cnpa-base/legacy.yaml 中编写使用 apiVersion: extensions/v1beta1 的 Ingress orders-legacy(命名空间 platform-baseline)。尝试应用,并将失败输出保存到 /root/cnpa-base/legacy-reject.txt
  4. /root/cnpa-base/app.yaml 中编写并应用 apps/v1 Deployment orders。要求:spec.replicas: 2;元数据标签为 app.kubernetes.io/name: ordersapp.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)。
  5. /root/cnpa-base/servicemonitor.yaml 中编写并应用 ServiceMonitor orders(命名空间 platform-baseline)。spec.selector.matchLabelsapp.kubernetes.io/name: ordersspec.endpoints[0].portmetricsinterval30s
  6. /root/cnpa-base/exception.yaml 中编写并应用命名空间 platform-legacy。标签为 pod-security.kubernetes.io/enforce: baselinepod-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,保持原样。
  7. orders 的 Pod 模板符合 restricted 基线。在 Pod 级别加入 runAsNonRoot: truerunAsUser: 10001seccompProfile.type: RuntimeDefault,在容器级别加入 allowPrivilegeEscalation: falsecapabilities.drop: [ALL]。重新应用并等新 Pod 启动后,把 platform-baselineenforce 标签提升为 restrictedenforce-version 仍保持 v1.30
  8. /root/cnpa-base/baseline.json 中记录现状。键为 namespaceenforceenforce_versiondeployments(该命名空间的 Deployment 数量)、servicemonitor(名称)、exception_namespaceexception_expires

参考

基线命名空间

创建命名空间 platform-baseline 并添加标签:pod-security.kubernetes.io/enforce=baselinepod-security.kubernetes.io/enforce-version=v1.30pod-security.kubernetes.io/warn=restrictedpod-security.kubernetes.io/warn-version=v1.30platform.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: ordersapp.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.matchLabelsapp.kubernetes.io/name: ordersspec.endpoints[0].portmetricsinterval30s

ServiceMonitor 通过标签选择 Service,端口引用的是 Service 端口名而不是编号。创建后,用 kubectl 反查该选择器实际选中了什么。

调查例外与升级影响

/root/cnpa-base/exception.yaml 中编写并应用命名空间 platform-legacy。标签为 pod-security.kubernetes.io/enforce: baselinepod-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: truerunAsUser: 10001seccompProfile.type: RuntimeDefault,在容器级别加入 allowPrivilegeEscalation: falsecapabilities.drop: [ALL]。重新应用并等新 Pod 启动后,把 platform-baselineenforce 标签提升为 restrictedenforce-version 仍保持 v1.30

restricted 要求四项:不以 root 运行、使用默认 seccomp 配置文件、禁止权限提升、丢弃全部 capability。前两项写在 Pod 级别,后两项写在容器级别。先修正工作负载,再提升等级。

用数值记录基线现状

/root/cnpa-base/baseline.json 中记录现状。键为 namespaceenforceenforce_versiondeployments(该命名空间的 Deployment 数量)、servicemonitor(名称)、exception_namespaceexception_expires

报告中的所有数字都应能从集群重新统计。分别查询命名空间标签、Deployment 数量、ServiceMonitor 名称和例外到期日后填写。