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
相关推荐
真上帝的左手2 小时前
11. 容器化 vs 虚拟化-K8s-工作负载实战
云原生·容器·kubernetes
极客先躯3 小时前
高级java每日一道面试题-2026年01月18日-实战篇[Docker]-如何清理仓库中的旧镜像?
java·运维·docker·容器
张忠琳5 小时前
【kubernetes v1.21】(controller-manager part 1)kube-controller-manager 核心架构与启动流程
云原生·架构·kubernetes
qq_452396235 小时前
第十五篇:《Docker 与 Kubernetes 集成:从 Swarm 到 K8s 的迁移》
docker·容器·kubernetes
HackTwoHub6 小时前
K8s综合渗透测试工具,集成信息搜集、权限逃逸、横向移动,一站式搞定全流程渗透测试工作
人工智能·安全·web安全·云原生·容器·kubernetes·系统安全
jing.wang_20256 小时前
TI TMS320C6678芯片实现IP及端口在线修改并生效
网络·嵌入式硬件·tcp/ip·dsp开发
做个文艺程序员6 小时前
第05篇:K8s CI/CD 全流程:GitOps × ArgoCD × Harbor——Java SaaS 从代码提交到生产部署一键直达
ci/cd·kubernetes·argocd
人工智能培训6 小时前
数字孪生建模常用方式有哪些?
人工智能·深度学习·机器学习·容器·知识图谱
lpfasd1236 小时前
docker中默认网络的作用和注意事项
网络·docker·容器
IT策士6 小时前
第 37 篇 k8s之调度进阶:亲和性、污点与容忍
云原生·容器·kubernetes