Skip to content

Commit d527a09

Browse files
committed
add ExternalTrafficPolicy support for External IPs in ipvs kubeproxy
1 parent efc4b12 commit d527a09

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

pkg/proxy/ipvs/ipset.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ const (
4040
kubeExternalIPSetComment = "Kubernetes service external ip + port for masquerade and filter purpose"
4141
kubeExternalIPSet = "KUBE-EXTERNAL-IP"
4242

43+
kubeExternalIPLocalSetComment = "Kubernetes service external ip + port with externalTrafficPolicy=local"
44+
kubeExternalIPLocalSet = "KUBE-EXTERNAL-IP-LOCAL"
45+
4346
kubeLoadBalancerSetComment = "Kubernetes service lb portal"
4447
kubeLoadBalancerSet = "KUBE-LOAD-BALANCER"
4548

pkg/proxy/ipvs/proxier.go

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ var ipsetInfo = []struct {
140140
{kubeLoopBackIPSet, utilipset.HashIPPortIP, kubeLoopBackIPSetComment},
141141
{kubeClusterIPSet, utilipset.HashIPPort, kubeClusterIPSetComment},
142142
{kubeExternalIPSet, utilipset.HashIPPort, kubeExternalIPSetComment},
143+
{kubeExternalIPLocalSet, utilipset.HashIPPort, kubeExternalIPLocalSetComment},
143144
{kubeLoadBalancerSet, utilipset.HashIPPort, kubeLoadBalancerSetComment},
144145
{kubeLoadbalancerFWSet, utilipset.HashIPPort, kubeLoadbalancerFWSetComment},
145146
{kubeLoadBalancerLocalSet, utilipset.HashIPPort, kubeLoadBalancerLocalSetComment},
@@ -1236,12 +1237,21 @@ func (proxier *Proxier) syncProxyRules() {
12361237
Protocol: protocol,
12371238
SetType: utilipset.HashIPPort,
12381239
}
1239-
// We have to SNAT packets to external IPs.
1240-
if valid := proxier.ipsetList[kubeExternalIPSet].validateEntry(entry); !valid {
1241-
klog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeExternalIPSet].Name))
1242-
continue
1240+
1241+
if utilfeature.DefaultFeatureGate.Enabled(features.ExternalPolicyForExternalIP) && svcInfo.OnlyNodeLocalEndpoints() {
1242+
if valid := proxier.ipsetList[kubeExternalIPLocalSet].validateEntry(entry); !valid {
1243+
klog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeExternalIPLocalSet].Name))
1244+
continue
1245+
}
1246+
proxier.ipsetList[kubeExternalIPLocalSet].activeEntries.Insert(entry.String())
1247+
} else {
1248+
// We have to SNAT packets to external IPs.
1249+
if valid := proxier.ipsetList[kubeExternalIPSet].validateEntry(entry); !valid {
1250+
klog.Errorf("%s", fmt.Sprintf(EntryInvalidErr, entry, proxier.ipsetList[kubeExternalIPSet].Name))
1251+
continue
1252+
}
1253+
proxier.ipsetList[kubeExternalIPSet].activeEntries.Insert(entry.String())
12431254
}
1244-
proxier.ipsetList[kubeExternalIPSet].activeEntries.Insert(entry.String())
12451255

12461256
// ipvs call
12471257
serv := &utilipvs.VirtualServer{
@@ -1257,7 +1267,12 @@ func (proxier *Proxier) syncProxyRules() {
12571267
if err := proxier.syncService(svcNameString, serv, true); err == nil {
12581268
activeIPVSServices[serv.String()] = true
12591269
activeBindAddrs[serv.Address.String()] = true
1260-
if err := proxier.syncEndpoint(svcName, false, serv); err != nil {
1270+
1271+
onlyNodeLocalEndpoints := false
1272+
if utilfeature.DefaultFeatureGate.Enabled(features.ExternalPolicyForExternalIP) {
1273+
onlyNodeLocalEndpoints = svcInfo.OnlyNodeLocalEndpoints()
1274+
}
1275+
if err := proxier.syncEndpoint(svcName, onlyNodeLocalEndpoints, serv); err != nil {
12611276
klog.Errorf("Failed to sync endpoint for service: %v, err: %v", serv, err)
12621277
}
12631278
} else {
@@ -1668,15 +1683,8 @@ func (proxier *Proxier) writeIptablesRules() {
16681683
}
16691684
}
16701685

1671-
if !proxier.ipsetList[kubeExternalIPSet].isEmpty() {
1672-
// Build masquerade rules for packets to external IPs.
1673-
args = append(args[:0],
1674-
"-A", string(kubeServicesChain),
1675-
"-m", "comment", "--comment", proxier.ipsetList[kubeExternalIPSet].getComment(),
1676-
"-m", "set", "--match-set", proxier.ipsetList[kubeExternalIPSet].Name,
1677-
"dst,dst",
1678-
)
1679-
writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
1686+
// externalIPRules adds iptables rules applies to Service ExternalIPs
1687+
externalIPRules := func(args []string) {
16801688
// Allow traffic for external IPs that does not come from a bridge (i.e. not from a container)
16811689
// nor from a local process to be forwarded to the service.
16821690
// This rule roughly translates to "all traffic from off-machine".
@@ -1691,6 +1699,28 @@ func (proxier *Proxier) writeIptablesRules() {
16911699
writeLine(proxier.natRules, append(dstLocalOnlyArgs, "-j", "ACCEPT")...)
16921700
}
16931701

1702+
if !proxier.ipsetList[kubeExternalIPSet].isEmpty() {
1703+
// Build masquerade rules for packets to external IPs.
1704+
args = append(args[:0],
1705+
"-A", string(kubeServicesChain),
1706+
"-m", "comment", "--comment", proxier.ipsetList[kubeExternalIPSet].getComment(),
1707+
"-m", "set", "--match-set", proxier.ipsetList[kubeExternalIPSet].Name,
1708+
"dst,dst",
1709+
)
1710+
writeLine(proxier.natRules, append(args, "-j", string(KubeMarkMasqChain))...)
1711+
externalIPRules(args)
1712+
}
1713+
1714+
if !proxier.ipsetList[kubeExternalIPLocalSet].isEmpty() {
1715+
args = append(args[:0],
1716+
"-A", string(kubeServicesChain),
1717+
"-m", "comment", "--comment", proxier.ipsetList[kubeExternalIPLocalSet].getComment(),
1718+
"-m", "set", "--match-set", proxier.ipsetList[kubeExternalIPLocalSet].Name,
1719+
"dst,dst",
1720+
)
1721+
externalIPRules(args)
1722+
}
1723+
16941724
// -A KUBE-SERVICES -m addrtype --dst-type LOCAL -j KUBE-NODE-PORT
16951725
args = append(args[:0],
16961726
"-A", string(kubeServicesChain),

0 commit comments

Comments
 (0)