通過靜態發現方式部署etcd叢集

NO IMAGE

通過靜態發現方式部署etcd叢集

 發表於 2017-04-11 |  分類於 docker |  閱讀次數: 1860

在「etcd使用入門」一文中對etcd的基本知識點和安裝做了一個簡要的介紹,這次我們來說說如何部署一個etcd叢集。

etcd構建自身高可用叢集主要有三種形式:

  • 靜態發現: 預先已知etcd叢集中有哪些節點,在啟動時通過--initial-cluster引數直接指定好etcd的各個節點地址。

  • etcd動態發現: 通過已有的etcd叢集作為資料互動點,然後在擴充套件新的叢集時實現通過已有叢集進行服務發現的機制。比如官方提供的:discovery.etcd.io

  • DNS動態發現: 通過DNS查詢方式獲取其他節點地址資訊。

本文將介紹如何通過靜態發現這種方式來部署一個etcd叢集,這種方式也是最簡單的。

環境準備

通常按照需求將叢集節點部署為3,5,7,9個節點。這裡能選擇偶數個節點嗎?最好不要這樣。原因有二:

  • 偶數個節點叢集不可用風險更高,表現在選主過程中,有較大概率或等額選票,從而觸發下一輪選舉。
  • 偶數個節點叢集在某些網路分割的場景下無法正常工作。當網路分割發生後,將叢集節點對半分割開。此時叢集將無法工作。按照RAFT協議,此時叢集寫操作無法使得大多數節點同意,從而導致寫失敗,叢集無法正常工作。

這裡將部署一個3節點的叢集, 以下為3臺主機資訊,系統環境為Ubuntu 16.04。

節點名稱地址
etcd1192.168.2.210
etcd2192.168.2.211
etcd3192.168.2.212

安裝etcd

在「etcd使用入門」一文中對如何安裝已經做了介紹,這裡就不再重複講解了。如果你還不會安裝可參考「etcd使用入門」。

配置etcd叢集

修改etcd配置檔案,我這裡的環境是在/opt/etcd/config/etcd.conf,請根據實際情況修改。

  • etcd1配置示例
1
2
3
4
5
6
7
8
9
10
11
12
# 編輯配置檔案
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
ETCD_LISTEN_PEER_URLS="http://192.168.2.210:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.210:2379,http://192.168.2.210:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.210:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380,etcd3=http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.210:2379,http://192.168.2.210:4001"
  • etcd2配置示例
1
2
3
4
5
6
7
8
9
10
11
12
# 編輯配置檔案
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd2
ETCD_DATA_DIR="/var/lib/etcd/etcd2"
ETCD_LISTEN_PEER_URLS="http://192.168.2.211:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.211:2379,http://192.168.2.211:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.211:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380,etcd3=http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.211:2379,http://192.168.2.211:4001"
  • etcd3配置示例
1
2
3
4
5
6
7
8
9
10
11
12
# 編輯配置檔案
$ vim /opt/etcd/config/etcd.conf
ETCD_NAME=etcd3
ETCD_DATA_DIR="/var/lib/etcd/etcd3"
ETCD_LISTEN_PEER_URLS="http://192.168.2.212:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.2.212:2379,http://192.168.2.212:4001"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380,etcd3=http://192.168.2.212:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="hilinux-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.2.212:2379,http://192.168.2.212:4001"

針對上面幾個配置引數做下簡單的解釋:

  • ETCD_NAME :ETCD的節點名
  • ETCD_DATA_DIR:ETCD的資料儲存目錄
  • ETCD_SNAPSHOT_COUNTER:多少次的事務提交將觸發一次快照
  • ETCD_HEARTBEAT_INTERVAL:ETCD節點之間心跳傳輸的間隔,單位毫秒
  • ETCD_ELECTION_TIMEOUT:該節點參與選舉的最大超時時間,單位毫秒
  • ETCD_LISTEN_PEER_URLS:該節點與其他節點通訊時所監聽的地址列表,多個地址使用逗號隔開,其格式可以劃分為scheme://IP:PORT,這裡的scheme可以是http、https
  • ETCD_LISTEN_CLIENT_URLS:該節點與客戶端通訊時監聽的地址列表
  • ETCD_INITIAL_ADVERTISE_PEER_URLS:該成員節點在整個叢集中的通訊地址列表,這個地址用來傳輸叢集資料的地址。因此這個地址必須是可以連線叢集中所有的成員的。
  • ETCD_INITIAL_CLUSTER:配置叢集內部所有成員地址,其格式為:ETCD_NAME=ETCD_INITIAL_ADVERTISE_PEER_URLS,如果有多個使用逗號隔開
  • ETCD_ADVERTISE_CLIENT_URLS:廣播給叢集中其他成員自己的客戶端地址列表
  • ETCD_INITIAL_CLUSTER_STATE:初始化叢集狀態,new表示新建
  • ETCD_INITIAL_CLUSTER_TOKEN:初始化叢集token

注意:所有ETCD_MY_FLAG的配置引數也可以通過命令列引數進行設定,但是命令列指定的引數優先順序更高,同時存在時會覆蓋環境變數對應的值。

下面給出常用配置的引數和它們的解釋:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--name:方便理解的節點名稱,預設為default,在叢集中應該保持唯一,可以使用 hostname
--data-dir:服務執行資料儲存的路徑,預設為 ${name}.etcd
--snapshot-count:指定有多少事務(transaction)被提交時,觸發擷取快照儲存到磁碟
--heartbeat-interval:leader 多久傳送一次心跳到 followers。預設值是 100ms
--eletion-timeout:重新投票的超時時間,如果 follow 在該時間間隔沒有收到心跳包,會觸發重新投票,預設為 1000 ms
--listen-peer-urls:和同伴通訊的地址,比如 http://ip:2380,如果有多個,使用逗號分隔。需要所有節點都能夠訪問,所以不要使用 localhost!
--listen-client-urls:對外提供服務的地址:比如 http://ip:2379,http://127.0.0.1:2379,客戶端會連線到這裡和 etcd 互動
--advertise-client-urls:對外公告的該節點客戶端監聽地址,這個值會告訴叢集中其他節點
--initial-advertise-peer-urls:該節點同伴監聽地址,這個值會告訴叢集中其他節點
--initial-cluster:叢集中所有節點的資訊,格式為 node1=http://ip1:2380,node2=http://ip2:2380,…。注意:這裡的 node1 是節點的 --name 指定的名字;後面的 ip1:2380 是 --initial-advertise-peer-urls 指定的值
--initial-cluster-state:新建叢集的時候,這個值為new;假如已經存在的叢集,這個值為 existing
--initial-cluster-token:建立叢集的token,這個值每個叢集保持唯一。這樣的話,如果你要重新建立叢集,即使配置和之前一樣,也會再次生成新的叢集和節點 uuid;否則會導致多個叢集之間的衝突,造成未知的錯誤
所有以--init開頭的配置都是在bootstrap叢集的時候才會用到,後續節點的重啟會被忽略。

測試etcd叢集

按上面配置好各叢集節點後,分別在各節點啟動etcd。

1
$ systemctl start etcd

啟動完成後,在任意節點執行etcdctl member list可列所有叢集節點資訊,如下所示:

1
2
3
4
$ etcdctl --endpoints "http://192.168.2.210:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=true
a8589aa8629b731b: name=etcd1 peerURLs=http://192.168.2.210:2380 clientURLs=http://192.168.2.210:2379,http://192.168.2.210:4001 isLeader=false
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=false

這裡顯示指定的叢集地址,是因為在上面的配置中繫結了IP。如不指定會報如下錯誤:

1
2
3
4
5
6
$ etcdctl member list
Error:  client: etcd cluster is unavailable or misconfigured; error #0: dial tcp 127.0.0.1:4001: getsockopt: connection refused
; error #1: dial tcp 127.0.0.1:2379: getsockopt: connection refused
error #0: dial tcp 127.0.0.1:4001: getsockopt: connection refused
error #1: dial tcp 127.0.0.1:2379: getsockopt: connection refused

etcd叢集基本管理

  • 檢視叢集健康狀態
1
2
3
4
5
$ etcdctl --endpoints "http://192.168.2.210:2379"  cluster-health
member a3ba19408fd4c829 is healthy: got healthy result from http://192.168.2.212:2379
member a8589aa8629b731b is healthy: got healthy result from http://192.168.2.210:2379
member e4a3e95f72ced4a7 is healthy: got healthy result from http://192.168.2.211:2379
cluster is healthy
  • 檢視叢集成員

在任一節點上執行,可以看到叢集的節點情況,並能看出哪個是leader節點。

1
2
3
4
$ etcdctl --endpoints "http://192.168.2.210:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=true
a8589aa8629b731b: name=etcd1 peerURLs=http://192.168.2.210:2380 clientURLs=http://192.168.2.210:2379,http://192.168.2.210:4001 isLeader=false
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=false
  • 更新一個節點
1
2
3
4
5
6
7
8
9
# 如果你想更新一個節點的IP(peerURLS),首先你需要知道那個節點的ID
$ etcdctl --endpoints "http://192.168.2.210:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=false
a8589aa8629b731b: name=etcd1 peerURLs=http://192.168.2.210:2380 clientURLs=http://192.168.2.210:2379,http://192.168.2.210:4001 isLeader=false
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=true
# 更新一個節點
$ etcdctl --endpoints "http://192.168.2.210:2379" member update a8589aa8629b731b http://192.168.2.210:2380
Updated member with ID a8589aa8629b731b in cluster
  • 刪除一個節點
1
2
3
4
5
6
7
8
9
10
11
$ etcdctl --endpoints "http://192.168.2.210:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=false
a8589aa8629b731b: name=etcd1 peerURLs=http://192.168.2.210:2380 clientURLs=http://192.168.2.210:2379,http://192.168.2.210:4001 isLeader=false
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=true
$ etcdctl --endpoints "http://192.168.2.210:2379" member remove a8589aa8629b731b
Removed member a8589aa8629b731b from cluster
$ etcdctl --endpoints "http://192.168.2.211:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=false
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=true
  • 增加一個新節點

注意:步驟很重要,不然會報叢集ID不匹配。

a. 將目標節點新增到叢集

1
2
3
4
5
6
7
$ etcdctl --endpoints "http://192.168.2.211:2379" member add etcd1 http://192.168.2.210:2380
Added member named etcd1 with ID baab0aae8b58c802 to cluster
ETCD_NAME="etcd1"
ETCD_INITIAL_CLUSTER="etcd3=http://192.168.2.212:2380,etcd1=http://192.168.2.210:2380,etcd2=http://192.168.2.211:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

b. 檢視新增成員列表

etcd1狀態現在為unstarted

1
2
3
4
$ etcdctl --endpoints "http://192.168.2.211:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=false
baab0aae8b58c802[unstarted]: peerURLs=http://192.168.2.210:2380
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=true

c. 清空目標節點資料

目標節點從叢集中刪除後,成員資訊會更新。新節點是作為一個全新的節點加入叢集,如果data-dir有資料,etcd啟動時會讀取己經存在的資料,仍然用舊的memberID會造成無法加入叢集,所以一定要清空新節點的data-dir。

1
$ rm -rf /var/lib/etcd/etcd1

d. 在目標節點上啟動新增加的成員

修改配置檔案中ETCD_INITIAL_CLUSTER_STATE標記為existing,如果為new,則會自動生成一個新的memberID,這和前面新增節點時生成的ID不一致,故日誌中會報節點ID不匹配的錯。

1
2
$ vim /opt/etcd/config/etcd.conf
ETCD_INITIAL_CLUSTER_STATE="existing"

啟動etcd

1
$ systemctl start etcd

檢視新節點是否成功加入

1
2
3
4
$ etcdctl --endpoints "http://192.168.2.210:2379" member list
a3ba19408fd4c829: name=etcd3 peerURLs=http://192.168.2.212:2380 clientURLs=http://192.168.2.212:2379,http://192.168.2.212:4001 isLeader=false
baab0aae8b58c802: name=etcd1 peerURLs=http://192.168.2.210:2380 clientURLs=http://192.168.2.210:2379,http://192.168.2.210:4001 isLeader=false
e4a3e95f72ced4a7: name=etcd2 peerURLs=http://192.168.2.211:2380 clientURLs=http://192.168.2.211:2379,http://192.168.2.211:4001 isLeader=true

參考文件

http://www.google.com
http://t.cn/RX7JagC
http://cizixs.com/2016/08/02/intro-to-etcd
http://zkread.com/article/1227544.html