diff --git a/Documentation/0.5/clustering.md b/Documentation/0.5/clustering.md index 8b49bc779..b34ed78cf 100644 --- a/Documentation/0.5/clustering.md +++ b/Documentation/0.5/clustering.md @@ -70,6 +70,18 @@ etcd: infra0 has different advertised URLs in the cluster and advertised peer UR exit 1 ``` +If you configure a peer with a different set of configuration and attempt to +join this cluster you will get a cluster ID mismatch and etcd will exit. + +``` +$ etcd -name infra3 -advertise-peer-urls http://10.0.1.13:2379 \ + -initial-cluster infra0=http://10.0.1.10:2379,infra1=http://10.0.1.11:2379,infra3=http://10.0.1.13:2379 \ + -initial-cluster-state=new +etcd: conflicting cluster ID to the target cluster (c6ab534d07e8fcc4 != bc25ea2a74fb18b0). Exiting. +exit 1 +``` + + ## Discovery In a number of cases you might not know the IPs of your cluster peers ahead of diff --git a/etcdserver/cluster_store.go b/etcdserver/cluster_store.go index 6890d3acd..049fff995 100644 --- a/etcdserver/cluster_store.go +++ b/etcdserver/cluster_store.go @@ -221,11 +221,11 @@ func httpPost(c *http.Client, url string, cid uint64, data []byte) bool { switch resp.StatusCode { case http.StatusPreconditionFailed: // TODO: shutdown the etcdserver gracefully? - log.Panicf("clusterID mismatch") + log.Fatalf("etcd: conflicting cluster ID with the target cluster (%s != %s). Exiting.", resp.Header.Get("X-Etcd-Cluster-ID"), strconv.FormatUint(cid, 16)) return false case http.StatusForbidden: // TODO: stop the server - log.Panicf("the member has been removed") + log.Fatalf("etcd: this member has been permanently removed from the cluster. Exiting.") return false case http.StatusNoContent: return true diff --git a/etcdserver/etcdhttp/http.go b/etcdserver/etcdhttp/http.go index d9f90c247..3c9b308f5 100644 --- a/etcdserver/etcdhttp/http.go +++ b/etcdserver/etcdhttp/http.go @@ -222,8 +222,10 @@ func (h serverHandler) serveRaft(w http.ResponseWriter, r *http.Request) { return } - gcid := r.Header.Get("X-Etcd-Cluster-ID") wcid := strconv.FormatUint(h.clusterStore.Get().ID(), 16) + w.Header().Set("X-Etcd-Cluster-ID", wcid) + + gcid := r.Header.Get("X-Etcd-Cluster-ID") if gcid != wcid { log.Printf("etcdhttp: request ignored: clusterID mismatch got %s want %x", gcid, wcid) http.Error(w, "clusterID mismatch", http.StatusPreconditionFailed)