星的博客
type: channel
link: https://axzys.cn/
description: 星的博客
items: istio流量分析
items: 问题
items: F9P和DETA配置
items: test
items: 测试子分类
items: OBU和MDT私有协议数据帧
items: istio
items: cilium部署
items: Ansible ubuntu 22.04 双主

istio流量分析
type: item
date: 2026-02-03T15:21:24+00:00
description: 一、流量走势NodePort → ingressgateway Service → ingressgateway Pod(Envoy) → Gateway 筛选 → VirtualService 路由 → productpage Service:9080 → productpage Pod #如果不是NodePort 就需要kubectl port-forward -n istio-system --address 0.0.0.0 svc/istio-ingressgateway 8080:80 进行端口暴露 只需要记住一点svc只是负责把流量转发到对应的pod 而网关和路由的匹配则是istio-ingressgateway进行处理二、对应的yaml文件cat gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bookinfo-gateway namespace: default spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" root@k8s-01:/woke/istio# kubectl get virtualservice bookinfo -n default -o yaml apiVersion: networking.istio.io/v1 kind: VirtualService metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"bookinfo","namespace":"default"},"spec":{"gateways":["bookinfo-gateway"],"hosts":["*"],"http":[{"match":[{"uri":{"prefix":"/"}}],"route":[{"destination":{"host":"productpage","port":{"number":9080}}}]}]}} creationTimestamp: "2025-12-31T05:30:04Z" generation: 1 name: bookinfo namespace: default resourceVersion: "8121204" uid: b0fd2c20-35ab-475c-8c1a-d6dc36749ce8 spec: gateways: - bookinfo-gateway hosts: - '*' http: - match: - uri: prefix: / route: - destination: host: productpage port: number: 9080三、对应svc和podroot@k8s-01:/woke/istio# kubectl get pod NAME READY STATUS RESTARTS AGE bookinfo-gateway-istio-6c4c8d9b74-z7c4j 1/1 Running 0 18d details-v1-7b88fb8889-5qt26 2/2 Running 0 33d nginx-5fd58574d-2c9z9 2/2 Running 0 13d nginx-test-78b8db46d6-cfd98 2/2 Running 0 13d productpage-v1-79d79d6-mktpd 2/2 Running 0 33d ratings-v1-5b89cf4bbf-c9xdg 2/2 Running 0 33d reviews-v1-ffd57b847-w9dkr 2/2 Running 0 33d reviews-v2-8cc6fd8dc-q9bd9 2/2 Running 0 33d reviews-v3-cf48455-znts5 2/2 Running 0 33d traefik-gw-istio-7867b4f544-hkknj 1/1 Running 0 18d root@k8s-01:/woke/istio# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-I…

问题
type: item
date: 2026-01-29T14:14:00+00:00
description: 一、找回密码root@k8s-01:~# kubectl -n monitoring get pod | grep grafana grafana-7ff454c477-l9x2k 1/1 Running 0 8d root@k8s-01:~# kubectl -n monitoring exec -it grafana-7ff454c477-l9x2k -- sh /usr/share/grafana $ grafana-cli admin reset-admin-password '33070595Abc' Deprecation warning: The standalone 'grafana-cli' program is deprecated and will be removed in the future. Please update all uses of 'grafana-cli' to 'grafana cli' INFO [01-29|12:45:37] Starting Grafana logger=settings version= commit= branch= compiled=1970-01-01T00:00:00Z INFO [01-29|12:45:37] Config loaded from logger=settings file=/usr/share/grafana/conf/defaults.ini INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_DATA=/var/lib/grafana" INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_LOGS=/var/log/grafana" INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_PLUGINS=/var/lib/grafana/plugins" INFO [01-29|12:45:37] Config overridden from Environment variable logger=settings var="GF_PATHS_PROVISIONING=/etc/grafana/provisioning" INFO [01-29|12:45:37] Target logger=settings target=[all] INFO [01-29|12:45:37] Path Home logger=settings path=/usr/share/grafana INFO [01-29|12:45:37] Path Data logger=settings path=/var/lib/grafana INFO [01-29|12:45:37] Path Logs logger=settings path=/var/log/grafana INFO [01-29|12:45:37] Path Plugins logger=settings path=/var/lib/grafana/plugins INFO [01-29|12:45:37] Path Provisioning logger=settings path=/etc/grafana/provisioning INFO [01-29|12:45:37] App mode production logger=settings INFO [01-29|12:45:37] FeatureToggles logger=featuremgmt recoveryThreshold=true panelMonitoring=true lokiQuerySplitting=true nestedFolders=true logsContextDatasourceUi=true cloudWatchNewLabelParsing=true logRowsPopoverMenu=true kubernetesPlaylists=true dataplaneFrontendFallback=true recordedQueriesMulti=true transformationsVariableSupport=true addFieldFromCalculation…

F9P和DETA配置
type: item
date: 2026-01-27T13:02:00+00:00
description: 一、F9P接线 F9P TX1 → DETA R3 F9P GND → DETA G #数据 05:39:17 $GNRMC,053917.00,A,2232.90388,N,11356.18681,E,0.101,,270126,,,A,V*10 05:39:17 $GNVTG,,T,,M,0.101,N,0.187,K,A*33 05:39:17 $GNGGA,053917.00,2232.90388,N,11356.18681,E,1,10,1.84,37.4,M,-2.7,M,,*62 05:39:17 $GNGSA,A,3,01,02,04,17,,,,,,,,,2.70,1.84,1.97,1*07 05:39:17 $GNGSA,A,3,84,85,73,,,,,,,,,,2.70,1.84,1.97,2*00 05:39:17 $GNGSA,A,3,15,34,08,,,,,,,,,,2.70,1.84,1.97,3*0F 05:39:17 $GNGSA,A,3,16,,,,,,,,,,,,2.70,1.84,1.97,4*04 05:39:17 $GPGSV,3,1,12,01,50,161,45,02,65,092,40,03,01,168,,04,12,190,25,1*6D 05:39:17 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,19,1*62 05:39:17 $GPGSV,3,3,12,16,12,088,19,17,12,243,27,27,14,044,19,30,31,318,,1*6D 05:39:17 $GPGSV,3,1,12,01,50,161,33,02,65,092,,03,01,168,,04,12,190,18,6*61 05:39:17 $GPGSV,3,2,12,07,61,311,,08,42,027,,09,21,220,,14,09,301,,6*6D 05:39:17 $GPGSV,3,3,12,16,12,088,,17,12,243,25,27,14,044,,30,31,318,,6*68 05:39:17 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,26,74,35,346,,1*78 05:39:17 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,39,85,34,202,17,1*75 05:39:17 $GLGSV,2,1,08,71,04,228,,72,06,275,,73,53,055,21,74,35,346,,3*7D 05:39:17 $GLGSV,2,2,08,80,16,110,,83,36,031,,84,82,143,32,85,34,202,19,3*72 05:39:17 $GAGSV,3,1,09,02,35,061,21,07,32,265,,08,27,205,13,15,32,176,28,7*78 05:39:17 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,45,7*76 05:39:17 $GAGSV,3,3,09,36,23,048,24,7*44 05:39:17 $GAGSV,3,1,09,02,35,061,,07,32,265,,08,27,205,27,15,32,176,31,2*71 05:39:17 $GAGSV,3,2,09,27,17,299,,29,07,312,,30,48,348,,34,54,106,38,2*79 05:39:17 $GAGSV,3,3,09,36,23,048,,2*47 05:39:17 $GBGSV,1,1,01,16,83,123,40,1*4F 05:39:17 $GBGSV,1,1,01,16,83,123,34,3*4E 05:39:17 $GNGLL,2232.90388,N,11356.18681,E,053917.00,A,A*73 05:39:18 $GNRMC,053918.00,A,2232.90388,N,11356.18681,E,0.060,,270126,,,A,V*19 05:39:18 $GNVTG,,T,,M,0.060,N,0.111,K,A*3A 05:39:18 $GNGGA,053918.00,2232.90388,N,11356.18681,E,1,10,1.84,37.4,M,-2.7,M,,*6D 05:39:18 $GNGSA,A,3,01,02,04,17,,,,,,,,,2…

test
type: item
date: 2026-01-26T15:03:57+00:00

测试子分类
type: item
date: 2026-01-26T13:59:41+00:00
description: 测试子分类

OBU和MDT私有协议数据帧
type: item
date: 2026-01-22T07:38:00+00:00
description: 一、OBU [2026-01-21 10:07:45.968] FF FF 52 00 20 06 26 [2026-01-21 10:07:46.105] FF FF 4B 28 23 64 C6 25 [2026-01-21 10:07:46.113] 00 8C FF FF 56 2E 05 19 [2026-01-21 10:07:46.121] 00 64 2E 28 23 00 40 00 [2026-01-21 10:07:46.130] 00 00 00 33 [2026-01-21 10:07:46.458] FF FF 53 E3 20 00 00 C3 [2026-01-21 10:07:46.467] 01 27 40 2B E3 20 73 00 [2026-01-21 10:07:46.475] 00 00 00 FD 帧：FF FF 52 00 20 06 26 payload = 00 20 06 chk = 00^20^06 = 26 ✅ 这就是典型的 3-byte bitmask（24 个勾选位够用），你“bit 对应 UI 哪个勾”暂时先别钉死，等你再抓几组“勾选变化”的对照包就能反推出来。 帧：FF FF 4B 28 23 64 C6 25 00 8C 映射： Ko_raw = 0x2328 = 9000 → Ko = 9000/10 = 900 KoCount = 0x64 → 100 KPO_raw = 0x25C6 = 9670 KPOCount = 0x00 → 0 chk XOR ✅ 帧：FF FF 56 2E 05 19 00 64 2E 28 23 00 40 00 00 00 00 33 19 00 -> 25°C（当作“温度”） 因为你后面自己也用新截图验证了：UI 的 Temp 变了，但这两个字节不变。 所以它几乎可以排除是“实时温度”。 这帧看起来像“DR 标定快照 + 一些运行状态”，其中： 2E 05 作为 u16le = 0x052E = 1326 → Vcc = 1326/400 = 3.315V ✅ 2E 单字节 → Vr_raw，Vr = 2E/20 = 2.30 ✅ 28 23 → Ko_raw（再次出现）✅ 00（在 Ko 后面那个单字节）非常像 Vrev（UI 里 Vrev=0）✅ 40 很像一个 flag byte（或其中一个 flag byte）✅ 后面一串 00 基本就是保留/对齐/扩展 GPS State（3 字节 flags，高置信是“bitmask”） 完整帧：FF FF 52 00 20 06 26 idx hex 含义 0 FF 帧头 1 FF 帧头 2 52 块类型：GPS State 3 00 GPS 状态 flags[0]（bitmask，当前全 0） 4 20 GPS 状态 flags[1]（bitmask，bit5=1，高概率对应 UI 的 GPS 勾选） 5 06 GPS 状态 flags[2]（bitmask，bit1+bit2=1，高概率对应 OPK OK、Vr OK 这类勾选） 6 26 校验：00 XOR 20 XOR 06 = 26 ✅ 这页 UI checkbox 很多，3 字节=24 个 bit 完全够装。 DrCalibration（Ko / KPO / Count，高置信） 你日志把它拆行了，但应当拼成一帧： 完整帧：FF FF 4B 28 23 64 C6 25 00 8C payload（6 字节）：28 23 64 C6 25 00 idx hex 含义（小端） 0 FF 帧头 1 FF 帧头 2 4B 块类型：DrCalibration 3 28 Ko_raw 低字节 4 23 Ko_raw 高字节 → 0x2328 = 9000（UI Ko=900 很像 Ko=Ko_raw/10） 5 64 Ko Count → 0x64 = 100（UI 里 Ko 那行 Count=100） 6 C6 KPO 低字节 7 25 KPO 高字节 → 0x25C6 = 9670（UI KPO=9670） 8 00 KPO Count → 0（UI KPO 那行 Count=0） 9 8C 校验：28^23^64^C6^25^00 = 8C ✅ 完整帧：FF FF 56 2E 05 19 00 64 2E 28 23 00 40 00 00 00 33 payload（13 字节）： 2E 05 19 00 64 2E 28 23 00 40 00 00 00 idx hex 目前能确定的 / 可能的含义 0 FF 帧头 1 FF 帧头 2 56 块类型：0x56（未知块，像“配置/快照”） 3 2E 2E 05…

istio
type: item
date: 2025-12-30T09:59:00+00:00
description: istio是什么？Istio 是一种开源服务网格，可透明地分层到现有的分布式应用程序上。 Istio 的强大功能提供了一种统一且更高效的方式来保护、连接和监控服务。 Istio 是实现负载均衡、服务到服务身份验证和监控的途径 - 几乎无需更改服务代码。 功能： 使用双向 TLS 加密、强大的基于身份的身份验证和鉴权在集群中保护服务到服务通信 HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡 使用丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制 支持访问控制、限流和配额的可插入策略层和配置 API 集群内所有流量（包括集群入口和出口）的自动指标、日志和链路追踪 如何工作？ Istio 使用代理来拦截您的所有网络流量，从而根据您设置的配置允许使用一系列应用程序感知功能。 控制平面采用您所需的配置及其对服务的视图，并动态地编程代理服务器，并根据规则或环境的变化对其进行更新。 数据平面是服务之间的通信。如果没有服务网格，网络就无法理解正在发送的流量，也无法根据流量类型、流量来源或目的地做出任何决策。 Istio 支持两种数据平面模式： Sidecar 模式，它会与您在集群中启动的每个 Pod 一起部署一个 Envoy 代理，或者与在虚拟机上运行的服务一同运行。（下面使用的了sidecar模式） Ambient 模式，它使用每个节点的四层代理，并且可选地使用每个命名空间的 Envoy 代理来实现七层功能。 一、部署#官网 https://istio.io/#下载 https://github.com/istio/istio/releases/download/1.28.2/istio-1.28.2-linux-amd64.tar.gz #解压 tar -zxvf istio-1.28.2-linux-amd64.tar.gz #部署 root@k8s-01:/woke/istio# ls istio-1.28.2 istio-1.28.2-linux-amd64.tar.gz root@k8s-01:/woke/istio# cd istio-1.28.2/ root@k8s-01:/woke/istio/istio-1.28.2# export PATH=$PWD/bin:$PATH root@k8s-01:/woke/istio/istio-1.28.2# istioctl install -f samples/bookinfo/demo-profile-no-gateways.yaml -y |\ | \ | \ | \ /|| \ / || \ / || \ / || \ / || \ / || \ /______||__________\ ____________________ \__ _____/ \_____/ ✔ Istio core installed ⛵️ Processing resources for Istiod. Waiting for Deployment/istio-system/istiod ✔ Istiod installed 🧠 ✔ Installation complete root@k8s-01:/woke/istio/istio-1.28.2# kubectl label namespace default istio-injection=enabled namespace/default labeled root@k8s-01:/woke/istio/istio-1.28.2# root@k8s-01:/woke/istio/istio-1.28.2# root@k8s-01:/woke/istio/istio-1.28.2# root@k8s-01:/woke/istio/istio-1.28.2# root@k8s-01:/woke/istio/istio-1.28.2# root@k8s-01:/woke/istio/istio-1.28.2# kubectl get crd gateways.gateway.networking.k8s.io NAME CREATED AT gateways.gateway.networking.k8s.io 2025-11-17T15:05:26Z root@k8s-01:/woke/istio/istio-1.28.2# kubectl get crd httproutes.gateway.networking.k8s.io NAME CREATED AT httproutes.gateway.networking.k8s.io 2025-11-17T15:05:26Z root@k8s-01:/woke/…

问题
type: item
date: 2025-12-28T16:45:00+00:00
description: 调用 grafana 接口失败 error trying to reach service: dial tcp 10.244.2.60:3000: i/o timeout① 背景（30 秒） “有一次我们在 Kubernetes 集群里部署监控体系（Prometheus + Grafana），Grafana Pod 本身是 Running 的，但从节点或者其他组件访问 Grafana 的 Pod IP 的时候一直超时，curl 会直接 i/o timeout，影响监控平台的接入和联调。” “表面看 Grafana 是正常的，但网络层面存在异常。”② 问题拆解与排查思路（1 分钟） “我当时按分层排查的思路来做，而不是直接改网络策略。” 1️⃣ 先排除应用问题 我先 kubectl exec 进 Grafana Pod，直接 curl 127.0.0.1:3000/api/health 返回 200，说明 Grafana 本身没问题，端口监听正常 👉 这一步可以明确：不是应用、不是容器启动问题。 2️⃣ 再定位是 Service 层还是 Pod 网络问题 我确认 Service / Endpoint 都指向正确的 Pod IP 但从节点直接 curl PodIP 仍然超时 在同节点起一个临时 curl Pod 访问 PodIP，也同样超时 👉 这一步可以确定： 不是宿主机路由问题，而是 Pod 网络路径被拦截。 3️⃣ 确认 CNI 和隧道是否正常 集群使用的是 Cilium + VXLAN 我抓包看到 8472/UDP 的 VXLAN 流量是存在的 说明 overlay 隧道本身工作正常，否则整个集群通信都会异常 👉 到这里，网络连通性问题基本被排除。③ 关键突破点（40 秒） “真正的突破点是在 Cilium 的可观测工具 上。” 我在节点上执行了： cilium monitor --type drop 发现每一次访问 Grafana 3000 端口的 TCP SYN 都被丢弃 丢包原因非常明确：Policy denied 源身份显示为 remote-node 或 host 👉 这一步明确告诉我： 不是网络问题，而是被 Cilium 的策略明确拒绝了。④ 根因分析（30 秒） “回头检查发现，Grafana 所在命名空间里存在默认的 NetworkPolicy，只允许 Prometheus Pod 访问 Grafana 的 3000 端口。” 节点 / 宿主机访问 Grafana 时： 在 Cilium 里会被标记为 host 或 remote-node 并不属于普通 Pod identity 所以即使我用 Kubernetes NetworkPolicy 加了 ipBlock，依然无法命中这类流量 👉 本质原因是： Cilium 是以 identity/entity 为核心做策略决策，而不是单纯基于 IP。⑤ 解决方案（30 秒） “最终我使用的是 CiliumNetworkPolicy，显式放行来自节点的流量。” 在策略里允许： fromEntities: host fromEntities: remote-node 只放行到 Grafana 的 3000/TCP 应用策略后，从节点 curl PodIP 立刻恢复正常。⑥ 总结与价值（20 秒） “这个问题让我印象很深的一点是： 在使用 Cilium 这类 eBPF CNI 时，排查网络问题一定要用它自己的观测工具，而不是只停留在 Kubernetes NetworkPolicy 的抽象层。” “后续我也把这个问题整理成了 SOP，明确： Pod→Pod Node→Pod Service→Pod 在 Cilium 下对应的 identity 和策略差异，避免再踩坑。”面试官常见追问 & 标准答法（加分项） ❓追问 1：为什么 ipBlock 不生效？ 答： “因为在 Cilium 里，Node / Host 流量优先按 identity（host / remote-node）匹配策略，而不是单纯按源 IP。 NetworkPolicy 的 ipBlock 在这类流量场景下不会命中，所以需要用 CiliumNetworkPolicy 的 fromEntities。” ❓追问 2：为什么不用 NodePort / LoadBalancer？ 答： “NodePort 确实能绕开 Pod 网络策略，但会引入额外暴露面，不符合最小权限原则。 这里的目标只是节点内部访问 Pod 服务，用 CNI 级别策略精确放行更安全、更可控。” ❓追问 3：如何避免以后再发生？ 答： 明确区分 Pod 流量 vs Node/Host 流量 在启用 Cilium 的集群里： 默认 Network…

cilium部署
type: item
date: 2025-12-23T03:01:00+00:00
description: 一、cilium介绍Cilium 本质上是一个 Kubernetes 的网络与安全组件（通常以 CNI 插件的身份安装），它用 eBPF 在 Linux 内核里实现：Pod/Service 的转发、网络策略（NetworkPolicy）、可观测性（流量可视化/追踪）、负载均衡，甚至部分服务网格能力。 可以把它理解成：“把 Kubernetes 网络、负载均衡和安全策略，尽量下沉到内核里做”，相比传统 iptables 方案更高性能、更可观测、策略能力更强。二、cilium是什么在 K8s 里，想让 Pod 能互通、能访问 Service、能做 NetworkPolicy，需要一个网络方案。Cilium 通常承担这些职责： 1. CNI（容器网络接口）：给 Pod 分配 IP、配置路由/隧道/网卡，把 Pod 接入集群网络 2. Service 负载均衡实现：让访问 ClusterIP/NodePort/LoadBalancer 服务能正确转发到后端 Pod 3. 网络安全策略：实现 Kubernetes NetworkPolicy，甚至更强的 L3/L4/L7（HTTP/gRPC/DNS）策略 4. 网络可观测性：看到“谁在跟谁说话、延迟多少、丢包在哪里、命中了哪些策略” 5. （可选）替代 kube-proxy：用 eBPF 实现 Service 转发（kube-proxy replacement）三、cilium有什么用（解决了哪些痛点）A. 更快、更稳的转发与负载均衡 传统 kube-proxy 依赖 iptables/ipvs，规则多了会膨胀、调试困难。Cilium 用 eBPF 做转发和 LB： 1. 内核态快速转发（少走用户态/少遍历规则） 2. 大规模 Service/Endpoint 场景下更稳定 3. 更容易观测“为什么这次转发去了哪个后端、命中什么规则” B. 更强的安全能力（不仅是“允许/拒绝”） K8s 原生 NetworkPolicy 更多是 L3/L4（IP/端口）。Cilium 能做到更细： 1. 按 Pod 标签、命名空间、服务账户 做策略（身份感更强） 2. L7 策略（可选，通常依赖 Envoy）： 3. 允许某些 HTTP Path / Method 4. gRPC 服务/方法级别控制 5. DNS 解析策略（允许访问哪些域名） C. 可观测性（排障神器） Cilium 自带/配套 Hubble（可选）可以做到： 1. 实时看流量（flow logs）：谁访问了谁、是允许还是被拒绝、RTT、丢包 2. 快速定位：是 DNS 问题？策略拦了？还是 Service LB 选后端异常？ D. 可选的高级能力（看你是否启用） 不同环境会选用其中一部分能力： 1. 透明加密（节点间/Pod 间加密） 2. BGP/路由通告（部分场景下替代或配合传统 LB） 3. Gateway API / Ingress（通过 cilium-envoy） 4. 多集群互联（ClusterMesh）三、cilium是怎么工作的（核心：eBPF 数据面）关键点：eBPF eBPF 是 Linux 内核机制，允许把程序挂到内核的网络钩子上（如 tc、XDP、cgroup），从而： 1. 在包进入/离开网卡、进入容器、进入 socket 前后做处理 2. 实现 NAT、负载均衡、策略过滤、可观测统计 3. 尽量减少 iptables 链式规则带来的复杂性 Cilium 常见组件（你 kubectl get pod -n kube-system 看到的那些） 1. cilium (DaemonSet)：每个节点一个 agent，负责该节点上的转发/策略/eBPF 程序装载 2. cilium-operator (Deployment)：做控制面工作（例如管理 IPAM、节点资源、状态同步等） 3. cilium-envoy (DaemonSet，可选)：用于 L7 能力/Gateway/Ingress 等（不是所有场景都必须）四、IPAM 是什么IPAM = IP Address Management，就是“Pod 的 IP 从哪里来、怎么分配、怎么回收”。 Cilium 支持多种 IPAM 模式（不同环境选不同方式），常见两类理解： 1. kubernetes 模式：Pod IP 通常来自每个节点的 PodCIDR（例如你看到的 10.244.x.x） 2. cluster-pool / 等模式：由 Cilium 自己维护一个地址池分配（适合一些特定架构或需要 Cilium 管理地址的场景） 遇到的现象（Helm 改了 ipam.mode=kubernetes 但不重启不生效）很符合实际（后面案例）： ConfigMap …

Ansible ubuntu 22.04 双主
type: item
date: 2025-12-21T07:28:07+00:00
description: 这个文件一共 两个 play： Play 1（localhost）：只在控制机（你现在跑 ansible 的那台）做准备工作：生成/读取 SSH 公钥、写 ssh config、准备离线目录、尝试下载 k8s apt keyring（可选、失败不报错）。 Play 2（k8s_cluster）：对所有 k8s 节点做“真正的装机 + Kubernetes 初始化/加入”流程：系统基础配置、离线 apt repo 挂载、安装 containerd/k8s 组件、VIP 负载均衡（haproxy+keepalived，仅 master）、kubeadm init（首个 master）、其余 master join、worker join。Play 1：Prepare controller SSH key (localhost) 目标：让控制机具备 SSH key，并把公钥内容作为 fact 传给后续 play 使用。 关键点： 1.确保 ~/.ssh 存在 file 创建目录、权限 0700。 2.若缺失则生成 SSH key ssh-keygen -t rsa -b 4096 -N "" -f "{{ controller_ssh_key }}" creates: 保证幂等：文件存在则不再执行。 3.读取控制机公钥并 set_fact slurp 会把文件内容 base64 读回来；再 b64decode 变成文本。 存到 controller_pubkey，供后续节点写入 authorized_keys。 4.可选：写入控制机的 ~/.ssh/config 对 192.168.30.* 统一指定： 用户 root IdentityFile 使用 controller 生成的 key StrictHostKeyChecking no / UserKnownHostsFile /dev/null（方便自动化，但安全性降低） 这一步不影响节点配置，只是让你控制机 ssh 更省事。 5.确保 files/offline 目录存在 后续用到离线包、keyring 都放在 files/offline。 6.尝试下载 kubernetes apt keyring（最佳努力，不失败） failed_when: false + changed_when: false 有网就生成 kubernetes-apt-keyring.gpg，没网也继续往下跑。 随后 stat 检测是否存在，并设置 controller_has_k8s_keyring。 注意：你这里的离线 repo list 使用了 trusted=yes，所以 即使没有 keyring 也能装。但保留 keyring 逻辑可以让你以后切回在线源/或者取消 trusted=yes 更安全。Play 2：Bootstrap all k8s nodes（核心） 2.1 vars：整套集群“参数中心” ssh_user / ssh_user_home：依据 ansible_user 判断是 /root 还是 /home/<user>，用来给该用户写 authorized_keys。 VIP / keepalived / haproxy： apiserver_vip=192.168.30.58 apiserver_vip_port=16443（VIP 对外暴露端口） apiserver_bind_port=6443（kube-apiserver 实际监听端口） apiserver_vip_iface：用默认网卡名（拿 facts） keepalived_virtual_router_id/auth_pass：VRRP 参数 离线 repo： offline_tools_repo_tar、offline_containerd_repo_tar、offline_k8s_repo_tar、offline_lb_repo_tar 以及对应解压目录、apt list 文件路径 k8s 版本： k8s_pkg_version: 1.30.14-1.1 kubeadm_kubernetes_version: v1.30.14 kubeadm_image_repository：你用阿里镜像仓库，适合国内/离线镜像同步场景 containerd： containerd_sandbox_image 指定 pause 镜像 SystemdCgroup=true 内核模块：overlay、br_netfilter、ipvs 一套 + nf_conntrack 集群网络：pod/service 子网、domain、cri socket LB 节点选择逻辑（很关键）： lb_masters: "{{ (groups['k8…