Cilium 环境下端口分配失败(EADDRINUSE)问题定位笔记

部署运行你感兴趣的模型镜像


Cilium 环境下端口分配失败(EADDRINUSE)问题定位笔记

📌 背景概述

业务程序(例如某 CLI 工具,sqlcmd)在执行 TCP 连接时失败,通过 strace 观察发现:

export LD_LIBRARY_PATH=/app
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_TCP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) 
    = -1 EADDRINUSE (Address already in use)

同时,使用 Python 简单脚本模拟端口动态分配,也出现:

socket.error: [Errno 98] Address already in use

说明 系统无法分配 ephemeral port(临时端口)

此问题在运行 Cilium 的 Kubernetes 节点上出现,怀疑可能与 eBPF NAT / sockmap 相关。


1. 关键现象汇总

✔ 1.1 动态分配端口失败

无论程序还是 Python,都无法通过下列方式分配随机端口:

s.bind(('0.0.0.0', 0))

报错均为:

EADDRINUSE (Address already in use)

说明 操作系统认为所有可用源端口都已被占用


✔ 1.2 IPv6 bind 也失败

即使换成 IPv6:

s = socket.socket(AF_INET6)
s.bind(('::', 0))

仍然返回:

Address already in use

说明问题与 IPv4/IPv6 无关,并非单协议栈问题。


✔ 1.3 Cilium BPF Maps 缺失

尝试查看 Cilium 的 sockops map:

bpftool map dump pinned /sys/fs/bpf/tc/globals/cilium_sock_ops_v4

结果:

No such file or directory

说明当前节点未加载此 bpf map —— 可能是 Cilium 配置或版本差异导致。


✔ 1.4 Cilium BPF 文件系统正常挂载

mount | grep bpf

输出正常:

/sys/fs/bpf on /sys/fs/bpf type bpf (rw,relatime)

且 Cilium 也能探测到:

cilium bpf fs show

2. 潜在原因分析

🔎 2.1 系统 ephemeral port 耗尽

当所有可分配端口被占用后,就会出现:

bind(..., port=0) → EADDRINUSE

可能原因包括:

  • 大量 TIME_WAIT 端口未回收
  • 程序长时间占用大量短连接
  • Cilium NAT eBPF 重写导致端口池异常

端口范围可检查:

cat /proc/sys/net/ipv4/ip_local_port_range

🔎 2.2 Cilium NAT / CT 表异常

Cilium 依赖 eBPF 的 conntrack(CT)和 NAT 映射维护端口分配。
一旦此表膨胀或泄漏,可能导致端口被“认为已占用”。

可查询 NAT 状态:

cilium bpf nat list
cilium bpf ct list global

若 NAT/CT 表巨大或不断增长,则可能存在 Cilium NAT 泄漏。


🔎 2.3 sockmap 未加载(非根因,但说明版本差异)

节点上不存在:

/sys/fs/bpf/tc/globals/cilium_sock_ops_v4

说明:

  • 该节点上 Cilium 未启用 socket-level eBPF(sockops)
  • 不影响 NAT,但说明 Cilium 功能集不完整
  • 原因可能是版本差异(节点间版本 1.10.x vs 1.12.x)

3. 定位思路与验证

✔ 3.1 Python 端口扫描验证

Python 测试脚本在 Pod 内执行:

import socket

for i in range(10):
    s = socket.socket(socket.AF_INET)
    try:
        s.bind(('0.0.0.0', 0))
        print("Port OK:", s.getsockname()[1])
    except:
        print("Port FAILED")
    finally:
        s.close()

结果:

可用端口数量: 0
占用端口: 全部

确认 操作系统认为所有端口都已经被占用


✔ 3.2 Cilium NAT / CT Failure 判断依据

若以下命令输出为空,则 Cilium NAT 功能没有正常生效:

bpftool map dump pinned /sys/fs/bpf/tc/globals/cilium_snat_v4_external

bpftool map dump pinned /sys/fs/bpf/tc/globals/cilium_sock_v4_*

如果全都不存在,则 Cilium 使用的 BPF 程序可能受版本冲突影响 未加载


4. 结论

从当前症状判断:

问题根因:节点上可用的 ephemeral ports 被耗尽

来源可能是:

  • Cilium NAT/CT 表泄漏(常见)
  • Docker 或大量 TIME_WAIT 连接造成端口不释放
  • 某进程持续建立 TCP outbound,端口不回收

Cilium BPF map 缺失属于信号,但非直接根因


5. 建议的修复方案

方案 A:重启 Cilium(清理 NAT/CT 表)

systemctl restart cilium

或:

kubectl rollout restart ds cilium -n kube-system

方案 B:清理 netfilter conntrack

conntrack -F

方案 C:扩展主机可分配端口范围

echo "1024 65000" > /proc/sys/net/ipv4/ip_local_port_range

方案 D:排查 TIME_WAIT 是否过多

ss -ant | grep TIME_WAIT | wc -l

6. 后续建议

为避免再次发生建议:

✔ 监控 Cilium NAT / CT 表大小

cilium bpf nat list | wc -l
cilium bpf ct list global | wc -l

✔ 确认节点上 Cilium 版本一致

混合版本(如 1.10 + 1.12)会导致 BPF 程序加载不一致。


您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>我们正在解决的是在卸载Cilium后,DNS Pod(如CoreDNS)无法启动的问题。根据引用[1]和[2]中的信息,问题通常与残留的Cilium配置文件或网络设置有关。特别是,错误信息可能类似于“dial unix /var/run/cilium/cilium.sock: connect: no such file or directory”或“network: stat /var/lib/calico/nodename: no such file or directory”。 ### 问题分析 1. **Cilium卸载不彻底**:卸载Cilium后,可能残留了一些配置文件或Unix域套接字文件(如`/var/run/cilium/cilium.sock`),这些残留会导致后续启动的Pod(尤其是CoreDNS)无法正确创建网络命名空间。 2. **残留网络配置文件**:引用[1]中提到,删除cilium网络配置文件后,所有Pod恢复正常。这表明Cilium的配置文件可能仍然被kubelet或其他组件引用。 3. **节点上的残留文件**:引用[2]指出错误信息可能包含`/var/lib/calico/nodename`,这虽然是Calico的文件,但类似地,Cilium也可能在节点上留下配置文件。 ### 解决方法 以下是彻底清理Cilium残留的步骤,以解决DNS Pod无法启动的问题: #### 步骤1: 删除Cilium的Kubernetes资源 使用Helm卸载Cilium(如果之前是用Helm安装的): ```bash helm uninstall cilium -n kube-system ``` 或者使用manifest文件安装的,则用kubectl删除: ```bash kubectl delete -f <cilium-manifest.yaml> ``` #### 步骤2: 删除Cilium的配置文件 在**每个节点**上执行以下清理操作: 1. **删除Cilium的运行时文件和配置目录**: ```bash sudo rm -rf /var/run/cilium sudo rm -rf /etc/cilium ``` 2. **删除CNI配置文件和链接**: ```bash sudo rm -rf /etc/cni/net.d/*cilium* # 注意:如果使用Flannel,请确保Flannel的CNI配置文件存在(通常为/etc/cni/net.d/10-flannel.conflist) ``` 3. **清理网络命名空间和虚拟设备**(可选,但建议): ```bash # 删除cilium相关的虚拟网络设备(通常以cilium_为前缀) sudo ip link delete cilium_vxlan sudo ip link delete cilium_host sudo ip link delete cilium_net # 注意:设备名可能因版本而异,使用`ip link show`查看 ``` #### 步骤3: 重启kubelet服务 清理文件后,重启kubelet以重新加载CNI配置: ```bash sudo systemctl restart kubelet ``` #### 步骤4: 重新部署CoreDNS 删除CoreDNS Pod让其重新创建: ```bash kubectl delete pod -n kube-system -l k8s-app=kube-dns ``` 等待几分钟,检查CoreDNS状态: ```bash kubectl get pods -n kube-system -l k8s-app=kube-dns ``` #### 步骤5: 验证网络 如果CoreDNS仍无法启动,检查其日志: ```bash kubectl logs -n kube-system <coredns-pod-name> -c coredns ``` 常见错误: - 如果出现`/var/run/cilium/cilium.sock`相关的错误,说明清理不彻底,需重复步骤2。 - 如果出现Flannel相关错误,确保Flannel已正确部署(参考之前的Flannel部署命令)。 ### 附加说明 - **Flannel部署**:如果集群使用Flannel作为替代,请确保Flannel已部署且配置正确。部署命令: ```bash kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml ``` - **CNI配置优先级**:kubelet默认使用`/etc/cni/net.d`下按字母顺序的第一个配置文件。确保Flannel的配置文件(如`10-flannel.conflist`)存在且没有其他残留的Cilium配置文件(如`05-cilium.conf`)。 ### 预防措施 - 在卸载网络插件前,先删除所有非系统Pod(或至少确保没有关键Pod运行)。 - 使用官方卸载指南:参考[Cilium官方文档](https://docs.cilium.io/en/stable/operations/uninstall/)。 通过以上步骤,应能解决Cilium卸载后CoreDNS无法启动的问题。如果问题依旧,请检查节点网络设置(如iptables规则)或考虑重启节点。 §§相关问题§§ 1. 如何彻底卸载Kubernetes集群中的网络插件? 2. 在Kubernetes中替换网络插件的最佳实践是什么? 3. CoreDNS持续处于CrashLoopBackOff状态的其他可能原因有哪些?</think>### 解决Cilium卸载后DNS Pod无法启动的方法 当卸载Cilium后出现DNS Pod(如CoreDNS)无法启动的问题,通常是由于残留配置文件或网络组件未清理干净所致。以下是完整的解决步骤: #### 步骤1: 清理残留Cilium配置文件 在**所有节点**上执行以下操作: ```bash # 删除Cilium运行时文件和配置 sudo rm -rf /var/run/cilium sudo rm -rf /etc/cilium # 删除CNI配置文件(关键步骤) sudo rm -f /etc/cni/net.d/*cilium* ``` #### 步骤2: 清理Kubernetes资源 ```bash # 删除Cilium的CRD和配置 kubectl delete crd ciliumnetworkpolicies.cilium.io kubectl delete crd ciliumclusterwidenetworkpolicies.cilium.io kubectl delete crd ciliumendpoints.cilium.io # 清理残留的NetworkPolicy kubectl delete ciliumnetworkpolicies --all -A ``` #### 步骤3: 重置CNI配置 1. 检查`/etc/cni/net.d`目录,确保只保留需要的CNI配置文件(如Flannel的`10-flannel.conflist`) 2. 重启kubelet服务: ```bash sudo systemctl restart kubelet ``` #### 步骤4: 修复CoreDNS配置 1. 编辑CoreDNS的ConfigMap: ```bash kubectl edit configmap coredns -n kube-system ``` 2. 移除所有Cilium相关的配置项(如`cilium.io`相关设置) 3. 确保配置包含标准DNS设置: ```yaml apiVersion: v1 data: Corefile: | .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf { max_concurrent 1000 } cache 30 loop reload loadbalance } ``` #### 步骤5: 重建DNS Pod ```bash # 删除现有DNS Pod强制重建 kubectl delete pod -n kube-system -l k8s-app=kube-dns # 验证状态(等待2-3分钟) kubectl get pods -n kube-system -l k8s-app=kube-dns ``` #### 常见错误处理 1. **`dial unix /var/run/cilium/cilium.sock`错误**: - 确保已执行步骤1中的`rm -rf /var/run/cilium` - 检查kubelet日志:`journalctl -u kubelet | grep cilium` 2. **`network: stat /var/lib/calico/nodename`错误**: ```bash sudo rm -f /var/lib/calico/nodename # 删除残留文件 sudo systemctl restart kubelet ``` 3. **持续CrashLoopBackOff**: - 检查DNS Pod日志:`kubectl logs -n kube-system <coredns-pod-name>` - 验证网络连通性:`kubectl run test --image=busybox --rm -it -- ping <目标IP>` #### 预防措施 1. 卸载Cilium前先清理工作负载: ```bash kubectl delete --all pods --grace-period=0 --force ``` 2. 使用官方卸载流程: ```bash helm uninstall cilium -n kube-system cilium uninstall # 如果已安装CLI工具 ``` 3. 在集群维护窗口操作,避免影响生产服务 > **重要提示**:如果集群计划改用Flannel,需在卸载Cilium后立即部署Flannel: > ```bash > kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml > ``` 通过以上步骤,应能解决99%的Cilium卸载后DNS异常问题。如果问题仍存在,建议检查节点iptables规则(`sudo iptables-save | grep cilium`)并重启节点[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值