From cb1fc9b051fa288b4f33435f7ae13e568407cb35 Mon Sep 17 00:00:00 2001 From: Rob Brockbank Date: Wed, 27 Jun 2018 19:38:52 -0700 Subject: [PATCH] Add environment option to disable installation of SNAT --- pkg/networkutils/network.go | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/pkg/networkutils/network.go b/pkg/networkutils/network.go index 43024dbb98..5a6c2d2c58 100644 --- a/pkg/networkutils/network.go +++ b/pkg/networkutils/network.go @@ -15,6 +15,8 @@ package networkutils import ( "net" + "os" + "strconv" "strings" "syscall" @@ -42,6 +44,11 @@ const ( fromPodRulePriority = 1536 mainRoutingTable = 254 + + // This environment is used to specify whether an external NAT gateway will be used to provide SNAT of + // secondary ENI IP addresses. If set to "true", the SNAT iptables rule and off-VPC ip rule will not + // be installed and will be removed if they are already installed. + envExternalSNAT = "AWS_VPC_K8S_CNI_EXTERNALSNAT" ) // NetworkAPIs defines the host level and the eni level network related operations @@ -67,17 +74,18 @@ func isDuplicateRuleAdd(err error) bool { return strings.Contains(err.Error(), "File exists") } -// SetupNodeNetwork performs node level network configuration +// SetupHostNetwork performs node level network configuration // TODO : implement ip rule not to 10.0.0.0/16(vpc'subnet) table main priority 1024 func (os *linuxNetwork) SetupHostNetwork(vpcCIDR *net.IPNet, primaryAddr *net.IP) error { + externalSNAT := useExternalSNAT() hostRule := os.netLink.NewRule() hostRule.Dst = vpcCIDR hostRule.Table = mainRoutingTable hostRule.Priority = hostRulePriority hostRule.Invert = true - // if this is a restart, cleanup previous rule first + // If this is a restart, cleanup previous rule first err := os.netLink.RuleDel(hostRule) if err != nil && !containsNoSuchRule(err) { log.Errorf("Failed to cleanup old host IP rule: %v", err) @@ -105,12 +113,20 @@ func (os *linuxNetwork) SetupHostNetwork(vpcCIDR *net.IPNet, primaryAddr *net.IP return errors.Wrapf(err, "host network setup: failed to add POSTROUTING rule for primary address %s", primaryAddr) } - if !exists { + if !exists && !externalSNAT { + // We are handling SNAT on-node, so include the iptables SNAT POSTROUTING rule. err = ipt.Append("nat", "POSTROUTING", natCmd...) if err != nil { return errors.Wrapf(err, "host network setup: failed to append POSTROUTING rule for primary address %s", primaryAddr) } + } else if exists && externalSNAT { + // We are not handling SNAT on-node, so delete the existing iptables SNAT POSTROUTING rule. + err = ipt.Delete("nat", "POSTROUTING", natCmd...) + + if err != nil { + return errors.Wrapf(err, "host network setup: failed to delete POSTROUTING rule for primary address %s", primaryAddr) + } } return nil @@ -123,6 +139,21 @@ func containsNoSuchRule(err error) bool { return false } +// useExternalSNAT returns whether SNAT of secondary ENI IPs should be handled with an external +// NAT gateway rather than on node. Failure to parse the setting will result in a log and the +// setting will be disabled. +func useExternalSNAT() bool { + if externalSNATStr := os.Getenv(envExternalSNAT); externalSNATStr != "" { + externalSNAT, err := strconv.ParseBool(externalSNATStr) + if err != nil { + log.Error("Failed to parse "+envExternalSNAT, err.Error()) + return false + } + return externalSNAT + } + return false +} + // LinkByMac returns linux netlink based on interface MAC func LinkByMac(mac string, netLink netlinkwrapper.NetLink) (netlink.Link, error) { links, err := netLink.LinkList()