Skip to content

Commit

Permalink
Merge pull request #13635 from ahrtr/v3_discovery
Browse files Browse the repository at this point in the history
support v3 discovery to bootstrap a new etcd cluster
  • Loading branch information
serathius committed Feb 21, 2022
2 parents f80f477 + ebc86d1 commit b5e224d
Show file tree
Hide file tree
Showing 13 changed files with 1,618 additions and 25 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG/CHANGELOG-3.6.md
Expand Up @@ -12,6 +12,10 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0).

- `etcd` will no longer start on data dir created by newer versions (for example etcd v3.6 will not run on v3.7+ data dir). To downgrade data dir please check out `etcdutl migrate` command.

### Deprecations

- Deprecated [V2 discovery](https://etcd.io/docs/v3.5/dev-internal/discovery_protocol/).

### etcdctl v3

- Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133).
Expand Down Expand Up @@ -40,6 +44,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0).
- Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to handle upgrade from v3.5.2 clusters with this feature enabled.
- Add [`etcdctl make-mirror --rev`](https://github.com/etcd-io/etcd/pull/13519) flag to support incremental mirror.
- Add [`etcd --experimental-wait-cluster-ready-timeout`](https://github.com/etcd-io/etcd/pull/13525) flag to wait for cluster to be ready before serving client requests.
- Add [v3 discovery](https://github.com/etcd-io/etcd/pull/13635) to bootstrap a new etcd cluster.
- Fix [non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/13435)
- Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13467).
- Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13399)
Expand Down
17 changes: 11 additions & 6 deletions server/config/config.go
Expand Up @@ -25,6 +25,7 @@ import (
"go.etcd.io/etcd/client/pkg/v3/transport"
"go.etcd.io/etcd/client/pkg/v3/types"
"go.etcd.io/etcd/pkg/v3/netutil"
"go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery"
"go.etcd.io/etcd/server/v3/storage/datadir"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"

Expand All @@ -34,12 +35,16 @@ import (

// ServerConfig holds the configuration of etcd as taken from the command line or discovery.
type ServerConfig struct {
Name string
DiscoveryURL string
DiscoveryProxy string
ClientURLs types.URLs
PeerURLs types.URLs
DataDir string
Name string

EnableV2Discovery bool
DiscoveryURL string
DiscoveryProxy string
DiscoveryCfg v3discovery.DiscoveryConfig

ClientURLs types.URLs
PeerURLs types.URLs
DataDir string
// DedicatedWALDir config will make the etcd to write the WAL to the WALDir
// rather than the dataDir/member/wal.
DedicatedWALDir string
Expand Down
47 changes: 42 additions & 5 deletions server/embed/config.go
Expand Up @@ -15,6 +15,7 @@
package embed

import (
"errors"
"fmt"
"net"
"net/http"
Expand All @@ -36,6 +37,7 @@ import (
"go.etcd.io/etcd/server/v3/etcdserver"
"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
"go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor"
"go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery"

bolt "go.etcd.io/bbolt"
"go.uber.org/multierr"
Expand All @@ -62,6 +64,11 @@ const (
DefaultDowngradeCheckTime = 5 * time.Second
DefaultWaitClusterReadyTimeout = 5 * time.Second

DefaultDiscoveryDialTimeout = 2 * time.Second
DefaultDiscoveryRequestTimeOut = 5 * time.Second
DefaultDiscoveryKeepAliveTime = 2 * time.Second
DefaultDiscoveryKeepAliveTimeOut = 6 * time.Second

DefaultListenPeerURLs = "http://localhost:2380"
DefaultListenClientURLs = "http://localhost:2379"

Expand All @@ -88,6 +95,8 @@ const (
// It's enabled by default.
DefaultStrictReconfigCheck = true

DefaultEnableV2Discovery = true

// maxElectionMs specifies the maximum value of election timeout.
// More details are listed in ../Documentation/tuning.md#time-parameters.
maxElectionMs = 50000
Expand Down Expand Up @@ -213,11 +222,15 @@ type Config struct {
// Note that cipher suites are prioritized in the given order.
CipherSuites []string `json:"cipher-suites"`

ClusterState string `json:"initial-cluster-state"`
DNSCluster string `json:"discovery-srv"`
DNSClusterServiceName string `json:"discovery-srv-name"`
Dproxy string `json:"discovery-proxy"`
Durl string `json:"discovery"`
ClusterState string `json:"initial-cluster-state"`
DNSCluster string `json:"discovery-srv"`
DNSClusterServiceName string `json:"discovery-srv-name"`
Dproxy string `json:"discovery-proxy"`

EnableV2Discovery bool `json:"enable-v2-discovery"`
Durl string `json:"discovery"`
DiscoveryCfg v3discovery.DiscoveryConfig `json:"discovery-config"`

InitialCluster string `json:"initial-cluster"`
InitialClusterToken string `json:"initial-cluster-token"`
StrictReconfigCheck bool `json:"strict-reconfig-check"`
Expand Down Expand Up @@ -504,6 +517,14 @@ func NewConfig() *Config {
ExperimentalMaxLearners: membership.DefaultMaxLearners,

V2Deprecation: config.V2_DEPR_DEFAULT,

EnableV2Discovery: DefaultEnableV2Discovery,
DiscoveryCfg: v3discovery.DiscoveryConfig{
DialTimeout: DefaultDiscoveryDialTimeout,
RequestTimeOut: DefaultDiscoveryRequestTimeOut,
KeepAliveTime: DefaultDiscoveryKeepAliveTime,
KeepAliveTimeout: DefaultDiscoveryKeepAliveTimeOut,
},
}
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
return cfg
Expand Down Expand Up @@ -667,6 +688,22 @@ func (cfg *Config) Validate() error {
return ErrConflictBootstrapFlags
}

// Check if both v2 discovery and v3 discovery flags are passed.
v2discoveryFlagsExist := cfg.Dproxy != ""
v3discoveryFlagsExist := cfg.DiscoveryCfg.CertFile != "" ||
cfg.DiscoveryCfg.KeyFile != "" ||
cfg.DiscoveryCfg.TrustedCAFile != "" ||
cfg.DiscoveryCfg.User != "" ||
cfg.DiscoveryCfg.Password != ""
if cfg.EnableV2Discovery && v3discoveryFlagsExist {
return errors.New("v2 discovery is enabled, but some v3 discovery " +
"settings (discovery-cert, discovery-key, discovery-cacert, " +
"discovery-user, discovery-password) are set")
}
if !cfg.EnableV2Discovery && v2discoveryFlagsExist {
return errors.New("v3 discovery is enabled, but --discovery-proxy is set")
}

if cfg.TickMs == 0 {
return fmt.Errorf("--heartbeat-interval must be >0 (set to %dms)", cfg.TickMs)
}
Expand Down
14 changes: 14 additions & 0 deletions server/embed/etcd.go
Expand Up @@ -175,8 +175,10 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) {
MaxWALFiles: cfg.MaxWalFiles,
InitialPeerURLsMap: urlsmap,
InitialClusterToken: token,
EnableV2Discovery: cfg.EnableV2Discovery,
DiscoveryURL: cfg.Durl,
DiscoveryProxy: cfg.Dproxy,
DiscoveryCfg: cfg.DiscoveryCfg,
NewCluster: cfg.IsNewCluster(),
PeerTLSInfo: cfg.PeerTLSInfo,
TickMs: cfg.TickMs,
Expand Down Expand Up @@ -345,6 +347,18 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized
zap.String("auto-compaction-interval", sc.AutoCompactionRetention.String()),
zap.String("discovery-url", sc.DiscoveryURL),
zap.String("discovery-proxy", sc.DiscoveryProxy),

zap.String("discovery-dial-timeout", sc.DiscoveryCfg.DialTimeout.String()),
zap.String("discovery-request-timeout", sc.DiscoveryCfg.RequestTimeOut.String()),
zap.String("discovery-keepalive-time", sc.DiscoveryCfg.KeepAliveTime.String()),
zap.String("discovery-keepalive-timeout", sc.DiscoveryCfg.KeepAliveTimeout.String()),
zap.Bool("discovery-insecure-transport", sc.DiscoveryCfg.InsecureTransport),
zap.Bool("discovery-insecure-skip-tls-verify", sc.DiscoveryCfg.InsecureSkipVerify),
zap.String("discovery-cert", sc.DiscoveryCfg.CertFile),
zap.String("discovery-key", sc.DiscoveryCfg.KeyFile),
zap.String("discovery-cacert", sc.DiscoveryCfg.TrustedCAFile),
zap.String("discovery-user", sc.DiscoveryCfg.User),

zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()),
zap.Int("max-learners", sc.ExperimentalMaxLearners),
)
Expand Down
15 changes: 14 additions & 1 deletion server/etcdmain/config.go
Expand Up @@ -185,10 +185,23 @@ func newConfig() *config {
"advertise-client-urls",
"List of this member's client URLs to advertise to the public.",
)
fs.BoolVar(&cfg.ec.EnableV2Discovery, "enable-v2-discovery", cfg.ec.EnableV2Discovery, "Enable to bootstrap the cluster using v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8.")
fs.StringVar(&cfg.ec.Durl, "discovery", cfg.ec.Durl, "Discovery URL used to bootstrap the cluster.")
fs.Var(cfg.cf.fallback, "discovery-fallback", fmt.Sprintf("Valid values include %q", cfg.cf.fallback.Valids()))

fs.StringVar(&cfg.ec.Dproxy, "discovery-proxy", cfg.ec.Dproxy, "HTTP proxy to use for traffic to discovery service.")
fs.DurationVar(&cfg.ec.DiscoveryCfg.DialTimeout, "discovery-dial-timeout", cfg.ec.DiscoveryCfg.DialTimeout, "V3 discovery: dial timeout for client connections.")
fs.DurationVar(&cfg.ec.DiscoveryCfg.RequestTimeOut, "discovery-request-timeout", cfg.ec.DiscoveryCfg.RequestTimeOut, "V3 discovery: timeout for discovery requests (excluding dial timeout).")
fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTime, "discovery-keepalive-time", cfg.ec.DiscoveryCfg.KeepAliveTime, "V3 discovery: keepalive time for client connections.")
fs.DurationVar(&cfg.ec.DiscoveryCfg.KeepAliveTimeout, "discovery-keepalive-timeout", cfg.ec.DiscoveryCfg.KeepAliveTimeout, "V3 discovery: keepalive timeout for client connections.")
fs.BoolVar(&cfg.ec.DiscoveryCfg.InsecureTransport, "discovery-insecure-transport", true, "V3 discovery: disable transport security for client connections.")
fs.BoolVar(&cfg.ec.DiscoveryCfg.InsecureSkipVerify, "discovery-insecure-skip-tls-verify", false, "V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes).")
fs.StringVar(&cfg.ec.DiscoveryCfg.CertFile, "discovery-cert", "", "V3 discovery: identify secure client using this TLS certificate file.")
fs.StringVar(&cfg.ec.DiscoveryCfg.KeyFile, "discovery-key", "", "V3 discovery: identify secure client using this TLS key file.")
fs.StringVar(&cfg.ec.DiscoveryCfg.TrustedCAFile, "discovery-cacert", "", "V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle.")
fs.StringVar(&cfg.ec.DiscoveryCfg.User, "discovery-user", "", "V3 discovery: username[:password] for authentication (prompt if password is not supplied).")
fs.StringVar(&cfg.ec.DiscoveryCfg.Password, "discovery-password", "", "V3 discovery: password for authentication (if this option is used, --user option shouldn't include password).")

fs.StringVar(&cfg.ec.Dproxy, "discovery-proxy", cfg.ec.Dproxy, "HTTP proxy to use for traffic to discovery service. Will be deprecated in v3.7, and be decommissioned in v3.8.")
fs.StringVar(&cfg.ec.DNSCluster, "discovery-srv", cfg.ec.DNSCluster, "DNS domain used to bootstrap initial cluster.")
fs.StringVar(&cfg.ec.DNSClusterServiceName, "discovery-srv-name", cfg.ec.DNSClusterServiceName, "Service name to query when using DNS discovery.")
fs.StringVar(&cfg.ec.InitialCluster, "initial-cluster", cfg.ec.InitialCluster, "Initial cluster configuration for bootstrapping.")
Expand Down
9 changes: 8 additions & 1 deletion server/etcdmain/etcd.go
Expand Up @@ -17,6 +17,7 @@ package etcdmain
import (
"encoding/json"
"fmt"

"net/http"
"os"
"path/filepath"
Expand All @@ -34,6 +35,7 @@ import (
"go.etcd.io/etcd/server/v3/etcdserver"
"go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp"
"go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery"
"go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery"
"go.etcd.io/etcd/server/v3/proxy/httpproxy"

"go.uber.org/zap"
Expand Down Expand Up @@ -318,7 +320,12 @@ func startProxy(cfg *config) error {

if cfg.ec.Durl != "" {
var s string
s, err = v2discovery.GetCluster(lg, cfg.ec.Durl, cfg.ec.Dproxy)
if cfg.ec.EnableV2Discovery {
lg.Warn("V2 discovery is deprecated!")
s, err = v2discovery.GetCluster(lg, cfg.ec.Durl, cfg.ec.Dproxy)
} else {
s, err = v3discovery.GetCluster(lg, cfg.ec.Durl, &cfg.ec.DiscoveryCfg)
}
if err != nil {
return err
}
Expand Down
26 changes: 25 additions & 1 deletion server/etcdmain/help.go
Expand Up @@ -104,13 +104,37 @@ Clustering:
--advertise-client-urls 'http://localhost:2379'
List of this member's client URLs to advertise to the public.
The client URLs advertised should be accessible to machines that talk to etcd cluster. etcd client libraries parse these URLs to connect to the cluster.
--enable-v2-discovery 'true'
Enable to bootstrap the cluster using v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8.
--discovery ''
Discovery URL used to bootstrap the cluster.
--discovery-dial-timeout '2s'
V3 discovery: dial timeout for client connections.
--discovery-request-timeout '5s'
V3 discovery: timeout for discovery requests (excluding dial timeout).
--discovery-keepalive-time '2s'
V3 discovery: keepalive time for client connections.
--discovery-keepalive-timeout '6s'
V3 discovery: keepalive timeout for client connections.
--discovery-insecure-transport 'true'
V3 discovery: disable transport security for client connections.
--discovery-insecure-skip-tls-verify 'false'
V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes).
--discovery-cert ''
V3 discovery: identify secure client using this TLS certificate file.
--discovery-key ''
V3 discovery: identify secure client using this TLS key file.
--discovery-cacert ''
V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle.
--discovery-user ''
V3 discovery: username[:password] for authentication (prompt if password is not supplied).
--discovery-password ''
V3 discovery: password for authentication (if this option is used, --user option shouldn't include password).
--discovery-fallback 'proxy'
Expected behavior ('exit' or 'proxy') when discovery services fails.
"proxy" supports v2 API only.
--discovery-proxy ''
HTTP proxy to use for traffic to discovery service.
HTTP proxy to use for traffic to discovery service. Will be deprecated in v3.7, and be decommissioned in v3.8.
--discovery-srv ''
DNS srv domain used to bootstrap the cluster.
--discovery-srv-name ''
Expand Down

0 comments on commit b5e224d

Please sign in to comment.