diff --git a/pkg/render/typha.go b/pkg/render/typha.go index 0e33dff85c..cc352771dc 100644 --- a/pkg/render/typha.go +++ b/pkg/render/typha.go @@ -16,6 +16,7 @@ package render import ( "fmt" + "slices" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -681,11 +682,14 @@ func (c *typhaComponent) typhaEnvVarsNonClusterHost() []corev1.EnvVar { envVars = replaceOrAppendEnvVar(envVars, "TYPHA_CLIENTURISAN", c.cfg.TLS.NodeNonClusterHostURISAN) // NCH Typha runs pod-networked, so the host-network apiserver endpoint - // (e.g. MKE's proxy.local) may not be reachable. - if podEp := c.cfg.K8sServiceEpPodNetwork; podEp.Host != "" && podEp.Port != "" { - envVars = replaceOrAppendEnvVar(envVars, "KUBERNETES_SERVICE_HOST", podEp.Host) - envVars = replaceOrAppendEnvVar(envVars, "KUBERNETES_SERVICE_PORT", podEp.Port) - } + // (e.g. MKE's proxy.local) may not be reachable. Strip the inherited env + // vars so we fall back to the default kubernetes Service that kubelet + // injects into every pod, then re-add a pod-network endpoint if one was + // configured explicitly. + envVars = slices.DeleteFunc(envVars, func(e corev1.EnvVar) bool { + return e.Name == "KUBERNETES_SERVICE_HOST" || e.Name == "KUBERNETES_SERVICE_PORT" + }) + envVars = append(envVars, c.cfg.K8sServiceEpPodNetwork.EnvVars()...) // Tell the health aggregator to listen on all interfaces. envVars = append(envVars, corev1.EnvVar{Name: "TYPHA_HEALTHHOST", Value: "0.0.0.0"}) diff --git a/pkg/render/typha_test.go b/pkg/render/typha_test.go index e498da8336..40b38bd1c9 100644 --- a/pkg/render/typha_test.go +++ b/pkg/render/typha_test.go @@ -217,20 +217,20 @@ var _ = Describe("Typha rendering tests", func() { Expect(d.Spec.Template.Spec.Containers[0].ReadinessProbe.ProbeHandler.HTTPGet.Host).To(BeEmpty()) }) - It("should override KUBERNETES_SERVICE_HOST/PORT on the non-cluster-host Typha when a pod-network endpoint is configured", func() { + It("should strip the host-network apiserver endpoint from the non-cluster-host Typha and fall back to the default Service", func() { cfg.K8sServiceEp = k8sapi.ServiceEndpoint{Host: "proxy.local", Port: "6444"} - cfg.K8sServiceEpPodNetwork = k8sapi.ServiceEndpoint{Host: "10.96.0.1", Port: "443"} component := render.Typha(&cfg) resources, _ := component.Objects() + // NCH Typha is pod-networked; let kubelet's default service injection take over. d := rtest.GetResource(resources, "calico-typha-noncluster-host", "calico-system", "apps", "v1", "Deployment").(*appsv1.Deployment) - Expect(d.Spec.Template.Spec.Containers[0].Env).To(ContainElements( - corev1.EnvVar{Name: "KUBERNETES_SERVICE_HOST", Value: "10.96.0.1"}, - corev1.EnvVar{Name: "KUBERNETES_SERVICE_PORT", Value: "443"}, - )) + for _, e := range d.Spec.Template.Spec.Containers[0].Env { + Expect(e.Name).ToNot(Equal("KUBERNETES_SERVICE_HOST")) + Expect(e.Name).ToNot(Equal("KUBERNETES_SERVICE_PORT")) + } - // The host-networked Typha should still use the host-network endpoint. + // The host-networked Typha still gets the configured endpoint. dMain := rtest.GetResource(resources, "calico-typha", "calico-system", "apps", "v1", "Deployment").(*appsv1.Deployment) Expect(dMain.Spec.Template.Spec.Containers[0].Env).To(ContainElements( corev1.EnvVar{Name: "KUBERNETES_SERVICE_HOST", Value: "proxy.local"}, @@ -238,6 +238,20 @@ var _ = Describe("Typha rendering tests", func() { )) }) + It("should respect an explicit pod-network apiserver endpoint on the non-cluster-host Typha when configured", func() { + cfg.K8sServiceEp = k8sapi.ServiceEndpoint{Host: "proxy.local", Port: "6444"} + cfg.K8sServiceEpPodNetwork = k8sapi.ServiceEndpoint{Host: "10.96.0.1", Port: "443"} + + component := render.Typha(&cfg) + resources, _ := component.Objects() + + d := rtest.GetResource(resources, "calico-typha-noncluster-host", "calico-system", "apps", "v1", "Deployment").(*appsv1.Deployment) + Expect(d.Spec.Template.Spec.Containers[0].Env).To(ContainElements( + corev1.EnvVar{Name: "KUBERNETES_SERVICE_HOST", Value: "10.96.0.1"}, + corev1.EnvVar{Name: "KUBERNETES_SERVICE_PORT", Value: "443"}, + )) + }) + It("should use custom client common name when specified for non-cluster host Typha deployment", func() { cfg.TLS.NodeNonClusterHostCommonName = "custom-nch-cn" component := render.Typha(&cfg)