设计发布门禁与渐进式交付
目标
创建 kustomize base 和生产 overlay,对渲染结果设置 schema 与策略门禁,并确认门禁确实能够阻止违规。随后决定哪些服务分别采用金丝雀和蓝绿策略,并迁移为 Rollout。
为什么重要
CNPE 的 GitOps 领域权重最高,占 25%。在这个领域,实务和考试共同要求的不是工具用法,而是顺序:先渲染,再检查,而且检查结果必须转化为退出码。不遵循该顺序的流水线会亮绿灯,却什么也没有保护。
本实验的集群中既没有 Argo CD 控制器,也没有 Argo Rollouts 控制器。这里只注册了 CRD,因此清单会被真实验证并保存,但不会发生调谐(reconcile)。所以这里学习的不是“控制器会替我做什么”,而是**“我声明了什么”**。实际考试评分的同样是声明。
工作目录是 /root/cnpe-delivery,生产命名空间是 cnpe-prod。
步骤
- 在
/root/cnpe-delivery/base中创建 Deploymentcheckout和 Servicecheckout,并用kustomization.yaml将它们组合起来。容器端口和 Service 的 targetPort 均为 8080,replicas 为 1。不要在 base 中设置命名空间。 - 在
/root/cnpe-delivery/overlays/prod中创建生产 overlay。命名空间设为cnpe-prod,replicas 设为 4,镜像固定到 digest(@sha256:后跟 64 位十六进制字符);为容器同时配置 requests 和 limits,并设置runAsNonRoot: true。 - 在
/root/cnpe-delivery/policy/require-pinned.yaml中编写 Kyverno ClusterPolicy。将validationFailureAction设置为Enforce,以 Deployment 为目标检查两项内容:(a)镜像是否固定到 digest;(b)所有容器是否都设置了resources.limits.cpu和memory。 - 创建
/root/cnpe-delivery/gate.sh。脚本需要渲染 prod overlay,并对结果应用策略;如果存在违规,必须以非 0 状态码结束。为了从任何位置调用都能得到相同结果,脚本应先切换到自身所在目录。 - 在
/root/cnpe-delivery/rollout/checkout-canary.yaml中编写金丝雀 Rolloutcheckout,并应用到cnpe-prod。setWeight 依次为 10、30、60,每两个权重之间都设置 pause,且第一步必须是 setWeight。canaryService与stableService必须不同,progressDeadlineSeconds不得超过 600。容器镜像必须与 prod 渲染结果中的镜像完全相同。 - 在
/root/cnpe-delivery/argocd/application.yaml中编写 Argo CD Application。project使用非default的专用项目;source.path设为overlays/prod;targetRevision使用非HEAD的固定引用;在syncPolicy.automated中启用 prune 和 selfHeal,并在syncOptions中加入CreateNamespace=true。destination.namespace必须与渲染结果中的命名空间相同。 - 在
/root/cnpe-delivery/rollout/ledger-bluegreen.yaml中编写 AnalysisTemplateledger-smoke和蓝绿 Rolloutledger,并应用到cnpe-prod。activeService与previewService必须不同;autoPromotionEnabled设为 false;prePromotionAnalysis引用ledger-smoke;scaleDownDelaySeconds不得小于 300。 - 在
/root/cnpe-delivery/delivery-report.txt中写入prod_image、prod_replicas、canary_weights、auto_promotion四行,格式为키=값。所有值都必须直接从渲染结果和集群中查询得到。
参考
- 读取渲染结果时,可使用
kustomize build overlays/prod | yq -o=json -I=0 ea '[.]' | jq ...。 kyverno apply <정책> --resource <파일>在发现违规时会返回退出码 1。请直接以此作为门禁判断依据。- 可通过
kubectl get rollout checkout -n cnpe-prod -o jsonpath='{.spec.strategy.canary.steps[*].setWeight}'重新统计金丝雀权重。 - 一个常见错误是让 overlay 使用绝对路径引用 base。必须使用相对路径,这样即使整体移动仓库也仍能渲染。
- 另一个错误是创建门禁后只确认通过。请故意加入一次违规,亲眼确认红灯。
创建 base 并确认可以渲染
在 /root/cnpe-delivery/base 中创建 Deployment checkout 和 Service checkout,并用 kustomization.yaml 将它们组合起来。容器端口和 Service 的 targetPort 均为 8080,replicas 为 1。不要在 base 中设置命名空间。
base 只包含与环境无关的公共部分。如果把命名空间或各环境的 replicas 放在这里,overlay 就不得不与它们反复覆盖。请直接运行 kustomize build 确认渲染结果。
明确生产 overlay 增加的内容
在 /root/cnpe-delivery/overlays/prod 中创建生产 overlay。命名空间设为 cnpe-prod,replicas 设为 4,镜像固定到 digest(@sha256: 后跟 64 位十六进制字符);为容器同时配置 requests 和 limits,并设置 runAsNonRoot: true。
kustomize 的 images 项除了 newTag,还可以使用 digest。通过 replicas 项设置副本数,通过 patches 添加资源和安全配置。请检查 kustomize build 的结果,而不是只看文件。
确定策略要阻止什么
在 /root/cnpe-delivery/policy/require-pinned.yaml 中编写 Kyverno ClusterPolicy。将 validationFailureAction 设置为 Enforce,以 Deployment 为目标检查两项内容:(a)镜像是否固定到 digest;(b)所有容器是否都设置了 resources.limits.cpu 和 memory。
在 Kyverno 的 validate.pattern 中,*@sha256:* 表示部分匹配,?* 表示“非空值”。策略范围过宽时连正常清单也会被阻止,因此应同时测试应通过和应阻止的情况。
确认门禁确实能够阻止违规
创建 /root/cnpe-delivery/gate.sh。脚本需要渲染 prod overlay,并对结果应用策略;如果存在违规,必须以非 0 状态码结束。为了从任何位置调用都能得到相同结果,脚本应先切换到自身所在目录。
门禁的核心不是执行检查,而是把检查结果转换为退出码。要让脚本从任何位置调用都表现一致,应在开头切换到脚本自身目录。完成后,请故意加入一次违规,确认红灯。
为金丝雀发布留出判断时机
在 /root/cnpe-delivery/rollout/checkout-canary.yaml 中编写金丝雀 Rollout checkout,并应用到 cnpe-prod。setWeight 依次为 10、30、60,每两个权重之间都设置 pause,且第一步必须是 setWeight。canaryService 与 stableService 必须不同,progressDeadlineSeconds 不得超过 600。容器镜像必须与 prod 渲染结果中的镜像完全相同。
只罗列权重,不过是速度稍慢的全量发布。请在每个权重之间加入 pause,并拆分服务,以便单独观测金丝雀版本。直接从渲染结果复制镜像更安全。
固定同步来源与目标位置
在 /root/cnpe-delivery/argocd/application.yaml 中编写 Argo CD Application。project 使用非 default 的专用项目;source.path 设为 overlays/prod;targetRevision 使用非 HEAD 的固定引用;在 syncPolicy.automated 中启用 prune 和 selfHeal,并在 syncOptions 中加入 CreateNamespace=true。destination.namespace 必须与渲染结果中的命名空间相同。
此 Pod 中没有 Argo CD 控制器,因此检查的是声明,而不是同步结果。不过 destination.namespace 必须与渲染结果的命名空间完全一致。两者不一致时,同步可能显示成功,却没有应用到预期位置。
为无法拆分写入的服务选择策略
在 /root/cnpe-delivery/rollout/ledger-bluegreen.yaml 中编写 AnalysisTemplate ledger-smoke 和蓝绿 Rollout ledger,并应用到 cnpe-prod。activeService 与 previewService 必须不同;autoPromotionEnabled 设为 false;prePromotionAnalysis 引用 ledger-smoke;scaleDownDelaySeconds 不得小于 300。
本步骤检查蓝绿声明和分析模板引用。预览服务和手动提升并不能阻止数据写入。真实账本还需要单独验证单写入者控制、schema 兼容性和恢复能力。这里请同时创建被引用的分析模板,并区分 activeService 与 previewService。
以具体值记录发布结果
在 /root/cnpe-delivery/delivery-report.txt 中写入 prod_image、prod_replicas、canary_weights、auto_promotion 四行,格式为 키=값。所有值都必须直接从渲染结果和集群中查询得到。
四个值都不要凭空填写,而要查询后记录。镜像和副本数来自渲染结果,权重和自动提升设置来自集群中的 Rollout。评分器会重新计算相同值并进行比对。