mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
Merge pull request #55519 from MrHohn/fix-esipp-session-affinity
Automatic merge from submit-queue (batch tested with PRs 55561, 55519). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.
[kube-proxy] Fix session affinity with local endpoints traffic
**What this PR does / why we need it**:
Set up session affinity rules in `svcXlbChain` over local endpoints. It is basically a mirror of what we set in `svcChain`:
012b085ac8/pkg/proxy/iptables/proxier.go (L1423-L1433)
**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #55429
**Special notes for your reviewer**:
@nicksardo @bowei
**Release note**:
```release-note
Fix session affinity issue with external load balancer traffic when ExternalTrafficPolicy=Local.
```
This commit is contained in:
commit
72a2b0be69
@ -1516,6 +1516,18 @@ func (proxier *Proxier) syncProxyRules() {
|
||||
)
|
||||
writeLine(proxier.natRules, args...)
|
||||
} else {
|
||||
// First write session affinity rules only over local endpoints, if applicable.
|
||||
if svcInfo.sessionAffinityType == api.ServiceAffinityClientIP {
|
||||
for _, endpointChain := range localEndpointChains {
|
||||
writeLine(proxier.natRules,
|
||||
"-A", string(svcXlbChain),
|
||||
"-m", "comment", "--comment", svcNameString,
|
||||
"-m", "recent", "--name", string(endpointChain),
|
||||
"--rcheck", "--seconds", strconv.Itoa(svcInfo.stickyMaxAgeSeconds), "--reap",
|
||||
"-j", string(endpointChain))
|
||||
}
|
||||
}
|
||||
|
||||
// Setup probability filter rules only over local endpoints
|
||||
for i, endpointChain := range localEndpointChains {
|
||||
// Balancing rules in the per-service chain.
|
||||
|
@ -325,6 +325,15 @@ func NewFakeProxier(ipt utiliptables.Interface) *Proxier {
|
||||
return p
|
||||
}
|
||||
|
||||
func hasSessionAffinityRule(rules []iptablestest.Rule) bool {
|
||||
for _, r := range rules {
|
||||
if _, ok := r[iptablestest.Recent]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasJump(rules []iptablestest.Rule, destChain, destIP string, destPort int) bool {
|
||||
destPortStr := strconv.Itoa(destPort)
|
||||
match := false
|
||||
@ -769,6 +778,7 @@ func TestOnlyLocalLoadBalancing(t *testing.T) {
|
||||
NamespacedName: makeNSN("ns1", "svc1"),
|
||||
Port: "p80",
|
||||
}
|
||||
svcSessionAffinityTimeout := int32(10800)
|
||||
|
||||
makeServiceMap(fp,
|
||||
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *api.Service) {
|
||||
@ -784,6 +794,10 @@ func TestOnlyLocalLoadBalancing(t *testing.T) {
|
||||
IP: svcLBIP,
|
||||
}}
|
||||
svc.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyTypeLocal
|
||||
svc.Spec.SessionAffinity = api.ServiceAffinityClientIP
|
||||
svc.Spec.SessionAffinityConfig = &api.SessionAffinityConfig{
|
||||
ClientIP: &api.ClientIPConfig{TimeoutSeconds: &svcSessionAffinityTimeout},
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
@ -838,6 +852,9 @@ func TestOnlyLocalLoadBalancing(t *testing.T) {
|
||||
if !hasJump(lbRules, localEpChain, "", 0) {
|
||||
errorf(fmt.Sprintf("Didn't find jump from lb chain %v to local ep %v", lbChain, epStrNonLocal), lbRules, t)
|
||||
}
|
||||
if !hasSessionAffinityRule(lbRules) {
|
||||
errorf(fmt.Sprintf("Didn't find session affinity rule from lb chain %v", lbChain), lbRules, t)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnlyLocalNodePortsNoClusterCIDR(t *testing.T) {
|
||||
|
@ -32,6 +32,7 @@ const (
|
||||
Jump = "-j "
|
||||
Reject = "REJECT"
|
||||
ToDest = "--to-destination "
|
||||
Recent = "recent "
|
||||
)
|
||||
|
||||
type Rule map[string]string
|
||||
@ -111,7 +112,7 @@ func (f *FakeIPTables) GetRules(chainName string) (rules []Rule) {
|
||||
for _, l := range strings.Split(string(f.Lines), "\n") {
|
||||
if strings.Contains(l, fmt.Sprintf("-A %v", chainName)) {
|
||||
newRule := Rule(map[string]string{})
|
||||
for _, arg := range []string{Destination, Source, DPort, Protocol, Jump, ToDest} {
|
||||
for _, arg := range []string{Destination, Source, DPort, Protocol, Jump, ToDest, Recent} {
|
||||
tok := getToken(l, arg)
|
||||
if tok != "" {
|
||||
newRule[arg] = tok
|
||||
|
Loading…
Reference in New Issue
Block a user