Skip to content

Commit

Permalink
Ansible: add leader election flags, use lease-based election (#3457)
Browse files Browse the repository at this point in the history
* Ansible: add leader election flags, use lease-based election
* enable leader election by default
  • Loading branch information
jmrodri committed Jul 22, 2020
1 parent b021bec commit 1190181
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 18 deletions.
9 changes: 9 additions & 0 deletions changelog/fragments/ansible-leader-election.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# entries is a list of entries to include in
# release notes and/or the migration guide
entries:
- description: >
In the Ansible operator, use controller-runtime's lease-based leader
election instead of SDK's leader-for-life mechnism.
kind: "change"
breaking: false
34 changes: 17 additions & 17 deletions cmd/ansible-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package main

import (
"context"
"fmt"
"os"
"runtime"
Expand All @@ -40,7 +39,6 @@ import (
"github.com/operator-framework/operator-sdk/pkg/ansible/proxy/controllermap"
"github.com/operator-framework/operator-sdk/pkg/ansible/runner"
"github.com/operator-framework/operator-sdk/pkg/ansible/watches"
"github.com/operator-framework/operator-sdk/pkg/leader"
"github.com/operator-framework/operator-sdk/pkg/log/zap"
sdkVersion "github.com/operator-framework/operator-sdk/version"
)
Expand Down Expand Up @@ -71,11 +69,26 @@ func main() {
os.Exit(1)
}

// Deprecated: OPERATOR_NAME environment variable is an artifact of the
// legacy operator-sdk project scaffolding. Flag `--leader-election-id`
// should be used instead.
if operatorName, found := os.LookupEnv("OPERATOR_NAME"); found {
log.Info("Environment variable OPERATOR_NAME has been deprecated, use --leader-election-id instead.")
if pflag.CommandLine.Lookup("leader-election-id").Changed {
log.Info("Ignoring OPERATOR_NAME environment variable since --leader-election-id is set")
} else {
f.LeaderElectionID = operatorName
}
}

// Set default manager options
// TODO: probably should expose the host & port as an environment variables
options := manager.Options{
HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort),
MetricsBindAddress: f.MetricsAddress,
HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort),
MetricsBindAddress: f.MetricsAddress,
LeaderElection: f.EnableLeaderElection,
LeaderElectionID: f.LeaderElectionID,
LeaderElectionNamespace: f.LeaderElectionNamespace,
NewClient: func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
c, err := client.New(config, options)
if err != nil {
Expand Down Expand Up @@ -152,19 +165,6 @@ func main() {
}, w.Blacklist)
}

operatorName, err := k8sutil.GetOperatorName()
if err != nil {
log.Error(err, "Failed to get the operator name")
os.Exit(1)
}

// Become the leader before proceeding
err = leader.Become(context.TODO(), operatorName+"-lock")
if err != nil {
log.Error(err, "Failed to become leader.")
os.Exit(1)
}

err = mgr.AddHealthzCheck("ping", healthz.Ping)
if err != nil {
log.Error(err, "Failed to add Healthz check.")
Expand Down
3 changes: 3 additions & 0 deletions internal/scaffold/ansible/deploy_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ spec:
- name: [[.ProjectName]]
# Replace this with the built image name
image: "REPLACE_IMAGE"
args:
- "--enable-leader-election"
- "--leader-election-id=[[.ProjectName]]"
imagePullPolicy: "Always"
volumeMounts:
- mountPath: /tmp/ansible-operator/runner
Expand Down
22 changes: 21 additions & 1 deletion pkg/ansible/flags/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ type Flags struct {
ReconcilePeriod time.Duration
WatchesFile string
InjectOwnerRef bool
EnableLeaderElection bool
MaxConcurrentReconciles int
AnsibleVerbosity int
AnsibleRolesPath string
AnsibleCollectionsPath string
MetricsAddress string
LeaderElectionID string
LeaderElectionNamespace string
}

const AnsibleRolesPathEnvVar = "ANSIBLE_ROLES_PATH"
Expand Down Expand Up @@ -81,5 +84,22 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) {
":8080",
"The address the metric endpoint binds to",
)

flagSet.BoolVar(&f.EnableLeaderElection,
"enable-leader-election",
false,
"Enable leader election for controller manager. Enabling this will"+
" ensure there is only one active controller manager.",
)
flagSet.StringVar(&f.LeaderElectionID,
"leader-election-id",
"",
"Name of the configmap that is used for holding the leader lock.",
)
flagSet.StringVar(&f.LeaderElectionNamespace,
"leader-election-namespace",
"",
"Namespace in which to create the leader election configmap for"+
" holding the leader lock (required if running locally with leader"+
" election enabled).",
)
}

0 comments on commit 1190181

Please sign in to comment.