Skip to content

Commit e4e2d76

Browse files
committed
feat: support virtualIP.configuration API in handler
1 parent 27ad1b6 commit e4e2d76

File tree

6 files changed

+211
-11
lines changed

6 files changed

+211
-11
lines changed

charts/cluster-api-runtime-extensions-nutanix/templates/virtual-ip/kube-vip/manifests/kube-vip-configmap.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ data:
2222
- name: vip_arp
2323
value: "true"
2424
- name: port
25-
value: '{{ `{{ .ControlPlaneEndpoint.Port }}` }}'
25+
value: '{{ `{{ .Port }}` }}'
2626
- name: vip_nodename
2727
valueFrom:
2828
fieldRef:
@@ -46,7 +46,7 @@ data:
4646
- name: vip_retryperiod
4747
value: "2"
4848
- name: address
49-
value: '{{ `{{ .ControlPlaneEndpoint.Host }}` }}'
49+
value: '{{ `{{ .Address }}` }}'
5050
- name: prometheus_server
5151
image: ghcr.io/kube-vip/kube-vip:v0.8.3
5252
imagePullPolicy: IfNotPresent

docs/content/customization/nutanix/control-plane-endpoint.md

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title = "Control Plane Endpoint"
33
+++
44

5-
Configure Control Plane Endpoint. Defines the host IP and port of the CAPX Kubernetes cluster.
5+
Configure Control Plane Endpoint. Defines the host IP and port of the Nutanix Kubernetes cluster.
66

77
## Examples
88

@@ -51,6 +51,93 @@ spec:
5151
name: kube-vip
5252
namespace: kube-system
5353
spec:
54+
containers:
55+
- name: kube-vip
56+
args:
57+
- manager
58+
env:
59+
- name: port
60+
value: '6443'
61+
- name: address
62+
value: 'x.x.x.x'
63+
...
64+
owner: root:root
65+
path: /etc/kubernetes/manifests/kube-vip.yaml
66+
permissions: "0600"
67+
postKubeadmCommands:
68+
# Only added for clusters version >=v1.29.0
69+
- |-
70+
if [ -f /run/kubeadm/kubeadm.yaml ]; then
71+
sed -i 's#path: /etc/kubernetes/super-admin.conf#path: ...
72+
fi
73+
preKubeadmCommands:
74+
# Only added for clusters version >=v1.29.0
75+
- |-
76+
if [ -f /run/kubeadm/kubeadm.yaml ]; then
77+
sed -i 's#path: /etc/kubernetes/admin.conf#path: ...
78+
fi
79+
```
80+
81+
### Set Control Plane Endpoint and a Different Virtual IP
82+
83+
It is also possible to set a separate virtual IP to be used by kube-vip from the control plane endpoint.
84+
This is useful in VPC setups or other instances
85+
when you have an external floating IP already associated with the virtual IP.
86+
87+
```yaml
88+
apiVersion: cluster.x-k8s.io/v1beta1
89+
kind: Cluster
90+
metadata:
91+
name: <NAME>
92+
spec:
93+
topology:
94+
variables:
95+
- name: clusterConfig
96+
value:
97+
nutanix:
98+
controlPlaneEndpoint:
99+
host: x.x.x.x
100+
port: 6443
101+
virtualIP:
102+
configuration:
103+
address: y.y.y.y
104+
```
105+
106+
Applying this configuration will result in the following value being set:
107+
108+
- `NutanixCluster`:
109+
110+
```yaml
111+
spec:
112+
template:
113+
spec:
114+
controlPlaneEndpoint:
115+
host: x.x.x.x
116+
port: 6443
117+
```
118+
119+
- `KubeadmControlPlaneTemplate`
120+
121+
```yaml
122+
spec:
123+
kubeadmConfigSpec:
124+
files:
125+
- content: |
126+
apiVersion: v1
127+
kind: Pod
128+
metadata:
129+
name: kube-vip
130+
namespace: kube-system
131+
spec:
132+
containers:
133+
- name: kube-vip
134+
args:
135+
- manager
136+
env:
137+
- name: port
138+
value: '6443'
139+
- name: address
140+
value: 'y.y.y.y'
54141
...
55142
owner: root:root
56143
path: /etc/kubernetes/manifests/kube-vip.yaml

hack/addons/update-kube-vip-manifests.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ docker container run --rm ghcr.io/kube-vip/kube-vip:"${KUBE_VIP_VERSION}" \
3333
gojq --yaml-input --yaml-output \
3434
'del(.metadata.creationTimestamp, .status) |
3535
.spec.containers[].imagePullPolicy |= "IfNotPresent" |
36-
(.spec.containers[0].env[] | select(.name == "port").value) |= "{{ `{{ .ControlPlaneEndpoint.Port }}` }}" |
37-
(.spec.containers[0].env[] | select(.name == "address").value) |= "{{ `{{ .ControlPlaneEndpoint.Host }}` }}"
36+
(.spec.containers[0].env[] | select(.name == "port").value) |= "{{ `{{ .Port }}` }}" |
37+
(.spec.containers[0].env[] | select(.name == "address").value) |= "{{ `{{ .Address }}` }}"
3838
' >"${ASSETS_DIR}/${FILE_NAME}"
3939

4040
kubectl create configmap "{{ .Values.hooks.virtualIP.kubeVip.defaultTemplateConfigMap.name }}" --dry-run=client --output yaml \

pkg/handlers/generic/mutation/controlplanevirtualip/inject_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ spec:
264264
- name: vip_arp
265265
value: "true"
266266
- name: address
267-
value: "{{ .ControlPlaneEndpoint.Host }}"
267+
value: "{{ .Address }}"
268268
- name: port
269-
value: "{{ .ControlPlaneEndpoint.Port }}"
269+
value: "{{ .Port }}"
270270
`

pkg/handlers/generic/mutation/controlplanevirtualip/providers/kubevip_test.go

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,79 @@ func Test_GenerateFilesAndCommands(t *testing.T) {
105105
},
106106
},
107107
},
108+
{
109+
name: "should return templated data with both IP and port from virtual IP configuration overrides",
110+
controlPlaneEndpointSpec: v1alpha1.ControlPlaneEndpointSpec{
111+
Host: "10.20.100.10",
112+
Port: 6443,
113+
VirtualIPSpec: &v1alpha1.ControlPlaneVirtualIPSpec{
114+
Configuration: &v1alpha1.ControlPlaneVirtualIPConfiguration{
115+
Address: "172.20.100.10",
116+
Port: 8443,
117+
},
118+
},
119+
},
120+
configMap: &corev1.ConfigMap{
121+
ObjectMeta: metav1.ObjectMeta{
122+
Name: "default-kube-vip-template",
123+
Namespace: "default",
124+
},
125+
Data: map[string]string{
126+
"data": validKubeVIPTemplate,
127+
},
128+
},
129+
cluster: &clusterv1.Cluster{
130+
Spec: clusterv1.ClusterSpec{
131+
Topology: &clusterv1.Topology{
132+
Version: "v1.28.0",
133+
},
134+
},
135+
},
136+
expectedFiles: []bootstrapv1.File{
137+
{
138+
Content: expectedKubeVIPPodWithOverrides,
139+
Owner: kubeVIPFileOwner,
140+
Path: kubeVIPFilePath,
141+
Permissions: kubeVIPFilePermissions,
142+
},
143+
},
144+
},
145+
{
146+
name: "should return templated data with IP from virtual IP configuration overrides",
147+
controlPlaneEndpointSpec: v1alpha1.ControlPlaneEndpointSpec{
148+
Host: "10.20.100.10",
149+
Port: 8443,
150+
VirtualIPSpec: &v1alpha1.ControlPlaneVirtualIPSpec{
151+
Configuration: &v1alpha1.ControlPlaneVirtualIPConfiguration{
152+
Address: "172.20.100.10",
153+
},
154+
},
155+
},
156+
configMap: &corev1.ConfigMap{
157+
ObjectMeta: metav1.ObjectMeta{
158+
Name: "default-kube-vip-template",
159+
Namespace: "default",
160+
},
161+
Data: map[string]string{
162+
"data": validKubeVIPTemplate,
163+
},
164+
},
165+
cluster: &clusterv1.Cluster{
166+
Spec: clusterv1.ClusterSpec{
167+
Topology: &clusterv1.Topology{
168+
Version: "v1.28.0",
169+
},
170+
},
171+
},
172+
expectedFiles: []bootstrapv1.File{
173+
{
174+
Content: expectedKubeVIPPodWithOverrides,
175+
Owner: kubeVIPFileOwner,
176+
Path: kubeVIPFilePath,
177+
Permissions: kubeVIPFilePermissions,
178+
},
179+
},
180+
},
108181
}
109182

110183
for idx := range tests {
@@ -227,9 +300,9 @@ spec:
227300
- name: vip_arp
228301
value: "true"
229302
- name: address
230-
value: "{{ .ControlPlaneEndpoint.Host }}"
303+
value: "{{ .Address }}"
231304
- name: port
232-
value: "{{ .ControlPlaneEndpoint.Port }}"
305+
value: "{{ .Port }}"
233306
`
234307

235308
expectedKubeVIPPod = `
@@ -253,4 +326,26 @@ spec:
253326
- name: port
254327
value: "6443"
255328
`
329+
330+
expectedKubeVIPPodWithOverrides = `
331+
apiVersion: v1
332+
kind: Pod
333+
metadata:
334+
name: kube-vip
335+
namespace: kube-system
336+
spec:
337+
containers:
338+
- name: kube-vip
339+
image: ghcr.io/kube-vip/kube-vip:v1.1.1
340+
imagePullPolicy: IfNotPresent
341+
args:
342+
- manager
343+
env:
344+
- name: vip_arp
345+
value: "true"
346+
- name: address
347+
value: "172.20.100.10"
348+
- name: port
349+
value: "8443"
350+
`
256351
)

pkg/handlers/generic/mutation/controlplanevirtualip/providers/providers.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package providers
55

66
import (
77
"bytes"
8+
"cmp"
89
"context"
910
"fmt"
1011
"text/template"
@@ -35,11 +36,28 @@ func templateValues(
3536
}
3637

3738
type input struct {
38-
ControlPlaneEndpoint v1alpha1.ControlPlaneEndpointSpec
39+
Address string
40+
Port int32
3941
}
4042

43+
// If specified, use the virtual IP address and/or port,
44+
// otherwise fall back to the control plane endpoint host and port.
45+
address := controlPlaneEndpoint.Host
46+
port := controlPlaneEndpoint.Port
47+
if controlPlaneEndpoint.VirtualIPSpec != nil &&
48+
controlPlaneEndpoint.VirtualIPSpec.Configuration != nil {
49+
address = cmp.Or(
50+
controlPlaneEndpoint.VirtualIPSpec.Configuration.Address,
51+
controlPlaneEndpoint.Host,
52+
)
53+
port = cmp.Or(
54+
controlPlaneEndpoint.VirtualIPSpec.Configuration.Port,
55+
controlPlaneEndpoint.Port,
56+
)
57+
}
4158
templateInput := input{
42-
ControlPlaneEndpoint: controlPlaneEndpoint,
59+
Address: address,
60+
Port: port,
4361
}
4462

4563
var b bytes.Buffer

0 commit comments

Comments
 (0)