etcd集群部署与遇到的坑
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
etcd集群部署與遇到的坑 博客分類: 開源框架 etcd在k8s集群中使用了etcd作為數(shù)據(jù)中心,在實際操作中遇到了一些坑。今天記錄一下,為了以后更好操作。
ETCD參數(shù)說明
- —data-dir 指定節(jié)點的數(shù)據(jù)存儲目錄,這些數(shù)據(jù)包括節(jié)點ID,集群ID,集群初始化配置,Snapshot文件,若未指定—wal-dir,還會存儲WAL文件;
- —wal-dir 指定節(jié)點的was文件的存儲目錄,若指定了該參數(shù),wal文件會和其他數(shù)據(jù)文件分開存儲。
- —name 節(jié)點名稱
- —initial-advertise-peer-urls 告知集群其他節(jié)點url.
- — listen-peer-urls 監(jiān)聽URL,用于與其他節(jié)點通訊
- — advertise-client-urls 告知客戶端url, 也就是服務的url
- — initial-cluster-token 集群的ID
- — initial-cluster 集群中所有節(jié)點
?
節(jié)點遷移
在生產(chǎn)環(huán)境中,不可避免遇到機器硬件故障。當遇到硬件故障發(fā)生的時候,我們需要快速恢復節(jié)點。ETCD集群可以做到在不丟失數(shù)據(jù)的,并且不改變節(jié)點ID的情況下,遷移節(jié)點。
具體辦法是:
- 1)停止待遷移節(jié)點上的etc進程;
- 2)將數(shù)據(jù)目錄打包復制到新的節(jié)點;
- 3)更新該節(jié)點對應集群中peer url,讓其指向新的節(jié)點;
- 4)使用相同的配置,在新的節(jié)點上啟動etcd進程
-
etcd配置
-
node1
編輯etcd啟動腳本/usr/local/etcd/start.sh
/usr/local/etcd/etcd -name niub1 -debug \ -initial-advertise-peer-urls http://niub-etcd-1:2380 \ -listen-peer-urls http://niub-etcd-1:2380 \ -listen-client-urls http://niub-etcd-1:2379,http://127.0.0.1:2379 \ -advertise-client-urls http://niub-etcd-1:2379 \ -initial-cluster-token etcd-cluster-1 \ -initial-cluster niub1=http://niub-etcd-1:2380,niub2=http://niub-etcd-2:2380,niub3=http://niub-etcd-3:2380 \ -initial-cluster-state new >> /niub/etcd_log/etcd.log 2>&1 &node2
編輯etcd啟動腳本/usr/local/etcd/start.sh
/usr/local/etcd/etcd -name niub2 -debug \ -initial-advertise-peer-urls http://niub-etcd-2:2380 \ -listen-peer-urls http://niub-etcd-2:2380 \ -listen-client-urls http://niub-etcd-2:2379,http://127.0.0.1:2379 \ -advertise-client-urls http://niub-etcd-2:2379 \ -initial-cluster-token etcd-cluster-1 \ -initial-cluster niub1=http://niub-etcd-1:2380,niub2=http://niub-etcd-2:2380,niub3=http://niub-etcd-3:2380 \ -initial-cluster-state new >> /niub/etcd_log/etcd.log 2>&1 &node3
編輯etcd啟動腳本/usr/local/etcd/start.sh
/usr/local/etcd/etcd -name niub3 -debug \ -initial-advertise-peer-urls http://niub-etcd-3:2380 \ -listen-peer-urls http://niub-etcd-3:2380 \ -listen-client-urls http://niub-etcd-3:2379,http://127.0.0.1:2379 \ -advertise-client-urls http://niub-etcd-3:2379 \ -initial-cluster-token etcd-cluster-1 \ -initial-cluster niub1=http://niub-etcd-1:2380,niub2=http://niub-etcd-2:2380,niub3=http://niub-etcd-3:2380 \ -initial-cluster-state new >> /niub/etcd_log/etcd.log 2>&1 &防火墻
在這3臺node服務器開放2379、2380端口,命令:
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 2379 -j ACCEPT iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 2380 -j ACCEPThaproxy配置
haproxy配置過程略 編輯/etc/haproxy/haproxy.cfg文件,增加:
frontend etcd bind 10.10.0.14:2379 mode tcp option tcplog default_backend etcd log 127.0.0.1 local3 backend etcd balance roundrobin fullconn 1024 server etcd1 10.10.0.11:2379 check port 2379 inter 300 fall 3 server etcd2 10.10.0.12:2379 check port 2379 inter 300 fall 3 server etcd3 10.10.0.13:2379 check port 2379 inter 300 fall 3
?
檢查etcd服務運行狀態(tài)
使用curl訪問:
curl http://10.10.0.14:2379/v2/members返回以下結(jié)果為正常(3個節(jié)點):
{"members": [ { "id": "1f890e0c67371d24", "name": "niub1", "peerURLs": [ "http://niub-etcd-1:2380" ], "clientURLs": [ "http://niub-etcd-1:2379" ] }, { "id": "b952ccccefdd8a93", "name": "niub3", "peerURLs": [ "http://niub-etcd-3:2380" ], "clientURLs": [ "http://niub-etcd-3:2379" ] }, { "id": "d6dbdb24d5bfc20f", "name": "niub2", "peerURLs": [ "http://niub-etcd-2:2380" ], "clientURLs": [ "http://niub-etcd-2:2379" ] } ] }etcd備份
使用etcd自帶命令etcdctl進行etc備份,腳本如下:
#!/bin/bash date_time=`date +%Y%m%d` etcdctl backup --data-dir /usr/local/etcd/niub3.etcd/ --backup-dir /niub/etcd_backup/${date_time} find /niub/etcd_backup/ -ctime +7 -exec rm -r {} \;etcdctl操作
??更新一個節(jié)點
如果你想更新一個節(jié)點的 IP(peerURLS),首先你需要知道那個節(jié)點的 ID。你可以列出所有節(jié)點,找出對應節(jié)點的 ID。
$ etcdctl member list 6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792 924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793 a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791在本例中,我們假設要更新 ID 為?a8266ecf031671f3?的節(jié)點的 peerURLs 為:http://10.0.1.10:2380
$ etcdctl member update a8266ecf031671f3 http://10.0.1.10:2380 Updated member with ID a8266ecf031671f3 in cluster刪除一個節(jié)點
假設我們要刪除 ID 為?a8266ecf031671f3?的節(jié)點
$ etcdctl member remove a8266ecf031671f3 Removed member a8266ecf031671f3 from cluster執(zhí)行完后,目標節(jié)點會自動停止服務,并且打印一行日志:
etcd:?this member has been permanently removed from the cluster. Exiting.如果刪除的是?leader?節(jié)點,則需要耗費額外的時間重新選舉?leader。
增加一個新的節(jié)點
增加一個新的節(jié)點分為兩步:
-
通過?etcdctl?或?qū)?API 注冊新節(jié)點
-
使用恰當?shù)膮?shù)啟動新節(jié)點
先看第一步,假設我們要新加的節(jié)點取名為 infra3,?peerURLs?是?http://10.0.1.13:2380
$ etcdctl member add infra3 http://10.0.1.13:2380 added member 9bf1b35fc7761a23 to cluster ETCD_NAME="infra3" ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380" ETCD_INITIAL_CLUSTER_STATE=existingetcdctl?在注冊完新節(jié)點后,會返回一段提示,包含3個環(huán)境變量。然后在第二部啟動新節(jié)點的時候,帶上這3個環(huán)境變量即可。
$ export ETCD_NAME="infra3" $ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380" $ export ETCD_INITIAL_CLUSTER_STATE=existing $ etcd -listen-client-urls http://10.0.1.13:2379 -advertise-client-urls http://10.0.1.13:2379 -listen-peer-urls http://10.0.1.13:2380 -initial-advertise-peer-urls http://10.0.1.13:2380 -data-dir %data_dir%這樣,新節(jié)點就會運行起來并且加入到已有的集群中了。
值得注意的是,如果原先的集群只有1個節(jié)點,在新節(jié)點成功啟動之前,新集群并不能正確的形成。因為原先的單節(jié)點集群無法完成leader的選舉。
直到新節(jié)點啟動完,和原先的節(jié)點建立連接以后,新集群才能正確形成。
服務故障恢復
在使用etcd集群的過程中,有時會出現(xiàn)少量主機故障,這時我們需要對集群進行維護。然而,在現(xiàn)實情況下,還可能遇到由于嚴重的設備 或網(wǎng)絡的故障,導致超過半數(shù)的節(jié)點無法正常工作。
在etcd集群無法提供正常的服務,我們需要用到一些備份和數(shù)據(jù)恢復的手段。etcd背后的raft,保證了集群的數(shù)據(jù)的一致性與穩(wěn)定性。所以我們對etcd的恢復,更多的是恢復etcd的節(jié)點服務,并還原用戶數(shù)據(jù)。
首先,從剩余的正常節(jié)點中選擇一個正常的成員節(jié)點, 使用?etcdctl backup?命令備份etcd數(shù)據(jù)。
$ ./etcdctl backup --data-dir /var/lib/etcd -backup-dir /tmp/etcd_backup $ tar -zcxf backup.etcd.tar.gz /tmp/etcd_backup這個命令會將節(jié)點中的用戶數(shù)據(jù)全部寫入到指定的備份目錄中,但是節(jié)點ID,集群ID等信息將會丟失, 并在恢復到目的節(jié)點時被重新。這樣主要是防止原先的節(jié)點意外重新加入新的節(jié)點集群而導致數(shù)據(jù)混亂。
然后將Etcd數(shù)據(jù)恢復到新的集群的任意一個節(jié)點上, 使用?--force-new-cluster?參數(shù)啟動Etcd服務。這個參數(shù)會重置集群ID和集群的所有成員信息,其中節(jié)點的監(jiān)聽地址會被重置為localhost:2379, 表示集群中只有一個節(jié)點。
$ tar -zxvf backup.etcd.tar.gz -C /var/lib/etcd $ etcd --data-dir=/var/lib/etcd --force-new-cluster ...啟動完成單節(jié)點的etcd,可以先對數(shù)據(jù)的完整性進行驗證, 確認無誤后再通過Etcd API修改節(jié)點的監(jiān)聽地址,讓它監(jiān)聽節(jié)點的外部IP地址,為增加其他節(jié)點做準備。例如:
用etcd命令找到當前節(jié)點的ID。
$ etcdctl member list 98f0c6bf64240842: name=cd-2 peerURLs=http://127.0.0.1:2580 clientURLs=http://127.0.0.1:2579由于etcdctl不具備修改成員節(jié)點參數(shù)的功能, 下面的操作要使用API來完成。
$ curl http://127.0.0.1:2579/v2/members/98f0c6bf64240842 -XPUT \-H "Content-Type:application/json" -d '{"peerURLs":["http://127.0.0.1:2580"]}'注意,在Etcd文檔中, 建議首先將集群恢復到一個臨時的目錄中,從臨時目錄啟動etcd,驗證新的數(shù)據(jù)正確完整后,停止etcd,在將數(shù)據(jù)恢復到正常的目錄中。
最后,在完成第一個成員節(jié)點的啟動后,可以通過集群擴展的方法使用?etcdctl member add?命令添加其他成員節(jié)點進來。
?
擴展etcd集群
在集群中的任何一臺etcd節(jié)點上執(zhí)行命令,將新節(jié)點注冊到集群:
| 1 | curl http: //127 .0.0.1:2379 /v2/members? -XPOST -H? "Content-Type: application/json"? -d? '{"peerURLs": ["http://192.168.73.172:2380"]}' |
在新節(jié)點上啟動etcd容器,注意-initial-cluster-state參數(shù)為existing
| 1 2 3 4 5 6 7 8 9 10 11 | /usr/local/etcd/etcd \ -name etcd03 \ -advertise-client-urls http: //192 .168.73.150:2379,http: //192 .168.73.150:4001 \ -listen-client-urls http: //0 .0.0.0:2379 \ -initial-advertise-peer-urls http: //192 .168.73.150:2380 \ -listen-peer-urls http: //0 .0.0.0:2380 \ -initial-cluster-token etcd-cluster \ -initial-cluster? "etcd01=http://192.168.73.140:2380,etcd02=http://192.168.73.137:2380,etcd03=http://192.168.73.150:2380"? \ -initial-cluster-state existing |
任意節(jié)點執(zhí)行健康檢查:
| 1 2 3 4 | [root@docker01 ~] # etcdctl cluster-health member 2bd5fcc327f74dd5 is healthy: got healthy result from http: //192 .168.73.140:2379 member c8a9cac165026b12 is healthy: got healthy result from http: //192 .168.73.137:2379 cluster is healthy |
Etcd數(shù)據(jù)遷移
?
數(shù)據(jù)遷移
在 gzns-inf-platform53.gzns.baidu.com 機器上運行著一個 etcd 服務器,其 data-dir 為 /var/lib/etcd/。我們要以 /var/lib/etcd 中的數(shù)據(jù)為基礎,搭建一個包含三個節(jié)點的高可用的 etcd 集群,三個節(jié)點的主機名分別為:
gzns-inf-platform53.gzns.baidu.com gzns-inf-platform56.gzns.baidu.com gzns-inf-platform60.gzns.baidu.com初始化一個新的集群
我們先分別在上述三個節(jié)點上創(chuàng)建 /home/work/etcd/data-dir/ 文件夾當作 etcd 集群每個節(jié)點的數(shù)據(jù)存放目錄。然后以 gzns-inf-platform60.gzns.baidu.com 節(jié)點為起點創(chuàng)建一個單節(jié)點的 etcd 集群,啟動腳本 force-start-etcd.sh 如下:
#!/bin/bash# Don't start it unless etcd cluster has a heavily crash !../bin/etcd --name etcd2 --data-dir /home/work/etcd/data-dir --advertise-client-urls http://gzns-inf-platform60.gzns.baidu.com:2379,http://gzns-inf-platform60.gzns.baidu.com:4001 --listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 --initial-advertise-peer-urls http://gzns-inf-platform60.gzns.baidu.com:2380 --listen-peer-urls http://0.0.0.0:2380 --initial-cluster-token etcd-cluster-1 --initial-cluster etcd2=http://gzns-inf-platform60.gzns.baidu.com:2380 --force-new-cluster > ./log/etcd.log 2>&1這一步的?--force-new-cluster?很重要,可能是為了抹除舊 etcd 的一些屬性信息,從而能成功的創(chuàng)建一個單節(jié)點 etcd 的集群。
這時候通過
etcdctl member list查看 peerURLs 指向的是不是?http://gzns-inf-platform60.gzns.baidu.com:2380?? 如果不是,需要更新這個 etcd 的 peerURLs 的指向,否則這樣在加入新的節(jié)點時會失敗的。
我們手動更新這個 etcd 的 peerURLs 指向
etcdctl member update ce2a822cea30bfca http://gzns-inf-platform60.gzns.baidu.com:2380添加etcd1成員
然后添加 gzns-inf-platform56.gzns.baidu.com 節(jié)點上的 etcd1 成員
etcdctl member add etcd1 http://gzns-inf-platform56.gzns.baidu.com:2380注意要先添加 etcd1 成員后,再在 gzns-inf-platform56.gzns 機器上啟動這個 etcd1 成員
這時候我們登陸上 gzns-inf-platform56.gzns.baidu.com 機器上啟動這個 etcd1 實例,啟動腳本 force-start-etcd.sh 如下:
#!/bin/bash# Don't start it unless etcd cluster has a heavily crash !../bin/etcd --name etcd1 --data-dir /home/work/etcd/data-dir --advertise-client-urls http://gzns-inf-platform56.gzns.baidu.com:2379,http://gzns-inf-platform56.gzns.baidu.com:4001 --listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 --initial-advertise-peer-urls http://gzns-inf-platform56.gzns.baidu.com:2380 --listen-peer-urls http://0.0.0.0:2380 --initial-cluster-token etcd-cluster-1 --initial-cluster etcd2=http://gzns-inf-platform60.gzns.baidu.com:2380,etcd1=http://gzns-inf-platform56.gzns.baidu.com:2380 --initial-cluster-state existing > ./log/etcd.log 2>&1注意在這個節(jié)點上我們先把 data-dir 文件夾中的數(shù)據(jù)刪除(如果有內(nèi)容的情況下),然后設置 --initial-cluster和 --initial-cluster-state。
添加 etcd0 成員
這時候我們可以通過
etcdctl member list觀察到我們新加入的節(jié)點了,然后我們再以類似的步驟添加第三個節(jié)點 gzns-inf-platform53.gzns.baidu.com上 的 etcd0 實例
etcdctl member add etcd0 http://gzns-inf-platform53.gzns.baidu.com:2380然后登陸到 gzns-inf-platform53.gzns.baidu.com 機器上啟動 etcd0 這個實例,啟動腳本 force-start-etcd.sh 如下:
#!/bin/bash# Don't start it unless etcd cluster has a heavily crash !../bin/etcd --name etcd0 --data-dir /home/work/etcd/data-dir --advertise-client-urls http://gzns-inf-platform53.gzns.baidu.com:2379,http://gzns-inf-platform53.gzns.baidu.com:4001 --listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 --initial-advertise-peer-urls http://gzns-inf-platform53.gzns.baidu.com:2380 --listen-peer-urls http://0.0.0.0:2380 --initial-cluster-token etcd-cluster-1 --initial-cluster etcd2=http://gzns-inf-platform60.gzns.baidu.com:2380,etcd1=http://gzns-inf-platform56.gzns.baidu.com:2380,etcd0=http://gzns-inf-platform53.gzns.baidu.com:2380 --initial-cluster-state existing > ./log/etcd.log 2>&1過程同加入 etcd1 的過程相似,這樣我們就可以把單節(jié)點的 etcd 數(shù)據(jù)遷移到一個包含三個 etcd 實例組成的集群上了。
大體思路
先通過 --force-new-cluster 強行拉起一個 etcd 集群,抹除了原有 data-dir 中原有集群的屬性信息(內(nèi)部猜測),然后通過加入新成員的方式擴展這個集群到指定的數(shù)目。
高可用etcd集群方式(可選擇)
上面數(shù)據(jù)遷移的過程一般是在緊急的狀態(tài)下才會進行的操作,這時候可能 etcd 已經(jīng)停掉了,或者節(jié)點不可用了。在一般情況下如何搭建一個高可用的 etcd 集群呢,目前采用的方法是用 supervise 來監(jiān)控每個節(jié)點的 etcd 進程。
在數(shù)據(jù)遷移的過程中,我們已經(jīng)搭建好了一個包含三個節(jié)點的 etcd 集群了,這時候我們對其做一些改變,使用supervise 重新拉起這些進程。
首先登陸到 gzns-inf-platform60.gzns.baidu.com 節(jié)點上,kill 掉 etcd 進程,編寫 etcd 的啟動腳本 start-etcd.sh,其中 start-etcd.sh 的內(nèi)容如下:
#!/bin/bash ../bin/etcd --name etcd2 --data-dir /home/work/etcd/data-dir --advertise-client-urls http://gzns-inf-platform60.gzns.baidu.com:2379,http://gzns-inf-platform60.gzns.baidu.com:4001 --listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 --initial-advertise-peer-urls http://gzns-inf-platform60.gzns.baidu.com:2380 --listen-peer-urls http://0.0.0.0:2380 --initial-cluster-token etcd-cluster-1 --initial-cluster etcd2=http://gzns-inf-platform60.gzns.baidu.com:2380,etcd1=http://gzns-inf-platform56.gzns.baidu.com:2380,etcd0=http://gzns-inf-platform53.gzns.baidu.com:2380 --initial-cluster-state existing > ./log/etcd.log 2>&1然后使用 supervise 執(zhí)行 start-etcd.sh 這個腳本,使用 supervise 啟動 start-etcd.sh 的啟動腳本 etcd_control 如下:
#!/bin/shif [ $# -ne 1 ]; thenecho "$0: start|stop" fiwork_path=`dirname $0` cd ${work_path} work_path=`pwd`supervise=${work_path}/supervise/bin/supervise64.etcd mkdir -p ${work_path}/supervise/status/etcdcase "$1" in start) killall etcd supervise64.etcd${supervise} -f "sh ./start-etcd.sh" \-F ${work_path}/supervise/conf/supervise.conf \-p ${work_path}/supervise/status/etcdecho "START etcd daemon ok!" ;; stop)killall etcd supervise64.etcdif [ $? -ne 0 ] thenecho "STOP etcd daemon failed!"exit 1fi echo "STOP etcd daemon ok!"這里為什么不直接用 supervise 執(zhí)行 etcd 這個命令呢,反而以一個 start-etcd.sh 腳本的形式啟動這個 etcd 呢?原因在于我們需要將 etcd 的輸出信息重定向到文件中,
如果直接在 supervise 的 command 進行重定向,將發(fā)生錯誤。
分別登陸到以下兩臺機器
- gzns-inf-platform56.gzns.baidu.com
- gzns-inf-platform53.gzns.baidu.com
上進行同樣的操作,注意要針對每個節(jié)點的不同修改對應的etcd name 和 peerURLs 等。
常見問題
1、etcd 讀取已有的 data-dir 數(shù)據(jù)而啟動失敗,常常表現(xiàn)為cluster id not match什么的
可能原因是新啟動的 etcd 屬性與之前的不同,可以嘗 --force-new-cluster 選項的形式啟動一個新的集群
2、etcd 集群搭建完成后,通過 kubectl get pods 等一些操作發(fā)生錯誤的情況
目前解決辦法是重啟一下 apiserver 進程
3、還是 etcd啟動失敗的錯誤,大多數(shù)情況下都是與data-dir 有關(guān)系,data-dir 中記錄的信息與 etcd啟動的選項所標識的信息不太匹配造成的
如果能通過修改啟動參數(shù)解決這類錯誤就最好不過的了,非常情況下的解決辦法:
- 一種解決辦法是刪除data-dir文件
- 一種方法是復制其他節(jié)點的data-dir中的內(nèi)容,以此為基礎上以 --force-new-cluster 的形式強行拉起一個,然后以添加新成員的方式恢復這個集群,這是目前的幾種解決辦法
?
?
http://www.cnblogs.com/breg/p/5728237.html
轉(zhuǎn)載于:https://my.oschina.net/xiaominmin/blog/1598724
總結(jié)
以上是生活随笔為你收集整理的etcd集群部署与遇到的坑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: epoll的使用实例
- 下一篇: 分布式跟踪系统