Skip to content

Commit

Permalink
kube-proxy avoid race condition using LocalModeNodeCIDR
Browse files Browse the repository at this point in the history
Since kube-proxy in LocalModeNodeCIDR needs to obtain the PodCIDR
assigned to the node it watches for the Node object.

However, kube-proxy startup process requires to have these watches in
different places, that opens the possibility of having a race condition
if the same node is recreated and a different PodCIDR is assigned.

Initializing the second watch with the value obtained in the first one
allows us to detect this situation.

Change-Id: I6adeedb6914ad2afd3e0694dcab619c2a66135f8
Signed-off-by: Antonio Ojea <aojea@google.com>
  • Loading branch information
aojea committed Jun 6, 2023
1 parent a11ab1e commit 36ed0ac
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 3 deletions.
3 changes: 2 additions & 1 deletion cmd/kube-proxy/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ type ProxyServer struct {
ConfigSyncPeriod time.Duration
HealthzServer healthcheck.ProxierHealthUpdater
localDetectorMode kubeproxyconfig.LocalMode
podCIDRs []string // only used for LocalModeNodeCIDR
}

// createClients creates a kube client and an event client from the given config and masterOverride.
Expand Down Expand Up @@ -767,7 +768,7 @@ func (s *ProxyServer) Run() error {
nodeConfig := config.NewNodeConfig(currentNodeInformerFactory.Core().V1().Nodes(), s.ConfigSyncPeriod)
// https://issues.k8s.io/111321
if s.localDetectorMode == kubeproxyconfig.LocalModeNodeCIDR {
nodeConfig.RegisterEventHandler(&proxy.NodePodCIDRHandler{})
nodeConfig.RegisterEventHandler(proxy.NewNodePodCIDRHandler(s.podCIDRs))
}
nodeConfig.RegisterEventHandler(s.Proxier)

Expand Down
7 changes: 5 additions & 2 deletions cmd/kube-proxy/app/server_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,18 @@ func newProxyServer(
}

var nodeInfo *v1.Node
podCIDRs := []string{}
if detectLocalMode == proxyconfigapi.LocalModeNodeCIDR {
klog.InfoS("Watching for node, awaiting podCIDR allocation", "hostname", hostname)
nodeInfo, err = waitForPodCIDR(client, hostname)
if err != nil {
return nil, err
}
klog.InfoS("NodeInfo", "PodCIDR", nodeInfo.Spec.PodCIDR, "PodCIDRs", nodeInfo.Spec.PodCIDRs)
podCIDRs = nodeInfo.Spec.PodCIDRs
klog.InfoS("NodeInfo", "podCIDR", nodeInfo.Spec.PodCIDR, "podCIDRs", nodeInfo.Spec.PodCIDRs)
}

klog.V(2).InfoS("DetectLocalMode", "LocalMode", string(detectLocalMode))
klog.V(2).InfoS("DetectLocalMode", "localMode", string(detectLocalMode))

primaryProtocol := utiliptables.ProtocolIPv4
if netutils.IsIPv6(nodeIP) {
Expand Down Expand Up @@ -341,6 +343,7 @@ func newProxyServer(
ConfigSyncPeriod: config.ConfigSyncPeriod.Duration,
HealthzServer: healthzServer,
localDetectorMode: detectLocalMode,
podCIDRs: podCIDRs,
}, nil
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/proxy/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ type NodePodCIDRHandler struct {
podCIDRs []string
}

func NewNodePodCIDRHandler(podCIDRs []string) *NodePodCIDRHandler {
return &NodePodCIDRHandler{
podCIDRs: podCIDRs,
}
}

var _ config.NodeHandler = &NodePodCIDRHandler{}

// OnNodeAdd is a handler for Node creates.
Expand Down
5 changes: 5 additions & 0 deletions pkg/proxy/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ func TestNodePodCIDRHandlerAdd(t *testing.T) {
name: "initialized correctly",
newNodePodCIDRs: []string{"192.168.1.0/24", "fd00:1:2:3::/64"},
},
{
name: "already initialized and same node",
oldNodePodCIDRs: []string{"10.0.0.0/24", "fd00:3:2:1::/64"},
newNodePodCIDRs: []string{"10.0.0.0/24", "fd00:3:2:1::/64"},
},
{
name: "already initialized and different node",
oldNodePodCIDRs: []string{"192.168.1.0/24", "fd00:1:2:3::/64"},
Expand Down

0 comments on commit 36ed0ac

Please sign in to comment.