From 69434fd13e8013fe99a8241c9e8fe904974ba95a Mon Sep 17 00:00:00 2001 From: Eric Kidd Date: Mon, 11 Jan 2016 13:56:58 -0500 Subject: [PATCH] etcd: Allow disabling sync for load balanced etcd Some etcd configurations (such as that provided by compose.io) place the etcd cluster behind multiple load balancers or proxies. In this configuration, calling Sync (or AutoSync) on the etcd client will replace the load balancer addresses with the underlying etcd server address. This will cause the etcd client to bypass the load balancers, and may cause the connection to fail completely if the etcd servers are protected by a firewall. This patch provides a "sync" option for the etcd backend, which defaults to the current behavior, but which can be used to turn off of sync. This corresponds to etcdctl's --no-sync option. --- physical/etcd.go | 26 +++++++++++++++++++----- website/source/docs/config/index.html.md | 6 ++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/physical/etcd.go b/physical/etcd.go index ecd76e825..f0a54e4df 100644 --- a/physical/etcd.go +++ b/physical/etcd.go @@ -6,6 +6,7 @@ import ( "net/url" "os" "path/filepath" + "strconv" "strings" "sync" "time" @@ -43,6 +44,7 @@ const ( ) var ( + EtcdSyncConfigError = errors.New("client setup failed: unable to parse etcd sync field in config") EtcdSyncClusterError = errors.New("client setup failed: unable to sync etcd cluster") EtcdAddressError = errors.New("client setup failed: address must be valid URL (ex. 'scheme://host:port')") EtcdSemaphoreKeysEmptyError = errors.New("lock queue is empty") @@ -143,11 +145,25 @@ func newEtcdBackend(conf map[string]string) (Backend, error) { return nil, err } - ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout) - syncErr := c.Sync(ctx) - cancel() - if syncErr != nil { - return nil, EtcdSyncClusterError + // Should we sync the cluster state? There are three available options + // for our client library: don't sync (required for some proxies), sync + // once, or sync periodically with AutoSync. We currently support the + // first two. + sync := true + if v, ok := conf["sync"]; ok { + parsed, err := strconv.ParseBool(v) + if err != nil { + return nil, EtcdSyncConfigError + } + sync = parsed + } + if sync { + ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout) + syncErr := c.Sync(ctx) + cancel() + if syncErr != nil { + return nil, EtcdSyncClusterError + } } kAPI := client.NewKeysAPI(c) diff --git a/website/source/docs/config/index.html.md b/website/source/docs/config/index.html.md index bce124e8d..b85682cfd 100644 --- a/website/source/docs/config/index.html.md +++ b/website/source/docs/config/index.html.md @@ -221,6 +221,12 @@ For etcd, the following options are supported: Can be comma separated list (protocol://host:port) of many etcd instances. Defaults to "http://localhost:2379" if not specified. + * `sync` (optional) - Should we synchronize the list of available etcd + servers on startup? This will parse as a boolean value, and can be set + to "0", "no", "false", "1", "yes", or "true". Defaults to true. Set + to false if your etcd cluster is behind a proxy server and syncing + causes Vault to fail. + * `username` (optional) - Username to use when authenticating with the etcd server. May also be specified via the ETCD_USERNAME environment variable.