Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions api/v1/installation_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type InstallationSpec struct {
// If the specified value is not empty, the Operator will still attempt auto-detection, but
// will additionally compare the auto-detected value to the specified value to confirm they match.
// +optional
// +kubebuilder:validation:Enum="";EKS;GKE;AKS;OpenShift;DockerEnterprise;RKE2;TKG;
// +kubebuilder:validation:Enum="";EKS;GKE;AKS;OpenShift;DockerEnterprise;RKE2;TKG;Talos;
KubernetesProvider Provider `json:"kubernetesProvider,omitempty"`

// CNI specifies the CNI that will be used by this installation.
Expand Down Expand Up @@ -366,7 +366,7 @@ type ComponentResource struct {
}

// Provider represents a particular provider or flavor of Kubernetes. Valid options
// are: EKS, GKE, AKS, RKE2, OpenShift, DockerEnterprise, TKG.
// are: EKS, GKE, AKS, RKE2, OpenShift, DockerEnterprise, TKG, Talos.
type Provider string

var (
Expand All @@ -378,6 +378,7 @@ var (
ProviderOpenShift Provider = "OpenShift"
ProviderDockerEE Provider = "DockerEnterprise"
ProviderTKG Provider = "TKG"
ProviderTalos Provider = "Talos"
)

func (p Provider) IsNone() bool {
Expand Down Expand Up @@ -412,6 +413,10 @@ func (p Provider) IsTKG() bool {
return p == ProviderTKG
}

func (p Provider) IsTalos() bool {
return p == ProviderTalos
}

// ProductVariant represents the variant of the product.
//
// One of: Calico, TigeraSecureEnterprise
Expand Down
6 changes: 6 additions & 0 deletions pkg/controller/k8sapi/k8s-endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
)

const dockerEEProxyLocal = "proxy.local"
const talosKubePrismHost = "localhost"
const talosKubePrismPort = "7445"

// Endpoint is the default ServiceEndpoint learned from environment variables.
var Endpoint ServiceEndpoint
Expand Down Expand Up @@ -62,6 +64,10 @@ func (k8s ServiceEndpoint) EnvVars(hostNetworked bool, provider operator.Provide
return nil
}

if provider == operator.ProviderTalos && !hostNetworked && k8s.Host == talosKubePrismHost && k8s.Port == talosKubePrismPort {
return nil
}

return []v1.EnvVar{
{Name: "KUBERNETES_SERVICE_HOST", Value: k8s.Host},
{Name: "KUBERNETES_SERVICE_PORT", Value: k8s.Port},
Expand Down
25 changes: 25 additions & 0 deletions pkg/controller/utils/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ func AutoDiscoverProvider(ctx context.Context, clientset kubernetes.Interface) (
return operatorv1.ProviderRKE2, nil
}

// We failed to determine the platform based on API groups. Some platforms can be detected in other ways, though.
if talos, err := isTalos(ctx, clientset); err != nil {
return operatorv1.ProviderNone, fmt.Errorf("failed to check if Talos is the provider: %s", err)
} else if talos {
return operatorv1.ProviderTalos, nil
}

// Couldn't detect any specific platform.
return operatorv1.ProviderNone, nil
}
Expand Down Expand Up @@ -239,6 +246,24 @@ func isRKE2(ctx context.Context, c kubernetes.Interface) (bool, error) {
return foundRKE2Resource, nil
}

// isTalos returns true if running on a Talos cluster, and false otherwise.
// Talos doesn't have any provider-specific API groups, so we need to use a different approach than
// we use for other platforms in autodetectFromGroup.
func isTalos(ctx context.Context, c kubernetes.Interface) (bool, error) {
masterNodes, err := c.CoreV1().Nodes().List(ctx, metav1.ListOptions{LabelSelector: "node-role.kubernetes.io/control-plane"})
if err != nil {
return false, err
}
for _, n := range masterNodes.Items {
for l := range n.Annotations {
if strings.HasPrefix(l, "talos.dev") {
return true, nil
}
}
}
return false, nil
}

// UseExternalElastic returns true if this cluster is configured to use an external elasticsearch cluster,
// and false otherwise.
func UseExternalElastic(config *corev1.ConfigMap) bool {
Expand Down
17 changes: 17 additions & 0 deletions pkg/controller/utils/discovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,23 @@ var _ = Describe("provider discovery", func() {
Expect(p).To(Equal(operatorv1.ProviderTKG))
})

It("should detect Talos if a control-plane node has annotations prefixed with talos.dev", func() {
c := fake.NewSimpleClientset(&corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "control-plane-1",
Labels: map[string]string{
"node-role.kubernetes.io/control-plane": "",
},
Annotations: map[string]string{
"talos.dev/owned-labels": "[\"node-role.kubernetes.io/control-plane\"]",
},
},
})
p, e := AutoDiscoverProvider(context.Background(), c)
Expect(e).To(BeNil())
Expect(p).To(Equal(operatorv1.ProviderTalos))
})

It("should detect EKS based on eks-certificates-controller ConfigMap", func() {
c := fake.NewSimpleClientset(&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Expand Down
2 changes: 2 additions & 0 deletions pkg/crds/operator/operator.tigera.io_installations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6816,6 +6816,7 @@ spec:
- DockerEnterprise
- RKE2
- TKG
- Talos
type: string
logging:
description: Logging Configuration for Components
Expand Down Expand Up @@ -15689,6 +15690,7 @@ spec:
- DockerEnterprise
- RKE2
- TKG
- Talos
type: string
logging:
description: Logging Configuration for Components
Expand Down
34 changes: 34 additions & 0 deletions pkg/render/apiserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,40 @@ var _ = Describe("API server rendering tests (Calico Enterprise)", func() {
rtest.ExpectK8sServiceEpEnvVars(deployment.Spec.Template.Spec, "k8shost", "1234")
})

It("should not set KUBERENETES_SERVICE_... variables if not host networked on Talos with KubePrism", func() {
cfg.K8SServiceEndpoint.Host = "localhost"
cfg.K8SServiceEndpoint.Port = "7445"
cfg.Installation.KubernetesProvider = operatorv1.ProviderTalos

component, err := render.APIServer(cfg)
Expect(err).To(BeNil(), "Expected APIServer to create successfully %s", err)
Expect(component.ResolveImages(nil)).To(BeNil())
resources, _ := component.Objects()

deploymentResource := rtest.GetResource(resources, "tigera-apiserver", "tigera-system", "apps", "v1", "Deployment")
Expect(deploymentResource).ToNot(BeNil())

deployment := deploymentResource.(*appsv1.Deployment)
rtest.ExpectNoK8sServiceEpEnvVars(deployment.Spec.Template.Spec)
})

It("should set KUBERENETES_SERVICE_... variables if not host networked on Talos with non-KubePrism address", func() {
cfg.K8SServiceEndpoint.Host = "k8shost"
cfg.K8SServiceEndpoint.Port = "1234"
cfg.Installation.KubernetesProvider = operatorv1.ProviderTalos

component, err := render.APIServer(cfg)
Expect(err).To(BeNil(), "Expected APIServer to create successfully %s", err)
Expect(component.ResolveImages(nil)).To(BeNil())
resources, _ := component.Objects()

deploymentResource := rtest.GetResource(resources, "tigera-apiserver", "tigera-system", "apps", "v1", "Deployment")
Expect(deploymentResource).ToNot(BeNil())

deployment := deploymentResource.(*appsv1.Deployment)
rtest.ExpectK8sServiceEpEnvVars(deployment.Spec.Template.Spec, "k8shost", "1234")
})

It("should render an API server with custom configuration with MCM enabled at startup", func() {
cfg.ManagementCluster = managementCluster
component, err := render.APIServer(cfg)
Expand Down
15 changes: 15 additions & 0 deletions pkg/render/kubecontrollers/kube-controllers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,21 @@ var _ = Describe("kube-controllers rendering tests", func() {
rtest.ExpectNoK8sServiceEpEnvVars(deployment.Spec.Template.Spec)
})

It("should not add the KUBERNETES_SERVICE_... variables on Talos using KubePrism", func() {
k8sServiceEp.Host = "localhost"
k8sServiceEp.Port = "7445"
instance.KubernetesProvider = operatorv1.ProviderTalos

component := kubecontrollers.NewCalicoKubeControllers(&cfg)
Expect(component.ResolveImages(nil)).To(BeNil())
resources, _ := component.Objects()

depResource := rtest.GetResource(resources, kubecontrollers.KubeController, common.CalicoNamespace, "apps", "v1", "Deployment")
Expect(depResource).ToNot(BeNil())
deployment := depResource.(*appsv1.Deployment)
rtest.ExpectNoK8sServiceEpEnvVars(deployment.Spec.Template.Spec)
})

It("should add prometheus annotations to metrics service", func() {
for _, variant := range []operatorv1.ProductVariant{operatorv1.Calico, operatorv1.TigeraSecureEnterprise} {
cfg.Installation.Variant = variant
Expand Down