diff --git a/api/v1/installation_types.go b/api/v1/installation_types.go index f0206dbb15..69139054e9 100644 --- a/api/v1/installation_types.go +++ b/api/v1/installation_types.go @@ -537,6 +537,15 @@ func BGPOptionPtr(b BGPOption) *BGPOption { return &b } +// ClusterRoutingMode describes the mode of cluster routing. +// +kubebuilder:validation:Enum=BIRD;Felix +type ClusterRoutingMode string + +const ( + ClusterRoutingModeBIRD ClusterRoutingMode = "BIRD" + ClusterRoutingModeFelix ClusterRoutingMode = "Felix" +) + const ( BGPEnabled BGPOption = "Enabled" BGPDisabled BGPOption = "Disabled" @@ -614,6 +623,13 @@ type CalicoNetworkSpec struct { // +kubebuilder:validation:Enum=Enabled;Disabled BGP *BGPOption `json:"bgp,omitempty"` + // ClusterRoutingMode controls how nodes get a route to a workload on another node, + // when that workload's IP comes from an IP Pool with vxlanMode: Never. When ClusterRoutingMode is BIRD, + // confd and BIRD program that route. When ClusterRoutingMode is Felix, it is expected that Felix will program that route. + // Felix always programs such routes for IP Pools with vxlanMode: Always or vxlanMode: CrossSubnet. [Default: BIRD] + // +optional + ClusterRoutingMode *ClusterRoutingMode `json:"clusterRoutingMode,omitempty"` + // IPPools contains a list of IP pools to manage. If nil, a single IPv4 IP pool // will be created by the operator. If an empty list is provided, the operator will not create any IP pools and will instead // wait for IP pools to be created out-of-band. diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 7aab497499..773f3b8806 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1208,6 +1208,11 @@ func (in *CalicoNetworkSpec) DeepCopyInto(out *CalicoNetworkSpec) { *out = new(BGPOption) **out = **in } + if in.ClusterRoutingMode != nil { + in, out := &in.ClusterRoutingMode, &out.ClusterRoutingMode + *out = new(ClusterRoutingMode) + **out = **in + } if in.IPPools != nil { in, out := &in.IPPools, &out.IPPools *out = make([]IPPool, len(*in)) diff --git a/go.mod b/go.mod index 1f4433e241..d16850a0a0 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/sirupsen/logrus v1.9.4 github.com/snowzach/rotatefilehook v0.0.0-20220211133110-53752135082d github.com/stretchr/testify v1.11.1 - github.com/tigera/api v0.0.0-20260227222130-df0b9e289a34 + github.com/tigera/api v0.0.0-20260310182635-546021df243c github.com/tigera/operator/api v0.0.0-20260120220012-4a3f8a7d8399 github.com/urfave/cli/v3 v3.6.2 go.uber.org/zap v1.27.1 diff --git a/go.sum b/go.sum index 456f7638b4..22fbc30be8 100644 --- a/go.sum +++ b/go.sum @@ -406,8 +406,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/tigera/api v0.0.0-20260227222130-df0b9e289a34 h1:bFz27L2XauCys8mBwGQUXzYL8fS4oC5/ModvfujYKaQ= -github.com/tigera/api v0.0.0-20260227222130-df0b9e289a34/go.mod h1:CX/80DoAQD88kMvkvujV4h3XPmIBo0yeSf9OZmvZY0c= +github.com/tigera/api v0.0.0-20260310182635-546021df243c h1:XPwyK52lSkCFeTcUIOFUXp8+3HQr5ZHg83gk2gBCCKw= +github.com/tigera/api v0.0.0-20260310182635-546021df243c/go.mod h1:CX/80DoAQD88kMvkvujV4h3XPmIBo0yeSf9OZmvZY0c= github.com/urfave/cli/v3 v3.6.2 h1:lQuqiPrZ1cIz8hz+HcrG0TNZFxU70dPZ3Yl+pSrH9A8= github.com/urfave/cli/v3 v3.6.2/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= diff --git a/pkg/controller/installation/core_controller.go b/pkg/controller/installation/core_controller.go index 6a5cffade1..2b6f7f2300 100644 --- a/pkg/controller/installation/core_controller.go +++ b/pkg/controller/installation/core_controller.go @@ -1144,9 +1144,34 @@ func (r *ReconcileInstallation) Reconcile(ctx context.Context, request reconcile if err != nil { return false, err } - return u || u2, nil + + // Configure cluster routing mode. + u3, err := setClusterRoutingOnFelixConfiguration(instance, fc, reqLogger) + if err != nil { + return false, err + } + + updated := u || u2 || u3 + return updated, nil + }) + if err != nil { + return reconcile.Result{}, err + } + + // Set any non-default BGPConfiguration values that we need. + _, err = utils.PatchBGPConfiguration(ctx, r.client, func(bgpConfig *v3.BGPConfiguration) (bool, error) { + // Configure cluster routing mode. + u, err := setClusterRoutingOnBGPConfiguration(instance, bgpConfig, reqLogger) + if err != nil { + return false, err + } + + return u, nil }) if err != nil { + // Since, programClusterRoutes in FelixConfiguration is already updated earlier, + // failure in updating programClusterRouting in BGPConfiguration, essentially results in inconsistency + // between the configuration of BIRD and Felix in programming cluster routes, until the next reconcile convergence return reconcile.Result{}, err } @@ -2011,6 +2036,59 @@ func (r *ReconcileInstallation) setDefaultsOnFelixConfiguration(ctx context.Cont return updated, nil } +// setClusterRoutingOnFelixConfiguration sets programClusterRoutes in the FelixConfiguration resource +// based on the value of clusterRoutingMode in the install config. +func setClusterRoutingOnFelixConfiguration( + install *operatorv1.Installation, + fc *v3.FelixConfiguration, + reqLogger logr.Logger, +) (bool, error) { + updated := false + desiredValue := "Disabled" + if felixProgramsClusterRoutes(install) { + desiredValue = "Enabled" + } + + if fc.Spec.ProgramClusterRoutes == nil || *fc.Spec.ProgramClusterRoutes != desiredValue { + fc.Spec.ProgramClusterRoutes = &desiredValue + updated = true + reqLogger.Info("Patching FelixConfiguration", "programClusterRoutes", desiredValue) + } + + return updated, nil +} + +// setClusterRoutingOnBGPConfiguration sets programClusterRoutes in the BGPConfiguration resource +// based on the value of clusterRoutingMode in the install config. +func setClusterRoutingOnBGPConfiguration( + install *operatorv1.Installation, + bgpConfig *v3.BGPConfiguration, + reqLogger logr.Logger, +) (bool, error) { + updated := false + desiredValue := "Enabled" + + if felixProgramsClusterRoutes(install) { + desiredValue = "Disabled" + } + + if bgpConfig.Spec.ProgramClusterRoutes == nil || *bgpConfig.Spec.ProgramClusterRoutes != desiredValue { + bgpConfig.Spec.ProgramClusterRoutes = &desiredValue + updated = true + reqLogger.Info("Patching BGPConfiguration", "programClusterRoutes", desiredValue) + } + + return updated, nil +} + +func felixProgramsClusterRoutes(install *operatorv1.Installation) bool { + if install.Spec.CalicoNetwork != nil && install.Spec.CalicoNetwork.ClusterRoutingMode != nil && + *install.Spec.CalicoNetwork.ClusterRoutingMode == operatorv1.ClusterRoutingModeFelix { + return true + } + return false +} + // setBPFUpdatesOnFelixConfiguration will take the passed in fc and update any BPF properties needed // based on the install config and the daemonset. func (r *ReconcileInstallation) setBPFUpdatesOnFelixConfiguration(ctx context.Context, install *operatorv1.Installation, fc *v3.FelixConfiguration, reqLogger logr.Logger) (bool, error) { diff --git a/pkg/controller/installation/core_controller_test.go b/pkg/controller/installation/core_controller_test.go index 6964f531d9..c19f52b921 100644 --- a/pkg/controller/installation/core_controller_test.go +++ b/pkg/controller/installation/core_controller_test.go @@ -1427,6 +1427,92 @@ var _ = Describe("Testing core-controller installation", func() { Expect(pullSecret.Kind).To(Equal("Installation")) }) + It("should correctly patch FelixConfig and BGPConfig with ClusterRouteMode not set", func() { + cr.Spec.CalicoNetwork = &operator.CalicoNetworkSpec{} + Expect(c.Create(ctx, cr)).NotTo(HaveOccurred()) + _, err := r.Reconcile(ctx, reconcile.Request{}) + Expect(err).ShouldNot(HaveOccurred()) + + fc := &v3.FelixConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, fc) + Expect(err).ShouldNot(HaveOccurred()) + Expect(fc.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*fc.Spec.ProgramClusterRoutes).To(Equal("Disabled")) + + bgpConfig := &v3.BGPConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + Expect(err).ShouldNot(HaveOccurred()) + Expect(bgpConfig.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*bgpConfig.Spec.ProgramClusterRoutes).To(Equal("Enabled")) + }) + + It("should correctly patch FelixConfig and BGPConfig with ClusterRouteMode set to BIRD", func() { + bird := operator.ClusterRoutingModeBIRD + cr.Spec.CalicoNetwork = &operator.CalicoNetworkSpec{ClusterRoutingMode: &bird} + Expect(c.Create(ctx, cr)).NotTo(HaveOccurred()) + _, err := r.Reconcile(ctx, reconcile.Request{}) + Expect(err).ShouldNot(HaveOccurred()) + + fc := &v3.FelixConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, fc) + Expect(err).ShouldNot(HaveOccurred()) + Expect(fc.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*fc.Spec.ProgramClusterRoutes).To(Equal("Disabled")) + + bgpConfig := &v3.BGPConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + Expect(err).ShouldNot(HaveOccurred()) + Expect(bgpConfig.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*bgpConfig.Spec.ProgramClusterRoutes).To(Equal("Enabled")) + }) + + It("should correctly patch FelixConfig and BGPConfig with ClusterRouteMode set to Felix", func() { + felix := operator.ClusterRoutingModeFelix + cr.Spec.CalicoNetwork = &operator.CalicoNetworkSpec{ClusterRoutingMode: &felix} + Expect(c.Create(ctx, cr)).NotTo(HaveOccurred()) + _, err := r.Reconcile(ctx, reconcile.Request{}) + Expect(err).ShouldNot(HaveOccurred()) + + fc := &v3.FelixConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, fc) + Expect(err).ShouldNot(HaveOccurred()) + Expect(fc.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*fc.Spec.ProgramClusterRoutes).To(Equal("Enabled")) + + bgpConfig := &v3.BGPConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + Expect(err).ShouldNot(HaveOccurred()) + Expect(bgpConfig.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*bgpConfig.Spec.ProgramClusterRoutes).To(Equal("Disabled")) + }) + + It("should create the default BGPConfig and FelixConfig with ClusterRoutingMode set", func() { + bgpConfig := &v3.BGPConfiguration{} + err := c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + Expect(err).Should(HaveOccurred()) + + fc := &v3.FelixConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, fc) + Expect(err).Should(HaveOccurred()) + + felix := operator.ClusterRoutingModeFelix + cr.Spec.CalicoNetwork = &operator.CalicoNetworkSpec{ClusterRoutingMode: &felix} + Expect(c.Create(ctx, cr)).NotTo(HaveOccurred()) + _, err = r.Reconcile(ctx, reconcile.Request{}) + Expect(err).ShouldNot(HaveOccurred()) + + err = c.Get(ctx, types.NamespacedName{Name: "default"}, fc) + Expect(err).ShouldNot(HaveOccurred()) + Expect(fc.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*fc.Spec.ProgramClusterRoutes).To(Equal("Enabled")) + + bgpConfig = &v3.BGPConfiguration{} + err = c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + Expect(err).ShouldNot(HaveOccurred()) + Expect(bgpConfig.Spec.ProgramClusterRoutes).NotTo(BeNil()) + Expect(*bgpConfig.Spec.ProgramClusterRoutes).To(Equal("Disabled")) + }) + It("should set vxlanVNI to 10000 when provider is DockerEE", func() { cr.Spec.KubernetesProvider = operator.ProviderDockerEE Expect(c.Create(ctx, cr)).NotTo(HaveOccurred()) diff --git a/pkg/controller/installation/validation.go b/pkg/controller/installation/validation.go index 30fe58e99c..f934a94eab 100644 --- a/pkg/controller/installation/validation.go +++ b/pkg/controller/installation/validation.go @@ -139,6 +139,7 @@ func validateCustomResource(instance *operatorv1.Installation) error { // Verify Calico settings, if specified. if instance.Spec.CalicoNetwork != nil { bpfDataplane := instance.Spec.CalicoNetwork.LinuxDataplane != nil && *instance.Spec.CalicoNetwork.LinuxDataplane == operatorv1.LinuxDataplaneBPF + felixClusterRoutingMode := felixProgramsClusterRoutes(instance) // Perform validation on non-IPPool fields that rely on IP pool configuration. Validation of the IP pools themselves // happens in the IP pool controller. @@ -167,15 +168,17 @@ func validateCustomResource(instance *operatorv1.Installation) error { // Verify the specified encapsulation type is valid. switch pool.Encapsulation { case operatorv1.EncapsulationIPIP, operatorv1.EncapsulationIPIPCrossSubnet: - // IPIP currently requires BGP to be running in order to program routes. - if instance.Spec.CalicoNetwork.BGP == nil || *instance.Spec.CalicoNetwork.BGP == operatorv1.BGPDisabled { - return fmt.Errorf("IPIP encapsulation requires that BGP is enabled") + // In BIRD cluster routing mode, IPIP currently requires BGP to be running in order to program routes. + if !felixClusterRoutingMode && + (instance.Spec.CalicoNetwork.BGP == nil || *instance.Spec.CalicoNetwork.BGP == operatorv1.BGPDisabled) { + return fmt.Errorf("with BIRD cluster routing mode, IPIP encapsulation requires that BGP is enabled") } case operatorv1.EncapsulationVXLAN, operatorv1.EncapsulationVXLANCrossSubnet: case operatorv1.EncapsulationNone: - // Unencapsulated currently requires BGP to be running in order to program routes. - if instance.Spec.CalicoNetwork.BGP == nil || *instance.Spec.CalicoNetwork.BGP == operatorv1.BGPDisabled { - return fmt.Errorf("unencapsulated IP pools require that BGP is enabled") + // In BIRD cluster routing mode, Unencapsulated currently requires BGP to be running in order to program routes. + if !felixClusterRoutingMode && + (instance.Spec.CalicoNetwork.BGP == nil || *instance.Spec.CalicoNetwork.BGP == operatorv1.BGPDisabled) { + return fmt.Errorf("with BIRD cluster routing mode, unencapsulated IP pools require that BGP is enabled") } } case operatorv1.IPAMPluginHostLocal: diff --git a/pkg/controller/installation/validation_test.go b/pkg/controller/installation/validation_test.go index b7859bdcb5..d6bda1e6c0 100644 --- a/pkg/controller/installation/validation_test.go +++ b/pkg/controller/installation/validation_test.go @@ -245,7 +245,7 @@ var _ = Describe("Installation validation tests", func() { Expect(err).NotTo(HaveOccurred()) }) - It("should prevent IPIP if BGP is disabled", func() { + It("should prevent IPIP with BGP disabled in BIRD cluster routing mode", func() { disabled := operator.BGPDisabled instance.Spec.CalicoNetwork.BGP = &disabled instance.Spec.CalicoNetwork.IPPools = []operator.IPPool{ @@ -260,7 +260,7 @@ var _ = Describe("Installation validation tests", func() { Expect(err).To(HaveOccurred()) }) - It("should prevent IPIP cross-subnet if BGP is disabled", func() { + It("should prevent IPIP cross-subnet with BGP disabled in BIRD cluster routing mode", func() { disabled := operator.BGPDisabled instance.Spec.CalicoNetwork.BGP = &disabled instance.Spec.CalicoNetwork.IPPools = []operator.IPPool{ @@ -275,6 +275,72 @@ var _ = Describe("Installation validation tests", func() { Expect(err).To(HaveOccurred()) }) + It("should prevent no-encap with BGP disabled in BIRD cluster routing mode", func() { + disabled := operator.BGPDisabled + instance.Spec.CalicoNetwork.BGP = &disabled + instance.Spec.CalicoNetwork.IPPools = []operator.IPPool{ + { + CIDR: "192.168.0.0/24", + Encapsulation: operator.EncapsulationNone, + NATOutgoing: operator.NATOutgoingEnabled, + NodeSelector: "all()", + }, + } + err := validateCustomResource(instance) + Expect(err).To(HaveOccurred()) + }) + + It("should allow IPIP with BGP disabled in Felix cluster routing mode", func() { + disabled := operator.BGPDisabled + instance.Spec.CalicoNetwork.BGP = &disabled + clusterRoutingMode := operator.ClusterRoutingModeFelix + instance.Spec.CalicoNetwork.ClusterRoutingMode = &clusterRoutingMode + instance.Spec.CalicoNetwork.IPPools = []operator.IPPool{ + { + CIDR: "192.168.0.0/24", + Encapsulation: operator.EncapsulationIPIP, + NATOutgoing: operator.NATOutgoingEnabled, + NodeSelector: "all()", + }, + } + err := validateCustomResource(instance) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should allow IPIP cross-subnet with BGP disabled in Felix cluster routing mode", func() { + disabled := operator.BGPDisabled + instance.Spec.CalicoNetwork.BGP = &disabled + clusterRoutingMode := operator.ClusterRoutingModeFelix + instance.Spec.CalicoNetwork.ClusterRoutingMode = &clusterRoutingMode + instance.Spec.CalicoNetwork.IPPools = []operator.IPPool{ + { + CIDR: "192.168.0.0/24", + Encapsulation: operator.EncapsulationIPIPCrossSubnet, + NATOutgoing: operator.NATOutgoingEnabled, + NodeSelector: "all()", + }, + } + err := validateCustomResource(instance) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should allow no-encap with BGP disabled in Felix cluster routing mode", func() { + disabled := operator.BGPDisabled + instance.Spec.CalicoNetwork.BGP = &disabled + clusterRoutingMode := operator.ClusterRoutingModeFelix + instance.Spec.CalicoNetwork.ClusterRoutingMode = &clusterRoutingMode + instance.Spec.CalicoNetwork.IPPools = []operator.IPPool{ + { + CIDR: "192.168.0.0/24", + Encapsulation: operator.EncapsulationNone, + NATOutgoing: operator.NATOutgoingEnabled, + NodeSelector: "all()", + }, + } + err := validateCustomResource(instance) + Expect(err).NotTo(HaveOccurred()) + }) + It("should not error if CalicoNetwork is provided on EKS", func() { instance := &operator.Installation{} instance.Spec.CNI = &operator.CNISpec{Type: operator.PluginCalico} diff --git a/pkg/controller/utils/bgp_configuration.go b/pkg/controller/utils/bgp_configuration.go new file mode 100644 index 0000000000..4acd71c0ba --- /dev/null +++ b/pkg/controller/utils/bgp_configuration.go @@ -0,0 +1,78 @@ +// Copyright (c) 2026 Tigera, Inc. All rights reserved. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "context" + "fmt" + + v3 "github.com/tigera/api/pkg/apis/projectcalico/v3" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func PatchBGPConfiguration( + ctx context.Context, + c client.Client, + patchFn func(bgpc *v3.BGPConfiguration) (bool, error), +) (*v3.BGPConfiguration, error) { + // Fetch any existing default BGPConfiguration object. + bgpConfig := &v3.BGPConfiguration{} + err := c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + if err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("unable to read BGPConfiguration: %w", err) + } + + // Create a base state for the upcoming patch operation. + patchFrom := client.MergeFrom(bgpConfig.DeepCopy()) + + if err = RestoreV3Metadata(bgpConfig); err != nil { + return nil, err + } + + // Apply desired changes to the BGPConfiguration. + updated, err := patchFn(bgpConfig) + if err != nil { + return nil, err + } + if updated { + // Apply the patch. + if bgpConfig.ResourceVersion == "" { + bgpConfig.Name = "default" + if err := c.Create(ctx, bgpConfig); err != nil { + return nil, err + } + } else { + if err := c.Patch(ctx, bgpConfig, patchFrom); err != nil { + return nil, err + } + } + } + + return bgpConfig, nil +} + +func GetBGPConfiguration( + ctx context.Context, + c client.Client, +) (*v3.BGPConfiguration, error) { + bgpConfig := &v3.BGPConfiguration{} + err := c.Get(ctx, types.NamespacedName{Name: "default"}, bgpConfig) + if err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("unable to read BGPConfiguration: %w", err) + } + return bgpConfig, nil +} diff --git a/pkg/controller/utils/merge.go b/pkg/controller/utils/merge.go index fc5a0d3c60..03b78a6856 100644 --- a/pkg/controller/utils/merge.go +++ b/pkg/controller/utils/merge.go @@ -280,6 +280,11 @@ func mergeCalicoNetwork(cfg, override *operatorv1.CalicoNetworkSpec) *operatorv1 out.BGP = override.BGP } + switch compareFields(out.ClusterRoutingMode, override.ClusterRoutingMode) { + case BOnlySet, Different: + out.ClusterRoutingMode = override.ClusterRoutingMode + } + switch compareFields(out.IPPools, override.IPPools) { case BOnlySet, Different: out.IPPools = make([]operatorv1.IPPool, len(override.IPPools)) diff --git a/pkg/imports/crds/operator/operator.tigera.io_installations.yaml b/pkg/imports/crds/operator/operator.tigera.io_installations.yaml index c51e8453af..0ab5ce8142 100644 --- a/pkg/imports/crds/operator/operator.tigera.io_installations.yaml +++ b/pkg/imports/crds/operator/operator.tigera.io_installations.yaml @@ -1281,6 +1281,16 @@ spec: - Disabled - Enabled type: string + clusterRoutingMode: + description: |- + ClusterRoutingMode controls how nodes get a route to a workload on another node, + when that workload's IP comes from an IP Pool with vxlanMode: Never. When ClusterRoutingMode is BIRD, + confd and BIRD program that route. When ClusterRoutingMode is Felix, it is expected that Felix will program that route. + Felix always programs such routes for IP Pools with vxlanMode: Always or vxlanMode: CrossSubnet. [Default: BIRD] + enum: + - BIRD + - Felix + type: string containerIPForwarding: description: |- ContainerIPForwarding configures whether ip forwarding will be enabled for containers in the CNI configuration. @@ -10094,6 +10104,16 @@ spec: - Disabled - Enabled type: string + clusterRoutingMode: + description: |- + ClusterRoutingMode controls how nodes get a route to a workload on another node, + when that workload's IP comes from an IP Pool with vxlanMode: Never. When ClusterRoutingMode is BIRD, + confd and BIRD program that route. When ClusterRoutingMode is Felix, it is expected that Felix will program that route. + Felix always programs such routes for IP Pools with vxlanMode: Always or vxlanMode: CrossSubnet. [Default: BIRD] + enum: + - BIRD + - Felix + type: string containerIPForwarding: description: |- ContainerIPForwarding configures whether ip forwarding will be enabled for containers in the CNI configuration.