聊聊Etcd
Etcd是什么
Etcd
是一個分布式的,一致的key-value
存儲,主要用于共享配置和服務發現。Etcd是由CoreOS
開發并維護,通過Raft
一致性算法處理日志復制以保證強一致性。Raft
是一個來自Stanford
的新的一致性算法,適用于分布式系統的日志復制,Raft
通過選舉的方式來實現一致性,在Raft
中,任何一個節點都可能成為leader
。
Etcd
存儲了k8s集群中所有的元數據(以key-value的方式), K8s中所有元數據的增刪改查都是由kube-apiserver來執行的
Raft算法
raft
是工程上使用較為廣泛的強一致性、去中心化、高可用的分布式協議
參考:
leader選舉
raft協議中,一個節點任一時刻處于以下三個狀態之一:
- leader #領導者
- follower #追隨者
- candidate #候選人
所有節點啟動時都是follower狀態;在一段時間內如果沒有收到來自leader的心跳,從follower切換到candidate,發起選舉;如果收到多數的贊成票(含自己的一票)則切換到leader狀態;如果發現其他節點比自己更新,則主動切換到follower。
總之,系統中最多只有一個leader,如果在一段時間里發現沒有leader,則大家通過選舉-投票選出leader。leader會不停的給follower發心跳消息,表明自己的存活狀態。如果leader故障,那么follower會轉換成candidate,重新選出leader。
選舉過程詳解
- 狀態由follower切換到candidate狀態并投自己一票
- 并行(RPC協議)給其他節點發送投票請求
- 等待其他節點的回復,在這個過程中,根據來自其他節點的消息,可能出現三種結果:
- 收到多數的投票(含自己的一票),則贏得選舉,成為leader,成為新的leader會立刻給所有節點發消息,避免其余節點觸發新的選舉
- 被告知別人已當選,那么自行切換到follower
- 一段時間內沒有收到多數投票,也沒其他節點成為leader,則保持candidate狀態,重新發出選舉
日志復制(log replication)
- 當有了leader,系統應該進入對外工作期了
- 客戶端的一切請求來發送到leader
- leader來調度這些并發請求的順序
- 并且保證leader與followers狀態的一致性
- raft中的做法是,將這些請求以及執行順序告知followers
- leader和followers以相同的順序來執行這些請求,保證狀態一致。
- leader只需要日志被復制到大多數節點即可向客戶端返回,一旦向客戶端返回成功消息,那么系統就必須保證log(其實是log所包含的command)在任何異常的情況下都不會發生回滾。這里有兩個詞:
- commit(committed)是指日志被復制到了大多數節點后日志的狀態;
- apply(applied) 是節點將日志應用到狀態機,真正影響到節點狀態。
Prometheus監控Etcd集群
==前提Prometheus是用Prometheus Operator
安裝的==
安裝方法:
Prometheus Operator: https://www.qikqiak.com/post/first-use-prometheus-operator/
監控Etcd: https://www.qikqiak.com/post/prometheus-operator-monitor-etcd/
第一步建立一個 ServiceMonitor 對象,用于 Prometheus 添加監控項
第二步為 ServiceMonitor 對象關聯 metrics 數據接口的一個 Service 對象
第三步確保 Service 對象可以正確獲取到 metrics 數據
創建secrets資源
#查看etcd引用的證書文件
$ cat /usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/local/bin/etcd \
--name=11.0.64.5 \
--cert-file=/etc/kubernetes/ssl/kubernetes.pem \
--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
--peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem \
--peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
--trusted-ca-file=/etc/kubernetes/ssl/k8s-root-ca.pem \
--peer-trusted-ca-file=/etc/kubernetes/ssl/k8s-root-ca.pem \
--initial-advertise-peer-urls=https://11.0.64.5:2380 \
--listen-peer-urls=https://11.0.64.5:2380 \
--listen-client-urls=https://11.0.64.5:2379 \
--advertise-client-urls=https://11.0.64.5:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster=11.0.64.5=https://11.0.64.5:2380,11.0.64.6=https://11.0.64.6:2380,11.0.64.7=https://11.0.64.7:2380 \
--initial-cluster-state=new \
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
#創建secret資源
$ kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/ssl/kubernetes.pem --from-file=/etc/kubernetes/ssl/kubernetes-key.pem --from-file=/etc/kubernetes/ssl/k8s-root-ca.pem
apply Prometheus配置文件
#添加如下的 secrets 屬性:
$ vim prometheus-prometheus.yaml
replicas: 2
secrets:
- etcd-certs
$ kubectl apply -f prometheus-prometheus.yaml
#等到pod重啟后,進入pod查看是否可以看到證書
$ kubectl exec -it -n monitoring prometheus-k8s-0 -- /bin/sh
/prometheus $ ls -l /etc/prometheus/secrets/etcd-certs/
total 0
lrwxrwxrwx 1 root root 22 Oct 24 07:20 k8s-root-ca.pem -> ..data/k8s-root-ca.pem
lrwxrwxrwx 1 root root 25 Oct 24 07:20 kubernetes-key.pem -> ..data/kubernetes-key.pem
lrwxrwxrwx 1 root root 21 Oct 24 07:20 kubernetes.pem -> ..data/kubernetes.pem
創建 ServiceMonitor
$ vim prometheus-serviceMonitorEtcd.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: etcd-k8s
namespace: monitoring
labels:
k8s-app: etcd-k8s
spec:
jobLabel: k8s-app
endpoints:
- port: port
interval: 30s
scheme: https
tlsConfig:
caFile: /etc/prometheus/secrets/etcd-certs/k8s-root-ca.pem
certFile: /etc/prometheus/secrets/etcd-certs/kubernetes.pem
keyFile: /etc/prometheus/secrets/etcd-certs/kubernetes-key.pem
insecureSkipVerify: true
selector:
matchLabels:
k8s-app: etcd
namespaceSelector:
matchNames:
- kube-system
$ kubectl apply -f prometheus-serviceMonitorEtcd.yaml
上面我們在 monitoring 命名空間下面創建了名為 etcd-k8s 的 ServiceMonitor 對象,基本屬性和前面章節中的一致,匹配 kube-system 這個命名空間下面的具有 k8s-app=etcd 這個 label 標簽的 Service,jobLabel 表示用于檢索 job 任務名稱的標簽,和前面不太一樣的地方是 endpoints 屬性的寫法,配置上訪問 etcd 的相關證書,endpoints 屬性下面可以配置很多抓取的參數,比如 relabel、proxyUrl,tlsConfig 表示用于配置抓取監控數據端點的 tls 認證,由于證書 serverName 和 etcd 中簽發的可能不匹配,所以加上了 insecureSkipVerify=true
創建 Service
$ vim prometheus-etcdService.yaml
apiVersion: v1
kind: Service
metadata:
name: etcd-k8s
namespace: kube-system
labels:
k8s-app: etcd
spec:
type: ClusterIP
clusterIP: None
ports:
- name: port
port: 2379
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: etcd-k8s
namespace: kube-system
labels:
k8s-app: etcd
subsets:
- addresses:
- ip: 11.0.64.5
- ip: 11.0.64.6
- ip: 11.0.64.7
ports:
- name: port
port: 2379
protocol: TCP
$ kubectl apply -f prometheus-etcdService.yaml
Prometheus 的 Dashboard 中查看 targets,便會有 etcd 的監控項
數據采集到后,可以在 grafana 中導入編號為3070的 dashboard,獲取到 etcd 的監控圖表。
Etcd監控指標
參考: https://github.com/coreos/etcd/blob/master/Documentation/metrics.md
領導者相關
- etcd_server_has_leader etcd是否有leader
- etcd_server_leader_changes_seen_total etcd的leader變換次數
- etcd_debugging_mvcc_db_total_size_in_bytes 數據庫的大小
- process_resident_memory_bytes 進程駐留內存
網絡相關
- grpc_server_started_total grpc(高性能、開源的通用RPC(遠程過程調用)框架)服務器啟動總數
- etcd_network_client_grpc_received_bytes_total 接收到grpc客戶端的字節總數
- etcd_network_client_grpc_sent_bytes_total 發送給grpc客戶端的字節總數
- etcd_network_peer_received_bytes_total etcd網絡對等方接收的字節總數(對等網絡,即對等計算機網絡,是一種在對等者(Peer)之間分配任務和工作負載的分布式應用架構,是對等計算模型在應用層形成的一種組網或網絡形式)
- etcd_network_peer_sent_bytes_total etcd網絡對等方發送的字節總數
提案相關
- etcd_server_proposals_failed_total 目前正在處理的提案(提交會議討論決定的建議。)數量
- etcd_server_proposals_pending 失敗提案總數
- etcd_server_proposals_committed_total 已落實共識提案的總數。
- etcd_server_proposals_applied_total 已應用的共識提案總數。
這些指標描述了磁盤操作的狀態。
- etcd_disk_backend_commit_duration_seconds_sum etcd磁盤后端提交持續時間秒數總和
- etcd_disk_backend_commit_duration_seconds_bucket etcd磁盤后端提交持續時間
快照
- etcd_debugging_snap_save_total_duration_seconds_sum etcd快照保存用時
文件
- process_open_fds{service="etcd-k8s"} 打開文件描述符的數量
- process_max_fds{service="etcd-k8s"} 打開文件描述符的最大數量
- etcd_disk_wal_fsync_duration_seconds_sum Wal(預寫日志系統)調用的fsync(將文件數據同步到硬盤)的延遲分布
- etcd_disk_wal_fsync_duration_seconds_bucket 后端調用的提交的延遲分布
(輕易科技ops部)