重新创建目标 pod 后主机内 UDP 流量丢失

Intra-host UDP traffic missing after destination-pod re-created

我正在从主机上的 pods 向 <hostIP>:8125 发送 UDP 数据包 (statsd)。在另一端,一个收集器(使用 hostPort 的数据狗代理;通过 DaemonSet 每个主机一个)收集数据包并完成它。

通常这工作正常,但如果我删除并重新创建收集器(kubectl delete pod datadog-agent-xxxx;几秒钟后新 pod 在相同 IP/port 上启动),来自 [=31 的流量=] 现有 客户端套接字停止到达收集器(UDP 套接字在 pod 重新调度工作正常后创建)。

仅重新启动收集器 pod 内的代理(kubectl exec -it datadog-agent-xxxxx agent stop;约 30 秒后自动重新启动)相同的旧流量 会出现。所以容器一定会产生影响。

虽然 UDP(据说)是无状态的,但显然某处某物在保持状态!?任何 ideas/pointers?

每个 "client" pod 在 deployment/pod 中都有这样的东西:

kind: Deployment
...
spec:
  template:
    spec:
      containers:
        - name: webservice
          env:
            # Statsd defaults to localhost:8125, but that's this pod. Use `hostPort` on collector + hostIP here to get around that.
            DD_AGENT_HOST:
              valueFrom:
                fieldRef:
                  fieldPath: 'status.hostIP'

在收集器上(在 datadog's k8s docs 之后):

kind: DaemonSet
...
spec:
  template:
    spec:
      containers:
        - image: datadog/agent:6.140.0
          ports:
            - containerPort: 8125
              hostPort: 8125
              protocol: UDP
          env:
            - name: DD_DOGSTATSD_NON_LOCAL_TRAFFIC
              value: "true"
            - ...

这发生在 Google Kubernetes Engine 上的 Kubernetes 1.12 上。

这可能与此issue in the portmap plugin有关。当前的工作理论是,当客户端 pod 到达 UDP 主机端口时创建一个 conntrack 条目,并且当服务器 pod 被删除时该条目变得陈旧,但它并没有被删除,因此客户端不断点击它,本质上是黑洞流量.

您可以尝试在其中一台受影响的主机上使用 conntrack -D -p udp --dport 8125 之类的内容删除 conntrack 条目。如果这解决了问题,那么这就是问题的根本原因。

GitHub 问题中描述的解决方法应该可以缓解问题,直到合并修复:

你可以在服务器的 pod 中添加一个 initContainer 到 运行 启动时的 conntrack 命令:

initContainers: 
        - image: <conntrack-image>
          imagePullPolicy: IfNotPresent 
          name: conntrack 
          securityContext: 
            allowPrivilegeEscalation: true 
            capabilities: 
              add: ["NET_ADMIN"] 
          command: ['sh', '-c', 'conntrack -D -p udp']