使用 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 工具的基础镜像,例如 busyboxalpine(需要安装 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 或特殊加固需求)。两者各有优劣,可根据集群实际情况选择。

相关推荐
智码看视界1 天前
Day57-K8s核心概念速通:Pod、Deployment、Service与Ingress
云原生·容器·kubernetes·k8s·ingress·java后端·deployment
国医中兴2 天前
全文搜索的数据库选择:MySQL Fulltext与Elasticsearch的深度对比
微服务·云原生·容器·kubernetes·k8s
万里侯2 天前
GitOps 2026年演进趋势:从配置管理到环境即代码的范式转移及Pull vs Push模型的再思考
微服务·容器·k8s
张洛闻Eren5 天前
云原生k8s【第一课】: Docker 容器技术
运维·云原生·容器·k8s
KeepSeek10 天前
AI集群搭建k8s实战(docker)
k8s
要开心吖ZSH10 天前
测试环境 K8s 502 故障复盘:被 ClusterIP 表象误导,最终定位 kube-proxy 规则缺失
云原生·容器·kubernetes·k8s·502 bad gateway·kube-proxy
m0_5257247212 天前
Jenkins共享库实现流水线复用
自动化·k8s·devops
菜地里的小菜鸟19 天前
failed to get imageFs info: non-existent label “docker-images
k8s·failedtogetimagefsin·k8s报错
菜地里的小菜鸟20 天前
kubectl debug
k8s·kubectldebug