diff --git a/Dockerfile b/Dockerfile index 641dbc2..51a8861 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ ARG ARCH=amd64 FROM golang:1.16-alpine3.13 AS builder WORKDIR /src ADD . /src +RUN CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go get github.com/alexflint/go-arg RUN CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go build -ldflags='-s -w -extldflags "-static"' -o elector cmd/leader-elector/main.go FROM gcr.io/distroless/static:nonroot-${ARCH} diff --git a/README.md b/README.md index c598fe4..3f165af 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,15 @@ A simple leader election sidecar container for Kubernetes based on the recent [c ## Configuration Flags -* `election` - name of the election and the corresponding lock resource. -* `namespace` - the Kubernetes namespace to run the election in. -* `locktype` - the leaselock resource type to use for this deployment. Supported lock types are: +The following arguments can be passed on the command line, or by setting the environment variable named in brackets. + +* `election` - name of the election and the corresponding lock resource (ELECTION_NAME). +* `namespace` - the Kubernetes namespace to run the election in (ELECTION_NAMESPACE). +* `locktype` - the leaselock resource type to use for this deployment (ELECTION_TYPE). Supported lock types are: * `configmaps` - default * `leases` * `endpoints` -* `port` - the port on which the election sidecar can be queried. +* `port` - the port on which the election sidecar can be queried (ELECTION_PORT). ## Example A working example deployment can be found under `example/deployment.yaml` diff --git a/cmd/leader-elector/main.go b/cmd/leader-elector/main.go old mode 100644 new mode 100755 index 72e0f71..907d7e8 --- a/cmd/leader-elector/main.go +++ b/cmd/leader-elector/main.go @@ -3,26 +3,28 @@ package main import ( "context" "encoding/json" - "flag" "net/http" "os" "os/signal" "syscall" "time" + "github.com/alexflint/go-arg" "github.com/kkosmrli/leader-elector/pkg/election" "k8s.io/klog" ) var ( - electionName string - electionNamespace string - lockType string - renewDeadline time.Duration - retryPeriod time.Duration - leaseDuration time.Duration - port string - leader Leader + args struct { + LockName string `arg:"--election,env:ELECTION_NAME" default:"default" help:"Name of this election"` + Namespace string `arg:"env:ELECTION_NAMESPACE" default:"default" help:"Namespace of this election"` + LockType string `arg:"env:ELECTION_TYPE" default:"configmaps" help:"Resource lock type, must be one of the following: configmaps, endpoints, leases"` + RenewDeadline time.Duration `arg:"--renew-deadline,env:ELECTION_RENEW_DEADLINE" default:"10s" help:"Duration that the acting leader will retry refreshing leadership before giving up"` + RetryPeriod time.Duration `arg:"--retry-period,env:ELECTION_RETRY_PERIOD" default:"2s" help:"Duration between each action retry"` + LeaseDuration time.Duration `arg:"--lease-duration,env:ELECTION_LEASE_DURATION" default:"15s" help:"Duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot"` + Port string `arg:"env:ELECTION_PORT" default:"4040" help:"Port on which to query the leader"` + } + leader Leader ) // Leader contains the name of the current leader of this election @@ -40,23 +42,8 @@ func leaderHandler(res http.ResponseWriter, req *http.Request) { res.Write(data) } -func parseFlags() { - flag.StringVar(&electionName, "election", "default", "Name of the resource used for this election") - flag.StringVar(&electionNamespace, "namespace", "default", "Namespace of the resource used for this election") - flag.StringVar(&lockType, "locktype", "configmaps", - "Resource lock type, must be one of the following: configmaps, endpoints, leases") - flag.DurationVar(&renewDeadline, "renew-deadline", 10*time.Second, - "Duration that the acting leader will retry refreshing leadership before giving up") - flag.DurationVar(&leaseDuration, "lease-duration", 15*time.Second, - `Duration that non-leader candidates will wait after observing a leadership - renewal until attempting to acquire leadership of a led but unrenewed leader slot`) - flag.DurationVar(&retryPeriod, "retry-period", 2*time.Second, "Duration between each action retry") - flag.StringVar(&port, "port", "4040", "Port on which to query the leader") - flag.Parse() -} - func main() { - parseFlags() + arg.MustParse(&args) // configuring context ctx, cancel := context.WithCancel(context.Background()) @@ -73,7 +60,7 @@ func main() { // configuring HTTP server http.HandleFunc("/", leaderHandler) - server := &http.Server{Addr: ":" + port, Handler: nil} + server := &http.Server{Addr: ":" + args.Port, Handler: nil} go func() { if err := server.ListenAndServe(); err != nil { klog.Fatal(err) @@ -87,12 +74,12 @@ func main() { } electionConfig := election.Config{ - LockName: electionName, - LockNamespace: electionNamespace, - LockType: lockType, - RenewDeadline: renewDeadline, - RetryPeriod: retryPeriod, - LeaseDuration: leaseDuration, + LockName: args.LockName, + LockNamespace: args.Namespace, + LockType: args.LockType, + RenewDeadline: args.RenewDeadline, + RetryPeriod: args.RetryPeriod, + LeaseDuration: args.LeaseDuration, Callback: callback, } election.Run(ctx, electionConfig)