Docker - 流量镜像

4
我有两个不同的运行容器。 我想将发送到容器#1的流量镜像到容器#2中。 这个问题有没有docker命令来解决?

“镜像流量”是什么意思?流量镜像通常在比Docker容器操作的更低的网络层上完成。也许你指的是“负载均衡流量”? - Hans Then
3个回答

6

在Linux接口上可能进行流量镜像,但我不认为Docker提供了设置的方法。如果您手动添加,则应该通过Docker为每个容器设置的veth接口进行镜像。

流量控制

tc允许您以多种方式管理流量,通常用于服务质量类型的排队。 tc还提供mirror操作。 以下匹配所有入站和出站流量,并将其镜像到另一个接口。

tc qdisc add dev vethb692b75@if13 ingress
tc filter add dev vethb692b75@if13 parent ffff: \
   protocol all prio 2 u32 \
   match u32 0 0 flowid 1:1 \
   action mirred egress mirror dev veth4305fdd@if15

tc qdisc replace dev vethb692b75@if13 parent root handle 10: prio
tc filter add dev vethb692b75@if13 parent 10: \
   protocol all prio 2 u32 \
   match u32 0 0 flowid 10:1 \
   action mirred egress mirror dev veth4305fdd@if15

IP表

iptables可以将克隆的数据包转发到可路由的主机。这通常用于将流量镜像到外部主机。

iptables -t mangle -I PREROUTING -i vethb692b75@if13 -j TEE --gateway <monitor_ip>
iptables -t mangle –I POSTROUTING -i vethb692b75@if13 -j TEE --gateway <monitor_ip>

tcpdump

在Linux世界中,大多数网络监控软件都涉及到tcpdump。您可以将主机接口上的tcpdump转储到一个fifo中,并将其挂载到监控容器中。

mkfifo /tmp/remotecapture.fifo 
tcpdump -s 0 -n -w - -U -i vethb692b75@if13 > /tmp/remotecapture.fifo
docker run -v /tmp/remotecapture.fifo:/tmp/remotecapture.fifo <image> netmonitor -f /tmp/remotecapture.fifo

注释

每次启动容器时,会为每个容器分配veth名称,因此捕获需要成为您的容器启动/停止过程的一部分。您希望在容器停止时删除任何规则。

在将流量转发到某个地方的情况下,接收者容器/主机不应将任何这些数据包路由回原始目标或其原始目标。


考虑到提问者的问题,那可能比我的回答更合适。+1 - VonC
谢谢!那非常有用。请问还有一个问题,如何根据容器名称获取桥接器名称? - Efrat Levy
@EfratLevy 提交另一个问题。 - Matt

2
容器#2作为容器#1的反向代理设置会更容易。
这意味着容器#2看到所有的流量并将其发送到容器#1。
您可以使用traefik.io/作为容器#2。它被用于负载均衡,但在您的情况下,您可以定义只有一个后端(因此没有负载均衡),引用容器#1。
您可以很容易地构建一个traefik容器(例如arm架构,请参见此Dockerfile)。

谢谢。我不希望容器#2设置为反向代理,因为这意味着如果它失败了,主容器就无法获得任何流量。有其他解决方案吗? - Efrat Levy
@EfratLevy,您可以直接在容器#1中安装Traefik,并将流量发送到容器#1的主服务器以及容器#2。 - VonC

0

编辑:如果您只处理HTTP流量

您可以在第三个容器中运行Nginx,并将其用作Docker容器的入口点。然后使用nginx作为Container 1的反向代理,并使用nginx镜像指令将所有请求镜像到Container 2。

实际上,Container 1将接收所有请求并发送响应。 Container 2也会收到请求,但其响应不会发送回发出请求的用户/客户端。

这是一个示例Nginx配置。

upstream logger {
    server app2:3002;
}

upstream app {
    server app1:3002;
}

server {
    listen 8000;
    location / {
        mirror /mirror;
        mirror_request_body on;
        proxy_pass http://app;
    }
    location  = /mirror {
        internal;
        proxy_connect_timeout 200ms;
        proxy_read_timeout 200ms;
        proxy_pass http://logger$request_uri;
        proxy_set_header HOST $http_host;
        proxy_set_header X-FORWARDED-FOR $remote_addr;
    }
}

但它可以是UDP流量 - 不是HTTP(S)。 - Dmytro
@Dmytro 是的,这只适用于 HTTP(s),对于 TCP,我会遵循 Matt 的答案。 - Karan Raina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接