Skip to content

Commit 738e4a5

Browse files
osmmanmhutchinson
andauthored
Add kubernetes election module (#3721)
Introduce a new election module using the Kubernetes Lease API. Modify the existing mechanism to allow selection of election mechanisms by introducing the `--election_system` parameter, following the same pattern used for storage and quota system selection. --------- Co-authored-by: Martin Hutchinson <mhutchinson@gmail.com>
1 parent 545ac44 commit 738e4a5

File tree

18 files changed

+884
-43
lines changed

18 files changed

+884
-43
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## HEAD
44

5+
* Add `--election_system` parameter to allow selection of the election system by @osmman in https://github.com/google/trillian/pull/3721
6+
* Add Kubernetes-based leader election system by @osmman in https://github.com/google/trillian/pull/3721
7+
58
## v1.7.1
69

710
### Storage

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ Pierre Phaneuf <pphaneuf@google.com> <pphaneuf@gmail.com>
3737
Rob Percival <robpercival@google.com>
3838
Rob Stradling <rob@sectigo.com>
3939
Roger Ng <rogerng@google.com> <roger2hk@gmail.com>
40+
Tomas Turek <tturek@redhat.com>
4041
Vishal Kuo <vishalkuo@gmail.com>

cmd/internal/provider/default_systems.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import (
55

66
"github.com/google/trillian/quota"
77
"github.com/google/trillian/storage"
8+
"github.com/google/trillian/util/election2"
89
)
910

1011
var (
11-
DefaultQuotaSystem string
12-
DefaultStorageSystem string
12+
DefaultQuotaSystem string
13+
DefaultStorageSystem string
14+
DefaultElectionSystem string
1315
)
1416

1517
func init() {
@@ -27,4 +29,12 @@ func init() {
2729
defaultProvider = providers[0]
2830
}
2931
DefaultQuotaSystem = defaultProvider
32+
33+
defaultProvider = "etcd"
34+
providers = election2.Providers()
35+
if len(providers) > 0 && !slices.Contains(providers, defaultProvider) {
36+
slices.Sort(providers)
37+
defaultProvider = providers[0]
38+
}
39+
DefaultElectionSystem = defaultProvider
3040
}

cmd/internal/provider/etcd.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//go:build etcd || !k8s
2+
3+
package provider
4+
5+
import (
6+
_ "github.com/google/trillian/util/election2/etcd"
7+
)

cmd/internal/provider/k8s.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//go:build k8s || !etcd
2+
3+
package provider
4+
5+
import (
6+
_ "github.com/google/trillian/util/election2/k8s"
7+
)

cmd/trillian_log_signer/main.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ import (
4646
"github.com/google/trillian/util/clock"
4747
"github.com/google/trillian/util/election"
4848
"github.com/google/trillian/util/election2"
49-
etcdelect "github.com/google/trillian/util/election2/etcd"
5049
clientv3 "go.etcd.io/etcd/client/v3"
5150
"google.golang.org/grpc"
5251
"k8s.io/klog/v2"
@@ -66,7 +65,6 @@ var (
6665
sequencerGuardWindowFlag = flag.Duration("sequencer_guard_window", 0, "If set, the time elapsed before submitted leaves are eligible for sequencing")
6766
forceMaster = flag.Bool("force_master", false, "If true, assume master for all logs")
6867
etcdHTTPService = flag.String("etcd_http_service", "trillian-logsigner-http", "Service name to announce our HTTP endpoint under")
69-
lockDir = flag.String("lock_file_path", "/test/multimaster", "etcd lock file directory path")
7068
healthzTimeout = flag.Duration("healthz_timeout", time.Second*5, "Timeout used during healthz checks")
7169

7270
quotaSystem = flag.String("quota_system", provider.DefaultQuotaSystem, fmt.Sprintf("Quota system to use. One of: %v", quota.Providers()))
@@ -76,6 +74,7 @@ var (
7674

7775
storageSystem = flag.String("storage_system", provider.DefaultStorageSystem, fmt.Sprintf("Storage system to use. One of: %v", storage.Providers()))
7876

77+
electionSystem = flag.String("election_system", provider.DefaultElectionSystem, fmt.Sprintf("Election system to use. One of: %v", election2.Providers()))
7978
preElectionPause = flag.Duration("pre_election_pause", 1*time.Second, "Maximum time to wait before starting elections")
8079
masterHoldInterval = flag.Duration("master_hold_interval", 60*time.Second, "Minimum interval to hold mastership for")
8180
masterHoldJitter = flag.Duration("master_hold_jitter", 120*time.Second, "Maximal random addition to --master_hold_interval")
@@ -133,17 +132,16 @@ func main() {
133132
defer cancel()
134133
go util.AwaitSignal(ctx, cancel)
135134

136-
hostname, _ := os.Hostname()
137-
instanceID := fmt.Sprintf("%s.%d", hostname, os.Getpid())
138135
var electionFactory election2.Factory
139136
switch {
140137
case *forceMaster:
141138
klog.Warning("**** Acting as master for all logs ****")
142139
electionFactory = election2.NoopFactory{}
143-
case client != nil:
144-
electionFactory = etcdelect.NewFactory(instanceID, client, *lockDir)
145140
default:
146-
klog.Exit("Either --force_master or --etcd_servers must be supplied")
141+
electionFactory, err = election2.NewProvider(*electionSystem)
142+
if err != nil {
143+
klog.Exitf("Failed to get election provider: %v", err)
144+
}
147145
}
148146

149147
qm, err := quota.NewManager(*quotaSystem)

docs/Feature_Implementation_Matrix.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ Supported monitoring frameworks, allowing for production monitoring and alerting
109109

110110
Supported frameworks for providing Master Election.
111111

112-
| Election | Status | Deployed in prod | Notes |
113-
|:--- | :---: | :---: |:--- |
114-
| Chubby | GA || Google internal-only. |
115-
| etcd | GA || |
112+
| Election | Status | Deployed in prod | Notes |
113+
|:---------|:------:|:----------------:|:---------------------------------------------------------------------------------------|
114+
| Chubby | GA || Google internal-only. |
115+
| etcd | GA || |
116+
| k8s | Alpha | | Supported by [Tomas Turek](https://github.com/osmman) at [Red Hat](https://redhat.com) |
116117

117118
### Quota
118119

go.mod

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ require (
4343
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
4444
google.golang.org/protobuf v1.36.3
4545
gopkg.in/yaml.v2 v2.4.0
46+
k8s.io/api v0.31.5
47+
k8s.io/apimachinery v0.31.5
48+
k8s.io/client-go v0.31.5
4649
k8s.io/klog/v2 v2.130.1
50+
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
4751
)
4852

4953
require (
@@ -85,16 +89,23 @@ require (
8589
github.com/docker/go-connections v0.5.0 // indirect
8690
github.com/docker/go-units v0.5.0 // indirect
8791
github.com/dustin/go-humanize v1.0.1 // indirect
92+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
8893
github.com/envoyproxy/go-control-plane v0.13.1 // indirect
8994
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
9095
github.com/felixge/httpsnoop v1.0.4 // indirect
96+
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
9197
github.com/go-logr/logr v1.4.2 // indirect
9298
github.com/go-logr/stdr v1.2.2 // indirect
99+
github.com/go-openapi/jsonpointer v0.20.2 // indirect
100+
github.com/go-openapi/jsonreference v0.20.4 // indirect
101+
github.com/go-openapi/swag v0.22.9 // indirect
93102
github.com/gofrs/flock v0.8.1 // indirect
94103
github.com/gogo/protobuf v1.3.2 // indirect
95104
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
96105
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
97106
github.com/golang/protobuf v1.5.4 // indirect
107+
github.com/google/gnostic-models v0.6.8 // indirect
108+
github.com/google/gofuzz v1.2.0 // indirect
98109
github.com/google/licenseclassifier/v2 v2.0.0 // indirect
99110
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
100111
github.com/google/s2a-go v0.1.9 // indirect
@@ -120,8 +131,10 @@ require (
120131
github.com/jhump/protoreflect v1.16.0 // indirect
121132
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 // indirect
122133
github.com/jonboulle/clockwork v0.4.0 // indirect
134+
github.com/josharian/intern v1.0.0 // indirect
123135
github.com/json-iterator/go v1.1.12 // indirect
124136
github.com/klauspost/compress v1.17.11 // indirect
137+
github.com/mailru/easyjson v0.7.7 // indirect
125138
github.com/mattn/go-runewidth v0.0.13 // indirect
126139
github.com/miekg/pkcs11 v1.1.1 // indirect
127140
github.com/mitchellh/copystructure v1.0.0 // indirect
@@ -152,6 +165,7 @@ require (
152165
github.com/spf13/pflag v1.0.5 // indirect
153166
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect
154167
github.com/urfave/cli v1.22.14 // indirect
168+
github.com/x448/float16 v0.8.4 // indirect
155169
github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 // indirect
156170
go.etcd.io/bbolt v1.3.11 // indirect
157171
go.etcd.io/etcd/api/v3 v3.5.17 // indirect
@@ -178,10 +192,16 @@ require (
178192
golang.org/x/mod v0.22.0 // indirect
179193
golang.org/x/net v0.34.0 // indirect
180194
golang.org/x/oauth2 v0.25.0 // indirect
195+
golang.org/x/term v0.28.0 // indirect
181196
golang.org/x/text v0.21.0 // indirect
182197
golang.org/x/time v0.9.0 // indirect
183198
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
199+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
200+
gopkg.in/inf.v0 v0.9.1 // indirect
184201
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
185202
gopkg.in/yaml.v3 v3.0.1 // indirect
203+
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
204+
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
205+
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
186206
sigs.k8s.io/yaml v1.4.0 // indirect
187207
)

0 commit comments

Comments
 (0)