diff --git a/cloud/annotations/annotations.go b/cloud/annotations/annotations.go index 380a08b0..3973a4df 100644 --- a/cloud/annotations/annotations.go +++ b/cloud/annotations/annotations.go @@ -38,8 +38,9 @@ const ( // addresses for its LoadBalancer ingress. When set to "true", both addresses will be included in the status. AnnLinodeEnableIPv6Ingress = "service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-ingress" - AnnLinodeNodePrivateIP = "node.k8s.linode.com/private-ip" - AnnLinodeHostUUID = "node.k8s.linode.com/host-uuid" + AnnLinodeNodePrivateIP = "node.k8s.linode.com/private-ip" + AnnLinodeHostUUID = "node.k8s.linode.com/host-uuid" + AnnLinodeNodePublicIPv6 = "node.k8s.linode.com/public-ipv6" AnnLinodeNodeIPSharingUpdated = "node.k8s.linode.com/ip-sharing-updated" AnnExcludeNodeFromNb = "node.k8s.linode.com/exclude-from-nb" diff --git a/cloud/linode/node_controller.go b/cloud/linode/node_controller.go index bcefb661..8cbb7473 100644 --- a/cloud/linode/node_controller.go +++ b/cloud/linode/node_controller.go @@ -270,10 +270,11 @@ func (s *nodeController) handleNode(ctx context.Context, node *v1.Node) error { lastUpdate := s.LastMetadataUpdate(node.Name) uuid, foundLabel := node.Labels[annotations.AnnLinodeHostUUID] - configuredPrivateIP, foundAnnotation := node.Annotations[annotations.AnnLinodeNodePrivateIP] + configuredPrivateIP, foundPrivateIPAnnotation := node.Annotations[annotations.AnnLinodeNodePrivateIP] + configuredPublicIPv6, foundIPv6Annotation := node.Annotations[annotations.AnnLinodeNodePublicIPv6] metaAge := time.Since(lastUpdate) - if foundLabel && foundAnnotation && metaAge < s.ttl { + if foundLabel && foundPrivateIPAnnotation && foundIPv6Annotation && metaAge < s.ttl { klog.V(3).InfoS("Skipping refresh, ttl not reached", "node", klog.KObj(node), "ttl", s.ttl, @@ -298,7 +299,8 @@ func (s *nodeController) handleNode(ctx context.Context, node *v1.Node) error { } } - if uuid == linode.HostUUID && node.Spec.ProviderID != "" && configuredPrivateIP == expectedPrivateIP { + expectedPublicIPv6 := linode.IPv6 + if uuid == linode.HostUUID && node.Spec.ProviderID != "" && configuredPrivateIP == expectedPrivateIP && configuredPublicIPv6 == expectedPublicIPv6 { s.SetLastMetadataUpdate(node.Name) return nil } @@ -325,6 +327,9 @@ func (s *nodeController) handleNode(ctx context.Context, node *v1.Node) error { if nodeResult.Annotations[annotations.AnnLinodeNodePrivateIP] != expectedPrivateIP && expectedPrivateIP != "" { nodeResult.Annotations[annotations.AnnLinodeNodePrivateIP] = expectedPrivateIP } + if nodeResult.Annotations[annotations.AnnLinodeNodePublicIPv6] != expectedPublicIPv6 && expectedPublicIPv6 != "" { + nodeResult.Annotations[annotations.AnnLinodeNodePublicIPv6] = expectedPublicIPv6 + } updatedNode, err = s.kubeclient.CoreV1().Nodes().Update(ctx, nodeResult, metav1.UpdateOptions{}) return err }); err != nil { diff --git a/cloud/linode/node_controller_test.go b/cloud/linode/node_controller_test.go index c7e00ab0..af1634b7 100644 --- a/cloud/linode/node_controller_test.go +++ b/cloud/linode/node_controller_test.go @@ -226,8 +226,9 @@ func TestNodeController_handleNode(t *testing.T) { // Test: Successful metadata update publicIP := net.ParseIP("172.234.31.123") privateIP := net.ParseIP("192.168.159.135") + publicIPv6SLAAC := "2001:db::f03c:91ff:fe2b:1a2b" client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{ - {ID: 123, Label: "test-node", IPv4: []*net.IP{&publicIP, &privateIP}, HostUUID: "123"}, + {ID: 123, Label: "test-node", IPv4: []*net.IP{&publicIP, &privateIP}, IPv6: publicIPv6SLAAC, HostUUID: "123"}, }, nil) err = nodeCtrl.handleNode(t.Context(), node) require.NoError(t, err, "expected no error during handleNode") @@ -241,6 +242,7 @@ func TestNodeController_handleNode(t *testing.T) { // Annotations set, no update needed as ttl not reached node.Labels[annotations.AnnLinodeHostUUID] = "123" node.Annotations[annotations.AnnLinodeNodePrivateIP] = privateIP.String() + node.Annotations[annotations.AnnLinodeNodePublicIPv6] = publicIPv6SLAAC err = nodeCtrl.handleNode(t.Context(), node) require.NoError(t, err, "expected no error during handleNode") @@ -257,7 +259,7 @@ func TestNodeController_handleNode(t *testing.T) { nodeCtrl.instances = newInstances(client) nodeCtrl.metadataLastUpdate["test-node"] = time.Now().Add(-2 * nodeCtrl.ttl) client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{ - {ID: 123, Label: "test-node", IPv4: []*net.IP{&publicIP, &privateIP}, HostUUID: "123"}, + {ID: 123, Label: "test-node", IPv4: []*net.IP{&publicIP, &privateIP}, IPv6: publicIPv6SLAAC, HostUUID: "123"}, }, nil) err = nodeCtrl.handleNode(t.Context(), node) assert.NoError(t, err, "expected no error during handleNode") diff --git a/docs/configuration/environment.md b/docs/configuration/environment.md index 2a21e955..842fc902 100644 --- a/docs/configuration/environment.md +++ b/docs/configuration/environment.md @@ -56,7 +56,7 @@ The CCM supports the following flags: | `--node-cidr-mask-size-ipv4` | Int | `24` | ipv4 cidr mask size for pod cidrs allocated to nodes | | `--node-cidr-mask-size-ipv6` | Int | `64` | ipv6 cidr mask size for pod cidrs allocated to nodes | | `--nodebalancer-prefix` | String | `ccm` | Name prefix for NoadBalancers. | -| `--disable-ipv6-node-cidr-allocation` | `false` | disables allocating IPv6 CIDR ranges to nodes when using CCM for node IPAM (set to `true` if IPv6 ranges are not configured on Linode interfaces) | +| `--disable-ipv6-node-cidr-allocation` | Boolean | `false` | disables allocating IPv6 CIDR ranges to nodes when using CCM for node IPAM (set to `true` if IPv6 ranges are not configured on Linode interfaces) | ## Configuration Methods