使用 Init Container + iptables 强制隔离 Pod 网络(Flannel 环境)

使用 Init Container + iptables 强制隔离 Pod 网络(Flannel 环境)

背景

Flannel 是最常用的 Kubernetes CNI 插件之一,但其本身不支持 NetworkPolicy。在 Flannel 环境下,要实现 Pod 级别的网络隔离,可以采用在 Pod 启动前通过 Init Container 设置 iptables 规则的方法。这种方法也可以用于对 NetworkPolicy 进行额外加固。

原理

Kubernetes 中每个 Pod 内的所有容器(包括 Init Container)共享同一个网络命名空间(由 pause 容器创建)。Init Container 在主容器启动之前运行,因此可以在 Init Container 中执行 iptables 命令,为主容器预设网络访问控制规则。这样主容器启动后,其网络流量就会受到这些规则的约束。

实施步骤

1. 确定关键信息

  • Pod CIDR :集群中 Pod 的网段,用于放行同网段流量。例如 10.244.0.0/16。
  • DNS 服务 IP :CoreDNS 的 ClusterIP,通常是 kube-system 命名空间下 kube-dns 服务的 ClusterIP,例如 10.96.0.10。
  • Kubernetes API Server IP(可选):如果 Pod 需要访问 API Server,需要放行。

2. 设计 iptables 规则

目标:默认丢弃所有出站和入站流量,仅放行:

  • 回环接口(lo)的流量
  • DNS 查询(UDP/TCP 53 到 DNS 服务 IP)
  • 同网段 Pod 之间的流量(源或目标为 Pod CIDR)
  • 可能需要的其他白名单(如访问外部特定服务)

3. 编写 Init Container

使用带有 iptables 工具的基础镜像,例如 busybox 或 alpine(需要安装 iptables)。推荐使用 docker.io/library/busybox:latest,因为 busybox 自带 iptables(较新版本)。或者使用 ghcr.io/linuxserver/iptables 等专用镜像。

Init Container 脚本示例:

yaml 复制代码
initContainers:
  - name: iptables-init
    image: busybox:1.36
    securityContext:
      capabilities:
        add:
          - NET_ADMIN
    command:
      - sh
      - -c
      - |
        set -ex
        # 设置默认策略
        iptables -P INPUT DROP
        iptables -P FORWARD DROP
        iptables -P OUTPUT DROP

        # 放行回环接口
        iptables -A INPUT -i lo -j ACCEPT
        iptables -A OUTPUT -o lo -j ACCEPT

        # 放行 DNS(假设 DNS IP 为 10.96.0.10)
        iptables -A OUTPUT -p udp --dport 53 -d 10.96.0.10 -j ACCEPT
        iptables -A OUTPUT -p tcp --dport 53 -d 10.96.0.10 -j ACCEPT
        # 允许 DNS 响应进入(状态跟踪)
        iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
        # 放行同网段 Pod 流量
        iptables -A INPUT -s 10.244.0.0/16 -j ACCEPT
        iptables -A OUTPUT -d 10.244.0.0/16 -j ACCEPT

        # 可选:放行访问 API Server(如果 Pod 需要)
        # iptables -A OUTPUT -d <api-server-ip> -p tcp --dport 6443 -j ACCEPT

        # 完成,记录日志
        echo "iptables rules applied"

4. 完整 Pod 示例

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: isolated-pod
  namespace: your-namespace
spec:
  initContainers:
    - name: iptables-init
      image: busybox:1.36
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
      command:
        - sh
        - -c
        - |
          iptables -P INPUT DROP
          iptables -P FORWARD DROP
          iptables -P OUTPUT DROP
          iptables -A INPUT -i lo -j ACCEPT
          iptables -A OUTPUT -o lo -j ACCEPT
          iptables -A OUTPUT -p udp --dport 53 -d 10.96.0.10 -j ACCEPT
          iptables -A OUTPUT -p tcp --dport 53 -d 10.96.0.10 -j ACCEPT
          iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
          iptables -A INPUT -s 10.244.0.0/16 -j ACCEPT
          iptables -A OUTPUT -d 10.244.0.0/16 -j ACCEPT
  containers:
    - name: app
      image: nginx:alpine
      ports:
        - containerPort: 80

5. 应用与验证

  • 创建 Pod,查看 Init Container 日志确认规则已应用。
  • 进入主容器,测试网络连通性:
    • 访问同命名空间其他 Pod 的 IP,应该成功。
    • 访问外部网站(如 curl https://www.google.com),应该失败(因为出站被 DROP)。
    • 解析域名(nslookup kubernetes.default),应该成功(DNS 被放行)。
    • 访问 API Server,根据是否放行而定。

6. 注意事项与限制

  • 权限要求 :Init Container 需要 NET_ADMIN capability,否则无法修改 iptables。
  • 规则持久性:iptables 规则只在当前网络命名空间有效,Pod 重启后需要重新执行 Init Container。
  • Pod 级别隔离:此方法只能对单个 Pod 设置规则,若要应用于命名空间内所有 Pod,需要为每个 Pod 模板添加 Init Container,或者使用 Admission Webhook(如 Kyverno、OPA)自动注入。
  • 性能影响:每个 Pod 启动时多一个 Init Container,略有开销,但可以接受。
  • 维护复杂度:与 NetworkPolicy 相比,手动管理 iptables 规则更容易出错,且不易审计。
  • 推荐场景:Flannel 环境下需要临时加固,或者作为额外防护层,但长期建议迁移到支持 NetworkPolicy 的 CNI。

总结

本文介绍了两种实现 Kubernetes 命名空间/Pod 网络隔离的方法:使用 NetworkPolicy(标准做法,适用于 Calico/Cilium)和使用 Init Container + iptables(适用于 Flannel 或特殊加固需求)。两者各有优劣,可根据集群实际情况选择。

相关推荐
mengge.cloud2 天前
1022小白入门教程(番外筑基)— nerdctl 容器基本功 + K8s 资源编写
linux·网络·云原生·容器·kubernetes·云计算·k8s
上火的金鱼妹3 天前
节点调度优化 + redis 现有问题优化
k8s
fengkai45454 天前
3、Kubernetes的Namespace&Contexts&Pod&YAML格式
运维·容器·kubernetes·k8s·namespace·yaml·pod
meijinmeng4 天前
Karpenter + Keda 让Kuberntes实现动态扩缩容机制方案指南
k8s
.冰块.5 天前
VMware+Ubuntu24.04 kubeadm 部署 K8s 1.30.2 三节点集群
运维·云原生·容器·kubernetes·k8s·容器编排
我不会起名字3227 天前
K8s Ingress 返回 502 但后端日志正常:4 类上游断连与排查链
kubernetes·k8s·ingress·502·keepalive
Eminem897 天前
18、k8s配置管理中心Secret
k8s
我不会起名字3227 天前
K8s 服务 DNS 解析偶发 5 秒超时:conntrack 与 ndots 的 3 个坑
kubernetes·k8s·dns·conntrack·coredns
KIDULT°8 天前
Kubeadm 部署 Kubernetes v1.30.2 实战:Ubuntu24.04 三节点集群 + 排坑记录
ubuntu·云原生·容器·kubernetes·k8s
Eminem898 天前
15、k8s控制器Statefulset
k8s