Browse Source

main: use initial-cluster and initial-cluster-state flags

In preperation for adding the ability to join a machine to an existing
cluster force the user to specify whether they expect this to me a new
cluster or an active one.

The error for not specifying the initial-cluster-state is:
```
etcd: initial cluster state unset and no wal found
```
Brandon Philips 11 years ago
parent
commit
e2d8037ded
6 changed files with 106 additions and 29 deletions
  1. 31 23
      Documentation/0.5/clustering.md
  2. 3 3
      Procfile
  3. 35 0
      etcdserver/cluster_state.go
  4. 27 0
      etcdserver/cluster_state_test.go
  5. 3 0
      etcdserver/server.go
  6. 7 3
      main.go

+ 31 - 23
Documentation/0.5/clustering.md

@@ -15,12 +15,12 @@ before starting we can use an offline bootstrap configuration. Each machine
 will get either the following command line or environment variables:
 
 ```
-ETCD_INITIAL_CLUSTER=”infra0=http://10.0.1.10:2379,infra1=http://infra1=10.0.1.11:2379,infra2=http://10.0.1.12:2379”
+ETCD_INITIAL_CLUSTER=”infra0=http://10.0.1.10:2379,infra1=http://10.0.1.11:2379,infra2=http://10.0.1.12:2379”
 ETCD_INITIAL_CLUSTER_STATE=new
 ```
 
 ```
--initial-cluster infra0=http://10.0.1.10:2379,http://infra1=10.0.1.11:2379,infra2=http://10.0.1.12:2379 \
+-initial-cluster infra0=http://10.0.1.10:2379,http://10.0.1.11:2379,infra2=http://10.0.1.12:2379 \
 	-initial-cluster-state new
 ```
 
@@ -38,30 +38,27 @@ $ etcd -name infra2 -advertise-peer-urls https://10.0.1.12:2379 \
 	-initial-cluster-state new
 ```
 
-These initial cluster command line parameters will be ignored on subsequent
-runs of etcd. You are free to remove the environment variables or command line
-flags after the initial bootstrap process. If you need to make changes to the
-configuration later see our guide on runtime configuration(link needed).
+The command line parameters starting with `-initial-cluster` will be ignored on
+subsequent runs of etcd. You are free to remove the environment variables or
+command line flags after the initial bootstrap process. If you need to make
+changes to the configuration later see our guide on runtime configuration.
 
 ### Error Cases
 
 In the following case we have not included our new host in the list of
-enumerated nodes.  If this is a new cluster, the node must be added to the list
-of initial cluster members.  If this is an existing cluster to which a new node
-is being added we must make the corresponding change to the existing cluster’s
-configuration and then bring the new node online.
-
+enumerated nodes. If this is a new cluster, the node must be added to the list
+of initial cluster members.
 ```
-$ etcd -name infra5 -advertise-peer-urls http://10.0.1.10:2379 \
-	-initial-cluster infra0=http://10.0.1.10:2379,infra1=http://10.0.1.11:2379,infra2=http://10.0.1.12:2379 \
-	-initial-cluster-state=new
-etcd: infra5 not listed in the initial cluster config
+$ etcd -name infra1 -advertise-peer-urls http://10.0.1.11:2379 \
+	-initial-cluster infra0=http://10.0.1.10:2379
+	-initial-cluster-state new
+etcd: infra1 not listed in the initial cluster config
 exit 1
 ```
 
 In this case we are attempting to map a node (infra0) on a different address
 (127.0.0.1:2379) than its enumerated address in the cluster list
-(10.0.1.10:2379).  If this node is to listen on multiple addresses, all
+(10.0.1.10:2379). If this node is to listen on multiple addresses, all
 addresses must be reflected in the “initial-cluster” configuration directive.
 
 ```
@@ -87,7 +84,10 @@ $ curl https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817
 ```
 
 The URL you will use in this case will be
-`https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83`.
+`https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83`
+and the machines will use the
+`https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83`
+directory for registration as they start.
 
 If you do not have access to an existing cluster you can use the hosted
 discovery.etcd.io service.  You can create a private discovery URL using the
@@ -120,24 +120,32 @@ $ etcd -name infra2 -advertise-peer-urls http://10.0.1.12:2379 -discovery https:
 This will cause each machine to register itself with the etcd service and begin
 the cluster once all machines have been registered.
 
-### Error Cases
+### Error and Warning Cases
+
+#### Discovery Server Errors
 
 ```
 $ etcd -name infra0 -advertise-peer-urls http://10.0.1.10:2379 -discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
-etcd: error: the cluster using discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de has already started with all 5 members
+etcd: error: the cluster doesn’t have a size configuration value in https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de/_config
 exit 1
 ```
 
+#### User Errors
+
 ```
 $ etcd -name infra0 -advertise-peer-urls http://10.0.1.10:2379 -discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
-etcd: error: the cluster doesn’t have a size configuration value in https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de/_config
+etcd: error: the cluster using discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de has already started with all 5 members
 exit 1
 ```
 
+#### Warnings
+
+This is a harmless warning notifying you that the discovery URL will be
+ignored on this machine.
+
 ```
 $ etcd -name infra0 -advertise-peer-urls http://10.0.1.10:2379 -discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
 etcd: warn: ignoring discovery URL: etcd has already been initialized and has a valid log in /var/lib/etcd
-exit 1
 ```
 
 # 0.4 to 0.5+ Migration Guide
@@ -153,6 +161,6 @@ To make understanding this feature easier, we changed the naming of some flags,
 |-----------------------|-----------------------|---------------------------------------------------------------------------------------|
 |-peer-addr		|-advertise-peer-urls 	|If specified, peer-addr will be used as the only peer URL. Error if both flags specified.|
 |-addr			|-advertise-client-urls	|If specified, addr will be used as the only client URL. Error if both flags specified.|
-|-peer-bind-addr	|-listen-peer-urls	|If specified, peer-bind-addr will be used as the only peer URL. Error if both flags specified.|
-|-bind-addr		|-listen-client-urls	|If specified, bind-addr will be used as the only client URL. Error if both flags specified.|
+|-peer-bind-addr	|-listen-peer-urls	|If specified, peer-bind-addr will be used as the only peer bind URL. Error if both flags specified.|
+|-bind-addr		|-listen-client-urls	|If specified, bind-addr will be used as the only client bind URL. Error if both flags specified.|
 |-peers			|none			|Deprecated. The -initial-cluster flag provides a similar concept with different semantics. Please read this guide on cluster startup.|

+ 3 - 3
Procfile

@@ -1,5 +1,5 @@
 # Use goreman to run `go get github.com/mattn/goreman`
-etcd1: bin/etcd -name node1 -listen-client-urls http://127.0.0.1:4001 -advertise-client-urls http://127.0.0.1:4001 -listen-peer-urls http://127.0.0.1:7001 -advertise-peer-urls http://127.0.0.1:7001 -bootstrap-config 'node1=http://localhost:7001,node2=http://localhost:7002,node3=http://localhost:7003'
-etcd2: bin/etcd -name node2 -listen-client-urls http://127.0.0.1:4002 -advertise-client-urls http://127.0.0.1:4002 -listen-peer-urls http://127.0.0.1:7002 -advertise-peer-urls http://127.0.0.1:7002 -bootstrap-config 'node1=http://localhost:7001,node2=http://localhost:7002,node3=http://localhost:7003'
-etcd3: bin/etcd -name node3 -listen-client-urls http://127.0.0.1:4003 -advertise-client-urls http://127.0.0.1:4003 -listen-peer-urls http://127.0.0.1:7003 -advertise-peer-urls http://127.0.0.1:7003 -bootstrap-config 'node1=http://localhost:7001,node2=http://localhost:7002,node3=http://localhost:7003'
+etcd1: bin/etcd -name node1 -listen-client-urls http://127.0.0.1:4001 -advertise-client-urls http://127.0.0.1:4001 -listen-peer-urls http://127.0.0.1:7001 -advertise-peer-urls http://127.0.0.1:7001 -initial-cluster 'node1=http://localhost:7001,node2=http://localhost:7002,node3=http://localhost:7003' -initial-cluster-state new
+etcd2: bin/etcd -name node2 -listen-client-urls http://127.0.0.1:4002 -advertise-client-urls http://127.0.0.1:4002 -listen-peer-urls http://127.0.0.1:7002 -advertise-peer-urls http://127.0.0.1:7002 -initial-cluster 'node1=http://localhost:7001,node2=http://localhost:7002,node3=http://localhost:7003' -initial-cluster-state new
+etcd3: bin/etcd -name node3 -listen-client-urls http://127.0.0.1:4003 -advertise-client-urls http://127.0.0.1:4003 -listen-peer-urls http://127.0.0.1:7003 -advertise-peer-urls http://127.0.0.1:7003 -initial-cluster 'node1=http://localhost:7001,node2=http://localhost:7002,node3=http://localhost:7003' -initial-cluster-state new
 #proxy: bin/etcd -proxy=on -bind-addr 127.0.0.1:8080 -peers 'localhost:7001,localhost:7002,localhost:7003'

+ 35 - 0
etcdserver/cluster_state.go

@@ -0,0 +1,35 @@
+package etcdserver
+
+import (
+	"errors"
+)
+
+const (
+	ClusterStateValueNew = "new"
+)
+
+var (
+	ClusterStateValues = []string{
+		ClusterStateValueNew,
+	}
+)
+
+// ClusterState implements the flag.Value interface.
+type ClusterState string
+
+// Set verifies the argument to be a valid member of ClusterStateFlagValues
+// before setting the underlying flag value.
+func (cs *ClusterState) Set(s string) error {
+	for _, v := range ClusterStateValues {
+		if s == v {
+			*cs = ClusterState(s)
+			return nil
+		}
+	}
+
+	return errors.New("invalid value")
+}
+
+func (cs *ClusterState) String() string {
+	return string(*cs)
+}

+ 27 - 0
etcdserver/cluster_state_test.go

@@ -0,0 +1,27 @@
+package etcdserver
+
+import (
+	"testing"
+)
+
+func TestClusterStateSet(t *testing.T) {
+	tests := []struct {
+		val  string
+		pass bool
+	}{
+		// known values
+		{"new", true},
+
+		// unrecognized values
+		{"foo", false},
+		{"", false},
+	}
+
+	for i, tt := range tests {
+		pf := new(ClusterState)
+		err := pf.Set(tt.val)
+		if tt.pass != (err == nil) {
+			t.Errorf("#%d: want pass=%t, but got err=%v", i, tt.pass, err)
+		}
+	}
+}

+ 3 - 0
etcdserver/server.go

@@ -91,6 +91,7 @@ type ServerConfig struct {
 	DataDir      string
 	SnapCount    int64
 	Cluster      *Cluster
+	ClusterState ClusterState
 	Transport    *http.Transport
 }
 
@@ -125,6 +126,8 @@ func NewServer(cfg *ServerConfig) *EtcdServer {
 			if err = cfg.Cluster.Set(s); err != nil {
 				log.Fatalf("etcd: %v", err)
 			}
+		} else if (cfg.ClusterState) != ClusterStateValueNew {
+			log.Fatalf("etcd: initial cluster state unset and no wal or discovery URL found")
 		}
 		if w, err = wal.Create(waldir); err != nil {
 			log.Fatal(err)

+ 7 - 3
main.go

@@ -31,7 +31,9 @@ var (
 	snapCount    = flag.Uint64("snapshot-count", etcdserver.DefaultSnapCount, "Number of committed transactions to trigger a snapshot")
 	printVersion = flag.Bool("version", false, "Print the version and exit")
 
-	cluster   = &etcdserver.Cluster{}
+	cluster      = &etcdserver.Cluster{}
+	clusterState = new(etcdserver.ClusterState)
+
 	cors      = &pkg.CORSInfo{}
 	proxyFlag = new(flagtypes.Proxy)
 
@@ -56,7 +58,8 @@ var (
 )
 
 func init() {
-	flag.Var(cluster, "bootstrap-config", "Initial cluster configuration for bootstrapping")
+	flag.Var(cluster, "initial-cluster", "Initial cluster configuration for bootstrapping")
+	flag.Var(clusterState, "initial-cluster-state", "Initial cluster configuration for bootstrapping")
 	cluster.Set("default=http://localhost:2380,default=http://localhost:7001")
 
 	flag.Var(flagtypes.NewURLsValue("http://localhost:2380,http://localhost:7001"), "advertise-peer-urls", "List of this member's peer URLs to advertise to the rest of the cluster")
@@ -146,8 +149,9 @@ func startEtcd() {
 		DataDir:      *dir,
 		SnapCount:    int64(*snapCount),
 		Cluster:      cluster,
-		Transport:    pt,
 		DiscoveryURL: *durl,
+		ClusterState: *clusterState,
+		Transport:    pt,
 	}
 	s := etcdserver.NewServer(cfg)
 	s.Start()