diff --git a/cmd/antrea-agent/agent.go b/cmd/antrea-agent/agent.go index ea075866f2e..0988e9034a8 100644 --- a/cmd/antrea-agent/agent.go +++ b/cmd/antrea-agent/agent.go @@ -131,7 +131,6 @@ func run(o *Options) error { } defer ovsdbConnection.Close() - egressEnabled := features.DefaultFeatureGate.Enabled(features.Egress) enableAntreaIPAM := features.DefaultFeatureGate.Enabled(features.AntreaIPAM) enableBridgingMode := enableAntreaIPAM && o.config.EnableBridgingMode enableNodePortLocal := features.DefaultFeatureGate.Enabled(features.NodePortLocal) && o.config.NodePortLocal.Enable @@ -150,7 +149,7 @@ func run(o *Options) error { features.DefaultFeatureGate.Enabled(features.AntreaProxy), features.DefaultFeatureGate.Enabled(features.AntreaPolicy), l7NetworkPolicyEnabled, - egressEnabled, + o.enableEgress, features.DefaultFeatureGate.Enabled(features.FlowExporter), o.config.AntreaProxy.ProxyAll, connectUplinkToBridge, @@ -458,7 +457,7 @@ func run(o *Options) error { var externalIPController *serviceexternalip.ServiceExternalIPController var memberlistCluster *memberlist.Cluster - if egressEnabled || features.DefaultFeatureGate.Enabled(features.ServiceExternalIP) { + if o.enableEgress || features.DefaultFeatureGate.Enabled(features.ServiceExternalIP) { externalIPPoolController = externalippool.NewExternalIPPoolController( crdClient, externalIPPoolInformer, ) @@ -477,7 +476,7 @@ func run(o *Options) error { return fmt.Errorf("error creating new memberlist cluster: %v", err) } } - if egressEnabled { + if o.enableEgress { egressController, err = egress.NewEgressController( ofClient, antreaClientProvider, crdClient, ifaceStore, routeClient, nodeConfig.Name, nodeConfig.NodeTransportInterfaceName, memberlistCluster, egressInformer, nodeInformer, podUpdateChannel, o.config.Egress.MaxEgressIPsPerNode, @@ -700,12 +699,12 @@ func run(o *Options) error { informerFactory.Start(stopCh) crdInformerFactory.Start(stopCh) - if egressEnabled || features.DefaultFeatureGate.Enabled(features.ServiceExternalIP) { + if o.enableEgress || features.DefaultFeatureGate.Enabled(features.ServiceExternalIP) { go externalIPPoolController.Run(stopCh) go memberlistCluster.Run(stopCh) } - if egressEnabled { + if o.enableEgress { go egressController.Run(stopCh) } diff --git a/cmd/antrea-agent/options.go b/cmd/antrea-agent/options.go index cdfe606a480..6d5ab837194 100644 --- a/cmd/antrea-agent/options.go +++ b/cmd/antrea-agent/options.go @@ -82,6 +82,10 @@ type Options struct { nplEndPort int dnsServerOverride string nodeType config.NodeType + + // enableEgress represents whether Egress should run or not, calculated from its feature gate configuration and + // whether the traffic mode supports it. + enableEgress bool } func newOptions() *Options { @@ -423,6 +427,27 @@ func (o *Options) setK8sNodeDefaultOptions() { } } +func (o *Options) validateEgressConfig(encapMode config.TrafficEncapModeType) error { + if !features.DefaultFeatureGate.Enabled(features.Egress) { + return nil + } + if encapMode != config.TrafficEncapModeEncap { + klog.InfoS("The Egress feature gate is enabled, but it won't work because it is only applicable to the encap mode") + return nil + } + for _, cidr := range o.config.Egress.ExceptCIDRs { + _, _, err := net.ParseCIDR(cidr) + if err != nil { + return fmt.Errorf("Egress Except CIDR %s is invalid", cidr) + } + } + if o.config.Egress.MaxEgressIPsPerNode > defaultMaxEgressIPsPerNode { + return fmt.Errorf("maxEgressIPsPerNode cannot be greater than %d", defaultMaxEgressIPsPerNode) + } + o.enableEgress = true + return nil +} + func (o *Options) validateK8sNodeOptions() error { if o.config.TunnelType != ovsconfig.VXLANTunnel && o.config.TunnelType != ovsconfig.GeneveTunnel && o.config.TunnelType != ovsconfig.GRETunnel && o.config.TunnelType != ovsconfig.STTTunnel { @@ -485,13 +510,8 @@ func (o *Options) validateK8sNodeOptions() error { if err := o.validateMulticastConfig(); err != nil { return fmt.Errorf("failed to validate multicast config: %v", err) } - if features.DefaultFeatureGate.Enabled(features.Egress) { - for _, cidr := range o.config.Egress.ExceptCIDRs { - _, _, err := net.ParseCIDR(cidr) - if err != nil { - return fmt.Errorf("Egress Except CIDR %s is invalid", cidr) - } - } + if err := o.validateEgressConfig(encapMode); err != nil { + return fmt.Errorf("failed to validate egress config: %v", err) } if err := o.validateMulticlusterConfig(encapMode, encryptionMode); err != nil { return err @@ -520,11 +540,6 @@ func (o *Options) validateK8sNodeOptions() error { o.dnsServerOverride = hostPort } - if features.DefaultFeatureGate.Enabled(features.Egress) { - if o.config.Egress.MaxEgressIPsPerNode > defaultMaxEgressIPsPerNode { - return fmt.Errorf("maxEgressIPsPerNode cannot be greater than %d", defaultMaxEgressIPsPerNode) - } - } return nil } diff --git a/cmd/antrea-agent/options_test.go b/cmd/antrea-agent/options_test.go index 539cd288e11..eafcb580a9b 100644 --- a/cmd/antrea-agent/options_test.go +++ b/cmd/antrea-agent/options_test.go @@ -18,8 +18,12 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "antrea.io/antrea/pkg/agent/config" agentconfig "antrea.io/antrea/pkg/config/agent" + "antrea.io/antrea/pkg/features" ) func TestOptionsValidateTLSOptions(t *testing.T) { @@ -73,3 +77,63 @@ func TestOptionsValidateTLSOptions(t *testing.T) { }) } } + +func TestOptionsValidateEgressConfig(t *testing.T) { + tests := []struct { + name string + featureGateValue bool + trafficEncapMode config.TrafficEncapModeType + egressConfig agentconfig.EgressConfig + expectedErr string + expectedEnableEgress bool + }{ + { + name: "enabled", + featureGateValue: true, + trafficEncapMode: config.TrafficEncapModeEncap, + expectedEnableEgress: true, + }, + { + name: "unsupported encap mode", + featureGateValue: true, + trafficEncapMode: config.TrafficEncapModeNoEncap, + expectedEnableEgress: false, + }, + { + name: "too large maxEgressIPsPerNode", + featureGateValue: true, + trafficEncapMode: config.TrafficEncapModeEncap, + egressConfig: agentconfig.EgressConfig{ + MaxEgressIPsPerNode: 300, + }, + expectedErr: "maxEgressIPsPerNode cannot be greater than", + expectedEnableEgress: false, + }, + { + name: "invalid exceptCIDRs", + featureGateValue: true, + trafficEncapMode: config.TrafficEncapModeEncap, + egressConfig: agentconfig.EgressConfig{ + ExceptCIDRs: []string{"1.1.1.300/32"}, + }, + expectedErr: "Egress Except CIDR 1.1.1.300/32 is invalid", + expectedEnableEgress: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, features.DefaultFeatureGate, features.Egress, tt.featureGateValue)() + + o := &Options{config: &agentconfig.AgentConfig{ + Egress: tt.egressConfig, + }} + err := o.validateEgressConfig(tt.trafficEncapMode) + if tt.expectedErr == "" { + require.NoError(t, err) + } else { + require.ErrorContains(t, err, tt.expectedErr) + } + assert.Equal(t, tt.expectedEnableEgress, o.enableEgress) + }) + } +}