mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	kube-proxy: fix duplicate port opening
When nodePortAddresses is not specified for kube-proxy, it tried to open the node port for a NodePort service twice, triggered by IPv4ZeroCIDR and IPv6ZeroCIDR separately. The first attempt would succeed and the second one would always generate an error log like below: "listen tcp4 :30522: bind: address already in use" This patch fixes it by ensuring nodeAddresses of a proxier only contain the addresses for its IP family.
This commit is contained in:
		@@ -975,6 +975,16 @@ func (proxier *Proxier) syncProxyRules() {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		klog.ErrorS(err, "Failed to get node ip address matching nodeport cidrs, services with nodeport may not work as intended", "CIDRs", proxier.nodePortAddresses)
 | 
							klog.ErrorS(err, "Failed to get node ip address matching nodeport cidrs, services with nodeport may not work as intended", "CIDRs", proxier.nodePortAddresses)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// nodeAddresses may contain dual-stack zero-CIDRs if proxier.nodePortAddresses is empty.
 | 
				
			||||||
 | 
						// Ensure nodeAddresses only contains the addresses for this proxier's IP family.
 | 
				
			||||||
 | 
						isIPv6 := proxier.iptables.IsIPv6()
 | 
				
			||||||
 | 
						for addr := range nodeAddresses {
 | 
				
			||||||
 | 
							if utilproxy.IsZeroCIDR(addr) && isIPv6 == netutils.IsIPv6CIDRString(addr) {
 | 
				
			||||||
 | 
								// if any of the addresses is zero cidr of this IP family, non-zero IPs can be excluded.
 | 
				
			||||||
 | 
								nodeAddresses = sets.NewString(addr)
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Build rules for each service.
 | 
						// Build rules for each service.
 | 
				
			||||||
	for svcName, svc := range proxier.serviceMap {
 | 
						for svcName, svc := range proxier.serviceMap {
 | 
				
			||||||
@@ -1438,7 +1448,6 @@ func (proxier *Proxier) syncProxyRules() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Finally, tail-call to the nodeports chain.  This needs to be after all
 | 
						// Finally, tail-call to the nodeports chain.  This needs to be after all
 | 
				
			||||||
	// other service portal rules.
 | 
						// other service portal rules.
 | 
				
			||||||
	isIPv6 := proxier.iptables.IsIPv6()
 | 
					 | 
				
			||||||
	for address := range nodeAddresses {
 | 
						for address := range nodeAddresses {
 | 
				
			||||||
		// TODO(thockin, m1093782566): If/when we have dual-stack support we will want to distinguish v4 from v6 zero-CIDRs.
 | 
							// TODO(thockin, m1093782566): If/when we have dual-stack support we will want to distinguish v4 from v6 zero-CIDRs.
 | 
				
			||||||
		if utilproxy.IsZeroCIDR(address) {
 | 
							if utilproxy.IsZeroCIDR(address) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1587,7 +1587,15 @@ COMMIT
 | 
				
			|||||||
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
 | 
					-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
 | 
				
			||||||
COMMIT
 | 
					COMMIT
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
						assert.Equal(t, []*netutils.LocalPort{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Description: "nodePort for ns1/svc1:p80",
 | 
				
			||||||
 | 
								IP:          "",
 | 
				
			||||||
 | 
								IPFamily:    netutils.IPv4,
 | 
				
			||||||
 | 
								Port:        svcNodePort,
 | 
				
			||||||
 | 
								Protocol:    netutils.TCP,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, fp.portMapper.(*fakePortOpener).openPorts)
 | 
				
			||||||
	assertIPTablesRulesEqual(t, expected, fp.iptablesData.String())
 | 
						assertIPTablesRulesEqual(t, expected, fp.iptablesData.String())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user