第 2
篇 确认 Pod 已被 proxy-injector 写入
linkerd-proxy(及可能的
linkerd-init)。成员资格成立只说明数据面容器存在;应用流量要获得
mTLS、发现与策略,还必须经过 iptables
重定向(或 CNI 等价路径)进入
proxy。许多「已注入但连不上」的事故落在轴 2,却被误当成
identity 或 destination 问题。
本篇回答:TCP 如何透明进入 linkerd2-proxy,init 与 CNI 两条路径差在哪,inbound/opaque 端口如何改变入站路径。 注入决策见第 2 篇;CSR 与握手见 第 4 篇。
本篇在系列中的位置
篇目 核心内容 第 2 篇 · 网格成员与注入 proxy-injector、native sidecar 第 3 篇 · 流量重定向 linkerd-init、CNI、iptables、opaque 第 4 篇 · identity 服务 CSR、mTLS 轮转 系列目录 关键问题、阅读路径
版本锚定:Linkerd 2.20(源码 tag
version-2.20)。数据面默认 native sidecar;CNI 文档 2.20 树写明 native 下应用initContainers可在 proxy 就绪后出网。机制对齐 Architecture 与 CNI Plugin 2.20 文档。无真实集群则不粘贴伪造 iptables 列表或linkerd check片段。
一、linkerd-init iptables
默认路径(未启用 Linkerd CNI)下,injector 在 Pod 中插入
linkerd-init 作为 init
容器。它在任何应用容器启动前运行,通过
iptables(具体变体由 init 模式配置)把进出
Pod 的 TCP 流量重定向到本机
linkerd-proxy 监听的端口。规则写完后 init
退出;后续由内核在数据路径上把连接交给
proxy,应用进程无需改代码。
官方 Architecture 把该机制称为数据面「透明」的基础:proxy 与业务容器共享网络命名空间,iptables 在命名空间边界内完成劫持。出站连接由 outbound proxy 处理发现、负载均衡与 mTLS 发起;入站连接由 inbound proxy 处理策略 enforcement 与指标。
| 要素 | 可核对事实 |
|---|---|
| 执行时机 | 应用容器与(legacy 模式下)proxy 容器启动前 |
| 权限需求 | CAP_NET_ADMIN(默认 init 路径) |
| 协议范围 | 文档明确为 TCP 透明代理 |
| 与 native sidecar | 2.20 默认 proxy 更早就绪;init 仍负责 iptables(非 CNI 时) |
工程间隙:iptables 重定向是 Linux 网络命名空间内的经典手法,与 eBPF TC 劫持(如部分 CNI 数据面)相比可移植性高,但依赖 NET_ADMIN 或外挂 CNI;这也是 Linkerd 提供 CNI 插件的原因(第二节)。
出站流量被重定向到 outbound proxy 监听端口后,proxy
才发起对 destination 的 Get()
流与对 identity 的 CSR——因此轴 2
失败时,指标上可能完全看不到 mTLS 或 golden
metrics,容易被误判为「应用本身不兼容 mesh」。验证方法是在
Pod 网络命名空间内确认进程监听与连接跟踪是否经过 proxy
端口(具体端口以 linkerd-config
与注入模板为准),而不是先抓 ServiceProfile。
二、Linkerd CNI 插件
部分集群禁止 Pod 持有 CAP_NET_ADMIN。Linkerd
提供 linkerd-cni
DaemonSet:通过 CNI chaining 在 Pod
网络配置阶段写入与 init 等价的 iptables 规则,使 meshed Pod
不再需要 linkerd-init
容器。
安装语义(官方 CNI Plugin):
- 先安装
linkerd-cniDaemonSet(linkerd install-cni或 Helmlinkerd2-cni); - 控制面安装时加
--linkerd-cni-enabled,在linkerd-configConfigMap 写入cniEnabled; - proxy-injector 读取该标志,省略 Pod
内的
linkerd-init。
CNI 与节点上已有 CNI 插件并存,不替代主
CNI;在 Cilium 上安装时需
cni.exclusive=false,避免独占
/etc/cni/net.d。
安装顺序错误是最常见的轴 2 生产事故之一:若先装控制面再补 CNI DaemonSet,已运行的 meshed Pod 可能长期缺少节点规则,而新建 Pod 在 CNI 就绪后表现正常——形成「只有旧 Pod 不正常」的诡异分裂。修复通常需要滚动 Pod 或确认节点上 CNI 配置已链入,而不是调高 destination 副本数。
native sidecar 与 CNI
的交叉(2.20):CNI 文档指出,启用 CNI 且
native sidecar 默认开启 时,proxy 在应用
initContainers 之前启动,需要网络的 init
可直接出网。若关闭 native sidecar,legacy
布局下 proxy 晚于所有 init 启动,init 发出的包会被 iptables
截获而 proxy 尚未监听——此时需让 init 以 proxy UID(默认
2102)运行以跳过规则,该流量不经
mesh。
flowchart LR
subgraph init_path ["Default: linkerd-init"]
pod1["meshed pod"] --> init1["linkerd-init iptables"]
init1 --> proxy1["linkerd-proxy"]
end
subgraph cni_path ["CNI enabled"]
cni["linkerd-cni on node"] --> pod2["meshed pod no init"]
pod2 --> proxy2["linkerd-proxy"]
end
图:两条路径目标一致——TCP 进 proxy;差异在规则安装者与 Pod 是否含 init 容器。
三、inbound / opaque 端口
重定向把流量送到 proxy 后,入站侧如何转发到应用端口,取决于协议探测与 opaque 配置。
- 默认 HTTP 路径:proxy 探测客户端字节,识别 HTTP/gRPC 等,再转发到容器目标端口。
- opaque
ports(
config.linkerd.io/opaque-ports):跳过探测,按 TCP 流转发;仍经 proxy,故 mTLS 与 TCP 指标保留。对 server-speaks-first 协议(如部分 Redis/MySQL 场景)通常需要 opaque 或 ServiceappProtocol。 - inbound 监听:meshed 入站流量先到达 proxy 的 inbound 端口(默认 4143),再由 inbound proxy 转发到应用端口。opaque 连接同样经此端口进入 proxy,而非直接打到应用端口。
这与 skip-inbound-ports 形成对照:后者修改 iptables,使流量根本不进 proxy(第 2 篇第四节)。排障时「只有某端口不通」要先分清是 opaque 汇聚到 4143 的 NP 问题,还是 skip 导致完全旁路。
官方 Protocol Detection 要求:对 meshed
客户端访问 opaque 服务,注解标在接收方
Pod;headless 或直接 Pod IP 访问时
appProtocol 可能不生效,必须依赖注解。
| 配置 | 作用点 | proxy 是否见流量 | mTLS |
|---|---|---|---|
| opaque-ports | 接收方 | 是 | 是 |
| skip-inbound-ports | 接收方 iptables | 否 | 否 |
| skip-outbound-ports | 发送方 iptables | 否 | 否 |
inbound 与 outbound 端口缺省值(以 2.20
文档与 linkerd-config 为准):proxy
在容器内监听 inbound(默认 4143)承接被
iptables 转发的入站
TCP,再转发到应用端口;outbound(默认
4140)承接本机进程出站连接。opaque 并不改变「先进
inbound」的入站路径,只改变 proxy 是否对字节流做 HTTP
探测。NetworkPolicy 若只允许应用端口(如 6379)而拒绝
4143,meshed 客户端访问 opaque 服务会失败——这与 Redis 等
chart 自带 NP 的组合在社区 issue 中已有复现路径。
四、与轴 1 衔接
五轴中轴 1(注入)与轴
2(重定向)是串联门:injector
写入的容器列表与 CNI 标志决定轴 2 是否存在
linkerd-init、proxy 何时就绪。
轴 1 证据包:Pod spec 含 linkerd-proxy;native vs legacy 形状
→ 轴 2 证据包:含 linkerd-init 或集群 cniEnabled;iptables/CNI 是否生效
→ 轴 3+:流量进入 proxy 后才涉及 identity CSR、destination.Get
典型串联失败:
- 已注入、init CrashLoop:应用容器可能根本未拿到重定向规则,表现为直连或连接挂起——先查 init 日志与 NET_ADMIN,而非 identity。
- CNI 未就绪即注入:缺少节点级规则,Pod
内无 init 兜底时流量旁路——查
linkerd-cniDaemonSet 与linkerd check --pre --linkerd-cni-enabled语义(有环境才执行)。 - legacy + CNI + 需要网络的 init:需 UID 2102 或改开 native sidecar——这是 2.20 默认门想消除的类。
McCanne & Jacobson(1993)BPF 谱系与 mesh 重定向的关系是间接的:iptables REDIRECT/TPROXY 仍是 Linux 上最广泛部署的「在内核路径选路」手段之一;Linkerd 没有为通用 L7 选择 Envoy,而是在 Rust 微代理内做协议探测(第 10 篇)。轴 2 的职责仅是把字节送进 proxy,不在此做 L7 路由——那是 destination + proxy 出站链的事。
与 istio-xds/14
对照:Istio 同样依赖 init/iptables 或 CNI
变体,但排障口令常落在 xDS 推送;Linkerd 在轴 2 必须先确认
init 或 CNI 路径哪条生效,再谈
linkerd2-proxy-api。
五、重定向失败表象
| 表象 | 优先轴 | 核对项 |
|---|---|---|
注入 Pod 内 curl 直连 Service IP 绕过
mesh |
2 | iptables 是否存在;是否误用 skip 注解 |
linkerd-init CrashLoopBackOff |
2 | NET_ADMIN;安全策略是否禁止 init |
| 仅 CNI 集群无 init 但流量未进 proxy | 2 | cniEnabled;节点 CNI 配置与 Cilium
exclusive |
| init 需要拉镜像/调 API 失败 | 1→2 | native sidecar 是否开启;legacy 下 UID 2102 |
| 某 L4 端口超时,其他端口正常 | 2→4 | opaque 与 4143;NetworkPolicy 是否放行 inbound |
| meshed 两端仍明文 | 2→3 | 流量是否经 proxy(skip 与未重定向) |
iptables 模式变体(官方
Architecture 仅点名「不同 mode 决定 iptables
变体」):具体 flag 以 version-2.20 的
linkerd-init 镜像与 linkerd-config
为准。排障时若仅 IPv6 失败而 IPv4 正常,应回到 init/CNI
规则族是否与双栈集群匹配,而不是先调 destination。
验证顺序建议(语义级,非伪造命令输出):先确认轴
1 注入与 proxy 监听;再确认轴 2 的 init 或
cniEnabled;对可疑端口检查 opaque/skip 与
NetworkPolicy;最后才进入 identity / destination 日志。
linkerd-init 退出后规则是否仍在:init 容器成功退出后,iptables 规则应保留在 Pod 网络命名空间内直至 Pod 销毁。若安全策略使用每容器网络隔离或某些 CRI 实现对 init 网络命名空间有特殊处理,可能出现「init 成功但规则未留存」的极端情况——此类问题需对照节点 CRI 版本与 Linkerd 发行说明,而非调整 ServiceProfile 超时。
开放问题:基于端口的 NetworkPolicy 与 opaque 流量经统一 inbound 端口的组合,在多 CNI 环境下仍易出现「成员资格成立、策略层拒绝」的灰区;社区讨论倾向于放宽 NP 或改用标签选择器,而非放弃 opaque。完整策略求值见本系列第 8 篇规划。
与 eBPF L4 的边界:Cilium 等可在 L3/L4
做身份与策略,但 Linkerd 轴 2 的 iptables/CNI 劫持发生在 Pod
网络命名空间内,与节点级 eBPF 程序是否共存取决于 CNI
chaining 配置(第 14 篇对照)。在同时安装 Linkerd CNI 与
Cilium 时,必须先核对 cni.exclusive 与 chaining
顺序,否则表现为「部分节点重定向失效」——这是节点级证据包,不是单
Pod 注解能修复的。
meshed 连接定义回顾(Architecture):仅当发起方与接受方 Pod 均已注入且流量经双方 proxy 时,连接才算 meshed。轴 2 失败时常见「一侧明文一侧 mesh」——出站 proxy 可能仍尝试 mTLS,入站却未走 inbound proxy,握手与指标都会异常。排障表中的「两端仍明文」应优先确认 iptables 是否对双方生效,而不是只查客户端。
UDP 与非 TCP 流量:官方架构明确透明代理对象为 TCP;UDP 等协议不在 linkerd-init 默认重定向范围内。若应用主要走 UDP,轴 2 的「透明 mesh」假设不成立——这是机制边界,不是配置遗漏。
参考资料
规范 / 官方文档(A)
- Linkerd, Architecture(linkerd-init、meshed connections、TCP 透明代理)
- Linkerd, CNI
Plugin(chaining、
--linkerd-cni-enabled、UID 2102、native sidecar 与 init 网络) - Linkerd, Protocol Detection(opaque vs
skip、
appProtocol) - Linkerd, Proxy Configuration(端口注解全集)
站内对照
工程反例(B)
- linkerd/linkerd2 issue #12382(opaque 与 NetworkPolicy / inbound 4143;native sidecar 相关修复线索)
上一篇:网格成员与注入
下一篇:identity 服务
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【Linkerd】网格成员与注入:proxy-injector 与 native sidecar 门
以 Linkerd 2.20 为锚,拆解 proxy-injector 如何把 Pod 变成 mesh 成员;native sidecar 默认与 legacy init+sidecar 分列证据包,以及 opaque ports 与 membership 失败落格。
【Linkerd】控制面全景:缺口、五轴坐标系与 16 篇路线
相对 istio-xds/14 对照篇与 architecture/76 税文,钉清 Linkerd 2.20 非 xDS 控制面缺口;定义注入、identity、destination、策略与数据面五条轴,并强调 native sidecar 与 legacy 路径分列证据包。
【Linkerd】identity 服务:CSR、mTLS 与工作负载证书轮转
拆解 linkerd-identity 如何校验 CSR 并签发绑定 ServiceAccount 的工作负载证书;自动轮转与 issuer/trust anchor 分层,并对照 Envoy SDS 路径与失败落格。
【Linkerd】destination 架构:四容器 Pod 与 Informer 驱动
拆解 linkerd-destination Pod 内 destination、sp-validator、policy 与反身 proxy 四容器分工;Informer/EndpointTranslator 如何把 Kubernetes 状态流式推给数据面,并钉住 2.20 内存优化门。