HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • 代理技术全栈手册

    • 代理技术全栈手册 - HiHuo
    • 原理篇

      • 第01章 代理是什么:正向 / 反向 / 透明 / 隧道的统一模型
      • 第02章 代理与网络层级:L3 / L4 / L5 / L7 在哪里截断流量
      • 第03章 一个请求穿过代理的一生:连接生命周期全景
    • 协议篇

      • 第04章 HTTP 代理协议:绝对 URI、CONNECT 隧道、转发头与连接池
      • 第05章 HTTPS 与 TLS 代理:终止 / 透传 / MITM / SNI / mTLS
      • 第06章 SOCKS 协议:SOCKS4/4a/5 与 UDP ASSOCIATE 报文级解析
      • 第07章 HTTP/2、gRPC 与 HTTP/3(QUIC) 代理的挑战
      • 第08章 代理自动配置:PAC / WPAD / 系统代理 / NO_PROXY
    • 层级与转发篇

      • 第09章 L4 代理:TCP/UDP 转发与连接级负载均衡
      • 第10章 L7 代理:协议感知与基于内容的路由
      • 第11章 透明代理:iptables REDIRECT/DNAT、TPROXY 与 eBPF 劫持
      • 第12章 数据搬运的艺术:splice / sendfile / 零拷贝 / io_uring
    • 组件横评篇

      • 第13章 Nginx / OpenResty:反向代理、upstream 与 Lua 可编程
      • 第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
      • 第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面
      • 第16章 Traefik / Caddy:自动服务发现与自动 HTTPS
      • 第17章 Squid 与正向/缓存代理:企业出网、缓存与审计
      • 第18章 mitmproxy:抓包、改包、脚本化调试
      • 第19章 内网穿透与隧道:frp / gost / SSH 隧道 / ngrok
      • 第20章 科学上网生态的技术原理(技术中立)
    • 多语言手写篇

      • 第21章 Go:100 行手写 HTTP/CONNECT + SOCKS5 代理
      • 第22章 Rust:基于 tokio 的高性能 TCP 代理
      • 第23章 Python:asyncio 实现,适合调试与脚本
      • 第24章 C:epoll 裸写与零拷贝,及语言选型对比
    • 容器与K8s篇

      • 第25章 Docker 里的代理:HTTP_PROXY、build/pull 与 daemon 配置
      • 第26章 Sidecar 与流量劫持:Istio init-container 的 iptables 原理
      • 第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API
      • 第28章 Egress 与出网治理:出口网关、registry mirror、审计
      • 第29章 Service Mesh 数据面:Envoy Sidecar 全链路
    • 进阶篇

      • 第30章 可编程代理:Lua / Wasm / eBPF / xDS,代理的"软件定义"
      • 第31章 性能调优:并发模型、连接池、超时与重试、压测
      • 第32章 排错决策树:502 / 504 / 握手失败 / 环路 / 泄漏
      • 第33章 代理安全:开放代理、SSRF、凭证泄漏与攻击面
    • 底层机制篇

      • 第34章 代理的背压与流控:一个代理最难的部分
      • 第35章 socket 与 TCP 状态机:半关闭、超时、连接生命周期
      • 第36章 HTTP/2 帧、流控与 HPACK:h2 代理的内部机制
      • 第37章 负载均衡算法推导与韧性状态机
      • 第38章 Capstone:把玩具代理改造成生产级骨架
    • 综合实战篇

      • 第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题
      • 第40章 端到端实战:把 6 类流量全代理通
      • 第41章 更刁钻的流量:gRPC、长轮询、WebRTC、大文件、双向流
      • 第42章 可落地完整参考实现:一套能跑的多协议转发栈
    • 附录

      • 附录 A:代理协议报文速查(HTTP / SOCKS / PAC / PROXY protocol)
      • 附录 B:组件选型决策树
      • 附录 C:抓包与命令速查

第26章 Sidecar 与流量劫持:Istio init-container 的 iptables 原理

学习目标

  • 理解 sidecar 模式:每 Pod 注入一个 Envoy 接管全部进出流量
  • 走通 Istio 的流量劫持全链路:init-container 用 iptables 把流量 REDIRECT 到 Envoy
  • 看懂 Istio 的端口模型(15001/15006/15090/15021…)与防环路机制
  • 了解 sidecarless(Ambient mesh)与 CNI 注入的演进

前置知识

  • 第11章 透明代理(iptables REDIRECT、SO_ORIGINAL_DST、防环路)——本章是它在 K8s 的落地
  • 第15章 Envoy、第05章 mTLS、apiGateway · 服务网格

原理

sidecar 模式:给每个 Pod 配一个代理

Service Mesh 的核心做法:给每个业务 Pod 注入一个 Envoy 代理容器(sidecar),让 Pod 的所有进出流量都经过它。于是 mTLS、路由、重试、限流、遥测全在这个代理里做,业务代码零侵入。

        一个 Pod
  ┌───────────────────────────────────┐
  │  [业务容器]      [istio-proxy/Envoy] │
  │      │ 所有流量被劫持给 Envoy ↑     │
  │      └──── iptables REDIRECT ───────┘
  └───────────────────────────────────┘
   业务容器以为在直连,其实全经过了 sidecar

注入:自动 vs 手动

  • 自动注入:给 namespace 打标签 istio-injection=enabled,Istio 的 mutating webhook 在 Pod 创建时自动改 Pod spec,塞入 istio-init 和 istio-proxy 两个容器
  • 手动注入:istioctl kube-inject -f deploy.yaml 把注入后的 yaml 生成出来

注入后,一个原本 1 容器的 Pod 变成:1 个 init-container(istio-init)+ 业务容器 + 1 个 sidecar(istio-proxy)。

流量劫持全链路(呼应第11章)

这是 第11章透明代理 的终极落地。istio-init 这个 init-container 在 Pod 的网络命名空间里执行 iptables 规则(需要 NET_ADMIN 能力),把流量劫持到 Envoy:

出站(业务容器访问外部服务):
  app ──▶ [iptables OUTPUT REDIRECT → 15001] ──▶ Envoy ──mTLS──▶ 对端 Pod

入站(外部访问本 Pod):
  对端 ──▶ [iptables PREROUTING REDIRECT → 15006] ──▶ Envoy ──▶ app

防环路(第11章核心):
  Envoy 以 UID 1337 运行,iptables 用 -m owner --uid-owner 1337 -j RETURN 放过它自己,
  否则 Envoy 转发出去的流量又被劫持 → 无限环路

完整出站链路(两个 Pod 间):

  A-app → A的iptables(OUTPUT) → A-Envoy:15001
        → [选路由+负载均衡+mTLS加密]
        → B-Envoy:15006 → B的iptables(放行到app) → B-app
  回程对称返回。整条链路 app 无感,mTLS/遥测全自动。

Istio 端口模型(看到这些端口别懵)

istio-proxy 容器监听一组固定端口:

端口用途
15001出站流量被 REDIRECT 到这(outbound)
15006入站流量被 REDIRECT 到这(inbound)
15021健康检查(/healthz/ready)
15090Envoy Prometheus 指标
15000Envoy admin(config_dump 等,第15章)
15020Pilot agent 合并指标/agent

sidecar 的代价与演进

每 Pod 一个 Envoy 不是免费的:

  • 资源:每个 sidecar 几十 MB 内存 + CPU,规模大时累加可观
  • 延迟:每跳多两次代理(出站 + 入站各一次)
  • 启动顺序:init-container 先跑、业务容器要等 sidecar ready 才能出网(否则启动瞬间流量失败)
  • 生命周期:sidecar 与业务容器的优雅关闭顺序

演进方向:

  • Istio Ambient(sidecarless):用每节点一个 ztunnel(L4 mTLS)+ 按需 waypoint(L7 代理)取代每 Pod sidecar,大幅省资源(呼应 第11章 的 eBPF)
  • istio-cni:用 CNI 插件配 iptables 取代 init-container,免去业务 Pod 的 NET_ADMIN 特权

️ 实现 / 命令

实验一:开启注入并观察 Pod 多了什么

kubectl label namespace default istio-injection=enabled
kubectl apply -f deploy.yaml
kubectl rollout restart deploy/myapp        # 重建 Pod 触发注入

# 看 Pod:现在有 2 个容器(业务 + istio-proxy)+ 1 个 init
kubectl get pod -l app=myapp -o jsonpath='{.items[0].spec.containers[*].name}'
# myapp istio-proxy
kubectl get pod -l app=myapp -o jsonpath='{.items[0].spec.initContainers[*].name}'
# istio-init

实验二:看 init-container 配的 iptables(呼应第11章)

# 在 sidecar 容器里看 NAT 表(Istio 生成的 ISTIO_* 链)
kubectl exec <pod> -c istio-proxy -- iptables -t nat -S | grep ISTIO
# -A ISTIO_OUTPUT ... -j ISTIO_REDIRECT          出站重定向
# -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
# -A ISTIO_INBOUND ... -j ISTIO_IN_REDIRECT      入站重定向到 15006
# -A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN   ← 放过 Envoy 自己,防环路

亲眼看到 --uid-owner 1337 -j RETURN,第11章 讲的"放过代理自己防环路"就坐实了。

实验三:确认 Envoy 接管了路由

# 看这个 sidecar 拿到的 Listener/Cluster(控制面 xDS 下发,第15章)
istioctl proxy-config listeners <pod>
istioctl proxy-config clusters  <pod>
# 能看到 15001/15006 的 Listener 和指向各 Service 的 Cluster

实验四:验证 mTLS 生效

# 强制 namespace 全 mTLS
kubectl apply -f - <<'EOF'
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata: { name: default, namespace: default }
spec: { mtls: { mode: STRICT } }
EOF
# 此后 Pod 间流量自动 mTLS 加密(第05章),抓包看到的是 TLS 而非明文
istioctl authn tls-check <pod>     # 查看 mTLS 状态

排错

现象根因解决
Pod 没注入 sidecarnamespace 没标签 / Pod 没重建打 istio-injection=enabled 并 restart
init-container 失败缺 NET_ADMIN / PSP 限制放开权限,或改用 istio-cni
流量没被劫持iptables 没生效 / hostNetwork Pod查 ISTIO 链;hostNetwork Pod 不注入
启动瞬间请求失败业务容器先于 Envoy ready配 holdApplicationUntilProxyStarts
调用一直 503mTLS 模式不匹配(一边 STRICT 一边明文)统一 PeerAuthentication(第29章)
无限环路/CPU 高防环路规则缺失确认 --uid-owner 1337 RETURN(第11章)

本章小结

  • sidecar 模式:每 Pod 注入 Envoy,劫持全部进出流量,业务零侵入。
  • 劫持靠 init-container 在 Pod netns 配 iptables:出站→15001、入站→15006,--uid-owner 1337 RETURN 防环路(第11章)。
  • 端口模型:15001/15006(流量)、15021(健康)、15090(指标)、15000(admin)。
  • 代价是资源/延迟/启动顺序;演进为 Ambient(ztunnel+waypoint) 与 istio-cni。

下一章 第27章 Ingress 与南北流量,从"东西流量的 sidecar"转到"南北流量的入口"——Ingress Controller 如何作为反向代理把外部流量送进集群,及 Gateway API 新标准。

Prev
第25章 Docker 里的代理:HTTP_PROXY、build/pull 与 daemon 配置
Next
第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API