文章目錄
- 一、Service原理
- 1.1概述
- 1.2為什么需要service
- 1.3service
- 1.4service類型
- 1.5service組件協同
- 二、configMap原理
- 2.1概述
- 2.2命令
- 2.3類型
- 三、volume
- 2.1emptydir
- 2.2hostPath
- 2.3pv/pvc
- 2.4storageClass
- 四、調度管理
- 3.1概念
- 3.2特點
- 3.3親和性
- 3.4容忍和污點
- 3.5固定節點調度
- 五、etcd
- 5.1概述
- 5.2相關操作
- 查看告警事件
- 5.3etcd數據庫相關操作
- 增加(put)
- 查詢(get)
- 刪除(del)
- 更新(put覆蓋)
- 查詢鍵歷史記錄查詢
- 監聽命令
- 監聽單個鍵
- 同時監聽多個鍵
- 租約命令
- 添加租約
- 查看租約
- 租約續約
- 刪除租約
- 多key同一租約
- 備份恢復命令
- 生成快照
- 查看快照
- 恢復快照
- 備份恢復演示
一、Service原理
1.1概述
暴漏服務的重要方式
KubernetesService
定義了這樣一種抽象:一個Pod
的邏輯分組,一種可以訪問它們的策略-- 通常稱為微服務。這一組Pod
能夠被Service
訪問到,通常是通過’Label Selector
1.2為什么需要service
如果不用service可以實現如圖的效果,部署nginx和tomcat,但是如果tomcat的pod壞了一臺,deployment會創建新的Pod,但是pod的ip變化了,之前可以實現負載均衡,但是現在ip變了,負載均衡無法代理到新的pod ip上
如果我們中間加了service
service:標簽選擇器和集群
不管Pod如何更新,都會被加入到負載均衡集群
1.3service
service-userspace:
service-iptables:
service-ipvs:
1.4service類型
ClusterIP:
如圖所示,deployment所控制的是兩臺機器,nginx代理的是23和46兩臺,現在46機器損壞,控制器會創建新的pod,但是新的pod,ip地址會發生改變,nginx無法代理,也就無法實現負載均衡
ClusterIP:提供一個集群內部的虛擬ip以供Pod訪問,他只會收集滿足條件的pod
NodePort:
由于用戶無法訪問虛擬ip,所以我們引入了NodePort,他會提供一個真實的ip,供外部訪問
LoadBalancer:
通過外部的負載均衡器來訪問
1.5service組件協同
clusterIP:
案例:
會自動生成一個資源清單:
二、configMap原理
配置信息的保存方式
2.1概述
ConfigMap 功能在 Kubernetes1.2 版本中引入,許多應用程序會從配置文件、命令行參數或環境變量中讀取配置信息。ConfigMap API給我們提供了向容器中注入配置信息的機制ConfigMap 可以被用來保存單個屬性,也可以用來保存整個配置文件或者 JSON 二進制等對象
2.2命令
–from-file
要求
文件內部必須是一行一對的k=v,可以在使用的時候注入至內部變成環境變量
1.txt
name-zhangsan
passwd=123
文件內部不符合要求,創建的時候依然可以變為k,val的形式,但是不會成為內部的環境變量
2.txt
今天去爬山
案例1:
注入環境變量
案例2:
把環境變量作為啟動參數
2.3類型
Clusterip:
如圖所示是一個簡單的nginx負載均衡,他現在代理的是23和46這兩臺機器,如果第二臺機器出現問題了,那么deployment會重建一個新的,但是這個新的機器ip地址可能會發生變化,導致nginx無法實現負載均衡
Clusterip:他會收集滿足條件的pod,他會動態的更新后端Pod的狀態
NodePort:
創建的真實ip就可以指向我們當前的Pod上
整個集群的高可用:
三、volume
容器磁盤上的文件的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題。首先,當容器崩潰時,kubelet 會重啟它,但是容器中的文件將丟失–容器以干凈的狀態(鏡像最初的狀態)重新啟動。其次,在Pod'中同時運行多個容器時,這些容器之間通常需要共享文件。Kubernetes 中的Volume
抽象就很好的解決了這些問題
2.1emptydir
當 Pod 被分配給節點時,首先創建emptyDir'卷,并且只要該 Pod 在該節點上運行,該卷就會存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以讀取和寫入
emptyDir’卷中的相同文件,盡管該卷可以掛載到每個容器中的相同或不同路徑上。當出于任何原因從節點中刪除Pod 時,emptyDir
中的數據將被永久刪除
容器崩漬不會從節點中移除 pod,因此emptyDir
卷中的數據在容器崩潰時是安全的
emptyDir 的用法有:
》暫存空間,例如用于基于磁盤的合并排序、用作長時間計算崩潰恢復時的檢查點>Web 服務器容器提供數據時,保存內容管理器容器提取的文件
案例1:
驗證:訪問nginx頁面并
打印busybox容器日志:
或者可以在節點上查看日志
我們在日志中加入元素并查看busybox日志:確實訪問一致
案例2:共享內存
2.2hostPath
hostPath 卷將主機節點的文件系統中的文件或目錄掛載到集群中
hostPath 用途如下
》運行需要訪問 Docker 內部的容器;使用/var/lib/docker'的
hostPath》在容器中運行 cAdvisor;使用/dev/cgroups
的hostPath允許 pod 指定給定的 hostPath 是否應該在 pod 運行之前存在,是否應該創建,以及它應該以什么形式存在 除了所需的'path
屬性之外,用戶還可以為hostPath
卷指定`type
類型:
注意:
案例:
path:/data是pod最后分配節點的跟data
必須保證節點有這個目錄才會創建成功
2.3pv/pvc
回收策略:
狀態:
保護:
案例:
所有的幾點都要安裝yum install -y nfs-common nfs-utils rpcbindmkdir /nfsdata
master:創建共享目錄并賦予權限
為了方便測試,可以多創建幾個測試文件
查看當前的共享結果:
驗證:
node1節點上:
部署PV:
創建PVC:
改一下數量:
驗證的stateful的特性:有序創建,有序回收
特性:
2.4storageClass
一種動態的申請存儲機制
nfs-client-provisioner:
案例:
cat sa.yaml
apiVersion: v1
kind: Namespace
metadata:name: newnfs
---
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisionernamespace: newnfs
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: nfs-client-provisioner-runner
rules:- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]- apiGroups: [""]resources: ["events"]verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: run-nfs-client-provisioner
subjects:- kind: ServiceAccountname: nfs-client-provisionernamespace: newnfs
roleRef:kind: ClusterRolename: nfs-client-provisioner-runnerapiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisionernamespace: newnfs
rules:- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisionernamespace: newnfs
subjects:- kind: ServiceAccountname: nfs-client-provisionernamespace: newnfs
roleRef:kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io
cat nfs.yaml
kind: Deployment
apiVersion: apps/v1
metadata:name: nfs-client-provisionernamespace: newnfs
spec:replicas: 1selector:matchLabels:app: nfs-client-provisionerstrategy:type: Recreate #設置升級策略為刪除再創建(默認為滾動更新)template:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisioner #上一步創建的ServiceAccount名稱containers:- name: nfs-client-provisionerimage: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0imagePullPolicy: IfNotPresentvolumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAME # Provisioner的名稱,以后設置的storageclass要和這個保持一致value: storage-nfs- name: NFS_SERVER # NFS服務器地址,需和valumes參數中配置的保持一致value: 192.168.166.3- name: NFS_PATH # NFS服務器數據存儲目錄,需和volumes參數中配置的保持一致value: /data- name: ENABLE_LEADER_ELECTIONvalue: "true"volumes:- name: nfs-client-rootnfs:server: 192.168.166.3 # NFS服務器地址path: /data # NFS共享目錄
執行文件:
創建存儲類:
在node節點上查看nfs的版本
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-storageannotations:storageclass.kubernetes.io/is-default-class: "false" ## 是否設置為默認的storageclass
provisioner: storage-nfs ## 動態卷分配者名稱,必須和上面創建的deploy中環境變量“PROVISIONER_NAME”變量值一致
parameters:archiveOnDelete: "true" ## 設置為"false"時刪除PVC不會保留數據,"true"則保留數據
mountOptions: - hard ## 指定為硬掛載方式- nfsvers=4
注意:
需要 “隔離” 的資源(如 Pod、PVC) → 加命名空間,避免不同團隊 / 業務互相影響;
需要 “全局復用” 的資源(如 StorageClass、PV) → 不加命名空間,讓整個集群的資源能共用同一套配置。
創建pvc,通過storageclass動態生成pv:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:name: storage-pvcnamespace: newnfs
spec:storageClassName: nfs-storage ## 需要與上面創建的storageclass的名稱一致accessModes:- ReadWriteOnceresources:requests:storage: 1Mi
編寫pod綁定pvc:
apiVersion: v1
kind: Pod
metadata:name: pod-pvc1namespace: newnfs
spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentvolumeMounts:- name: nginx-htmlmountPath: /usr/share/nginx/htmlvolumes:- name: nginx-htmlpersistentVolumeClaim:claimName: storage-pvc
驗證:
四、調度管理
3.1概念
案例:自定義調度器
基于shell自定義:
3.2特點
3.3親和性
生產上為了保證應用的高可用性,需要將同一應用的不同pod分散在不同的宿主機上,以防宿主機出現宕機等情況導致pod重建,影響到業務的連續性。要想實現這樣的效果,需要用到k8s自帶的pod親和性和反親和性特性。
Pod 的親和性與反親和性有兩種類型:
requiredDuringSchedulingIgnoredDuringExecution ##一定滿足
preferredDuringSchedulingIgnoredDuringExecution ##盡量滿足
**podAffinity(親和性):**pod和pod更傾向膩在一起,把相近的pod結合到相近的位置,如同一區域,同一機架,這樣的話pod和pod之間更好通信,比方說有兩個機房,這兩個機房部署的集群有1000臺主機,那么我們希望把nginx和tomcat都部署同一個地方的node節點上,可以提高通信效率;
**podAntiAffinity(反親和性):**pod和pod更傾向不膩在一起,如果部署兩套程序,那么這兩套程序更傾向于反親和性,這樣相互之間不會有影響。
第一個pod隨機選則一個節點,做為評判后續的pod能否到達這個pod所在的節點上的運行方式,這就稱為pod親和性;我們怎么判定哪些節點是相同位置的,哪些節點是不同位置的;我們在定義pod親和性時需要有一個前提,哪些pod在同一個位置,哪些pod不在同一個位置,這個位置是怎么定義的,標準是什么?以節點名稱為標準,這個節點名稱相同的表示是同一個位置,節點名稱不相同的表示不是一個位置。
案例:軟策性:
從運行結果來看,他都運行在Node2節點上,說明node2優于node1
硬策略:
狀態為pending
滿足條件:
驗證:滿足條件
反親和性:軟策略
反親和性:硬策略
總結:
3.4容忍和污點
污點:
污點的組成:
我們使用descibe查看詳細信息
添加污點:
再次查看:
刪除污點:
我們創建10個pod:
master出現節點了.所以說明不是master無法分配節點,而是它本身存在污點
容忍:
我們先把master本身的污點加上:
設置方式:
特殊類型:
3.5固定節點調度
pod.spec.nodename將pod直接調度到指定節點上,跳過scheduler的調度策略,屬于強制匹配
為了更方便實驗,可以把nodeName改為master節點
及時設置污點,也能分配到master節點
我們也可以通過標簽選擇器去實現
因為我們沒有這個標簽,所以容器處于pending狀態:
現在我們添加這個標簽:
五、etcd
5.1概述
etcd 是 K8s 的唯一數據存儲源(Single Source of Truth),所有組件(如 API Server、Controller Manager、Scheduler、kubelet 等)的配置與狀態都依賴 etcd 存儲,具體包括:
集群拓撲信息:節點(Node)的注冊與狀態
資源對象數據:Pod、Service、Deployment、ConfigMap、Secret、Namespace 等的定義和運行狀態
集群配置:如集群網絡 CIDR、API Server 地址、證書信息等
狀態數據:如 Pod 的運行狀態(Running/Pending)、Service 的 endpoints 列表等
注意:K8s 中僅 API Server 有權直接讀寫 etcd,其他組件(如 Controller Manager、kubelet)需通過 API Server 的接口間接操作 etcd 數據,確保數據一致性和安全性。
5.2相關操作
etcdctl的tar包可以從github上獲取
環境變量配置:
查看etcd版本:
查看etcd集群節點信息:
查看etcd集群的健康狀態:
查看告警事件
如果內部出現問題,會觸發告警,可以通過命令查看告警引起原因,命令如下所示:
etcdctl alarm <subcommand> [flags]
常用的子命令主要有兩個:
# 查看所有告警
etcdctl alarm list
# 解除所有告警
etcdctl alarm disarm
5.3etcd數據庫相關操作
增加(put)
添加一個鍵值,基本用法如下所示:
etcdctl put [options] <key> <value> [flags]
常用參數如下所示:
參數 | 功能描述 |
---|---|
–prev-kv | 輸出修改前的鍵值 |
注意事項:
- 其中value接受從stdin的輸入內容
- 如果value是以橫線-開始,將會被視為flag,如果不希望出現這種情況,可以使用兩個橫線代替–
- 若鍵已經存在,則進行更新并覆蓋原有值,若不存在,則進行添加
示例
[root@tiaoban etcd]# etcdctl put name cuiliang
OK
[root@tiaoban etcd]# etcdctl put location -- -beijing
OK
[root@tiaoban etcd]# etcdctl put foo1 bar1
OK
[root@tiaoban etcd]# etcdctl put foo2 bar2
OK
[root@tiaoban etcd]# etcdctl put foo3 bar3
OK
查詢(get)
查詢鍵值,基本用法如下所示:
etcdctl get [options] <key> [range_end] [flags]
常用參數如下所示:
參數 | 功能描述 |
---|---|
–hex | 以十六進制形式輸出 |
–limit number | 設置輸出結果的最大值 |
–prefix | 根據prefix進行匹配key |
–order | 對輸出結果進行排序,ASCEND 或 DESCEND |
–sort-by | 按給定字段排序,CREATE, KEY, MODIFY, VALUE, VERSION |
–print-value-only | 僅輸出value值 |
–from-key | 按byte進行比較,獲取大于等于指定key的結果 |
–keys-only | 僅獲取keys |
示例
# 獲取鍵值
[root@tiaoban etcd]# etcdctl get name
name
cuiliang
#查看所有的key
etcdctl get / --prefix --keys-only
# 只獲取值
[root@tiaoban etcd]# etcdctl get location --print-value-only
-beijing
# 批量取從foo1到foo3的值,不包括foo3
[root@tiaoban etcd]# etcdctl get foo foo3 --print-value-only
bar1
bar2
# 批量獲取前綴為foo的值
[root@tiaoban etcd]# etcdctl get --prefix foo --print-value-only
bar1
bar2
bar3
# 批量獲取符合前綴的前兩個值
[root@tiaoban etcd]# etcdctl get --prefix --limit=2 foo --print-value-only
bar1
bar2
# 批量獲取前綴為foo的值,并排序
[root@tiaoban etcd]# etcdctl get --prefix foo --print-value-only --order DESCEND
bar3
bar2
bar1
刪除(del)
刪除鍵值,基本用法如下所示:
etcdctl del [options] <key> [range_end] [flags]
常用參數如下所示:
參數 | 功能描述 |
---|---|
–prefix | 根據prefix進行匹配刪除 |
–prev-kv | 輸出刪除的鍵值 |
–from-key | 按byte進行比較,刪除大于等于指定key的結果 |
示例
# 刪除name的鍵值
[root@tiaoban etcd]# etcdctl del name
1
# 刪除從foo1到foo3且不包含foo3的鍵值
[root@tiaoban etcd]# etcdctl del foo1 foo3
2
# 刪除前綴為foo的所有鍵值
[root@tiaoban etcd]# etcdctl del --prefix foo
1
更新(put覆蓋)
若鍵已經存在,則進行更新并覆蓋原有值,若不存在,則進行添加。
查詢鍵歷史記錄查詢
etcd在每次鍵值變更時,都會記錄變更信息,便于我們查看鍵變更記錄
監聽命令
watch是監聽鍵或前綴發生改變的事件流, 主要用法如下所示:
etcdctl watch [options] [key or prefix] [range_end] [--] [exec-command arg1 arg2 ...] [flags]
示例如下所示:
# 對某個key監聽操作,當key1發生改變時,會返回最新值
etcdctl watch name
# 監聽key前綴
etcdctl watch name --prefix
# 監聽到改變后執行相關操作
etcdctl watch name -- etcdctl get age
etcdctl watch name – etcdctl put name Kevin,如果寫成,會不會變成死循環,導致無限監視,盡量避免。
示例
監聽單個鍵
# 啟動監聽命令
[root@tiaoban etcd]# etcdctl watch foo#另一個控制臺執行新增命令
[root@tiaoban ~]# etcdctl put foo bar
OK# 觀察控制臺監聽輸出
[root@tiaoban etcd]# etcdctl watch foo
PUT
foo
bar#另一個控制臺執行更新命令
[root@tiaoban ~]# etcdctl put foo bar123
OK# 觀察控制臺監聽輸出
[root@tiaoban etcd]# etcdctl watch foo
PUT
foo
bar
PUT
foo
bar123#另一個控制臺執行刪除命令
[root@tiaoban ~]# etcdctl del foo
1# 觀察控制臺監聽輸出
[root@tiaoban etcd]# etcdctl watch foo
PUT
foo
bar
PUT
foo
bar123
DELETE
foo
同時監聽多個鍵
# 監聽前綴為foo的鍵
[root@tiaoban etcd]# etcdctl watch --prefix foo
# 另一個控制臺執行操作
[root@tiaoban ~]# etcdctl put foo1 bar1
OK
[root@tiaoban ~]# etcdctl put foo2 bar2
OK
[root@tiaoban ~]# etcdctl del foo1
1
# 觀察控制臺輸出
[root@tiaoban etcd]# etcdctl watch --prefix foo
PUT
foo1
bar1
PUT
foo2
bar2
DELETE
foo1# 監聽指定的多個鍵
[root@tiaoban etcd]# etcdctl watch -i
watch name
watch location# 另一個控制臺執行操作
[root@tiaoban ~]# etcdctl put name cuiliang
OK
[root@tiaoban ~]# etcdctl del name
1
[root@tiaoban ~]# etcdctl put location beijing
OK
# 觀察控制臺輸出
[root@tiaoban etcd]# etcdctl watch -i
watch name
watch location
PUT
name
cuiliang
DELETE
namePUT
location
beijing
租約命令
租約具有生命周期,需要為租約授予一個TTL(time to live),將租約綁定到一個key上,則key的生命周期與租約一致,可續租,可撤銷租約,類似于redis為鍵設置過期時間。其主要用法如下所示:
etcdctl lease <subcommand> [flags]
添加租約
主要用法如下所示:
etcdctl lease grant <ttl> [flags]
示例:
# 設置60秒后過期時間
[root@tiaoban etcd]# etcdctl lease grant 60
lease 6e1e86f4c6512a2b granted with TTL(60s)
# 把foo和租約綁定,設置成60秒后過期
[root@tiaoban etcd]# etcdctl put --lease=6e1e86f4c6512a29 foo bar
OK
# 租約期內查詢鍵值
[root@tiaoban etcd]# etcdctl get foo
foo
bar
# 租約期外查詢鍵值
[root@tiaoban etcd]# etcdctl get foo
返回為空
查看租約
查看租約信息,以便續租或查看租約是否仍然存在或已過期。
查看租約詳情主要用法如下所示:
etcdctl lease timetolive <leaseID> [options] [flags]
示例:
# 添加一個50秒的租約
[root@tiaoban etcd]# etcdctl lease grant 50
lease 6e1e86f4c6512a32 granted with TTL(50s)
# 將name鍵綁定到6e1e86f4c6512a32租約上
[root@tiaoban etcd]# etcdctl put --lease=6e1e86f4c6512a32 name cuiliang
OK
# 查看所有租約列表
[root@tiaoban etcd]# etcdctl lease list
found 1 leases
6e1e86f4c6512a32
# 查看租約詳情,remaining(6s) 剩余有效時間6秒;--keys 獲取租約綁定的 key
[root@tiaoban etcd]# etcdctl lease timetolive --keys 6e1e86f4c6512a32
lease 6e1e86f4c6512a32 granted with TTL(50s), remaining(6s), attached keys([name])
租約續約
通過刷新 TTL 值來保持租約的有效,使其不會過期。
主要用法如下所示:
etcdctl lease keep-alive [options] <leaseID> [flags]
示例如下所示:
# 設置60秒后過期租約
[root@tiaoban etcd]# etcdctl lease grant 60
lease 6e1e86f4c6512a36 granted with TTL(60s)
# 把name和租約綁定,設置成 60 秒后過期
[root@tiaoban etcd]# etcdctl put --lease=6e1e86f4c6512a36 name cuiliang
OK
# 自動定時執行續約,續約成功后每次租約為60秒
[root@tiaoban etcd]# etcdctl lease keep-alive 6e1e86f4c6512a36
lease 6e1e86f4c6512a36 keepalived with TTL(60)
lease 6e1e86f4c6512a36 keepalived with TTL(60)
lease 6e1e86f4c6512a36 keepalived with TTL(60)
……
刪除租約
通過租約 ID 撤銷租約,撤銷租約將刪除其所有綁定的 key。
主要用法如下所示:
etcdctl lease revoke <leaseID> [flags]
示例如下所示:
# 設置600秒后過期租約
[root@tiaoban etcd]# etcdctl lease grant 600
lease 6e1e86f4c6512a39 granted with TTL(600s)
# 把foo和租約綁定,600秒后過期
[root@tiaoban etcd]# etcdctl put --lease=6e1e86f4c6512a39 foo bar
OK
# 查看租約詳情
[root@tiaoban etcd]# etcdctl lease timetolive --keys 6e1e86f4c6512a39
lease 6e1e86f4c6512a39 granted with TTL(600s), remaining(556s), attached keys([foo])
# 刪除租約
[root@tiaoban etcd]# etcdctl lease revoke 6e1e86f4c6512a39
lease 6e1e86f4c6512a39 revoked
# 查看租約詳情
[root@tiaoban etcd]# etcdctl lease timetolive --keys 6e1e86f4c6512a39
lease 6e1e86f4c6512a39 already expired
# 獲取鍵值
[root@tiaoban etcd]# etcdctl get foo
返回為空
多key同一租約
一個租約支持綁定多個 key
# 設置60秒后過期的租約
[root@tiaoban etcd]# etcdctl lease grant 60
lease 6e1e86f4c6512a3e granted with TTL(60s)
# foo1與租約綁定
[root@tiaoban etcd]# etcdctl put --lease=6e1e86f4c6512a3e foo1 bar1
OK
# foo2與租約綁定
[root@tiaoban etcd]# etcdctl put --lease=6e1e86f4c6512a3e foo2 bar2
OK
# 查看租約詳情
[root@tiaoban etcd]# etcdctl lease timetolive --keys 6e1e86f4c6512a3e
lease 6e1e86f4c6512a3e granted with TTL(60s), remaining(14s), attached keys([foo1 foo2])
租約過期后,所有 key 值都會被刪除,因此:
- 當租約只綁定了一個 key 時,想刪除這個 key,最好的辦法是撤銷它的租約,而不是直接刪除這個 key。
- 當租約沒有綁定key時,應主動把它撤銷掉,單純刪除 key 后,續約操作持續進行,會造成內存泄露。
直接刪除key演示:
# 設置租約并綁定 zoo1
[root@tiaoban etcd]# etcdctl lease grant 60
lease 6e1e86f4c6512a43 granted with TTL(60s)
[root@tiaoban etcd]# etcdctl --lease=6e1e86f4c6512a43 put zoo1 val1
OK
# 續約
[root@tiaoban etcd]# etcdctl lease keep-alive 6e1e86f4c6512a43
lease 6e1e86f4c6512a43 keepalived with TTL(60)# 此時在另一個控制臺執行刪除key操作:
[root@tiaoban ~]# etcdctl del zoo1
1
# 單純刪除 key 后,續約操作持續進行,會造成內存泄露
[root@tiaoban etcd]# etcdctl lease keep-alive 6e1e86f4c6512a43
lease 6e1e86f4c6512a43 keepalived with TTL(60)
lease 6e1e86f4c6512a43 keepalived with TTL(60)
lease 6e1e86f4c6512a43 keepalived with TTL(60)
...
撤銷key的租約演示:
# 設置租約并綁定 zoo1
[root@tiaoban etcd]# etcdctl lease grant 50
lease 32698142c52a1717 granted with TTL(50s)
[root@tiaoban etcd]# etcdctl --lease=32698142c52a1717 put zoo1 val1
OK# 續約
[root@tiaoban etcd]# etcdctl lease keep-alive 32698142c52a1717
lease 32698142c52a1717 keepalived with TTL(50)
lease 32698142c52a1717 keepalived with TTL(50)# 另一個控制臺執行:etcdctl lease revoke 32698142c52a1717# 續約撤銷并退出
lease 32698142c52a1717 expired or revoked.
[root@tiaoban etcd]# etcdctl get zoo1
# 返回空
備份恢復命令
主要用于管理節點的快照,其主要用法如下所示:
etcdctl snapshot <subcommand> [flags]
生成快照
其主要用法如下所示:
etcdctl snapshot save <filename> [flags]
示例如下所示:
etcdctl snapshot save etcd-snapshot.db
查看快照
其主要用法如下所示:
etcdctl snapshot status <filename> [flags]
示例如下所示:
etcdctl snapshot status etcd-snapshot.db -w table
恢復快照
其主要用法如下所示:
etcdctl snapshot restore <filename> [options] [flags]
備份恢復演示
- 新建一個名為name的key
[root@tiaoban ~]# etcdctl put name cuiliang
OK
[root@tiaoban ~]# etcdctl get name
name
cuiliang
[root@tiaoban ~]# etcdctl endpoint status -w table
+---------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+---------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| 192.168.10.100:2379 | 2e0eda3ad6bc6e1e | 3.4.23 | 20 kB | true | false | 4 | 10 | 10 | |
| 192.168.10.11:2379 | bc34c6bd673bdf9f | 3.4.23 | 20 kB | false | false | 4 | 10 | 10 | |
| 192.168.10.12:2379 | 5d2c1bd3b22f796f | 3.4.23 | 20 kB | false | false | 4 | 10 | 10 | |
+---------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
- 生成快照,創建名為snap.db的備份文件
[root@k8s-work1 ~]# etcdctl snapshot save snap.db
{"level":"info","ts":1679220752.5883558,"caller":"snapshot/v3_snapshot.go:119","msg":"created temporary db file","path":"snap.db.part"}
{"level":"info","ts":"2023-03-19T18:12:32.592+0800","caller":"clientv3/maintenance.go:200","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":1679220752.5924425,"caller":"snapshot/v3_snapshot.go:127","msg":"fetching snapshot","endpoint":"127.0.0.1:2379"}
{"level":"info","ts":"2023-03-19T18:12:32.595+0800","caller":"clientv3/maintenance.go:208","msg":"completed snapshot read; closing"}
{"level":"info","ts":1679220752.597161,"caller":"snapshot/v3_snapshot.go:142","msg":"fetched snapshot","endpoint":"127.0.0.1:2379","size":"25 kB","took":0.008507131}
{"level":"info","ts":1679220752.5973082,"caller":"snapshot/v3_snapshot.go:152","msg":"saved","path":"snap.db"}
Snapshot saved at snap.db
- 查看備份文件詳情
[root@k8s-work1 ~]# ls -lh snap.db
-rw------- 1 root root 25K 3月 19 18:12 snap.db
[root@k8s-work1 ~]# etcdctl snapshot status snap.db -w table
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| 8f097221 | 39 | 47 | 25 kB |
+----------+----------+------------+------------+
- 把快照文件傳到其他節點
[root@k8s-work1 ~]# scp snap.db 192.168.10.100:/root 100% 24KB 6.9MB/s 00:00
[root@k8s-work1 ~]# scp snap.db 192.168.10.12:/root
- 停止所有節點的etcd服務,并刪除數據目錄
[root@k8s-work1 ~]# rm -rf /var/lib/etcd/*
[root@k8s-work1 ~]# etcdctl snapshot restore test.db
[root@k8s-work1 ~]# cp -r default.etcd/member/ /var/lib/etcd/
[root@k8s-work1 ~]# docker ps -a | grep etcd
[root@k8s-work1 ~]# docker restart 550
[root@k8s-work1 ~]# etcdctl get s
s
1
# 其余兩個節點相同操作