feat(api): validate advertiseAddress is an IP and clarify its docs (#1202)

advertiseAddress is passed verbatim to the API server's --advertise-address
flag, which only accepts an IP address. A DNS name was silently admitted and
only surfaced as a tenant API server CrashLoopBackOff ("failed to parse IP"),
three layers removed from the misconfiguration.

Add a CEL validation (consistent with the existing isCIDR rules on
serviceCidr/podCidr in the same struct) so the value is rejected at admission
time, and clarify the field documentation: it must be an IP, it feeds
--advertise-address, and the supported way to use a hostname is a DNS record
pointing at a stable VIP plus networkProfile.certSANs.

Closes #1197

Signed-off-by: Jakob Hahn <jakob.hahn@hetzner.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Jakob
2026-06-24 09:45:10 +02:00
committed by GitHub
co-authored by Claude
parent c7c08b7d18
commit 825b39a2df
4 changed files with 47 additions and 16 deletions
+11 -4
View File
@@ -31,10 +31,17 @@ type NetworkProfileSpec struct {
// Address where API server will be exposed.
// In the case of LoadBalancer Service, this can be empty in order to use the exposed IP provided by the cloud controller manager.
Address string `json:"address,omitempty"`
// AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity).
// When set, the management address is used for CAPI and status reporting, while this address
// is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf.
// Both addresses are included in the API server certificate SANs.
// AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity).
// It is passed to the API server's --advertise-address flag and used for the kubeadm
// ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used
// for CAPI and status reporting. Both addresses are included in the API server certificate SANs.
//
// This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes"
// Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS
// record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure
// see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for
// client-certificate authentication).
//+kubebuilder:validation:XValidation:rule="self == '' || isIP(self)",message="advertiseAddress must be a valid IP address"
AdvertiseAddress string `json:"advertiseAddress,omitempty"`
// The default domain name used for DNS resolution within the cluster.
//+kubebuilder:default="cluster.local"
@@ -8545,11 +8545,20 @@ versions:
type: string
advertiseAddress:
description: |-
AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity).
When set, the management address is used for CAPI and status reporting, while this address
is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf.
Both addresses are included in the API server certificate SANs.
AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity).
It is passed to the API server's --advertise-address flag and used for the kubeadm
ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used
for CAPI and status reporting. Both addresses are included in the API server certificate SANs.
This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes"
Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS
record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure
see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for
client-certificate authentication).
type: string
x-kubernetes-validations:
- message: advertiseAddress must be a valid IP address
rule: self == '' || isIP(self)
allowAddressAsExternalIP:
description: |-
AllowAddressAsExternalIP will include tenantControlPlane.Spec.NetworkProfile.Address in the section of
@@ -8553,11 +8553,20 @@ spec:
type: string
advertiseAddress:
description: |-
AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity).
When set, the management address is used for CAPI and status reporting, while this address
is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf.
Both addresses are included in the API server certificate SANs.
AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity).
It is passed to the API server's --advertise-address flag and used for the kubeadm
ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used
for CAPI and status reporting. Both addresses are included in the API server certificate SANs.
This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes"
Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS
record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure
see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for
client-certificate authentication).
type: string
x-kubernetes-validations:
- message: advertiseAddress must be a valid IP address
rule: self == '' || isIP(self)
allowAddressAsExternalIP:
description: |-
AllowAddressAsExternalIP will include tenantControlPlane.Spec.NetworkProfile.Address in the section of
+10 -4
View File
@@ -47869,10 +47869,16 @@ In the case of LoadBalancer Service, this can be empty in order to use the expos
<td><b>advertiseAddress</b></td>
<td>string</td>
<td>
AdvertiseAddress is the address advertised to tenant-side consumers (workers, konnectivity).
When set, the management address is used for CAPI and status reporting, while this address
is used for kubeadm ControlPlaneEndpoint, cluster-info, and admin.conf.
Both addresses are included in the API server certificate SANs.<br/>
AdvertiseAddress is the IP address advertised to tenant-side consumers (workers, konnectivity).
It is passed to the API server's --advertise-address flag and used for the kubeadm
ControlPlaneEndpoint, cluster-info, and admin.conf; when set, the management address is used
for CAPI and status reporting. Both addresses are included in the API server certificate SANs.
This must be an IP address, not a DNS name: --advertise-address and the in-tenant "kubernetes"
Service endpoints only accept IPs. To expose the control plane under a hostname, point a DNS
record at a stable VIP and add the hostname to networkProfile.certSANs; for L7/hostname exposure
see spec.controlPlane.ingress / spec.controlPlane.gateway (mind the TLS-passthrough caveats for
client-certificate authentication).<br/>
</td>
<td>false</td>
</tr><tr>