使用 `docker-compose` 模拟 Istio 的流量镜像(traffic mirroring)
解读
国内云原生面试中,“不用 Istio 也能实现流量镜像” 是高频追问,目的是考察候选人是否真正理解 “镜像=旁路复制” 的本质,而不是只会背 Istio CRD。
Docker Compose 虽然没有 VirtualService 的 mirror 字段,但可以通过 “双服务+七层代理” 的方案,在本地开发环境低成本复现生产级观测、灰度、压测场景。
面试官期待你给出 可一行行复现的 Compose 模板,并解释 镜像流量对业务零侵入、零返回 的关键细节。
知识点
- 流量镜像定义:将生产请求 完整复制一份 发到影子实例,影子响应被丢弃,不影响真实调用链。
- Compose 网络模型:同一
networks下容器 DNS 互认,ingress 代理 可作为透明流量锚点。 - nginx 流量镜像:使用
mirror模块(ngx_http_mirror_module)在 七层 完成复制,1:1 实时性 优于 tcpdump+replay。 - 零返回关键:
mirror指令默认 忽略影子响应;若用 Envoy,需设置shadow集群request_mirror_policy的runtime_fraction=100%并关闭shadow_alpn。 - 资源隔离:影子服务 单独 deployment(Compose 里即独立 service),避免 CPU 抢占导致基线失真。
- 可观测性:影子容器内 开启 DEBUG 日志 并挂载同一
promtailsidecar,实现 Grafana 实时对比(本地可用grafana/agent容器替代)。 - 国内镜像加速:
nginx:alpine与httpbin镜像需加 registry.cn-hangzhou.aliyuncs.com 前缀,避免面试现场拉取超时。 - 安全合规:影子环境 禁止写库,通过 只读账号 与 Mock 服务 兜底,满足国内金融客户 等保 要求。
答案
给出一份 单文件 docker-compose.yml,可在 2 分钟内拉起,真实请求 100% 镜像 到影子容器,且影子响应被丢弃。
目录结构
traffic-mirror/
├── docker-compose.yml
├── nginx.conf
docker-compose.yml
version: "3.9"
services:
proxy:
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx:1.25-alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "80:80"
networks:
- mesh
depends_on:
- primary
- shadow
primary:
image: registry.cn-hangzhou.aliyuncs.com/google_containers/httpbin:latest
networks:
- mesh
environment:
- GUNICORN_CMD_ARGS="--access-logfile -"
command: ["gunicorn", "-b", "0.0.0.0:80", "httpbin:app"]
shadow:
image: registry.cn-hangzhou.aliyuncs.com/google_containers/httpbin:latest
networks:
- mesh
environment:
- GUNICORN_CMD_ARGS="--access-logfile -"
command: ["sh", "-c", "echo '*** SHADOW START ***' && gunicorn -b 0.0.0.0:80 httpbin:app"]
networks:
mesh:
driver: bridge
nginx.conf
events { worker_connections 1024; }
http {
upstream primary { server primary:80; }
upstream shadow { server shadow:80; }
server {
listen 80;
location / {
mirror /shadow;
proxy_pass http://primary;
}
location = /shadow {
internal;
proxy_pass http://shadow$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Shadow-Request-ID $request_id;
}
}
}
启动与验证
docker compose up -d
# 发一条请求
curl localhost/get?foo=bar
# 观察 shadow 日志,出现相同请求但客户端只收到一次响应
docker compose logs -f shadow
面试现场加分话术:
“mirror 指令由 nginx 原生支持,无需 iptables,性能损耗 <1%;若后续迁到 K8s,只需把 nginx 替换成 Envoy,同一套 shadow 概念平移到 Istio VirtualService 即可。”
拓展思考
- 动态采样:通过
mirror_request_body off;与map变量实现 按 Header 灰度,例如只镜像带X-Test: stress的请求,模拟生产压测 而不影响全量流量。 - 响应对比:在 shadow 容器内 注入 diff sidecar,把真实响应与影子响应做 JSON 字段级对比,零人工回归 发现兼容性问题。
- 出口流量镜像:若后端是 gRPC,可把 nginx 换成 Envoy 容器,用
envoy.yaml的request_mirror_policy,同一套 Compose 文件 只需换镜像即可。 - 资源限制:国内 4C8G 笔记本跑全量镜像容易 OOM,为 shadow 加 mem_limit: 512m,并用
cpus: 0.5模拟 低配灰度节点,面试时展示 cgroup 限制 意识。 - 合规脱敏:镜像流量可能带 手机号、身份证,在 nginx 层加
sub_filter或 Lua 脚本 做 字段打码,满足 《个人信息保护法》 要求,体现 国内落地经验。