Skip to content

Commit a598b51

Browse files
committed
Fix ipv6 handling and update the docs with behavior
1 parent 8099f2a commit a598b51

6 files changed

Lines changed: 56 additions & 12 deletions

File tree

cloud/linode/loadbalancers.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,8 +1418,10 @@ func getNodeBackendIP(service *v1.Service, node *v1.Node, subnetID int, useIPv6B
14181418
}
14191419

14201420
if publicIPv6, exists := node.Annotations[annotations.AnnLinodeNodePublicIPv6]; exists {
1421-
if parsed := net.ParseIP(publicIPv6); parsed != nil && parsed.To4() == nil {
1422-
return publicIPv6, nil
1421+
if prefix, err := netip.ParsePrefix(publicIPv6); err == nil {
1422+
if addr := prefix.Addr(); addr.Is6() {
1423+
return addr.String(), nil
1424+
}
14231425
}
14241426
}
14251427

cloud/linode/loadbalancers_test.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4116,7 +4116,7 @@ func Test_getNodeBackendIP(t *testing.T) {
41164116
ObjectMeta: metav1.ObjectMeta{
41174117
Name: "node-1",
41184118
Annotations: map[string]string{
4119-
annotations.AnnLinodeNodePublicIPv6: "2600:3c06::1",
4119+
annotations.AnnLinodeNodePublicIPv6: "2600:3c06::1/128",
41204120
},
41214121
},
41224122
Status: v1.NodeStatus{
@@ -4136,7 +4136,7 @@ func Test_getNodeBackendIP(t *testing.T) {
41364136
Name: "node-1",
41374137
Annotations: map[string]string{
41384138
annotations.AnnLinodeNodePrivateIP: "192.168.10.10",
4139-
annotations.AnnLinodeNodePublicIPv6: "2600:3c06::1",
4139+
annotations.AnnLinodeNodePublicIPv6: "2600:3c06::1/128",
41404140
},
41414141
},
41424142
Status: v1.NodeStatus{
@@ -4150,6 +4150,44 @@ func Test_getNodeBackendIP(t *testing.T) {
41504150
useIPv6Backends: true,
41514151
expectedIP: "2600:3c06::1",
41524152
},
4153+
{
4154+
name: "errors when public IPv6 annotation is missing prefix length",
4155+
node: &v1.Node{
4156+
ObjectMeta: metav1.ObjectMeta{
4157+
Name: "node-1",
4158+
Annotations: map[string]string{
4159+
annotations.AnnLinodeNodePublicIPv6: "2600:3c06::2",
4160+
},
4161+
},
4162+
Status: v1.NodeStatus{
4163+
Addresses: []v1.NodeAddress{
4164+
{Type: v1.NodeExternalIP, Address: "172.232.0.2"},
4165+
{Type: v1.NodeExternalIP, Address: "fd00::11"},
4166+
},
4167+
},
4168+
},
4169+
useIPv6Backends: true,
4170+
expectErr: true,
4171+
},
4172+
{
4173+
name: "errors when public IPv6 annotation is not a valid IPv6 value",
4174+
node: &v1.Node{
4175+
ObjectMeta: metav1.ObjectMeta{
4176+
Name: "node-1",
4177+
Annotations: map[string]string{
4178+
annotations.AnnLinodeNodePublicIPv6: "not-an-ip",
4179+
},
4180+
},
4181+
Status: v1.NodeStatus{
4182+
Addresses: []v1.NodeAddress{
4183+
{Type: v1.NodeExternalIP, Address: "172.232.0.2"},
4184+
{Type: v1.NodeExternalIP, Address: "2600:3c06::1"},
4185+
},
4186+
},
4187+
},
4188+
useIPv6Backends: true,
4189+
expectErr: true,
4190+
},
41534191
{
41544192
name: "errors when IPv6 backends are requested and node lacks public IPv6 annotation",
41554193
node: &v1.Node{
@@ -4334,7 +4372,7 @@ func Test_buildLoadBalancerRequestPreservesVPCConfigForIPv6Backends(t *testing.T
43344372
ObjectMeta: metav1.ObjectMeta{
43354373
Name: "node-1",
43364374
Annotations: map[string]string{
4337-
annotations.AnnLinodeNodePublicIPv6: "2600:3c06:e727:1::1",
4375+
annotations.AnnLinodeNodePublicIPv6: "2600:3c06:e727:1::1/128",
43384376
},
43394377
},
43404378
Status: v1.NodeStatus{

deploy/chart/values.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,11 @@ tolerations:
108108
# This can also be controlled per-service using the "service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-ingress" annotation
109109
# enableIPv6ForLoadBalancers: true
110110

111-
# Enable IPv6 backend addresses for NodeBalancer services (including VPC-backed NodeBalancers).
111+
# Enable public IPv6 backend addresses for NodeBalancer services.
112+
# VPC IPv6 backend addresses are not currently supported.
112113
# When enabled globally, both newly created and existing eligible services may be reconciled to use IPv6 backends.
113114
# Per-service behavior can be overridden with the "service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backends" annotation; set it to "false" to keep a service on IPv4 backends only.
114-
# All selected backend nodes must have the required IPv6 address (public or VPC, depending on the NodeBalancer configuration).
115+
# If your cluster uses VPC-backed NodeBalancers, the nodes must still expose public IPv6 endpoints so CCM can read the node.k8s.linode.com/public-ipv6 annotation and program IPv6 backends.
115116
# enableIPv6ForNodeBalancerBackends: false
116117

117118
# disableNodeBalancerVPCBackends is used to disable the use of VPC backends for NodeBalancers.

docs/configuration/annotations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The keys and the values in [annotations must be strings](https://kubernetes.io/d
4040
| `firewall-acl` | string | | The Firewall rules to be applied to the NodeBalancer. See [Firewall Configuration](#firewall-configuration) |
4141
| `nodebalancer-type` | string | | The type of NodeBalancer to create (options: common, premium, premium_40gb). See [NodeBalancer Types](#nodebalancer-type). Note: NodeBalancer types should always be specified in lowercase. |
4242
| `enable-ipv6-ingress` | bool | `false` | When `true`, both IPv4 and IPv6 addresses will be included in the LoadBalancerStatus ingress |
43-
| `enable-ipv6-backends` | bool | `false` | When `true`, NodeBalancer services use IPv6 backend nodes. If VPC-backed NodeBalancers are enabled, CCM preserves the NodeBalancer VPC configuration. This requires a dual-stack cluster and a dual-stack Service configuration. Reconciliation fails if a selected backend node does not have the required IPv6 address. |
43+
| `enable-ipv6-backends` | bool | `false` | When `true`, NodeBalancer services use node public IPv6 addresses as backend targets. VPC IPv6 backend addresses are not supported. |
4444
| `backend-ipv4-range` | string | | The IPv4 range from VPC subnet to be applied to the NodeBalancer backend. See [Nodebalancer VPC Configuration](#nodebalancer-vpc-configuration) |
4545
| `backend-vpc-name` | string | | VPC which is connected to the NodeBalancer backend. See [Nodebalancer VPC Configuration](#nodebalancer-vpc-configuration) |
4646
| `backend-subnet-name` | string | | Subnet within VPC which is connected to the NodeBalancer backend. See [Nodebalancer VPC Configuration](#nodebalancer-vpc-configuration) |

docs/configuration/environment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The CCM supports the following flags:
5353
| `--nodebalancer-backend-ipv4-subnet-name` | String | `""` | ipv4 subnet name to use for NodeBalancer backends |
5454
| `--disable-nodebalancer-vpc-backends` | Boolean | `false` | don't use VPC specific ip-addresses for nodebalancer backend ips when running in VPC (set to `true` for backward compatibility if needed) |
5555
| `--enable-ipv6-for-loadbalancers` | Boolean | `false` | Set both IPv4 and IPv6 addresses for all LoadBalancer services (when disabled, only IPv4 is used). This can also be configured per-service using the `service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-ingress` annotation. |
56-
| `--enable-ipv6-for-nodebalancer-backends` | Boolean | `false` | Use IPv6 addresses for NodeBalancer service backends. If VPC-backed NodeBalancers are enabled, CCM preserves the NodeBalancer VPC configuration. Enabling this flag can migrate existing eligible NodeBalancer services from IPv4 to IPv6 backends during reconcile. This requires a dual-stack cluster and dual-stack Service configuration. If enabled, every selected backend node must have the required IPv6 address or reconciliation will fail. This can also be configured per-service using the `service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backends` annotation. |
56+
| `--enable-ipv6-for-nodebalancer-backends` | Boolean | `false` | Use node public IPv6 addresses for NodeBalancer service backends. VPC IPv6 backend addresses are not supported. Can also be configured per-service using the `service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backends` annotation. |
5757
| `--node-cidr-mask-size-ipv4` | Int | `24` | ipv4 cidr mask size for pod cidrs allocated to nodes |
5858
| `--node-cidr-mask-size-ipv6` | Int | `64` | ipv6 cidr mask size for pod cidrs allocated to nodes |
5959
| `--nodebalancer-prefix` | String | `ccm` | Name prefix for NoadBalancers. |

docs/configuration/loadbalancer.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,16 @@ metadata:
7171
```
7272

7373
When IPv6 backends are enabled:
74+
- NodeBalancer backend targets use the node public IPv6 annotation `node.k8s.linode.com/public-ipv6`
75+
- IPv6 NodeBalancer backends are currently supported only through node public IPv6 addresses, not VPC IPv6 backend addresses
7476
- both VPC-backed and non-VPC-backed NodeBalancer services are affected
7577
- when VPC-backed NodeBalancers are enabled, CCM preserves the NodeBalancer VPC configuration instead of dropping it
7678
- enabling the global `--enable-ipv6-for-nodebalancer-backends` flag can migrate existing eligible NodeBalancer services from IPv4 to IPv6 backends during reconcile
7779
- to keep an existing Service on IPv4 while the global flag is enabled, set `service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backends: "false"` on that Service
78-
- every selected backend node must have an IPv6 address in the currently selected backend path
80+
- every selected backend node must have a public IPv6 address available
81+
- if your cluster uses VPC backends, the nodes still need public IPv6 endpoints so CCM can program IPv6 NodeBalancer backends
7982
- the workload cluster and Service must be configured for dual-stack networking
80-
- reconciliation fails and CCM logs an error if a selected backend node does not have the required IPv6 address
83+
- reconciliation fails and CCM logs an error if a selected backend node does not have the required public IPv6 address
8184
8285
Recommended Service configuration for IPv6 backends:
8386
@@ -101,7 +104,7 @@ spec:
101104
app: my-app
102105
```
103106
104-
If your cluster does not provide IPv6-capable NodePort routing, the NodeBalancer may still be created with IPv6 backend addresses, but the backends will not become healthy.
107+
If your cluster does not provide IPv6-capable NodePort routing, the NodeBalancer may still be created with IPv6 backend addresses, but the backends will not become healthy. Likewise, if your cluster is using VPC backends but the nodes do not also have public IPv6 endpoints, IPv6 backend reconciliation will fail because CCM does not currently program VPC IPv6 backend addresses.
105108
106109
### Basic Configuration
107110

0 commit comments

Comments
 (0)