Skip to content

Commit 293ad42

Browse files
kishorjTimothy-Dougherty
authored andcommitted
Add feature gates for ALB addons (kubernetes-sigs#1479)
* add feature gates and refactor command line flags add aws-max-retries cmdline flag add controller config options add feature gates for waf, wafv2 and shield * add sync-period flag * specify config as pure data add support for log-level flag hoonor the ingress-class flag configuration use AddonsConfig instead of FeatureGates * refactor, get rid of inClusterConfig warning * add webhook-bind-port and metrics-bind-addr flags * cleanup unused imports
1 parent a5204e1 commit 293ad42

File tree

15 files changed

+335
-85
lines changed

15 files changed

+335
-85
lines changed

controllers/elbv2/targetgroupbinding_controller.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
corev1 "k8s.io/api/core/v1"
2222
"sigs.k8s.io/aws-load-balancer-controller/controllers/elbv2/eventhandlers"
23+
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
2324
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
2425
"sigs.k8s.io/aws-load-balancer-controller/pkg/runtime"
2526
"sigs.k8s.io/aws-load-balancer-controller/pkg/targetgroupbinding"
@@ -38,21 +39,23 @@ const (
3839
)
3940

4041
// NewTargetGroupBindingReconciler constructs new targetGroupBindingReconciler
41-
func NewTargetGroupBindingReconciler(k8sClient client.Client, finalizerManager k8s.FinalizerManager, tgbResourceManager targetgroupbinding.ResourceManager, logger logr.Logger) *targetGroupBindingReconciler {
42+
func NewTargetGroupBindingReconciler(k8sClient client.Client, finalizerManager k8s.FinalizerManager, tgbResourceManager targetgroupbinding.ResourceManager, config config.ControllerConfig, logger logr.Logger) *targetGroupBindingReconciler {
4243
return &targetGroupBindingReconciler{
43-
k8sClient: k8sClient,
44-
finalizerManager: finalizerManager,
45-
tgbResourceManager: tgbResourceManager,
46-
logger: logger,
44+
k8sClient: k8sClient,
45+
finalizerManager: finalizerManager,
46+
tgbResourceManager: tgbResourceManager,
47+
logger: logger,
48+
maxConcurrentReconciles: config.TargetgroupBindingMaxConcurrentReconciles,
4749
}
4850
}
4951

5052
// targetGroupBindingReconciler reconciles a TargetGroupBinding object
5153
type targetGroupBindingReconciler struct {
52-
k8sClient client.Client
53-
finalizerManager k8s.FinalizerManager
54-
tgbResourceManager targetgroupbinding.ResourceManager
55-
logger logr.Logger
54+
k8sClient client.Client
55+
finalizerManager k8s.FinalizerManager
56+
tgbResourceManager targetgroupbinding.ResourceManager
57+
logger logr.Logger
58+
maxConcurrentReconciles int
5659
}
5760

5861
// +kubebuilder:rbac:groups=elbv2.k8s.aws,resources=targetgroupbindings,verbs=get;list;watch;update;patch;create;delete
@@ -117,7 +120,7 @@ func (r *targetGroupBindingReconciler) SetupWithManager(ctx context.Context, mgr
117120
For(&elbv2api.TargetGroupBinding{}).
118121
Watches(&source.Kind{Type: &corev1.Endpoints{}}, epEventsHandler).
119122
Watches(&source.Kind{Type: &corev1.Node{}}, nodeEventsHandler).
120-
WithOptions(controller.Options{MaxConcurrentReconciles: 3}).
123+
WithOptions(controller.Options{MaxConcurrentReconciles: r.maxConcurrentReconciles}).
121124
Complete(r)
122125
}
123126

controllers/ingress/group_controller.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"sigs.k8s.io/aws-load-balancer-controller/controllers/ingress/eventhandlers"
1212
"sigs.k8s.io/aws-load-balancer-controller/pkg/annotations"
1313
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws"
14+
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
1415
"sigs.k8s.io/aws-load-balancer-controller/pkg/deploy"
1516
"sigs.k8s.io/aws-load-balancer-controller/pkg/ingress"
1617
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
@@ -30,7 +31,7 @@ const (
3031

3132
// NewGroupReconciler constructs new GroupReconciler
3233
func NewGroupReconciler(cloud aws.Cloud, k8sClient client.Client, eventRecorder record.EventRecorder,
33-
networkingSGManager networkingpkg.SecurityGroupManager, networkingSGReconciler networkingpkg.SecurityGroupReconciler, clusterName string,
34+
networkingSGManager networkingpkg.SecurityGroupManager, networkingSGReconciler networkingpkg.SecurityGroupReconciler, config config.ControllerConfig,
3435
subnetsResolver networkingpkg.SubnetsResolver, logger logr.Logger) *groupReconciler {
3536
annotationParser := annotations.NewSuffixAnnotationParser(ingressAnnotationPrefix)
3637
authConfigBuilder := ingress.NewDefaultAuthConfigBuilder(annotationParser)
@@ -40,15 +41,17 @@ func NewGroupReconciler(cloud aws.Cloud, k8sClient client.Client, eventRecorder
4041
cloud.EC2(), cloud.ACM(),
4142
annotationParser, subnetsResolver,
4243
authConfigBuilder, enhancedBackendBuilder,
43-
cloud.VpcID(), clusterName, logger)
44+
cloud.VpcID(), config.ClusterName, logger)
4445
stackMarshaller := deploy.NewDefaultStackMarshaller()
45-
stackDeployer := deploy.NewDefaultStackDeployer(cloud, k8sClient, networkingSGManager, networkingSGReconciler, clusterName, ingressTagPrefix, logger)
46-
groupLoader := ingress.NewDefaultGroupLoader(k8sClient, annotationParser, "alb")
46+
stackDeployer := deploy.NewDefaultStackDeployer(cloud, k8sClient, networkingSGManager, networkingSGReconciler, config.ClusterName, ingressTagPrefix, logger, config)
47+
ingressConfig := config.IngressConfig
48+
groupLoader := ingress.NewDefaultGroupLoader(k8sClient, annotationParser, ingressConfig.IngressClass)
4749
k8sFinalizerManager := k8s.NewDefaultFinalizerManager(k8sClient, logger)
4850
finalizerManager := ingress.NewDefaultFinalizerManager(k8sFinalizerManager)
4951

5052
return &groupReconciler{
5153
k8sClient: k8sClient,
54+
ingressConfig: ingressConfig,
5255
eventRecorder: eventRecorder,
5356
groupLoader: groupLoader,
5457
finalizerManager: finalizerManager,
@@ -63,6 +66,7 @@ func NewGroupReconciler(cloud aws.Cloud, k8sClient client.Client, eventRecorder
6366
// GroupReconciler reconciles a ingress group
6467
type groupReconciler struct {
6568
k8sClient client.Client
69+
ingressConfig config.IngressConfig
6670
eventRecorder record.EventRecorder
6771
referenceIndexer ingress.ReferenceIndexer
6872
modelBuilder ingress.ModelBuilder
@@ -152,7 +156,7 @@ func (r *groupReconciler) updateIngressStatus(ctx context.Context, ing *networki
152156

153157
func (r *groupReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
154158
c, err := controller.New(controllerName, mgr, controller.Options{
155-
MaxConcurrentReconciles: 3,
159+
MaxConcurrentReconciles: r.ingressConfig.MaxConcurrentReconciles,
156160
Reconciler: r,
157161
})
158162
if err != nil {

controllers/service/service_controller.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"sigs.k8s.io/aws-load-balancer-controller/controllers/service/eventhandlers"
1010
"sigs.k8s.io/aws-load-balancer-controller/pkg/annotations"
1111
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws"
12+
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
1213
"sigs.k8s.io/aws-load-balancer-controller/pkg/deploy"
1314
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
1415
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
@@ -31,24 +32,26 @@ const (
3132

3233
func NewServiceReconciler(cloud aws.Cloud, k8sClient client.Client, eventRecorder record.EventRecorder,
3334
sgManager networking.SecurityGroupManager, sgReconciler networking.SecurityGroupReconciler,
34-
clusterName string, resolver networking.SubnetsResolver, logger logr.Logger) *serviceReconciler {
35+
config config.ControllerConfig, resolver networking.SubnetsResolver, logger logr.Logger) *serviceReconciler {
3536
annotationParser := annotations.NewSuffixAnnotationParser(serviceAnnotationPrefix)
36-
modelBuilder := nlb.NewDefaultModelBuilder(clusterName, resolver, annotationParser)
37+
modelBuilder := nlb.NewDefaultModelBuilder(config.ClusterName, resolver, annotationParser)
3738
return &serviceReconciler{
38-
k8sClient: k8sClient,
39-
eventRecorder: eventRecorder,
40-
annotationParser: annotationParser,
41-
finalizerManager: k8s.NewDefaultFinalizerManager(k8sClient, logger),
42-
modelBuilder: modelBuilder,
43-
stackMarshaller: deploy.NewDefaultStackMarshaller(),
44-
stackDeployer: deploy.NewDefaultStackDeployer(cloud, k8sClient, sgManager, sgReconciler, clusterName, serviceTagPrefix, logger),
45-
logger: logger,
39+
k8sClient: k8sClient,
40+
eventRecorder: eventRecorder,
41+
annotationParser: annotationParser,
42+
finalizerManager: k8s.NewDefaultFinalizerManager(k8sClient, logger),
43+
modelBuilder: modelBuilder,
44+
stackMarshaller: deploy.NewDefaultStackMarshaller(),
45+
stackDeployer: deploy.NewDefaultStackDeployer(cloud, k8sClient, sgManager, sgReconciler, config.ClusterName, serviceTagPrefix, logger, config),
46+
logger: logger,
47+
maxConcurrentReconciles: config.ServiceMaxConcurrentReconciles,
4648
}
4749
}
4850

4951
type serviceReconciler struct {
50-
k8sClient client.Client
51-
eventRecorder record.EventRecorder
52+
k8sClient client.Client
53+
eventRecorder record.EventRecorder
54+
maxConcurrentReconciles int
5255

5356
annotationParser annotations.Parser
5457
finalizerManager k8s.FinalizerManager
@@ -145,7 +148,7 @@ func (r *serviceReconciler) updateServiceStatus(ctx context.Context, svc *corev1
145148

146149
func (r *serviceReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
147150
c, err := controller.New(controllerName, mgr, controller.Options{
148-
MaxConcurrentReconciles: 3,
151+
MaxConcurrentReconciles: r.maxConcurrentReconciles,
149152
Reconciler: r,
150153
})
151154
if err != nil {

docs/guide/service/nlb_ip_mode.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
3434
```
3535
3636
## Security group
37-
NLB does not currently support a managed security group. For ingress access, the controller will resolve the security group for the ENI corresponding tho the endpoint pod. If the ENI has a single security group, it gets used. In case of multiple security gropus, the controller expects to find only one security group tagged with the Kubernetes cluster id. Controller will update the ingress rules on the security groups as per the service spec.
37+
NLB does not currently support a managed security group. For ingress access, the controller will resolve the security group for the ENI corresponding tho the endpoint pod. If the ENI has a single security group, it gets used. In case of multiple security groups, the controller expects to find only one security group tagged with the Kubernetes cluster id. Controller will update the ingress rules on the security groups as per the service spec.

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/prometheus/client_golang v1.0.0
1414
github.com/spf13/pflag v1.0.5
1515
github.com/stretchr/testify v1.5.1
16+
go.uber.org/zap v1.10.0
1617
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
1718
gomodules.xyz/jsonpatch/v2 v2.0.1
1819
k8s.io/api v0.18.4

main.go

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ package main
1818

1919
import (
2020
"context"
21-
"flag"
2221
"github.com/spf13/pflag"
22+
zapraw "go.uber.org/zap"
2323
"k8s.io/apimachinery/pkg/runtime"
2424
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
2525
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
@@ -30,6 +30,7 @@ import (
3030
"sigs.k8s.io/aws-load-balancer-controller/controllers/service"
3131
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws"
3232
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws/throttle"
33+
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
3334
inject "sigs.k8s.io/aws-load-balancer-controller/pkg/inject"
3435
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
3536
"sigs.k8s.io/aws-load-balancer-controller/pkg/networking"
@@ -42,14 +43,6 @@ import (
4243
// +kubebuilder:scaffold:imports
4344
)
4445

45-
const (
46-
flagMetricsAddr = "metrics-addr"
47-
flagEnableLeaderElection = "enable-leader-election"
48-
flagLeaderElectionID = "leader-election-id"
49-
flagK8sClusterName = "cluster-name"
50-
defaultLeaderElectionID = "aws-load-balancer-controller-leader"
51-
)
52-
5346
var (
5447
scheme = runtime.NewScheme()
5548
setupLog = ctrl.Log.WithName("setup")
@@ -63,49 +56,41 @@ func init() {
6356
}
6457

6558
func main() {
66-
var metricsAddr string
67-
var enableLeaderElection bool
68-
var k8sClusterName string
69-
var leaderElectionID string
7059
awsCloudConfig := aws.CloudConfig{ThrottleConfig: throttle.NewDefaultServiceOperationsThrottleConfig()}
7160
injectConfig := inject.Config{}
61+
controllerConfig := config.ControllerConfig{}
62+
7263
fs := pflag.NewFlagSet("", pflag.ExitOnError)
73-
fs.StringVar(&metricsAddr, flagMetricsAddr, ":8080", "The address the metric endpoint binds to.")
74-
fs.BoolVar(&enableLeaderElection, flagEnableLeaderElection, true,
75-
"Enable leader election for controller manager. "+
76-
"Enabling this will ensure there is only one active controller manager.")
77-
fs.StringVar(&leaderElectionID, flagLeaderElectionID, defaultLeaderElectionID,
78-
"Name of the leader election ID to use for this controller")
79-
fs.StringVar(&k8sClusterName, flagK8sClusterName, "", "Kubernetes cluster name")
8064
awsCloudConfig.BindFlags(fs)
8165
injectConfig.BindFlags(fs)
82-
fs.AddGoFlagSet(flag.CommandLine)
66+
controllerConfig.BindFlags(fs)
67+
8368
if err := fs.Parse(os.Args); err != nil {
8469
setupLog.Error(err, "invalid flags")
8570
os.Exit(1)
8671
}
87-
88-
ctrl.SetLogger(zap.New(zap.UseDevMode(false)))
89-
if len(k8sClusterName) == 0 {
90-
setupLog.Info("Kubernetes cluster name must be specified")
72+
if err := controllerConfig.Validate(); err != nil {
73+
setupLog.Error(err, "Failed to validate controller configuration")
9174
os.Exit(1)
9275
}
9376

77+
logLevel := zapraw.NewAtomicLevelAt(0)
78+
if controllerConfig.LogLevel == "debug" {
79+
logLevel = zapraw.NewAtomicLevelAt(-1)
80+
}
81+
ctrl.SetLogger(zap.New(zap.UseDevMode(false), zap.Level(&logLevel)))
82+
9483
cloud, err := aws.NewCloud(awsCloudConfig, metrics.Registry)
9584
if err != nil {
9685
setupLog.Error(err, "Unable to initialize AWS cloud")
9786
os.Exit(1)
9887
}
99-
100-
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
101-
102-
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
103-
Scheme: scheme,
104-
MetricsBindAddress: metricsAddr,
105-
LeaderElection: enableLeaderElection,
106-
LeaderElectionID: leaderElectionID,
107-
Port: 9443,
108-
})
88+
restCfg, err := config.BuildRestConfig(controllerConfig.RuntimeConfig)
89+
rtOpts := config.BuildRuntimeOptions(controllerConfig.RuntimeConfig, scheme)
90+
if err != nil {
91+
setupLog.Error(err, "Unable to build REST config")
92+
}
93+
mgr, err := ctrl.NewManager(restCfg, rtOpts)
10994
if err != nil {
11095
setupLog.Error(err, "unable to start manager")
11196
os.Exit(1)
@@ -117,16 +102,16 @@ func main() {
117102
sgReconciler := networking.NewDefaultSecurityGroupReconciler(sgManager, ctrl.Log)
118103
finalizerManager := k8s.NewDefaultFinalizerManager(mgr.GetClient(), ctrl.Log)
119104
tgbResManager := targetgroupbinding.NewDefaultResourceManager(mgr.GetClient(), cloud.ELBV2(),
120-
podENIResolver, nodeENIResolver, sgManager, sgReconciler, cloud.VpcID(), k8sClusterName, ctrl.Log)
105+
podENIResolver, nodeENIResolver, sgManager, sgReconciler, cloud.VpcID(), controllerConfig.ClusterName, ctrl.Log)
121106

122-
subnetResolver := networking.NewSubnetsResolver(cloud.EC2(), cloud.VpcID(), k8sClusterName, ctrl.Log.WithName("subnets-resolver"))
107+
subnetResolver := networking.NewSubnetsResolver(cloud.EC2(), cloud.VpcID(), controllerConfig.ClusterName, ctrl.Log.WithName("subnets-resolver"))
123108
ingGroupReconciler := ingress.NewGroupReconciler(cloud, mgr.GetClient(), mgr.GetEventRecorderFor("ingress"),
124-
sgManager, sgReconciler, k8sClusterName, subnetResolver,
109+
sgManager, sgReconciler, controllerConfig, subnetResolver,
125110
ctrl.Log.WithName("controllers").WithName("Ingress"))
126111
svcReconciler := service.NewServiceReconciler(cloud, mgr.GetClient(), mgr.GetEventRecorderFor("service"),
127-
sgManager, sgReconciler, k8sClusterName, subnetResolver,
112+
sgManager, sgReconciler, controllerConfig, subnetResolver,
128113
ctrl.Log.WithName("controllers").WithName("Service"))
129-
tgbReconciler := elbv2controller.NewTargetGroupBindingReconciler(mgr.GetClient(), finalizerManager, tgbResManager,
114+
tgbReconciler := elbv2controller.NewTargetGroupBindingReconciler(mgr.GetClient(), finalizerManager, tgbResManager, controllerConfig,
130115
ctrl.Log.WithName("controllers").WithName("TargetGroupBinding"))
131116

132117
ctx := context.Background()

pkg/aws/cloud.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func NewCloud(cfg CloudConfig, metricsRegisterer prometheus.Registerer) (Cloud,
7070
cfg.VpcID = vpcId
7171
}
7272

73-
awsCfg := aws.NewConfig().WithRegion(cfg.Region).WithSTSRegionalEndpoint(endpoints.RegionalSTSEndpoint)
73+
awsCfg := aws.NewConfig().WithRegion(cfg.Region).WithSTSRegionalEndpoint(endpoints.RegionalSTSEndpoint).WithMaxRetries(cfg.MaxRetries)
7474
sess = sess.Copy(awsCfg)
7575
return &defaultCloud{
7676
cfg: cfg,

pkg/aws/cloud_config.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,32 @@ import (
66
)
77

88
const (
9-
flagAWSRegion = "aws-region"
10-
flagAWSAPIThrottle = "aws-api-throttle"
11-
flagAWSVpcID = "aws-vpc-id"
9+
flagAWSRegion = "aws-region"
10+
flagAWSAPIThrottle = "aws-api-throttle"
11+
flagAWSVpcID = "aws-vpc-id"
12+
flagAWSMaxRetries = "aws-max-retries"
13+
defaultVpcID = ""
14+
defaultRegion = ""
15+
defaultAPIMaxRetries = 10
1216
)
1317

1418
type CloudConfig struct {
1519
// AWS Region for the kubernetes cluster
1620
Region string
1721

18-
// Throttle settings for aws APIs
22+
// Throttle settings for AWS APIs
1923
ThrottleConfig *throttle.ServiceOperationsThrottleConfig
2024

2125
// VPC ID of the Kubernetes cluster
2226
VpcID string
27+
28+
// Max retries configuration for AWS APIs
29+
MaxRetries int
2330
}
2431

2532
func (cfg *CloudConfig) BindFlags(fs *pflag.FlagSet) {
26-
fs.StringVar(&cfg.Region, flagAWSRegion, "", "AWS Region for the kubernetes cluster")
33+
fs.StringVar(&cfg.Region, flagAWSRegion, defaultRegion, "AWS Region for the kubernetes cluster")
2734
fs.Var(cfg.ThrottleConfig, flagAWSAPIThrottle, "throttle settings for AWS APIs, format: serviceID1:operationRegex1=rate:burst,serviceID2:operationRegex2=rate:burst")
28-
fs.StringVar(&cfg.VpcID, flagAWSVpcID, "", "AWS VPC ID for the Kubernetes cluster")
35+
fs.StringVar(&cfg.VpcID, flagAWSVpcID, defaultVpcID, "AWS VPC ID for the Kubernetes cluster")
36+
fs.IntVar(&cfg.MaxRetries, flagAWSMaxRetries, defaultAPIMaxRetries, "Maximum retries for AWS APIs")
2937
}

pkg/config/addons_config.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package config
2+
3+
import "github.com/spf13/pflag"
4+
5+
const (
6+
flagWAFEnabled = "enable-waf"
7+
flagWAFV2Enabled = "enable-wafv2"
8+
flagShieldEnabled = "enable-shield"
9+
defaultEnabled = true
10+
)
11+
12+
// AddonsConfig contains configuration for the addon features
13+
type AddonsConfig struct {
14+
// WAF addon for ALB
15+
WAFEnabled bool
16+
// WAFV2 addon for ALB
17+
WAFV2Enabled bool
18+
// Shield addon for ALB
19+
ShieldEnabled bool
20+
}
21+
22+
// BindFlags binds the command line flags to the fields in the config object
23+
func (f *AddonsConfig) BindFlags(fs *pflag.FlagSet) {
24+
fs.BoolVar(&f.WAFEnabled, flagWAFEnabled, defaultEnabled, "Enable WAF addon for ALB")
25+
fs.BoolVar(&f.WAFEnabled, flagWAFV2Enabled, defaultEnabled, "Enable WAF V2 addon for ALB")
26+
fs.BoolVar(&f.WAFEnabled, flagShieldEnabled, defaultEnabled, "Enable Shield addon for ALB")
27+
}

0 commit comments

Comments
 (0)