TT Lab
开始
学习 学习路径 课程

Istio 服务网格

把代理从 Pod 里拿出来——环境模式的组件与两个层

在 TT Lab 中继续学习

目标

渲染 Ambient profile,与边车模式比较组件,并确认如何通过命名空间标签选择数据平面,以及把两个标签叠加时分析器会抓到什么。生成 waypoint 清单并阅读其字段,亲自看看在这个集群中应用为什么会失败。最后制作一张按模式统计命名空间的检查清单。

为什么重要

Ambient 是把代理从 Pod 中剥离、移到节点上的设计。收益很明确——每个 Pod 不再有代理,所以资源减少,而且无需重启工作负载,就能把它加入或移出网格。作为代价,功能分成了两层。 仅靠节点上的 L4 代理,能做到的只有双向认证和 L4 授权;像基于 HTTP 路径的路由或按方法粒度的授权这样需要查看请求内容的事情,则必须有名为 waypoint 的独立 L7 代理。所以迁移计划不是从“把边车关掉吧”开始,而是从“这个命名空间使用的功能中,哪些需要 L7”开始。而且切换期间,两种模式会在一个集群中共存,所以用机器可读的方式把哪个命名空间处于哪种模式统计下来,比靠人来记忆可靠得多。

步骤

  1. 创建 /root/ist-ambient,把 istioctl manifest generate --set profile=ambient 的输出保存到 /root/ist-ambient/ambient.yaml。提取其中所有的 Deployment 和 DaemonSet,以 <kind>|<이름>(占位符依次为类型名和对象名)的格式排序后写入 /root/ist-ambient/ambient-workloads.tsv。
  2. 也渲染 default profile 并保存到 /root/ist-ambient/default.yaml,比较两次渲染中的 ServiceAccount 名称,以 only-ambient\t<이름> 和 only-default\t<이름>(占位符为名称)这样的行排序后写入 /root/ist-ambient/sa-diff.tsv(两边都有的不写)。
  3. 从第 1 步的渲染中,只取出名称为 istio 的 ConfigMap 的 data.mesh,保存到 /root/ist-ambient/ambient-mesh.yaml。并把该渲染中包含的所有 ConfigMap 名称逐行排序后写入 /root/ist-ambient/ambient-configmaps.txt。
  4. 创建两个命名空间——给 shop-sidecar 打上 istio-injection=enabled 标签,给 shop-ambient 打上 istio.io/dataplane-mode=ambient 标签。然后从集群中读取这两个命名空间的标签,以 <네임스페이스>\t<라벨키>=<값>(占位符依次为命名空间、标签键和标签值)的格式排序后写入 /root/ist-ambient/ns-labels.tsv。
  5. 创建命名空间 shop-both,把 istio-injection=enabled 和 istio.io/dataplane-mode=ambient 两个都打上。把 istioctl analyze -n shop-both -o json 的输出保存到 /root/ist-ambient/analyze-conflict.json——应该出现 IST0123。然后只去掉边车一侧的标签,并把同一条命令的输出保存到 /root/ist-ambient/analyze-fixed.json。这次不应出现 IST0123。
  6. 把 istioctl waypoint generate --for service -n shop-ambient --name shop-waypoint 的输出保存到 /root/ist-ambient/waypoint.yaml。并把从中读取的四项内容,按 apiVersion、gatewayClassName、port、protocol 四行写入 /root/ist-ambient/waypoint-fields.tsv。
  7. 再用 --for workload 生成一次,保存到 /root/ist-ambient/waypoint-workload.yaml,并把两个文件中 metadata.labels."istio.io/waypoint-for" 的值,按 service 和 workload 两行,以 <파일이름>\t<값>(占位符依次为文件名和标签值)的格式写入 /root/ist-ambient/waypoint-for.tsv(名称用 shop-waypoint-wl)。然后实际应用第 6 步的 waypoint.yaml,并把结果保存到 /root/ist-ambient/waypoint-apply.txt。
  8. 创建 /root/ist-ambient/mode-report.sh,让它把集群中所有命名空间按名称顺序,以 <네임스페이스>\t<모드>(占位符依次为命名空间和模式)的格式只输出到标准输出——模式规则是:两个标签都有则为 conflict,只有 Ambient 标签则为 ambient,istio-injection 为 enabled 则为 sidecar,其余为 none。把输出保存到 /root/ist-ambient/mode-report.txt。

参考

统计 Ambient profile 会启动什么

创建 /root/ist-ambient,把 istioctl manifest generate --set profile=ambient 的输出保存到 /root/ist-ambient/ambient.yaml。提取其中所有的 Deployment 和 DaemonSet,以 <kind>|<이름>(占位符依次为类型名和对象名)的格式排序后写入 /root/ist-ambient/ambient-workloads.tsv。

Ambient 不是给每个 Pod 放入代理,而是在每个节点上部署两样东西——负责拦截流量的一方和充当 L4 代理的一方。两者都以 DaemonSet 的形式出现。从渲染结果中提取时,像 yq -N e 'select(.kind=="DaemonSet") | .metadata.name' 这样按类型过滤即可。

与边车模式相比,身份增加两个、减少一个

也渲染 default profile 并保存到 /root/ist-ambient/default.yaml,比较两次渲染中的 ServiceAccount 名称,以 only-ambient\t<이름> 和 only-default\t<이름>(占位符为名称)这样的行排序后写入 /root/ist-ambient/sa-diff.tsv(两边都有的不写)。

组件增加或减少时,这些组件使用的 ServiceAccount 也会随之变动。把两个列表分别排序后用 comm 比较,就能得到只在一侧存在的名称。Ambient 默认没有网关这一点,也会在这里显现出来。

Ambient 的网格配置中多开启了什么

从第 1 步的渲染中,只取出名称为 istio 的 ConfigMap 的 data.mesh,保存到 /root/ist-ambient/ambient-mesh.yaml。并把该渲染中包含的所有 ConfigMap 名称逐行排序后写入 /root/ist-ambient/ambient-configmaps.txt。

在 Ambient 中,Pod 之间的流量经过节点上的 L4 代理,通过隧道传递。开启那条隧道的值位于代理元数据中,请查看 defaultConfig.proxyMetadata 之下。ConfigMap 列表中,比边车 profile 多出一个。

一行命名空间标签就能选择数据平面

创建两个命名空间——给 shop-sidecar 打上 istio-injection=enabled 标签,给 shop-ambient 打上 istio.io/dataplane-mode=ambient 标签。然后从集群中读取这两个命名空间的标签,以 <네임스페이스>\t<라벨키>=<값>(占位符依次为命名空间、标签键和标签值)的格式排序后写入 /root/ist-ambient/ns-labels.tsv。

两种模式使用不同的标签键。边车一侧是注入 Webhook 所看的标签,Ambient 一侧是节点上的 CNI 所看的标签。给 kubectl get ns -o json 接上 jq,就能直接取出标签。

同时打上两个标签,行为就不确定

创建命名空间 shop-both,把 istio-injection=enabled 和 istio.io/dataplane-mode=ambient 两个都打上。把 istioctl analyze -n shop-both -o json 的输出保存到 /root/ist-ambient/analyze-conflict.json——应该出现 IST0123。然后只去掉边车一侧的标签,并把同一条命令的输出保存到 /root/ist-ambient/analyze-fixed.json。这次不应出现 IST0123。

两个标签由不同的组件读取——一个是注入 Webhook,一个是节点上的 CNI。两者都打上时,该 Pod 使用哪种数据平面就不确定。去掉标签时,在键后面加一个减号。

需要 L7 时,另外建立 waypoint

把 istioctl waypoint generate --for service -n shop-ambient --name shop-waypoint 的输出保存到 /root/ist-ambient/waypoint.yaml。并把从中读取的四项内容,按 apiVersion、gatewayClassName、port、protocol 四行写入 /root/ist-ambient/waypoint-fields.tsv。

waypoint 不是 Istio 专用的对象,而是表示为 Gateway API 的 Gateway——是哪个网关类,决定了它成为 waypoint。监听器的端口和协议,就是 Ambient 在 Pod 之间使用的隧道本身。

这是为什么而设的 waypoint,以及为什么在这里无法应用

再用 --for workload 生成一次,保存到 /root/ist-ambient/waypoint-workload.yaml,并把两个文件中 metadata.labels."istio.io/waypoint-for" 的值,按 service 和 workload 两行,以 <파일이름>\t<값>(占位符依次为文件名和标签值)的格式写入 /root/ist-ambient/waypoint-for.tsv(名称用 shop-waypoint-wl)。然后实际应用第 6 步的 waypoint.yaml,并把结果保存到 /root/ist-ambient/waypoint-apply.txt。

waypoint 既可以建立在服务前面,也可以建立在工作负载前面——由一个标签说明其范围。在这个集群中,应用不会成功。为什么会这样,报错的句子已经直接说明了。

按模式统计集群中命名空间的检查清单

创建 /root/ist-ambient/mode-report.sh,让它把集群中所有命名空间按名称顺序,以 <네임스페이스>\t<모드>(占位符依次为命名空间和模式)的格式只输出到标准输出——模式规则是:两个标签都有则为 conflict,只有 Ambient 标签则为 ambient,istio-injection 为 enabled 则为 sidecar,其余为 none。把输出保存到 /root/ist-ambient/mode-report.txt。

用一次 kubectl get ns -o json 获取所有标签,再用 jq 筛选。标签键中混有点和斜杠,所以在 jq 中用方括号和引号取值更稳妥。istio-injection 的值也可能是 disabled,所以只能统计已开启的。