LabHub
学习 学习路径 课程

Istio 服务网格

用权重、请求头、镜像把金丝雀跑起来

在 LabHub 中继续学习

目标

能够根据场景选择权重、请求头、镜像这三种流量拆分方式,并制定明确写出回滚条件的金丝雀计划。

为什么重要

金丝雀发布的本质不是“分一点流量”,而是**“预先决定何时停止”。任何人都能提高权重,但如果把看到不良指标后是否回滚的判断交给人,就容易动摇。因此,需要在每个阶段写明判断标准,并让该标准直接成为自动化的输入。另一个重点是将 Pod 数量与流量比例分离**。在服务网格中,即使新版本 Pod 已全部启动,也可以保持 0% 流量;发现问题时,无需重新部署,只需把权重恢复为 0。

本实验混合了两种评分方式。 第 1、2、4、5 步查看保存的文件,第 6、7、8 步查看实际应用到集群的状态。因此,每一步都必须单独保留文件;如果持续覆盖同一个文件,前面的步骤会再次失败。每个 vs-*.yaml 文件中只能放置一个 VirtualService 文档(若一个文件包含多个文档,评分器无法确定第一个文档)。

步骤

开始前的准备。 每次实验都会启动新的实验 Pod,因此不会保留上一个实验的服务网格配置。如果 kubectl get crd virtualservices.networking.istio.io 没有输出,请先运行 istioctl manifest generate --set profile=minimal > /root/istio/manifest.yaml,然后将 kubectl apply -f /root/istio/manifest.yaml 执行两次,再用 kubectl create ns mesh-lab && kubectl label ns mesh-lab istio-injection=enabled 创建命名空间。第 6 步会通过标签查询存活的 Pod,因此必须等待夹具工作负载的 Pod 进入 Running 状态。

  1. 首先把 /opt/lab/fixtures/istio/workload-v1v2.yaml 应用到 mesh-lab,并应用一个 DestinationRule,其 spec.subsets 包含 v1labels: {version: v1})和 v2labels: {version: v2}),名称为 reviews。然后创建 /root/istio/canary/vs-baseline.yaml:其中只含一个 VirtualService,spec.http[0].route恰好有两个条目,subset: v1weight 为 100,subset: v2weight 为 0。
  2. 创建 /root/istio/canary/vs-90-10.yaml。v1 使用 weight: 90,v2 使用 weight: 10(总和为 100)。对该文件执行 kubectl apply,并把输出保存到 /root/istio/canary/out/applied-10.txt(必须看到 configured/created/unchanged 之一)。
  3. 创建一个权重总和不为 100 的文件(例如在 /root/istio/canary/vs-bad.yaml 中设置 v1 90 / v2 20),使用 istioctl validate -f 检查,并把拒绝消息连同标准错误保存到 /root/istio/canary/out/weight-error.txt。另外,在 /root/istio/canary/out/weight-note.txt 中写明权重总和必须为 100 的规则。
  4. 创建 /root/istio/canary/vs-header.yaml。把选择请求头 x-canary 恰好等于 true 的路由放在前面,目标为 subset: v2weight: 100。随后再放置一条无条件的默认路由(条件路由不能放在最后)。
  5. 创建 /root/istio/canary/vs-mirror.yamlspec.http[0].route 指向 subset: v1,且 weight: 100;在同一条目中设置 mirrorhost: reviewssubset: v2)和 mirrorPercentage.value: 10。然后在 /root/istio/canary/out/mirror-note.txt 中写明镜像请求的响应会被丢弃,以及写操作可能带来的副作用风险。
  6. 首先重新应用 vs-90-10.yaml,使配置同时引用 v1、v2。然后暂时将 DestinationRule reviews 的 subset 名称 v2 改为 v2-canary 并应用,把 istioctl analyze -n mesh-lab 的结果保存到 /root/istio/canary/out/analyze-mismatch.txt。将名称恢复为 v2(labels version: v2)并应用后,再次分析并保存到 /root/istio/canary/out/analyze-clean.txt(其中不得有 Error [)。
  7. 向 DestinationRule reviews 添加并应用 trafficPolicy.loadBalancer.consistentHash.httpHeaderName: x-user-id。然后在 /root/istio/canary/out/sticky-note.txt(至少 50 字节)中说明同一用户在不同版本之间来回切换为何会造成问题。
  8. 创建 /root/istio/canary/rollout.yaml。顶层必须包含 stages 数组(至少 5 个阶段)和 rollback 键。每个 stage 都必须同时包含 weight(v2 权重)与 criteria(进入下一阶段的判断标准);weight 从 0 开始、以 100 结束,且中间不得降低。最后,把实际 VirtualService reviews 应用为 v1 50 / v2 50(以 spec.http最后一个条目为准)。将 istioctl analyze -n mesh-lab 的结果保存到 /root/istio/canary/out/final-analyze.txt,且不得有错误。

参考

创建 100/0 起点清单

首先把 /opt/lab/fixtures/istio/workload-v1v2.yaml 应用到 mesh-lab,并应用一个 DestinationRule,其 spec.subsets 包含 v1labels: {version: v1})和 v2labels: {version: v2}),名称为 reviews。然后创建 /root/istio/canary/vs-baseline.yaml:其中只含一个 VirtualService,spec.http[0].route恰好有两个条目,subset: v1weight 为 100,subset: v2weight 为 0。

新版本已经部署,但尚未分配流量。把两个 subset 都写好后,从下一步开始只需修改数字。

将 10% 流量转移到新版本

创建 /root/istio/canary/vs-90-10.yaml。v1 使用 weight: 90,v2 使用 weight: 10(总和为 100)。对该文件执行 kubectl apply,并把输出保存到 /root/istio/canary/out/applied-10.txt(必须看到 configured/created/unchanged 之一)。

不要覆盖上一步的文件,请另存为新文件。应用结果的输出也必须作为证据保存。

观察权重总和错误时会发生什么

创建一个权重总和不为 100 的文件(例如在 /root/istio/canary/vs-bad.yaml 中设置 v1 90 / v2 20),使用 istioctl validate -f 检查,并把拒绝消息连同标准错误保存到 /root/istio/canary/out/weight-error.txt。另外,在 /root/istio/canary/out/weight-note.txt 中写明权重总和必须为 100 的规则。

特意创建错误文件并交给验证工具检查。拒绝消息本身就是本步骤的产物。由于命令会以失败结束,必须连同标准错误一起保存。

本步骤的关键是了解哪些错误会被发现、哪些不会。即使总和为 110,目前 istioctl 也会通过,因为 Envoy 改为按 total_weight 归一化后,验证器取消了总和必须为 100 的规则。相反,总和为 0 会被拒绝。请同时尝试两种情况并保留结果。你将在这里学到:验证工具无法发现所有错误。

只将内部测试人员送往新版本

创建 /root/istio/canary/vs-header.yaml。把选择请求头 x-canary 恰好等于 true 的路由放在前面,目标为 subset: v2weight: 100。随后再放置一条无条件的默认路由(条件路由不能放在最后)。

指定人员必须 100% 看到新版本。条件路由应位于默认路径之上,无条件的默认路径放在最后。

配置会丢弃响应的镜像流量

创建 /root/istio/canary/vs-mirror.yamlspec.http[0].route 指向 subset: v1,且 weight: 100;在同一条目中设置 mirrorhost: reviewssubset: v2)和 mirrorPercentage.value: 10。然后在 /root/istio/canary/out/mirror-note.txt 中写明镜像请求的响应会被丢弃,以及写操作可能带来的副作用风险。

镜像不会改变返回给用户的响应。实际流量仍由旧版本 100% 处理,只有副本会发送到新版本。不要忘记指定比例。

制造并修复 subset 与 Pod 标签不一致

首先重新应用 vs-90-10.yaml,使配置同时引用 v1、v2。然后暂时将 DestinationRule reviews 的 subset 名称 v2 改为 v2-canary 并应用,把 istioctl analyze -n mesh-lab 的结果保存到 /root/istio/canary/out/analyze-mismatch.txt。将名称恢复为 v2(labels version: v2)并应用后,再次分析并保存到 /root/istio/canary/out/analyze-clean.txt(其中不得有 Error [)。

如果路由引用的 subset 从定义中消失,静态分析会发现。分别保留不一致状态与修复后状态的分析结果。

将同一用户固定到一个版本

向 DestinationRule reviews 添加并应用 trafficPolicy.loadBalancer.consistentHash.httpHeaderName: x-user-id。然后在 /root/istio/canary/out/sticky-note.txt(至少 50 字节)中说明同一用户在不同版本之间来回切换为何会造成问题。

权重拆分会针对每个请求重新选择。将负载均衡器改为基于哈希,并指定使用哪个请求头作为键。

制定分阶段金丝雀计划并推进到中间阶段

创建 /root/istio/canary/rollout.yaml。顶层必须包含 stages 数组(至少 5 个阶段)和 rollback 键。每个 stage 都必须同时包含 weight(v2 权重)与 criteria(进入下一阶段的判断标准);weight 从 0 开始、以 100 结束,且中间不得降低。最后,把实际 VirtualService reviews 应用为 v1 50 / v2 50(以 spec.http最后一个条目为准)。将 istioctl analyze -n mesh-lab 的结果保存到 /root/istio/canary/out/final-analyze.txt,且不得有错误。

计划的每个阶段都需要权重与判断标准,整体还需要回滚方法。并将实际服务网格推进到中间阶段。