Skip to content

iptables SNAT optimization for containers

iptables SNAT optimization for containers is a network configuration technique used in containerized environments (specifically with Flannel) to ensure transparent access between containers across different hosts.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

The primary goal of this optimization is to resolve logging issues where requests between containers appear to originate from the host machine's IP address rather than the actual container IP.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md] This is achieved by modifying iptables rules to exclude internal cluster traffic from Source Network Address Translation (SNAT).^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

The Problem

In a default Flannel setup using the host-gw backend, iptables rules typically masquerade traffic leaving the container subnet.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

A standard default rule often looks like this: -s 172.7.21.0/24 ! -o docker0 -j MASQUERADE

This rule dictates that any packet originating from the local container subnet (e.g., 172.7.21.0/24) that exits via an interface other than docker0 should have its source IP masked (SNAT).^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

While this allows external access, it causes issues for internal cluster communication. When a container on Host A accesses a container on Host B, the source IP is replaced by Host A's physical IP. Consequently, application logs on the target container record the host IP, obscuring the true origin of the request.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

The Solution

To fix this, the iptables POSTROUTING chain must be updated to exclude destination addresses within the cluster's internal network (e.g., the Flannel network) from MASQUERADE.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md] This ensures that traffic destined for other cluster nodes retains the original container source IP.

Implementation Steps

  1. Install and start iptables services: Ensure the iptables-services package is installed and the service is enabled.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

    yum install iptables-services -y
    systemctl start iptables
    systemctl enable iptables
    

  2. Delete the old rule: Remove the default rule that broadly masquerades all non-docker0 traffic.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

    # Syntax: iptables -t nat -D POSTROUTING ...
    iptables -t nat -D POSTROUTING -s 172.7.21.0/24 ! -o docker0 -j MASQUERADE
    

  3. Insert the optimized rule: Add a new rule that explicitly excludes the internal cluster network (e.g., 172.7.0.0/16) from masquerading.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

    # Syntax: iptables -t nat -I POSTROUTING ...
    # Logic: Masquerade only if destination is NOT in cluster network AND output is NOT docker0
    iptables -t nat -I POSTROUTING -s 172.7.21.0/24 ! -d 172.7.0.0/16 ! -o docker0 -j MASQUERADE
    

  4. Persist the changes: Save the new rules to the system configuration so they survive a reboot.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

    iptables-save > /etc/sysconfig/iptables
    

Verification

After applying the changes, verify the configuration by checking the logs on the target container.^[400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md]

For example, if a container on 172.7.21.2 curls a service on 172.7.22.2, the access logs on 22 should now reflect the client IP as 172.7.21.2, rather than the host node's physical IP.

  • [[Flannel]]
  • [[Kubernetes Network Policies]]
  • [[iptables]]

Sources

  • 400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md