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¶
-
Install and start iptables services: Ensure the
iptables-servicespackage 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 -
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 -
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 -
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.
Related Concepts¶
- [[Flannel]]
- [[Kubernetes Network Policies]]
- [[iptables]]
Sources¶
- 400-devops__06-Kubernetes__k8s-paas__03.k8s集群.md