一文入門 ETCD
摘要:# 設置一個key值 [root@etcd-0-8 ~]# etcdctl set /msg "hello k8s" hello k8s # 獲取key的值 [root@etcd-0-8 ~]# etcdctl get /msg hello k8s # 獲取key值的詳細信息 [root@etcd-0-8 ~]# etcdctl -o extended get /msg Key: /msg Created-Index: 12 Modified-Index: 12 TTL: 0 Index: 12 hello k8s # 獲取不存在的key回報錯 [root@etcd-0-8 ~]# etcdctl get /xxzx Error: 100: Key not found (/xxzx) [12] # 設置key的ttl,過期後會被自動刪除 [root@etcd-0-8 ~]# etcdctl set /testkey "tmp key test" --ttl 5 tmp key test [root@etcd-0-8 ~]# etcdctl get /testkey Error: 100: Key not found (/testkey) [14] # key 替換操作 [root@etcd-0-8 ~]# etcdctl get /msg hello k8s # [root@etcd-0-8 ~]# etcdctl set --swap-with-value "hello k8s" /msg "goodbye" goodbye [root@etcd-0-8 ~]# etcdctl get /msg goodbye # mk 僅當key不存在時創建(set對同一個key會覆蓋) [root@etcd-0-8 ~]# etcdctl get /msg goodbye [root@etcd-0-8 ~]# etcdctl mk /msg "mktest" Error: 105: Key already exists (/msg) [18] [root@etcd-0-8 ~]# etcdctl mk /msg1 "mktest" mktest # 創建自排序的key [root@etcd-0-8 ~]# etcdctl mk --in-order /queue s1 s1 [root@etcd-0-8 ~]# etcdctl mk --in-order /queue s2 s2 [root@etcd-0-8 ~]# etcdctl ls --sort /queue /queue/00000000000000000021 /queue/00000000000000000022 [root@etcd-0-8 ~]# etcdctl get /queue/00000000000000000021 s1 # 更新key值 [root@etcd-0-8 ~]# etcdctl update /msg1 "update test" update test [root@etcd-0-8 ~]# etcdctl get /msg1 update test # 更新key的ttl及值 [root@etcd-0-8 ~]# etcdctl update --ttl 5 /msg "aaa" aaa # 創建目錄 [root@etcd-0-8 ~]# etcdctl mkdir /testdir 刪除空目錄 [root@etcd-0-8 ~]# etcdctl mkdir /test1 [root@etcd-0-8 ~]# etcdctl rmdir /test1 刪除非空目錄 [root@etcd-0-8 ~]# etcdctl get /testdir /testdir: is a directory [root@etcd-0-8 ~]# etcdctl rm --recursive /testdir # 列出目錄內容 [root@etcd-0-8 ~]# etcdctl ls / /tmp /msg1 /queue [root@etcd-0-8 ~]# etcdctl ls /tmp /tmp/a /tmp/b # 遞歸列出目錄的內容 [root@etcd-0-8 ~]# etcdctl ls --recursive / /msg1 /queue /queue/00000000000000000021 /queue/00000000000000000022 /tmp /tmp/b /tmp/a # 監聽key,當key發生改變的時候打印出變化 [root@etcd-0-8 ~]# etcdctl watch /msg1 xxx [root@VM_0_17_centos ~]# etcdctl update /msg1 "xxx" xxx # 監聽某個目錄,當目錄中任何 node 改變的時候,都會打印出來 [root@etcd-0-8 ~]# etcdctl watch --recursive / [update] /msg1 xxx [root@VM_0_17_centos ~]# etcdctl update /msg1 "xxx" xxx # 一直監聽,除非 `CTL + C` 導致退出監聽 [root@etcd-0-8 ~]# etcdctl watch --forever / # 監聽目錄,當發生變化時執行一條命令 [root@etcd-0-8 ~]# etcdctl exec-watch --recursive / -- sh -c "echo change" change backup [root@etcd-0-14 ~]# etcdctl backup --data-dir /data/app/etcd --backup-dir /root/etcd_backup 2019-12-04 10:25:16.113237 I | ignoring EntryConfChange raft entry 2019-12-04 10:25:16.113268 I | ignoring EntryConfChange raft entry 2019-12-04 10:25:16.113272 I | ignoring EntryConfChange raft entry 2019-12-04 10:25:16.113293 I | ignoring member attribute update on /0/members/2d2e457c6a1a76cb/attributes 2019-12-04 10:25:16.113299 I | ignoring member attribute update on /0/members/d2d2e9fc758e6790/attributes 2019-12-04 10:25:16.113305 I | ignoring member attribute update on /0/members/56e0b6dad4c53d42/attributes 2019-12-04 10:25:16.113310 I | ignoring member attribute update on /0/members/56e0b6dad4c53d42/attributes 2019-12-04 10:25:16.113314 I | ignoring member attribute update on /0/members/2d2e457c6a1a76cb/attributes 2019-12-04 10:25:16.113319 I | ignoring member attribute update on /0/members/d2d2e9fc758e6790/attributes 2019-12-04 10:25:16.113384 I | ignoring member attribute update on /0/members/56e0b6dad4c53d42/attributes # 使用v3版本 [root@etcd-0-14 ~]# export ETCDCTL_API=3 [root@etcd-0-14 ~]# etcdctl --endpoints="http://172.16.0.8:2379,http://172.16.0.14:2379,http://172.16.0.17:2379" snapshot save mysnapshot.db Snapshot saved at mysnapshot.db [root@etcd-0-14 ~]# etcdctl snapshot status mysnapshot.db -w json {"hash":928285884,"revision":0,"totalKey":5,"totalSize":20480}。[root@etcd-0-8 app]# cat /etc/etcd/etcd.conf [Member] ETCD_CORS="" ETCD_DATA_DIR="/data/app/etcd/" # etcd數據存儲目錄,建議存儲在數據盤 ETCD_WAL_DIR="" ETCD_LISTEN_PEER_URLS="http://172.16.0.8:2380" # 與同伴的通訊地址,和其他節點同伴的通訊地址 ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.8:2379" # 對外提供服務的地址 ETCD_MAX_SNAPSHOTS="5" #ETCD_MAX_WALS="5" ETCD_NAME="etcd-0-8" # etcd節點名稱,集羣內需要唯一 #ETCD_SNAPSHOT_COUNT="100000" #ETCD_HEARTBEAT_INTERVAL="100" #ETCD_ELECTION_TIMEOUT="1000" #ETCD_QUOTA_BACKEND_BYTES="0" ETCD_MAX_REQUEST_BYTES="1572864" ETCD_GRPC_KEEPALIVE_MIN_TIME="5s" ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s" ETCD_GRPC_KEEPALIVE_TIMEOUT="20s" [Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.8:2380" # 該節點同伴監聽地址,這個值會告訴集羣中其他節點 ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.8:2379" # 對外公告的該節點客戶端監聽地址,這個值會告訴集羣中其他節點 ETCD_DISCOVERY="" ETCD_DISCOVERY_FALLBACK="proxy" ETCD_DISCOVERY_PROXY="" ETCD_DISCOVERY_SRV="" ETCD_INITIAL_CLUSTER="etcd-0-8=http://172.16.0.8:2380,etcd-0-17=http://172.16.0.17:2380,etcd-0-14=http://172.16.0.14:2380" # 集羣中所有節點的信 ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" # 創建集羣的 token,這個值每個集羣保持唯一。
背景:近期k8s應用中etcd的功能存在一些困惑,對其進行來單獨的學習,能更深入理解k8s中的的一些特性。
1.1 etcd簡介
etcd是CoreOS團隊於2013年6月發起的開源項目,它的目標是構建一個高可用的分佈式鍵值(key-value)數據庫。etcd內部採用 raft
協議作爲一致性算法,etcd基於Go語言實現。
1.2 發展歷史
1.3 etcd的特點
- 簡單:安裝配置簡單,而且提供了HTTP API進行交互,使用也很簡單
- 安全:支持SSL證書驗證
- 快速:根據官方提供的benchmark數據,單實例支持每秒2k+讀操作
- 可靠:採用raft算法,實現分佈式系統數據的可用性和一致性
1.4 概念術語
-
Raft:etcd所採用的保證分佈式系統強一致性的算法。
-
Node:一個Raft狀態機實例。
-
Member: 一個etcd實例。它管理着一個Node,並且可以爲客戶端請求提供服務。
-
Cluster:由多個Member構成可以協同工作的etcd集羣。
-
Peer:對同一個etcd集羣中另外一個Member的稱呼。
-
Client: 向etcd集羣發送HTTP請求的客戶端。
-
WAL:預寫式日誌,etcd用於持久化存儲的日誌格式。
-
snapshot:etcd防止WAL文件過多而設置的快照,存儲etcd數據狀態。
-
Proxy:etcd的一種模式,爲etcd集羣提供反向代理服務。
-
Leader:Raft算法中通過競選而產生的處理所有數據提交的節點。
-
Follower:競選失敗的節點作爲Raft中的從屬節點,爲算法提供強一致性保證。
-
Candidate:當Follower超過一定時間接收不到Leader的心跳時轉變爲Candidate開始競選。
-
Term:某個節點成爲Leader到下一次競選時間,稱爲一個Term。
-
Index:數據項編號。Raft中通過Term和Index來定位數據。
1.5 數據讀寫順序
爲了保證數據的強一致性,etcd集羣中所有的數據流向都是一個方向,從 Leader (主節點)流向 Follower,也就是所有 Follower 的數據必須與 Leader 保持一致,如果不一致會被覆蓋。
用戶對於etcd集羣所有節點進行讀寫
- 讀取:由於集羣所有節點數據是強一致性的,讀取可以從集羣中隨便哪個節點進行讀取數據
- 寫入:etcd集羣有leader,如果寫入往leader寫入,可以直接寫入,然後然後Leader節點會把寫入分發給所有Follower,如果往follower寫入,然後Leader節點會把寫入分發給所有Follower
1.6 leader選舉
假設三個節點的集羣,三個節點上均運行Timer(每個Timer持續時間是隨機的),Raft算法使用隨機Timer來初始化Leader選舉流程,第一個節點率先完成了Timer,隨後它就會向其他兩個節點發送成爲Leader的請求,其他節點接收到請求後會以投票回應然後第一個節點被選舉爲Leader。
成爲Leader後,該節點會以固定時間間隔向其他節點發送通知,確保自己仍是Leader。有些情況下當Follower們收不到Leader的通知後,比如說Leader節點宕機或者失去了連接,其他節點會重複之前選舉過程選舉出新的Leader。
1.7 判斷數據是否寫入
etcd認爲寫入請求被Leader節點處理並分發給了多數節點後,就是一個成功的寫入。那麼多少節點如何判定呢,假設總結點數是N,那麼多數節點 Quorum=N/2+1
。關於如何確定etcd集羣應該有多少個節點的問題,上圖的左側的圖表給出了集羣中節點總數(Instances)對應的Quorum數量,用Instances減去Quorom就是集羣中容錯節點(允許出故障的節點)的數量。
所以在集羣中推薦的最少節點數量是3個,因爲1和2個節點的容錯節點數都是0,一旦有一個節點宕掉整個集羣就不能正常工作了。
二 etcd架構及解析
2.1 架構圖
2.2 架構解析
從 etcd 的架構圖中我們可以看到,etcd 主要分爲四個部分。
- HTTP Server:用於處理用戶發送的 API 請求以及其它 etcd 節點的同步與心跳信息請求。
- Store:用於處理 etcd 支持的各類功能的事務,包括數據索引、節點狀態變更、監控與反饋、事件處理與執行等等,是 etcd 對用戶提供的大多數 API 功能的具體實現。
- Raft:Raft 強一致性算法的具體實現,是 etcd 的核心。
- WAL:Write Ahead Log(預寫式日誌),是 etcd 的數據存儲方式。除了在內存中存有所有數據的狀態以及節點的索引以外,etcd 就通過 WAL 進行持久化存儲。WAL 中,所有的數據提交前都會事先記錄日誌。
- Snapshot 是爲了防止數據過多而進行的狀態快照;
- Entry 表示存儲的具體日誌內容。
通常,一個用戶的請求發送過來,會經由 HTTP Server 轉發給 Store 進行具體的事務處理,如果涉及到節點的修改,則交給 Raft 模塊進行狀態的變更、日誌的記錄,然後再同步給別的 etcd 節點以確認數據提交,最後進行數據的提交,再次同步。
三 應用場景
3.1 服務註冊與發現
etcd可以用於服務的註冊與發現
中間價已經後端服務在etcd中註冊,前端和中間價可以很輕鬆的從etcd中發現相關服務器然後服務器之間根據調用關係相關綁定調用
後端多個無狀態相同副本的app可以同事註冊到etcd中,前端可以通過haproxy從etcd中獲取到後端的ip和端口組,然後進行請求轉發,可以用來故障轉移屏蔽後端端口已經後端多組app實例。
3.2 消息發佈與訂閱
etcd可以充當消息中間件,生產者可以往etcd中註冊topic併發送消息,消費者從etcd中訂閱topic,來獲取生產者發送至etcd中的消息。
3.3 負載均衡
後端多組相同的服務提供者可以經自己服務註冊到etcd中,etcd並且會與註冊的服務進行監控檢查,服務請求這首先從etcd中獲取到可用的服務提供者真正的ip:port,然後對此多組服務發送請求,etcd在其中充當了負載均衡的功能
3.4 分部署通知與協調
- 當etcd watch服務發現丟失,會通知服務檢查
- 控制器向etcd發送啓動服務,etcd通知服務進行相應操作
- 當服務完成work會講狀態更新至etcd,etcd對應會通知用戶
3.5 分佈式鎖
當有多個競爭者node節點,etcd作爲總控,在分佈式集羣中與一個節點成功分配lock
3.6 分佈式隊列
有對個node,etcd根據每個node來創建對應node的隊列,根據不同的隊列可以在etcd中找到對應的competitor
3.7 集羣與監控與Leader選舉
etcd可以根據raft算法在多個node節點來選舉出leader
四 安裝部署
4.1 單機部署
可以使用二進制或源碼下載安裝,但是危害需要自己寫配置文件,如何要啓動需要自己寫服務啓動文件,推薦使用yum安裝方式
hostnamectl set-hostname etcd-1 wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -ivh epel-release-latest-7.noarch.rpm yum 倉庫中的etcd版本爲3.3.11,如果需要最新版本的etcd可以進行二進制安裝 yum -y install etcd systemctl enable etcd
可以查看yum安裝的etcd的有效配置文件,根據自己的需求來修改數據存儲目錄,已經監聽端口url/etcd的名稱等
- etcd 默認將數據存放到當前路徑的
default.etcd/
目錄下 - 在
http://localhost:2380
和集羣中其他節點通信 - 在
http://localhost:2379
提供 HTTP API 服務,供客戶端交互 - 該節點的名稱默認爲
default
- heartbeat 爲 100ms,後面會說明這個配置的作用
- election 爲 1000ms,後面會說明這個配置的作用
- snapshot count 爲 10000,後面會說明這個配置的作用
- 集羣和每個節點都會生成一個 uuid
- 啓動的時候,會運行 raft,選舉出 leader
[root@VM_0_8_centos tmp]# grep -Ev "^#|^$" /etc/etcd/etcd.conf ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_CLIENT_URLS="http://localhost:2379" ETCD_NAME="default" ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379" [root@VM_0_8_centos tmp]# systemctl status etcd
4.2 集羣部署
集羣部署最好部署奇數位,此能達到最好的集羣容錯
4.2.1 主機信息
主機名稱 | 系統 | IP地址 | 部署組件 |
---|---|---|---|
etcd-0-8 | CentOS 7.3 | 172.16.0.8 | etcd |
etcd-0-17 | CentOS 7.3 | 172.16.0.17 | etcd |
etcd-0-14 | CentOS 7.3 | 172.16.0.14 | etcd |
4.2.2 host配置
在此示例用三個節點來部署etcd集羣,各節點修改hosts
cat >> /etc/hosts << EOF 172.16.0.8 etcd-0-8 172.16.0.14 etcd-0-14 172.16.0.17 etcd-0-17 EOF
4.2.3 etcd安裝
三個節點均安裝etcd
wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -ivh epel-release-latest-7.noarch.rpm yum -y install etcd systemctl enable etcd mkdir -p /data/app/etcd/ chown etcd:etcd /data/app/etcd/
4.2.4 etcd配置
[root@etcd-0-8 app]# cat /etc/etcd/etcd.conf [Member] ETCD_CORS="" ETCD_DATA_DIR="/data/app/etcd/" # etcd數據存儲目錄,建議存儲在數據盤 ETCD_WAL_DIR="" ETCD_LISTEN_PEER_URLS="http://172.16.0.8:2380" # 與同伴的通訊地址,和其他節點同伴的通訊地址 ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.8:2379" # 對外提供服務的地址 ETCD_MAX_SNAPSHOTS="5" #ETCD_MAX_WALS="5" ETCD_NAME="etcd-0-8" # etcd節點名稱,集羣內需要唯一 #ETCD_SNAPSHOT_COUNT="100000" #ETCD_HEARTBEAT_INTERVAL="100" #ETCD_ELECTION_TIMEOUT="1000" #ETCD_QUOTA_BACKEND_BYTES="0" ETCD_MAX_REQUEST_BYTES="1572864" ETCD_GRPC_KEEPALIVE_MIN_TIME="5s" ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s" ETCD_GRPC_KEEPALIVE_TIMEOUT="20s" [Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.8:2380" # 該節點同伴監聽地址,這個值會告訴集羣中其他節點 ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.8:2379" # 對外公告的該節點客戶端監聽地址,這個值會告訴集羣中其他節點 ETCD_DISCOVERY="" ETCD_DISCOVERY_FALLBACK="proxy" ETCD_DISCOVERY_PROXY="" ETCD_DISCOVERY_SRV="" ETCD_INITIAL_CLUSTER="etcd-0-8=http://172.16.0.8:2380,etcd-0-17=http://172.16.0.17:2380,etcd-0-14=http://172.16.0.14:2380" # 集羣中所有節點的信 ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" # 創建集羣的 token,這個值每個集羣保持唯一。這樣的話,如果你要重新創建集羣,即使配置和之前一樣,也會再次生成新的集羣和節點 uuid;否則會導致多個集羣之間的衝突,造成未知的錯誤 ETCD_INITIAL_CLUSTER_STATE="new" ETCD_STRICT_RECONFIG_CHECK="true" #ETCD_ENABLE_V2="true" [Proxy] ETCD_PROXY="off" ETCD_PROXY_FAILURE_WAIT="5000" ETCD_PROXY_REFRESH_INTERVAL="30000" ETCD_PROXY_DIAL_TIMEOUT="1000" ETCD_PROXY_WRITE_TIMEOUT="5000" ETCD_PROXY_READ_TIMEOUT="0" [Security] ETCD_CERT_FILE="" ETCD_KEY_FILE="" ETCD_CLIENT_CERT_AUTH="false" ETCD_TRUSTED_CA_FILE="" ETCD_AUTO_TLS="false" ETCD_PEER_CERT_FILE="" ETCD_PEER_KEY_FILE="" ETCD_PEER_CLIENT_CERT_AUTH="false" ETCD_PEER_TRUSTED_CA_FILE="" ETCD_PEER_AUTO_TLS="false" [Logging] ETCD_DEBUG="false" ETCD_LOG_PACKAGE_LEVELS="" ETCD_LOG_OUTPUT="default" [Unsafe] ETCD_FORCE_NEW_CLUSTER="false" [Version] ETCD_VERSION="false" ETCD_AUTO_COMPACTION_RETENTION="0" [Profiling] ETCD_ENABLE_PPROF="false" ETCD_METRICS="basic" [Auth] ETCD_AUTH_TOKEN="simple"
etcd-0-8配置:
[root@etcd-server ~]# hostnamectl set-hostname etcd-0-8 [root@etcd-0-8 ~]# egrep "^#|^$" /etc/etcd/etcd.conf -v ETCD_DATA_DIR="/data/app/etcd/" ETCD_LISTEN_PEER_URLS="http://172.16.0.8:2380" ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.8:2379" ETCD_NAME="etcd-0-8" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.8:2380" ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.8:2379" ETCD_INITIAL_CLUSTER="etcd-0-8=http://172.16.0.8:2380,etcd-0-17=http://172.16.0.17:2380,etcd-0-14=http://172.16.0.14:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" ETCD_INITIAL_CLUSTER_STATE="new"
etcd-0-14配置:
[root@etcd-server ~]# hostnamectl set-hostname etcd-0-14 [root@etcd-server ~]# mkdir -p /data/app/etcd/ [[email protected] ~]# egrep "^#|^$" /etc/etcd/etcd.conf -v ETCD_DATA_DIR="/data/app/etcd/" ETCD_LISTEN_PEER_URLS="http://172.16.0.14:2380" ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.14:2379" ETCD_NAME="etcd-0-14" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.14:2380" ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.14:2379" ETCD_INITIAL_CLUSTER="etcd-0-8=http://172.16.0.8:2380,etcd-0-17=http://172.16.0.17:2380,etcd-0-14=http://172.16.0.14:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" ETCD_INITIAL_CLUSTER_STATE="new"
[root@etcd-server ~]# hostnamectl set-hostname etcd-0-17 [root@etcd-server ~]# mkdir -p /data/app/etcd/ [root@etcd-0-17 ~]# egrep "^#|^$" /etc/etcd/etcd.conf -v ETCD_DATA_DIR="/data/app/etcd/" ETCD_LISTEN_PEER_URLS="http://172.16.0.17:2380" ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.17:2379" ETCD_NAME="etcd-0-17" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.0.17:2380" ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://172.16.0.17:2379" ETCD_INITIAL_CLUSTER="etcd-0-8=http://172.16.0.8:2380,etcd-0-17=http://172.16.0.17:2380,etcd-0-14=http://172.16.0.14:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-token" ETCD_INITIAL_CLUSTER_STATE="new"
systemctl start etcd
4.2.5 查看集羣狀態
[root@etcd-0-8 default.etcd]# systemctl status etcd ● etcd.service - Etcd Server Loaded: loaded (/usr/lib/systemd/system/etcd.service; enabled; vendor preset: disabled) Active: active (running) since 二 2019-12-03 15:55:28 CST; 8s ago Main PID: 24510 (etcd) CGroup: /system.slice/etcd.service └─24510 /usr/bin/etcd --name=etcd-0-8 --data-dir=/data/app/etcd/ --listen-client-urls=http://172.16.0.8:2379 12月 03 15:55:28 etcd-0-8 etcd[24510]: set the initial cluster version to 3.0 12月 03 15:55:28 etcd-0-8 etcd[24510]: enabled capabilities for version 3.0 12月 03 15:55:30 etcd-0-8 etcd[24510]: peer 56e0b6dad4c53d42 became active 12月 03 15:55:30 etcd-0-8 etcd[24510]: established a TCP streaming connection with peer 56e0b6dad4c53d42 (stream Message reader) 12月 03 15:55:30 etcd-0-8 etcd[24510]: established a TCP streaming connection with peer 56e0b6dad4c53d42 (stream Message writer) 12月 03 15:55:30 etcd-0-8 etcd[24510]: established a TCP streaming connection with peer 56e0b6dad4c53d42 (stream MsgApp v2 reader) 12月 03 15:55:30 etcd-0-8 etcd[24510]: established a TCP streaming connection with peer 56e0b6dad4c53d42 (stream MsgApp v2 writer) 12月 03 15:55:32 etcd-0-8 etcd[24510]: updating the cluster version from 3.0 to 3.3 12月 03 15:55:32 etcd-0-8 etcd[24510]: updated the cluster version from 3.0 to 3.3 12月 03 15:55:32 etcd-0-8 etcd[24510]: enabled capabilities for version 3.3
- 查看端口監聽(如果未在本地監聽環回地址,那麼在本地使用etcdctl不能正常連入進去)
[root@etcd-0-8 default.etcd]# netstat -lntup |grep etcd tcp 0 0 172.16.0.8:2379 0.0.0.0:* LISTEN 25167/etcd tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 25167/etcd tcp 0 0 172.16.0.8:2380 0.0.0.0:* LISTEN 25167/etcd
[root@etcd-0-8 default.etcd]# etcdctl member list 2d2e457c6a1a76cb: name=etcd-0-8 peerURLs=http://172.16.0.8:2380 clientURLs=http://127.0.0.1:2379,http://172.16.0.8:2379 isLeader=false 56e0b6dad4c53d42: name=etcd-0-14 peerURLs=http://172.16.0.14:2380 clientURLs=http://127.0.0.1:2379,http://172.16.0.14:2379 isLeader=true d2d2e9fc758e6790: name=etcd-0-17 peerURLs=http://172.16.0.17:2380 clientURLs=http://127.0.0.1:2379,http://172.16.0.17:2379 isLeader=false [root@etcd-0-8 ~]# etcdctl cluster-health member 2d2e457c6a1a76cb is healthy: got healthy result from http://127.0.0.1:2379 member 56e0b6dad4c53d42 is healthy: got healthy result from http://127.0.0.1:2379 member d2d2e9fc758e6790 is healthy: got healthy result from http://127.0.0.1:2379 cluster is healthy
五 簡單使用
5.1 增加
指定某個鍵的值。例如:
$ etcdctl set /testdir/testkey "Hello world" Hello world
支持的選項包括:
--ttl '0' 該鍵值的超時時間(單位爲秒),不配置(默認爲0)則永不超時 --swap-with-value value 若該鍵現在的值是value,則進行設置操作 --swap-with-index '0' 若該鍵現在的索引值是指定索引,則進行設置操作
如果給定的鍵不存在,則創建一個新的鍵值。例如:
$ etcdctl mk /testdir/testkey "Hello world" Hello world
當鍵存在的時候,執行該命令會報錯,例如:
$ etcdctl mk /testdir/testkey "Hello world" Error: 105: Key already exists (/testdir/testkey) [8]
支持的選項爲:
--ttl '0' 超時時間(單位爲秒),不配置(默認爲 0)。則永不超時
如果給定的鍵目錄不存在,則創建一個新的鍵目錄。例如:
$ etcdctl mkdir testdir2
當鍵目錄存在的時候,執行該命令會報錯,例如:
$ etcdctl mkdir testdir2 Error: 105: Key already exists (/testdir2) [9]
支持的選項爲:
--ttl '0' 超時時間(單位爲秒),不配置(默認爲0)則永不超時。
創建一個鍵目錄。如果目錄不存在就創建,如果目錄存在更新目錄TTL。
$ etcdctl setdir testdir3
支持的選項爲:
--ttl '0' 超時時間(單位爲秒),不配置(默認爲0)則永不超時。
5.2 刪除
刪除某個鍵值。例如:
$ etcdctl rm /testdir/testkey PrevNode.Value: Hello
當鍵不存在時,則會報錯。例如:
$ etcdctl rm /testdir/testkey Error: 100: Key not found (/testdir/testkey) [7]
支持的選項爲:
--dir 如果鍵是個空目錄或者鍵值對則刪除 --recursive 刪除目錄和所有子鍵 --with-value 檢查現有的值是否匹配 --with-index '0'檢查現有的index是否匹配
刪除一個空目錄,或者鍵值對。
$ etcdctl setdir dir1 $ etcdctl rmdir dir1
若目錄不空,會報錯:
$ etcdctl set /dir/testkey hi hi $ etcdctl rmdir /dir Error: 108: Directory not empty (/dir) [17]
5.3 更新
當鍵存在時,更新值內容。例如:
$ etcdctl update /testdir/testkey "Hello" Hello
當鍵不存在時,則會報錯。例如:
$ etcdctl update /testdir/testkey2 "Hello" Error: 100: Key not found (/testdir/testkey2) [6]
支持的選項爲:
--ttl '0' 超時時間(單位爲秒),不配置(默認爲 0)則永不超時。
更新一個已經存在的目錄。
$ etcdctl updatedir testdir2
支持的選項爲:
--ttl '0' 超時時間(單位爲秒),不配置(默認爲0)則永不超時。
5.4 查詢
獲取指定鍵的值。例如:
$ etcdctl get /testdir/testkey Hello world
當鍵不存在時,則會報錯。例如:
$ etcdctl get /testdir/testkey2 Error: 100: Key not found (/testdir/testkey2) [5]
支持的選項爲:
--sort 對結果進行排序 --consistent 將請求發給主節點,保證獲取內容的一致性。
列出目錄(默認爲根目錄)下的鍵或者子目錄,默認不顯示子目錄中內容。
例如:
$ etcdctl ls /testdir /testdir2 /dir $ etcdctl ls dir /dir/testkey
支持的選項包括:
--sort 將輸出結果排序 --recursive 如果目錄下有子目錄,則遞歸輸出其中的內容 -p 對於輸出爲目錄,在最後添加/進行區分
5.5 watch
監測一個鍵值的變化,一旦鍵值發生更新,就會輸出最新的值並退出。
例如:用戶更新testkey鍵值爲Hello watch。
$ etcdctl get /testdir/testkey Hello world $ etcdctl set /testdir/testkey "Hello watch" Hello watch $ etcdctl watch testdir/testkey Hello watch
支持的選項包括:
--forever 一直監測直到用戶按CTRL+C退出 --after-index '0' 在指定index之前一直監測 --recursive 返回所有的鍵值和子鍵值
監測一個鍵值的變化,一旦鍵值發生更新,就執行給定命令。
例如:用戶更新testkey鍵值。
$ etcdctl exec-watch testdir/testkey -- sh -c 'ls' config Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
支持的選項包括:
--after-index '0' 在指定 index 之前一直監測 --recursive 返回所有的鍵值和子鍵值
5.6 備份
備份etcd的數據。
$ etcdctl backup --data-dir /var/lib/etcd --backup-dir /home/etcd_backup
支持的選項包括:
--data-dir etcd的數據目錄 --backup-dir 備份到指定路徑
5.7 member
通過 list
、 add
、 remove
命令列出、添加、刪除etcd實例到etcd集羣中。
查看集羣中存在的節點
$ etcdctl member list 8e9e05c52164694d: name=dev-master-01 peerURLs=http://localhost:2380 clientURLs=http://localhost:2379 isLeader=true
刪除集羣中存在的節點
$ etcdctl member remove 8e9e05c52164694d Removed member 8e9e05c52164694d from cluster
向集羣中新加節點
$ etcdctl member add etcd3 http://192.168.1.100:2380 Added member named etcd3 with ID 8e9e05c52164694d to cluster
示例:
# 設置一個key值 [root@etcd-0-8 ~]# etcdctl set /msg "hello k8s" hello k8s # 獲取key的值 [root@etcd-0-8 ~]# etcdctl get /msg hello k8s # 獲取key值的詳細信息 [root@etcd-0-8 ~]# etcdctl -o extended get /msg Key: /msg Created-Index: 12 Modified-Index: 12 TTL: 0 Index: 12 hello k8s # 獲取不存在的key回報錯 [root@etcd-0-8 ~]# etcdctl get /xxzx Error: 100: Key not found (/xxzx) [12] # 設置key的ttl,過期後會被自動刪除 [root@etcd-0-8 ~]# etcdctl set /testkey "tmp key test" --ttl 5 tmp key test [root@etcd-0-8 ~]# etcdctl get /testkey Error: 100: Key not found (/testkey) [14] # key 替換操作 [root@etcd-0-8 ~]# etcdctl get /msg hello k8s # [root@etcd-0-8 ~]# etcdctl set --swap-with-value "hello k8s" /msg "goodbye" goodbye [root@etcd-0-8 ~]# etcdctl get /msg goodbye # mk 僅當key不存在時創建(set對同一個key會覆蓋) [root@etcd-0-8 ~]# etcdctl get /msg goodbye [root@etcd-0-8 ~]# etcdctl mk /msg "mktest" Error: 105: Key already exists (/msg) [18] [root@etcd-0-8 ~]# etcdctl mk /msg1 "mktest" mktest # 創建自排序的key [root@etcd-0-8 ~]# etcdctl mk --in-order /queue s1 s1 [root@etcd-0-8 ~]# etcdctl mk --in-order /queue s2 s2 [root@etcd-0-8 ~]# etcdctl ls --sort /queue /queue/00000000000000000021 /queue/00000000000000000022 [root@etcd-0-8 ~]# etcdctl get /queue/00000000000000000021 s1 # 更新key值 [root@etcd-0-8 ~]# etcdctl update /msg1 "update test" update test [root@etcd-0-8 ~]# etcdctl get /msg1 update test # 更新key的ttl及值 [root@etcd-0-8 ~]# etcdctl update --ttl 5 /msg "aaa" aaa # 創建目錄 [root@etcd-0-8 ~]# etcdctl mkdir /testdir 刪除空目錄 [root@etcd-0-8 ~]# etcdctl mkdir /test1 [root@etcd-0-8 ~]# etcdctl rmdir /test1 刪除非空目錄 [root@etcd-0-8 ~]# etcdctl get /testdir /testdir: is a directory [root@etcd-0-8 ~]# etcdctl rm --recursive /testdir # 列出目錄內容 [root@etcd-0-8 ~]# etcdctl ls / /tmp /msg1 /queue [root@etcd-0-8 ~]# etcdctl ls /tmp /tmp/a /tmp/b # 遞歸列出目錄的內容 [root@etcd-0-8 ~]# etcdctl ls --recursive / /msg1 /queue /queue/00000000000000000021 /queue/00000000000000000022 /tmp /tmp/b /tmp/a # 監聽key,當key發生改變的時候打印出變化 [root@etcd-0-8 ~]# etcdctl watch /msg1 xxx [root@VM_0_17_centos ~]# etcdctl update /msg1 "xxx" xxx # 監聽某個目錄,當目錄中任何 node 改變的時候,都會打印出來 [root@etcd-0-8 ~]# etcdctl watch --recursive / [update] /msg1 xxx [root@VM_0_17_centos ~]# etcdctl update /msg1 "xxx" xxx # 一直監聽,除非 `CTL + C` 導致退出監聽 [root@etcd-0-8 ~]# etcdctl watch --forever / # 監聽目錄,當發生變化時執行一條命令 [root@etcd-0-8 ~]# etcdctl exec-watch --recursive / -- sh -c "echo change" change backup [root@etcd-0-14 ~]# etcdctl backup --data-dir /data/app/etcd --backup-dir /root/etcd_backup 2019-12-04 10:25:16.113237 I | ignoring EntryConfChange raft entry 2019-12-04 10:25:16.113268 I | ignoring EntryConfChange raft entry 2019-12-04 10:25:16.113272 I | ignoring EntryConfChange raft entry 2019-12-04 10:25:16.113293 I | ignoring member attribute update on /0/members/2d2e457c6a1a76cb/attributes 2019-12-04 10:25:16.113299 I | ignoring member attribute update on /0/members/d2d2e9fc758e6790/attributes 2019-12-04 10:25:16.113305 I | ignoring member attribute update on /0/members/56e0b6dad4c53d42/attributes 2019-12-04 10:25:16.113310 I | ignoring member attribute update on /0/members/56e0b6dad4c53d42/attributes 2019-12-04 10:25:16.113314 I | ignoring member attribute update on /0/members/2d2e457c6a1a76cb/attributes 2019-12-04 10:25:16.113319 I | ignoring member attribute update on /0/members/d2d2e9fc758e6790/attributes 2019-12-04 10:25:16.113384 I | ignoring member attribute update on /0/members/56e0b6dad4c53d42/attributes # 使用v3版本 [root@etcd-0-14 ~]# export ETCDCTL_API=3 [root@etcd-0-14 ~]# etcdctl --endpoints="http://172.16.0.8:2379,http://172.16.0.14:2379,http://172.16.0.17:2379" snapshot save mysnapshot.db Snapshot saved at mysnapshot.db [root@etcd-0-14 ~]# etcdctl snapshot status mysnapshot.db -w json {"hash":928285884,"revision":0,"totalKey":5,"totalSize":20480}
六 總結
-
etcd 默認只保存 1000 個歷史事件,所以不適合有大量更新操作的場景,這樣會導致數據的丟失。 etcd 典型的應用場景是配置管理和服務發現,這些場景都是讀多寫少的。
-
相比於 zookeeper,etcd 使用起來要簡單很多。不過要實現真正的服務發現功能,etcd 還需要和其他工具(比如 registrator、confd 等)一起使用來實現服務的自動註冊和更新。
-
目前 etcd 還沒有圖形化的工具。