Description
When a HostedCluster uses Route-based service publishing (servicePublishingStrategy.type: Route)
and the KAS serving certificate is signed by a non-HyperShift CA (e.g. a corporate PKI configured
via spec.configuration.apiServer.servingCerts.namedCertificates), worker nodes fail to connect to
the API server with:
tls: failed to verify certificate: x509: certificate signed by unknown authority
Root Cause
The worker node's kubelet kubeconfig (/var/lib/kubelet/kubeconfig) embeds only the HyperShift
root-ca as its certificate-authority-data. On Route-based clusters the local
kube-apiserver-proxy (HAProxy at 172.20.0.1:6443) does TCP passthrough to the KAS Route, so
the kubelet must verify the KAS TLS certificate directly.
spec.additionalTrustBundle correctly flows into the MCO user CA bundle on the node
(/etc/pki/ca-trust/source/anchors/), but the kubelet does not use the system trust store for API
server verification; it uses only the CA embedded in its kubeconfig.
The code path that builds the bootstrap kubeconfig (adaptBootstrapKubeconfigSecret in
control-plane-operator/.../v2/kas/kubeconfig.go) uses GenerateKubeConfig, which only fetches
root-ca. Compare with adaptCustomAdminKubeconfigSecret, which already calls
combineRootCAWithServingCerts to include named certificate CAs. The bootstrap kubeconfig does
not receive the same treatment.
Expected Behaviour
The bootstrap kubeconfig's certificate-authority-data should include:
- The HyperShift
root-ca
- CAs from
spec.configuration.apiServer.servingCerts.namedCertificates (consistent with the admin kubeconfig)
This would allow worker kubelets to verify KAS serving certificates signed by external CAs when
using Route-based service publishing.
Steps to Reproduce
- Create a HostedCluster with
servicePublishingStrategy.type: Route
- Configure
spec.configuration.apiServer.servingCerts.namedCertificates with a certificate
signed by a non-HyperShift CA
- Provision a worker node
- Observe kubelet logs:
tls: failed to verify certificate: x509: certificate signed by unknown authority
Workaround
A MachineConfig can be applied via the NodePool to inject a combined CA bundle (HyperShift root-ca +
external CA) into the kubelet kubeconfigs at boot time using a systemd oneshot service ordered
before kubelet.service. This is fragile and requires manual maintenance when CAs rotate.
Related
Description
When a HostedCluster uses Route-based service publishing (
servicePublishingStrategy.type: Route)and the KAS serving certificate is signed by a non-HyperShift CA (e.g. a corporate PKI configured
via
spec.configuration.apiServer.servingCerts.namedCertificates), worker nodes fail to connect tothe API server with:
Root Cause
The worker node's kubelet kubeconfig (
/var/lib/kubelet/kubeconfig) embeds only the HyperShiftroot-caas itscertificate-authority-data. On Route-based clusters the localkube-apiserver-proxy(HAProxy at172.20.0.1:6443) does TCP passthrough to the KAS Route, sothe kubelet must verify the KAS TLS certificate directly.
spec.additionalTrustBundlecorrectly flows into the MCO user CA bundle on the node(
/etc/pki/ca-trust/source/anchors/), but the kubelet does not use the system trust store for APIserver verification; it uses only the CA embedded in its kubeconfig.
The code path that builds the bootstrap kubeconfig (
adaptBootstrapKubeconfigSecretincontrol-plane-operator/.../v2/kas/kubeconfig.go) usesGenerateKubeConfig, which only fetchesroot-ca. Compare withadaptCustomAdminKubeconfigSecret, which already callscombineRootCAWithServingCertsto include named certificate CAs. The bootstrap kubeconfig doesnot receive the same treatment.
Expected Behaviour
The bootstrap kubeconfig's
certificate-authority-datashould include:root-caspec.configuration.apiServer.servingCerts.namedCertificates(consistent with the admin kubeconfig)This would allow worker kubelets to verify KAS serving certificates signed by external CAs when
using Route-based service publishing.
Steps to Reproduce
servicePublishingStrategy.type: Routespec.configuration.apiServer.servingCerts.namedCertificateswith a certificatesigned by a non-HyperShift CA
tls: failed to verify certificate: x509: certificate signed by unknown authorityWorkaround
A MachineConfig can be applied via the NodePool to inject a combined CA bundle (HyperShift root-ca +
external CA) into the kubelet kubeconfigs at boot time using a systemd oneshot service ordered
before
kubelet.service. This is fragile and requires manual maintenance when CAs rotate.Related