Skip to content

Commit 1343015

Browse files
authored
add support for version & adjust flags (kubernetes-sigs#1506)
* code adjustments * make the error logging concise
1 parent 4db6e2f commit 1343015

File tree

8 files changed

+188
-83
lines changed

8 files changed

+188
-83
lines changed

Dockerfile

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ RUN GOPROXY=direct go mod download
1212
FROM base AS build
1313
ARG TARGETOS
1414
ARG TARGETARCH
15+
ENV VERSION_PKG=sigs.k8s.io/aws-load-balancer-controller/pkg/version
1516
RUN --mount=type=bind,target=. \
1617
--mount=type=cache,target=/root/.cache/go-build \
18+
GIT_VERSION=$(git describe --tags --dirty --always) && \
19+
GIT_COMMIT=$(git rev-parse HEAD) && \
20+
BUILD_DATE=$(date +%Y-%m-%dT%H:%M:%S%z) && \
1721
GOOS=${TARGETOS} GOARCH=${TARGETARCH} GO111MODULE=on \
1822
CGO_CPPFLAGS="-D_FORTIFY_SOURCE=2" \
1923
CGO_LDFLAGS="-Wl,-z,relro,-z,now" \
20-
go build -ldflags="-s -w" -buildmode=pie -a -o /out/controller main.go
24+
go build -ldflags="-s -w -X ${VERSION_PKG}.GitVersion=${GIT_VERSION} -X ${VERSION_PKG}.GitCommit=${GIT_COMMIT} -X ${VERSION_PKG}.BuildDate=${BUILD_DATE}" -buildmode=pie -a -o /out/controller main.go
2125

2226
FROM amazonlinux:2 as bin-unix
2327
COPY --from=build /out/controller /controller

controllers/elbv2/targetgroupbinding_controller.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func NewTargetGroupBindingReconciler(k8sClient client.Client, finalizerManager k
5050
tgbResourceManager: tgbResourceManager,
5151
logger: logger,
5252

53-
maxConcurrentReconciles: config.TargetgroupBindingMaxConcurrentReconciles,
53+
maxConcurrentReconciles: config.TargetGroupBindingMaxConcurrentReconciles,
5454
}
5555
}
5656

main.go

+67-36
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
"context"
2121
"github.com/spf13/pflag"
2222
zapraw "go.uber.org/zap"
23-
"k8s.io/apimachinery/pkg/runtime"
23+
k8sruntime "k8s.io/apimachinery/pkg/runtime"
2424
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
2525
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
2626
"os"
@@ -31,10 +31,12 @@ import (
3131
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws"
3232
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws/throttle"
3333
"sigs.k8s.io/aws-load-balancer-controller/pkg/config"
34-
inject "sigs.k8s.io/aws-load-balancer-controller/pkg/inject"
34+
"sigs.k8s.io/aws-load-balancer-controller/pkg/inject"
3535
"sigs.k8s.io/aws-load-balancer-controller/pkg/k8s"
3636
"sigs.k8s.io/aws-load-balancer-controller/pkg/networking"
37+
"sigs.k8s.io/aws-load-balancer-controller/pkg/runtime"
3738
"sigs.k8s.io/aws-load-balancer-controller/pkg/targetgroupbinding"
39+
"sigs.k8s.io/aws-load-balancer-controller/pkg/version"
3840
corewebhook "sigs.k8s.io/aws-load-balancer-controller/webhooks/core"
3941
elbv2webhook "sigs.k8s.io/aws-load-balancer-controller/webhooks/elbv2"
4042
ctrl "sigs.k8s.io/controller-runtime"
@@ -44,7 +46,7 @@ import (
4446
)
4547

4648
var (
47-
scheme = runtime.NewScheme()
49+
scheme = k8sruntime.NewScheme()
4850
setupLog = ctrl.Log.WithName("setup")
4951
)
5052

@@ -56,41 +58,31 @@ func init() {
5658
}
5759

5860
func main() {
59-
awsCloudConfig := aws.CloudConfig{ThrottleConfig: throttle.NewDefaultServiceOperationsThrottleConfig()}
60-
injectConfig := inject.Config{}
61-
controllerConfig := config.ControllerConfig{}
62-
63-
fs := pflag.NewFlagSet("", pflag.ExitOnError)
64-
awsCloudConfig.BindFlags(fs)
65-
injectConfig.BindFlags(fs)
66-
controllerConfig.BindFlags(fs)
67-
68-
if err := fs.Parse(os.Args); err != nil {
69-
setupLog.Error(err, "invalid flags")
70-
os.Exit(1)
71-
}
72-
if err := controllerConfig.Validate(); err != nil {
73-
setupLog.Error(err, "Failed to validate controller configuration")
61+
setLogLevel("info")
62+
setupLog.Info("version",
63+
"GitVersion", version.GitVersion,
64+
"GitCommit", version.GitCommit,
65+
"BuildDate", version.BuildDate,
66+
)
67+
controllerCFG, err := loadControllerConfig()
68+
if err != nil {
69+
setupLog.Error(err, "unable to load controller config")
7470
os.Exit(1)
7571
}
72+
setLogLevel(controllerCFG.LogLevel)
7673

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-
83-
cloud, err := aws.NewCloud(awsCloudConfig, metrics.Registry)
74+
cloud, err := aws.NewCloud(controllerCFG.AWSConfig, metrics.Registry)
8475
if err != nil {
85-
setupLog.Error(err, "Unable to initialize AWS cloud")
76+
setupLog.Error(err, "unable to initialize AWS cloud")
8677
os.Exit(1)
8778
}
88-
restCfg, err := config.BuildRestConfig(controllerConfig.RuntimeConfig)
89-
rtOpts := config.BuildRuntimeOptions(controllerConfig.RuntimeConfig, scheme)
79+
restCFG, err := config.BuildRestConfig(controllerCFG.RuntimeConfig)
9080
if err != nil {
91-
setupLog.Error(err, "Unable to build REST config")
81+
setupLog.Error(err, "unable to build REST config")
82+
os.Exit(1)
9283
}
93-
mgr, err := ctrl.NewManager(restCfg, rtOpts)
84+
rtOpts := config.BuildRuntimeOptions(controllerCFG.RuntimeConfig, scheme)
85+
mgr, err := ctrl.NewManager(restCFG, rtOpts)
9486
if err != nil {
9587
setupLog.Error(err, "unable to start manager")
9688
os.Exit(1)
@@ -101,18 +93,18 @@ func main() {
10193
nodeENIResolver := networking.NewDefaultNodeENIInfoResolver(cloud.EC2(), ctrl.Log)
10294
sgManager := networking.NewDefaultSecurityGroupManager(cloud.EC2(), ctrl.Log)
10395
sgReconciler := networking.NewDefaultSecurityGroupReconciler(sgManager, ctrl.Log)
104-
subnetResolver := networking.NewSubnetsResolver(cloud.EC2(), cloud.VpcID(), controllerConfig.ClusterName, ctrl.Log.WithName("subnets-resolver"))
96+
subnetResolver := networking.NewSubnetsResolver(cloud.EC2(), cloud.VpcID(), controllerCFG.ClusterName, ctrl.Log.WithName("subnets-resolver"))
10597
tgbResManager := targetgroupbinding.NewDefaultResourceManager(mgr.GetClient(), cloud.ELBV2(),
106-
podENIResolver, nodeENIResolver, sgManager, sgReconciler, cloud.VpcID(), controllerConfig.ClusterName, ctrl.Log)
98+
podENIResolver, nodeENIResolver, sgManager, sgReconciler, cloud.VpcID(), controllerCFG.ClusterName, ctrl.Log)
10799

108100
ingGroupReconciler := ingress.NewGroupReconciler(cloud, mgr.GetClient(), mgr.GetEventRecorderFor("ingress"),
109101
finalizerManager, sgManager, sgReconciler, subnetResolver,
110-
controllerConfig, ctrl.Log.WithName("controllers").WithName("ingress"))
102+
controllerCFG, ctrl.Log.WithName("controllers").WithName("ingress"))
111103
svcReconciler := service.NewServiceReconciler(cloud, mgr.GetClient(), mgr.GetEventRecorderFor("service"),
112104
finalizerManager, sgManager, sgReconciler, subnetResolver,
113-
controllerConfig, ctrl.Log.WithName("controllers").WithName("service"))
105+
controllerCFG, ctrl.Log.WithName("controllers").WithName("service"))
114106
tgbReconciler := elbv2controller.NewTargetGroupBindingReconciler(mgr.GetClient(), finalizerManager, tgbResManager,
115-
controllerConfig, ctrl.Log.WithName("controllers").WithName("targetGroupBinding"))
107+
controllerCFG, ctrl.Log.WithName("controllers").WithName("targetGroupBinding"))
116108
ctx := context.Background()
117109
if err = ingGroupReconciler.SetupWithManager(ctx, mgr); err != nil {
118110
setupLog.Error(err, "unable to create controller", "controller", "Ingress")
@@ -127,7 +119,8 @@ func main() {
127119
os.Exit(1)
128120
}
129121

130-
podReadinessGateInjector := inject.NewPodReadinessGate(injectConfig, mgr.GetClient(), ctrl.Log.WithName("pod-readiness-gate-injector"))
122+
podReadinessGateInjector := inject.NewPodReadinessGate(controllerCFG.PodWebhookConfig,
123+
mgr.GetClient(), ctrl.Log.WithName("pod-readiness-gate-injector"))
131124
corewebhook.NewPodMutator(podReadinessGateInjector).SetupWithManager(mgr)
132125
elbv2webhook.NewTargetGroupBindingMutator(cloud.ELBV2(), ctrl.Log).SetupWithManager(mgr)
133126
elbv2webhook.NewTargetGroupBindingValidator(ctrl.Log).SetupWithManager(mgr)
@@ -139,3 +132,41 @@ func main() {
139132
os.Exit(1)
140133
}
141134
}
135+
136+
// loadControllerConfig loads the controller configuration.
137+
func loadControllerConfig() (config.ControllerConfig, error) {
138+
defaultAWSThrottleCFG := throttle.NewDefaultServiceOperationsThrottleConfig()
139+
controllerCFG := config.ControllerConfig{
140+
AWSConfig: aws.CloudConfig{ThrottleConfig: defaultAWSThrottleCFG},
141+
}
142+
143+
fs := pflag.NewFlagSet("", pflag.ExitOnError)
144+
controllerCFG.BindFlags(fs)
145+
146+
if err := fs.Parse(os.Args); err != nil {
147+
return config.ControllerConfig{}, err
148+
}
149+
150+
if err := controllerCFG.Validate(); err != nil {
151+
return config.ControllerConfig{}, err
152+
}
153+
return controllerCFG, nil
154+
}
155+
156+
// setLogLevel sets the log level of controller.
157+
func setLogLevel(logLevel string) {
158+
var zapLevel zapraw.AtomicLevel
159+
switch logLevel {
160+
case "info":
161+
zapLevel = zapraw.NewAtomicLevelAt(zapraw.InfoLevel)
162+
case "debug":
163+
zapLevel = zapraw.NewAtomicLevelAt(zapraw.DebugLevel)
164+
default:
165+
zapLevel = zapraw.NewAtomicLevelAt(zapraw.DebugLevel)
166+
}
167+
168+
logger := zap.New(zap.UseDevMode(false),
169+
zap.Level(zapLevel),
170+
zap.StacktraceLevel(zapraw.NewAtomicLevelAt(zapraw.FatalLevel)))
171+
ctrl.SetLogger(runtime.NewConciseLogger(logger))
172+
}

pkg/config/controller_config.go

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package config
22

33
import (
4-
"fmt"
4+
"github.com/pkg/errors"
55
"github.com/spf13/pflag"
6+
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws"
7+
"sigs.k8s.io/aws-load-balancer-controller/pkg/inject"
68
)
79

810
const (
911
flagLogLevel = "log-level"
1012
flagK8sClusterName = "cluster-name"
1113
flagServiceMaxConcurrentReconciles = "service-max-concurrent-reconciles"
12-
flagTargetgroupBindingMaxConcurrentReconciles = "targetgroupbinding-max-concurrent-reconciles"
14+
flagTargetGroupBindingMaxConcurrentReconciles = "targetgroupbinding-max-concurrent-reconciles"
1315
defaultLogLevel = "info"
1416
defaultMaxConcurrentReconciles = 3
1517
)
@@ -20,16 +22,21 @@ type ControllerConfig struct {
2022
LogLevel string
2123
// Name of the Kubernetes cluster
2224
ClusterName string
25+
// Configurations for AWS.
26+
AWSConfig aws.CloudConfig
27+
// Configurations for the Controller Runtime
28+
RuntimeConfig RuntimeConfig
29+
// Configurations for Pod inject webhook
30+
PodWebhookConfig inject.Config
2331
// Configurations for the Ingress controller
2432
IngressConfig IngressConfig
2533
// Configurations for Addons feature
2634
AddonsConfig AddonsConfig
27-
// Configurations for the Controller Runtime
28-
RuntimeConfig RuntimeConfig
35+
2936
// Max concurrent reconcile loops for Service objects
3037
ServiceMaxConcurrentReconciles int
3138
// Max concurrent reconcile loops for TargetGroupBinding objects
32-
TargetgroupBindingMaxConcurrentReconciles int
39+
TargetGroupBindingMaxConcurrentReconciles int
3340
}
3441

3542
// BindFlags binds the command line flags to the fields in the config object
@@ -39,18 +46,21 @@ func (cfg *ControllerConfig) BindFlags(fs *pflag.FlagSet) {
3946
fs.StringVar(&cfg.ClusterName, flagK8sClusterName, "", "Kubernetes cluster name")
4047
fs.IntVar(&cfg.ServiceMaxConcurrentReconciles, flagServiceMaxConcurrentReconciles, defaultMaxConcurrentReconciles,
4148
"Maximum number of concurrently running reconcile loops for service")
42-
fs.IntVar(&cfg.TargetgroupBindingMaxConcurrentReconciles, flagTargetgroupBindingMaxConcurrentReconciles, defaultMaxConcurrentReconciles,
43-
"Maximum number of concurrently running reconcile loops for targetgroup binding")
49+
fs.IntVar(&cfg.TargetGroupBindingMaxConcurrentReconciles, flagTargetGroupBindingMaxConcurrentReconciles, defaultMaxConcurrentReconciles,
50+
"Maximum number of concurrently running reconcile loops for targetGroupBinding")
51+
52+
cfg.AWSConfig.BindFlags(fs)
53+
cfg.RuntimeConfig.BindFlags(fs)
4454

55+
cfg.PodWebhookConfig.BindFlags(fs)
4556
cfg.IngressConfig.BindFlags(fs)
4657
cfg.AddonsConfig.BindFlags(fs)
47-
cfg.RuntimeConfig.BindFlags(fs)
4858
}
4959

5060
// Validate the controller configuration
5161
func (cfg *ControllerConfig) Validate() error {
5262
if len(cfg.ClusterName) == 0 {
53-
return fmt.Errorf("Kubernetes cluster name must be specified")
63+
return errors.New("kubernetes cluster name must be specified")
5464
}
5565
return nil
5666
}

pkg/config/runtime_config.go

+12-21
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"k8s.io/apimachinery/pkg/runtime"
77
"k8s.io/client-go/rest"
88
"k8s.io/client-go/tools/clientcmd"
9-
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
109
ctrl "sigs.k8s.io/controller-runtime"
1110
"time"
1211
)
@@ -19,10 +18,8 @@ const (
1918
flagLeaderElectionNamespace = "leader-election-namespace"
2019
flagWatchNamespace = "watch-namespace"
2120
flagSyncPeriod = "sync-period"
22-
flagMaster = "master"
2321
flagKubeconfig = "kubeconfig"
2422

25-
defaultMaster = ""
2623
defaultKubeconfig = ""
2724
defaultLeaderElectionID = "aws-load-balancer-controller-leader"
2825
defaultLeaderElectionNamespace = ""
@@ -53,8 +50,6 @@ type RuntimeConfig struct {
5350

5451
// BindFlags binds the command line flags to the fields in the config object
5552
func (c *RuntimeConfig) BindFlags(fs *pflag.FlagSet) {
56-
fs.StringVar(&c.APIServer, flagMaster, defaultMaster,
57-
"The address of the Kubernetes API server.")
5853
fs.StringVar(&c.KubeConfig, flagKubeconfig, defaultKubeconfig,
5954
"Path to the kubeconfig file containing authorization and API server information.")
6055
fs.StringVar(&c.MetricsBindAddress, flagMetricsBindAddr, defaultMetricsAddr,
@@ -74,27 +69,23 @@ func (c *RuntimeConfig) BindFlags(fs *pflag.FlagSet) {
7469
"Period at which the controller forces the repopulation of its local object stores.")
7570
}
7671

77-
func buildRestConfig(masterURL, kubeconfigPath string) (*rest.Config, error) {
78-
if kubeconfigPath == "" && masterURL == "" {
79-
kubeconfig, err := rest.InClusterConfig()
80-
if err == nil {
81-
return kubeconfig, nil
82-
}
83-
}
84-
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
85-
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
86-
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterURL}}).ClientConfig()
87-
}
88-
8972
// BuildRestConfig builds the REST config for the controller runtime
9073
func BuildRestConfig(rtCfg RuntimeConfig) (*rest.Config, error) {
91-
restCfg, err := buildRestConfig(rtCfg.APIServer, rtCfg.KubeConfig)
74+
var restCFG *rest.Config
75+
var err error
76+
if rtCfg.KubeConfig == "" {
77+
restCFG, err = rest.InClusterConfig()
78+
} else {
79+
restCFG, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
80+
&clientcmd.ClientConfigLoadingRules{ExplicitPath: rtCfg.KubeConfig}, &clientcmd.ConfigOverrides{}).ClientConfig()
81+
}
9282
if err != nil {
9383
return nil, err
9484
}
95-
restCfg.QPS = defaultQPS
96-
restCfg.Burst = defaultBurst
97-
return restCfg, nil
85+
86+
restCFG.QPS = defaultQPS
87+
restCFG.Burst = defaultBurst
88+
return restCFG, nil
9889
}
9990

10091
// BuildRuntimeOptions builds the options for the controller runtime based on config

pkg/runtime/concise_logger.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package runtime
2+
3+
import "github.com/go-logr/logr"
4+
5+
// NewConciseLogger constructs new conciseLogger
6+
func NewConciseLogger(logger logr.Logger) *conciseLogger {
7+
return &conciseLogger{
8+
Logger: logger,
9+
}
10+
}
11+
12+
var _ logr.Logger = &conciseLogger{}
13+
14+
// conciseLogger will log concise Error messages.
15+
// We have used github.com/pkg/errors extensively, when logged with zap logger, a full stacktrace is logged but it's usually unhelpful due to go routine usage.
16+
// this conciseLogger will wrap the error inside a conciseError, so that only necessary error message is logged.
17+
type conciseLogger struct {
18+
logr.Logger
19+
}
20+
21+
func (r *conciseLogger) Error(err error, msg string, keysAndValues ...interface{}) {
22+
r.Logger.Error(&conciseError{err: err}, msg, keysAndValues...)
23+
}
24+
25+
func (r *conciseLogger) WithValues(keysAndValues ...interface{}) logr.Logger {
26+
return NewConciseLogger(r.Logger.WithValues(keysAndValues...))
27+
}
28+
29+
func (r *conciseLogger) WithName(name string) logr.Logger {
30+
return NewConciseLogger(r.Logger.WithName(name))
31+
}
32+
33+
var _ error = &conciseError{}
34+
35+
// conciseError will only contain concise error message.
36+
type conciseError struct {
37+
err error
38+
}
39+
40+
func (e *conciseError) Error() string {
41+
return e.err.Error()
42+
}

0 commit comments

Comments
 (0)