kubernetes中etcd組件詳解_API

kubernetes中etcd組件詳解_List_02

- etcd    Raft 算法是比較核心的

Raft 選舉      

- leader   一個 修改操作

- follower

- candidate  


etcd      Server  

etcdctl   Client

127.0.0.1:2380   2380是server之間互相通信  

127.0.0.1:2379   2379是客户端訪問服務器用的端口Client > Server

kubernetes中etcd組件詳解_API_03

etcdctl 訪問 Server    127.0.0.1:2379

kubectl  尋找api server 是如何實現的?      答:   /root/.kube/config   

kubernetes中etcd組件詳解_List_04

直接找下圖server中的端口

kubernetes中etcd組件詳解_API_05

etcdctl  --endpoints=127.0.0.1:2379    


監控 etcd 狀態  

etcdctl  --endpoints=127.0.0.1:2379   member list   --write-out=table  


kubernetes中etcd組件詳解_Server_06

安裝

Bash
ETCD_VER=v3.4.28

# choose either URL
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}

rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test

curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1

/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version

啓動服務

Bash
[root@worker-01 etcd-v3.4.28-linux-amd64]# ./etcd
WARNING: Package "github.com/golang/protobuf/protoc-gen-go/generator" is deprecated.
        A future release of golang/protobuf will delete this package,
        which has long been excluded from the compatibility promise.

列出集羣成員

Bash
[root@worker-01 etcd-v3.4.28-linux-amd64]# ./etcdctl --endpoints=localhost:2379 member list --write-out=table
+------------------+---------+---------+-----------------------+-----------------------+------------+
|        ID        | STATUS  |  NAME   |      PEER ADDRS       |     CLIENT ADDRS      | IS LEARNER |
+------------------+---------+---------+-----------------------+-----------------------+------------+
| 8e9e05c52164694d | started | default | http://localhost:2380 | http://localhost:2379 |      false |
+------------------+---------+---------+-----------------------+-----------------------+------------+

kubernetes中etcd組件詳解_Server_07

kubernetes中etcd組件詳解_List_08



寫入操作

Bash
# 寫入數據
./etcdctl  --endpoints=localhost:2379 put /key1 val1
OK

# 讀取數據
./etcdctl  --endpoints=localhost:2379 get /key1
/key1
val1

# 按 Key 的前綴查詢數據
./etcdctl  --endpoints=localhost:2379 get --prefix /
/key1
val1

# 只顯示鍵值
./etcdctl  --endpoints=localhost:2379 get --prefix / --keys-only
/key1

# watch key 變化
./etcdctl  --endpoints=localhost:2379 watch --prefix / 

list-watch機制:

watch是持續監聽的意思,是K8S中的通知機制,當數據庫有增刪改查的操作時都會通知,這個機制是list-watch機制

Kubernetes 中的 List-Watch 機制就像是整個集羣的“神經系統”。它允許各個組件(比如調度器、節點代理等)實時感知到集羣資源(如 Pod、Service 等)的變化,而不需要頻繁地去“問”API Server“有什麼變化嗎?”。下面我用一個簡單的比喻幫你理解:


一個雜誌訂閲的比喻

想象一下你訂閲了一份雜誌(在 Kubernetes 中,這相當於一個組件,比如 kubelet,想要監聽 Pod 的變化):

  1. List(列表):拿到過刊合集 當你第一次訂閲時,雜誌社(相當於 API Server)會先寄給你一套迄今為止已經出版的所有過刊合集。這樣你手頭就有了完整的資料,知道了“當前狀態”。這個過程就是 List,它是一次性的,獲取的是資源的完整列表 。
  2. Watch(監聽):等待新刊送達 從下一期開始,你不再需要主動打電話問雜誌社“新雜誌到了沒”,而是雜誌社每出一期新刊,就會自動通過郵遞(相當於一個 HTTP 長連接)寄到你家裏。你只需要在家裏的郵箱旁等待即可。這個郵遞員會一直保持這條送貨通道,只要有新雜誌(相當於資源變更事件),就會立刻送過來。這個過程就是 Watch,它是持續的、事件驅動的 。


 list-watch機制在kubernetes中是如何工作的?

•   核心角色:

◦   API Server:集羣信息的唯一入口,就像雜誌社的“總編輯部”。

◦   Etcd:集羣數據的核心數據庫,可以理解為雜誌社的““檔案庫””,所有最終數據都存儲在這裏。

◦   客户端組件(如 Scheduler, Controller Manager, Kubelet):就像各個“訂閲者”。


•   基本工作流程:

    1.  初始化(List):一個組件(比如負責調度的 Scheduler)啓動時,會先向 API Server 發起一個 List 請求,獲取當前所有未被調度的 Pod 的完整列表,建立自己的初始狀態 。

    2.  持續監聽(Watch):緊接着,該組件會向 API Server 發起一個 Watch 請求,建立一個長連接。之後,一旦有新的 Pod 被創建、更新或刪除,API Server 就會通過這個長連接,將事件(ADDED, MODIFIED, DELETED)像推送消息一樣實時地推送給 Scheduler 。

    3.  事件處理:Scheduler 收到這些事件後,就會觸發相應的處理邏輯(比如為新增的 Pod 尋找一個合適的節點。


為什麼 List-Watch 如此重要?它的精妙之處在哪?

這種機制的設計非常精妙,解決了幾個核心問題: 

•   實時性:基於事件推送(Watch),變化一旦發生,組件幾乎能立刻感知,無需等待輪詢間隔 。

•   可靠性:即使網絡短暫中斷,組件在恢復後也可以通過 ResourceVersion(一個全局單調遞增的版本號)從斷點重新開始監聽,避免事件丟失 。

•   順序性:每個事件都帶有 ResourceVersion,確保了事件發生的先後順序,避免了狀態混亂 。

•   高性能:避免了客户端頻繁輪詢給 API Server 帶來巨大壓力。Watch 利用 HTTP 長連接和分塊傳輸編碼 技術,服務器可以持續發送數據,而無需預先知道數據的總大小 。


簡單小結

你可以這樣記住

•   List 是 問一次,拿全量(獲取當前快照)。

•   Watch 是 掛個電話,等通知(監聽後續變化)。

      正是這套機制,使得 Kubernetes 的各個組件能夠高效、可靠地協同工作,共同維護集羣的期望狀態,它是 Kubernetes 聲明式 API 和控制器模式能夠順暢運行的基石 。

Bash
./etcdctl --endpoints=localhost:2379 put /name k1s
./etcdctl --endpoints=localhost:2379 put /name k2s
./etcdctl --endpoints=localhost:2379 put /name k3s
./etcdctl --endpoints=localhost:2379 put /name k4s
./etcdctl --endpoints=localhost:2379 get /name -wjson

./etcdctl --endpoints=localhost:2379 watch --prefix /name --rev 1
PUT
/name
k1s
PUT
/name
k2s
PUT
/name
k3s
PUT
/name
k4s


#這裏可以看出kubernetes中key的變更都是有歷史記錄的,所以數據可以回滾;


災備etcd非常重要 需要數據備份


因為Raft算法,etcd集羣就像一個小團隊做決策,至少需要3個人,這樣即使其中1人請假,剩下的2人也能代表多數做出有效決定。如果團隊只有1人或2人,缺一個就徹底癱瘓了。

Bash
# 備份命令
    export ETCDCTL_API=3
    ENDPOINTS=localhost:2379
$ etcdctl --endpoints=${ENDPOINTS} snapshot save /data/etcd_backup_dir/etcd-snapshot.db
$ etcdctl --endpoints=${ENDPOINTS} snapshot restore snapshot.db


kubernetes中etcd組件詳解_Server_09

備份  :

做一個快照工作中一般每隔離 30m  1h 做一個快照:

etcdctl --endpoints=127.0.0.1:2379  snapshot save /data/etcd_backup/etcd-snapshot.db


恢復 快照

etcdctl --endpoints=127.0.0.1:2379 snapshot restore snapshot.db  


k8s 配置數據  保存到 etcd 中:


export ETCDCTL_API=3

etcdctl --endpoints https://localhost:2379 --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key  --cacert /etc/kubernetes/pki/etcd/ca.crt  get --keys-only --prefix /

etcdctl --endpoints https://localhost:2379 --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key  --cacert /etc/kubernetes/pki/etcd/ca.crt  get --keys-only --prefix /registry/pods/default/redis-pv-sts-0

etcdctl --endpoints https://localhost:2379 --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key  --cacert /etc/kubernetes/pki/etcd/ca.crt get /registry/pods/default/redis-pv-sts-0

etcdctl --endpoints https://localhost:2379 --cert /etc/kubernetes/pki/etcd/server.crt --key /etc/kubernetes/pki/etcd/server.key  --cacert /etc/kubernetes/pki/etcd/ca.crt  get /registry/configmaps/default/info


#下面是命令的拆解,其實就是加了三條安全認證:

 etcdctl --endpoints https://localhost:2379

 --cert /etc/kubernetes/pki/etcd/server.crt

 --key /etc/kubernetes/pki/etcd/server.key  

 --cacert /etc/kubernetes/pki/etcd/ca.crt

 get --keys-only --prefix /


雙向認證:客户端和服務器互相檢驗對方的身份,這裏kubernetes存數據就是雙向認證;

單向認證:僅客户端驗證服務器的身份即可;


數據存儲在/registry/類型/對象的名字:

/registry/poddisruptionbudgets/kube-system/calico-kube-controllers      

#這個是key值  value就是這個目錄下對應的YAML文件,但是這個文件中存儲的格式跟YAML不同

/registry/pods/default/busy-dep-7f9b565d88-hqljb



在工作中可以用第三方軟件來備份:Kubernetes 集羣備份 - Velero


Velero目前包含以下特性:

1.支持Kubernetes集羣數據備份和恢復;

2.支持複製當前Kubernetes集羣的資源到其它 Kubernetes 集羣;

3.支持複製生產環境到開發以及測試環境。


velero使用場景:

災備場景:提供備份恢復Kubernetes集羣的能力;

遷移場景:提供拷貝集羣資源到其他集羣的能力(複製同步開發,測試,生產環境的集羣配置,簡化環境配置)。


Velero 組件介紹 :

Velero CLI : 提供 Velero 組件的安裝、備份和恢復命令。

Velero 服務器(The Velero server)  :負責執行備份和恢復過程。

存儲提供者插件(Storage provider plug-ins)  :這些插件用於備份和還原到特定存儲系統


Etcd 備份腳本

Bash
#!/bin/bash
ETCDCTL_PATH='/usr/local/bin/etcdctl'
ENDPOINTS='https://192.168.200.153:2379'
ETCD_DATA_DIR="/var/lib/etcd"
BACKUP_DIR="/var/backups/kube_etcd/etcd-$(date +%Y-%m-%d-%H-%M-%S)"
KEEPBACKUPNUMBER='5'
ETCDBACKUPPERIOD='30'
ETCDBACKUPSCIPT='/usr/local/bin/kube-scripts'
ETCDBACKUPHOUR=''

ETCDCTL_CERT="/etc/ssl/etcd/ssl/admin-master1.pem"
ETCDCTL_KEY="/etc/ssl/etcd/ssl/admin-master1-key.pem"
ETCDCTL_CA_FILE="/etc/ssl/etcd/ssl/ca.pem"

[ ! -d $BACKUP_DIR ] && mkdir -p $BACKUP_DIR

export ETCDCTL_API=2;$ETCDCTL_PATH backup --data-dir $ETCD_DATA_DIR --backup-dir $BACKUP_DIR

sleep 3

{
export ETCDCTL_API=3;$ETCDCTL_PATH --endpoints="$ENDPOINTS" snapshot save $BACKUP_DIR/snapshot.db \
                                   --cacert="$ETCDCTL_CA_FILE" \
                                   --cert="$ETCDCTL_CERT" \
                                   --key="$ETCDCTL_KEY"
} > /dev/null

sleep 3

cd $BACKUP_DIR/../;ls -lt |awk '{if(NR > '$KEEPBACKUPNUMBER'){print "rm -rf "$9}}'|sh

if [[ ! $ETCDBACKUPHOUR ]]; then
  time="*/$ETCDBACKUPPERIOD * * * *"
else
  if [[ 0 == $ETCDBACKUPPERIOD ]];then
    time="* */$ETCDBACKUPHOUR * * *"
  else
    time="*/$ETCDBACKUPPERIOD */$ETCDBACKUPHOUR * * *"
  fi
fi

crontab -l | grep -v '#' > /tmp/file
echo "$time sh $ETCDBACKUPSCIPT/etcd-backup.sh" >> /tmp/file && awk ' !x[$0]++{print > "/tmp/file"}' /tmp/file
crontab /tmp/file
rm -rf /tmp/file