etcd 架構以及內部機制
一個 etcd
的集群節點之間透過 Raft
一致性演算法完成分散式一致性協同,從圖中可以知道會有一個 leader
,而當該 leader
故障時,會自動再選取其它節點做為 leader
,同時也完成數據的同步,對於客戶端來說只要選取任一節點即可做讀寫操作,內部的狀態和數據協同由 etcd
自身完成。etcd
中還有一個 quorum
概念,其表示容忍故障的數量。
客戶端對 etcd
做操作時只需簡單的使用 HTTP
方式即可存取。對於其數據可以想成是鍵值做一個儲存。同時 etcd
為了使用戶端訂閱數據變更,支援 watch
機制,透過 watch
即時獲取 etcd
中數據的增量更新,從而實現與 etcd
中的數據同步等業務邏輯。
etcd
主要提供了一下接口
- Put(key, value), Del(key, value)
- Get(key), Get(keyFrom, keyEnd)
- Watch(key/keyPrefix)
- Transactions(if/then/else ops.).Commit()
- Leases: Grant/Revoke/KeepAlive
etcd 版本機制
etcd
中有 term
的概念,表示整個集群 Leader
的任期。只要 Leader
發生變化就會加 1。再者就是 revision
,表示全域數據版本,當數據發生變更,包括創建、修改、刪除等,其 revision
都會加 1。不過 Leader
發生切換時 revision
是延續的。
使用場景
Server Discovery (Naming Service)
Distributed Coordination: leader election
Distributed Coordination
Kubernetes 中的 etcd
在 Kubernetes 中元件間的通訊都是藉由 API Server
通訊,而 API Server
是和 etcd
通訊的唯一元件,因此在 Kubernetes 上所有狀態都是藉由 API Server
來修改。從下面這個系統上預設元件來看,etcd
、coredns
、apiserver
、controller-manager
和 scheduler
都運行在 master 上,我們所下達的 kubectl
相關命令都是 API Server
向 kubelete
(每個節點都會安裝的代理) 發起。
$ kubectl get pods -n kube-system -o custom-columns=POD:metadata.name,NODE:spec.nodeName
POD NODE
coredns-66bff467f8-5pfbz master
coredns-66bff467f8-v4txv master
etcd-master master
kube-apiserver-master master
kube-controller-manager-master master
kube-flannel-ds-amd64-gljsn master
kube-flannel-ds-amd64-s58vt node01
kube-flannel-ds-amd64-w2q8g node02
kube-proxy-fm749 master
kube-proxy-xpt4b node01
kube-proxy-xxlnx node02
kube-scheduler-master master
對於只有一個 master 來說其元件都沒有高可用性,如果有實現的話 etcd
和 API Server
將可以並行執行,相對的其它元件只有一個會做回應,其餘都是備援狀態。
如何使用 etcd
etcd
是一個分散式以 Key-value 做儲存的軟體,etcd
在 Kubernetes 中是唯一儲存集群狀態和一些數據的地方,那為何只有 API Server
可以對 etcd
讀寫?它避免了 Optimistic Concurrency Control
或是增強驗證系統,這樣替換元件時也方便。
儲存在 etcd 的資源
儲存在 etcd
中的資源依照目前不同版本有不一樣的做法,在第二版會是以檔案系統方式建立,而第三版是以 /
做為取代目錄。這邊補充一個 etcd
使用 RAFT
演算法保證一致性。
$ sudo apt install etcd-client # 安裝套件
這邊使用的環境是 kubeadm
架設的,而預設 etcd 使用 tls。
$ sudo ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key get /registry/namespaces/default -w=json | jq .
{
"header": {
"cluster_id": 14991974125033499000,
"member_id": 13655367627031355000,
"revision": 205622,
"raft_term": 2
},
"kvs": [
{
"key": "L3JlZ2lzdHJ5L25hbWVzcGFjZXMvZGVmYXVsdA==",
"create_revision": 152,
"mod_revision": 152,
"version": 1,
"value": "azhzAAoPCgJ2MRIJTmFtZXNwYWNlErIBCpcBCgdkZWZhdWx0EgAaACIAKiQwN2ZjNjg5NS1lZDY2LTRlZDMtYWFkYS03MDRiZThmN2FjYjcyADgAQggInrvu+QUQAHoAigFPCg5rdWJlLWFwaXNlcnZlchIGVXBkYXRlGgJ2MSIICJ677vkFEAAyCEZpZWxkc1YxOh0KG3siZjpzdGF0dXMiOnsiZjpwaGFzZSI6e319fRIMCgprdWJlcm5ldGVzGggKBkFjdGl2ZRoAIgA="
}
],
"count": 1
}
$ sudo ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key get /registry/namespaces/ --prefix -w=json | jq . # --prefix 查看子目錄
這邊的 Key 使用 base64 編碼,解碼後就可以知道其結構
$ echo L3JlZ2lzdHJ5L25hbWVzcGFjZXMvZGVmYXVsdA== | base64 -d
/registry/namespaces/default
參考資源
更新日期
- 2020-11-05 新增 etcd 相關小細節