k8s 开启防火墙,容器内部无法访问外部 ip

在 Kubernetes 环境中,节点(宿主机)开启防火墙后导致容器内部无法访问外部/内网 IP,这是一个非常典型的问题。

为什么会发生这种情况?

Kubernetes 的网络插件(从 ip a 输出中可以看到 cali*tunl0,说明使用的是 Calico )和容器运行时(Docker/Containerd)严重依赖 Linux 的 iptablesipvs 来进行流量转发(Forwarding)、路由和源地址转换(SNAT/Masquerade)。

当手动开启系统的防火墙(如 firewalldufw)时,防火墙会清空或覆盖 Kubernetes 和 Calico 原本精心配置的 iptables 规则,并且默认的防火墙策略通常会拒绝转发(FORWARD)流量。导致容器发出的数据包无法被正确 NAT(伪装)并转发到宿主机的物理网卡(enp125s0f0)。

这里为提供两种解决方案:


方案一:关闭宿主机防火墙(K8s 官方及业界强烈推荐)

在 Kubernetes 集群中,通常不建议 在 Node 节点上直接运行 firewalldufw。网络隔离和安全控制应该交由 Kubernetes 的 NetworkPolicy 和云提供商的安全组(或物理防火墙)来实现。

如果环境允许,最彻底且无副作用的方法是关闭并禁用它:

如果是 CentOS/RHEL (firewalld):

bash 复制代码
systemctl stop firewalld
systemctl disable firewalld

如果是 Ubuntu/Debian (ufw):

bash 复制代码
ufw disable

关键的一步:重建 K8s 网络规则

关闭防火墙后,必须让 CNI 重新写入 iptables 规则:

  1. 重启容器运行时(根据环境选择):
bash 复制代码
systemctl restart containerd
# 或者
systemctl restart docker
  1. 重启 Calico 和 Kube-proxy 从而重建规则:
bash 复制代码
   kubectl delete pod -n kube-system -l k8s-app=calico-node
   kubectl delete pod -n kube-system -l k8s-app=kube-proxy

方案二:必须开启防火墙的解决办法(配置放行规则)

如果因为公司合规或安全要求,宿主机必须开启防火墙,需要手动对防火墙进行配置,放行 Kubernetes 的网络流量并开启 IP 伪装。

使用的是 firewalld(CentOS/RHEL 等主流环境):

1. 开启 IP 伪装 (Masquerade)

容器访问内网 10.110.151.44 必须经过 SNAT(源地址转换),否则目标服务器无法将回包路由回容器的内网 IP(如 10.244.x.x)。

bash 复制代码
firewall-cmd --permanent --add-masquerade
2. 将 Calico 和容器网卡加入信任区

ip a 可以看到有很多 caliXXX 虚拟网卡以及 tunl0 隧道网卡,必须放行这些网卡的流量:

bash 复制代码
# 信任 Calico 的虚拟网卡
firewall-cmd --permanent --zone=trusted --add-interface=cali+
# 信任 IPIP 隧道网卡
firewall-cmd --permanent --zone=trusted --add-interface=tunl0
# 如果有 docker0 或 cni0 也一并加入
firewall-cmd --permanent --zone=trusted --add-interface=docker0
3. 允许网卡之间的转发 (FORWARD)

防火墙可能默认 drop 了 forward 链的包:

bash 复制代码
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 1 -j ACCEPT
4. 重载防火墙并重启网络组件

让防火墙配置生效:

bash 复制代码
firewall-cmd --reload

防火墙重启后,K8s 之前的 iptables 规则又会被冲刷掉,因此必须重新触发 Calico 写入规则

bash 复制代码
# 重启 Calico 节点组件
kubectl delete pod -n kube-system -l k8s-app=calico-node

验证修复结果

完成上述任意一种方案后,进入一个容器内部测试连通性:

bash 复制代码
kubectl exec -it <Pod名称> -n <对应Namespace> -- sh
# 在容器内 ping 目标内网 IP
ping 10.110.151.44
相关推荐
IT利刃出鞘3 小时前
Docker Compose--安装WordPress--方法/示例
运维·docker·容器
疯狂打码的少年4 小时前
【计算机网络】TCP/IP协议族(四层体系结构,与OSI对比)
网络·笔记·tcp/ip·计算机网络
布莱克6055 小时前
TCP 三次握手与四次挥手详解
服务器·网络·tcp/ip·计算机网络·网络编程
严谨的麻辣烫8 小时前
AI Agent为什么越来越需要固定出口IP?从API白名单到生产环境网络管理
服务器·网络·tcp/ip·代理服务器
captain3769 小时前
TCP网络编程:ServerSocket与Socket详解
服务器·网络·tcp/ip
IT小白杨11 小时前
eBay多账号如何应对关联判定:主体、收款、IP、环境四层配置清单一次讲清
java·网络·网络协议·tcp/ip·自动化·指纹浏览器
wdfk_prog13 小时前
大型 Docker 镜像导出导入工程化:可靠性、磁盘与压缩
运维·docker·容器
隐擎fox13 小时前
网络传输安全剖析:WebRTC 本地真实 IP 泄漏机制(STUN/TURN)与 Python 防护检测实战
网络·网络协议·tcp/ip·安全·webrtc
郝开13 小时前
Docker Compose 模块化多环境配置规范指南:示例搭建Alf Tengine MD2DOC 1.1.1
运维·docker·容器
Albart57514 小时前
Docker Desktop 增量更新失败终极排查:Failed to apply delta update 反复回滚怎么办?
windows·docker·容器·docker部署大模型