重新创建目标 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']
我正在从主机上的 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']