自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

巧用 Kubernetes Finalizers 優(yōu)雅清理那些刪除失敗的 K8s 資源

系統(tǒng) Linux
本文將介紹當(dāng)你執(zhí)行 kubectl delete 語句時,K8s 內(nèi)部都執(zhí)行了哪些操作。以及為何有些資源『刪除不掉』(具體表現(xiàn)為一直 Terminating,刪除 namespace 時很容易遇到這種情況)。

你有沒有在使用 k8s 過程中遇到過這種情況:通過 kubectl delete 指令刪除一些資源時,一直處于 Terminating 狀態(tài)。這是為什么呢?

本文將介紹當(dāng)你執(zhí)行 kubectl delete 語句時,K8s 內(nèi)部都執(zhí)行了哪些操作。以及為何有些資源『刪除不掉』(具體表現(xiàn)為一直 Terminating,刪除 namespace 時很容易遇到這種情況)。

接下來,我們聚焦討論以下四個方面:

  1. 資源的哪些屬性會對刪除操作產(chǎn)生影響?
  2. finalizers 與 owner references 屬性是如何影響刪除操作的?
  3. 如何利用 Propagation Policy(分發(fā)策略)更改刪除順序?
  4. 刪除操作的工作原理?

方便起見,以下所有示例都將使用 ConfigMaps 和基本 shell 命令來演示該過程。

詞匯表

  1. 資源 : k8s 的資源對象(如 configmap, secret, pod...)
  2. finalizers: 終結(jié)器,存放鍵的列表。列表內(nèi)的鍵為空時資源才可被刪除
  3. owner references: 所有者引用(歸誰管理 / 父資源對象是誰)
  4. kubectl: K8s 客戶端工具

基本刪除操作

Kubernetes 提供了幾個不同的命令,您可以使用它們來創(chuàng)建、讀取、更新和刪除對象。出于本文的目的,我們將重點討論四個 kubectl 命令 :create、get、patch 和 delete。

   ?

   下面是 kubectl delete 命令的基本示例。

  • 創(chuàng)建名為 mymap 的 configmap 對象。
$ kubectl create configmap mymap
configmap/mymap created
  • 查看名為 mymap 的 configmap 對象。
$ kubectl get configmap/mymap
NAME DATA AGE
mymap 0 12s
  • 刪除名為 mymap 的 configmap 對象。
$ kubectl delete configmap/mymap
configmap "mymap" deleted
  • 查看名為 mymap 的 configmap 對象。
$ kubectl get configmap/mymap
Error from server (NotFound): configmaps "mymap" not found

基本 delete 命令的刪除操作狀態(tài)圖非常簡單:

刪除操作看似簡單,但是有很多因素可能會干擾刪除,包括 finalizers 與 owner references 屬性。

Finalizers 是什么?

上面我們提到了兩個屬性:finalizers 與 owner references 可能會干擾刪除操作,導(dǎo)致刪除阻塞或失敗。那 Finalizers 是什么?會對刪除有何影響呢?

當(dāng)要理解 Kubernetes 中的資源刪除原理時,了解 finalizers(以下我們稱 finalizers 為終結(jié)器)的工作原理是很有幫助的, 可以幫助您理解為什么有些對象無法被刪除。

終結(jié)器是資源發(fā)出預(yù)刪除操作信號的屬性, 控制著資源的垃圾收集,并用于提示控制器在刪除資源之前執(zhí)行哪些清理操作。

finalizers 本質(zhì)是包含鍵的列表,不具有實際意義。與 annotations(注釋)類似,finalizers 是可以被操作的(增刪改)。

以下終結(jié)器您可能遇到過:

  • kubernetes.io/pv-protection
  • kubernetes.io/pvc-protection

這兩個終結(jié)器作用于卷,以防止卷被意外刪除。

   ?

類似地,一些終結(jié)器可用于防止資源被刪除,但不由任何控制器管理。下面是一個自定義的 configmap,它沒有具體值,但包含一個終結(jié)器:

$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap
finalizers:
- kubernetes
EOF

終結(jié)器通常用于名稱空間 (namespace),而管理 configmap 資源的控制器不知道該如何處理 finalizers 字段。下面我們嘗試刪除這個 configmap 對象:

$ kubectl delete configmap/mymap &
configmap "mymap" deleted
$ jobs
[1]+ Running kubectl delete configmap/mymap

Kubernetes 返回該對象已被刪除,然而它并沒有真正意義上被刪除,而是在刪除的過程中。當(dāng)我們試圖再次獲取該對象時,我們發(fā)現(xiàn)該對象多了個 deletionTimestamp(刪除時間戳) 字段。

$ kubectl get cm mymap -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: "2021-09-29T11:04:40Z"
deletionGracePeriodSeconds: 0
deletionTimestamp: "2021-09-29T11:04:55Z"
finalizers:
- kubernetes
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:finalizers:
.: {}
v:"kubernetes": {}
manager: kubectl
operation: Update
time: "2021-09-29T11:04:40Z"
name: mymap
namespace: default
resourceVersion: "1378430"
selfLink: /api/v1/namespaces/default/configmaps/mymap
uid: 8d6ca0b1-4840-4597-8164-a63b526dbf5f

   ?

簡而言之,當(dāng)我們刪除帶有 finalizers 字段的對象時,該對象僅僅是被更新了,而不是被刪除了。這是因為 Kubernetes 獲取到該對象包含終 器,通過添加 deletionTimestamp(刪除時間戳)字段將其置于只讀狀態(tài)(刪除終結(jié)器鍵更新除外)。換句話說,在刪除該對象終結(jié)器之前,刪除都不會完成。

接下來我們嘗試通過 patch 命令刪除終結(jié)器,并觀察 configmap/mymap 是否會被『真正』刪除。

$ kubectl patch configmap/mymap \
--type json \
--patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]'
configmap/mymap patched

再次檢索該對象。

$ kubectl get cm mymap
Error from server (NotFound): configmaps "mymap" not found

發(fā)現(xiàn)該對象已被真正刪除,下圖描述了帶有 finalizers 字段的對象刪除流程:

   ?

總結(jié):當(dāng)您試圖刪除一個帶有終結(jié)器的對象,它將一直處于預(yù)刪除只讀狀態(tài), 直到控制器刪除了終結(jié)器鍵或使用 Kubectl 刪除了終結(jié)器。一旦終結(jié)器列表為空,Kubernetes 就可以回收該對象,并將其放入要從注冊表中刪除的隊列中。

帶有 finalizers 字段的對象無法刪除的原因大致如下:

  • 對象存在 finalizers,關(guān)聯(lián)的控制器故障未能執(zhí)行或執(zhí)行 finalizer 函數(shù) hang 住 : 比如 namespace 控制器無法刪除完空間內(nèi)所有的對象, 特別是在使用 aggregated apiserver 時,第三方 apiserver 服務(wù)故障導(dǎo)致無法刪除其對象。 此時,需要會恢復(fù)第三方 apiserver 服務(wù)或移除該 apiserver 的聚合,具體選擇哪種方案需根據(jù)實際情況而定。
  • 集群內(nèi)安裝的控制器給一些對象增加了自定義 finalizers,未刪除完 fianlizers 就下線了該控制器,導(dǎo)致這些 fianlizers 沒有控制器來移除他們。此時,需要恢復(fù)該控制器會手動移除 finalizers(多出現(xiàn)于自定義 operator),具體選擇哪種方案根據(jù)實際情況而定。

Owner References 又是什么?

上面我們提到了兩個屬性:finalizers 與 owner references 可能會干擾刪除操作,導(dǎo)致刪除阻塞或失敗。并介紹了 Finalizers,接下來我們聊聊 Owner References。

Owner References(所有者引用或所有者歸屬)描述了對象組之間的關(guān)系。指定了資源彼此關(guān)聯(lián)的屬性,因此可以級聯(lián)刪除整個資源樹。

   ?

當(dāng)存在所有者引用時,將處理終結(jié)器規(guī)則。所有者引用由名稱和 UID 組成。

所有者引用相同名稱空間內(nèi)的鏈接資源,它還需要 UID 以使該引用生效 (確保唯一)。Pods 通常具有對所屬副本集的所有者引用。因此,當(dāng) Deloyment 或有 StatefulSet 被刪除時,子 ReplicaSet 和 Pod 將在流程中被刪除。

我們通過下面的例子,來理解 Owner References(所有者引用)的工作原理:

  1. 創(chuàng)建 cm/mymap-parent 對象。
$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap-parent
EOF
  1. 獲取 cm/mymap-parent 的 UID。
CM_UID=$(kubectl get configmap mymap-parent -o jsonpath="{.metadata.uid}")
  1. 創(chuàng)建 cm/mymap-child 對象,并設(shè)置 ownerReferences 字段聲明所有者引用(通過 kind、name、uid 字段確保選擇器可以匹配到)。
$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap-child
ownerReferences:
- apiVersion: v1
kind: ConfigMap
name: mymap-parent
uid: $CM_UID
EOF

即 cm/mymap-parent 為 cm/mymap-child 的父對象,此時我們刪除 cm/mymap-parent 對象并觀察 cm/mymap-child 對象狀態(tài)。

$ kubectl get cm
NAME DATA AGE
mymap-child 0 2m44s
mymap-parent 0 3m
$ kubectl delete cm mymap-parent
configmap "mymap-parent" deleted
$ kubectl get cm
No resources found in default namespace.

即我們通過刪除父對象,間接刪除了父對象下的所有子對象。這種刪除 k8s 中被稱為級聯(lián)刪除。我們可不可以只刪除父對象,而不刪除子對象呢?

   ?

 答案是 : 可以的,刪除時通過添加--cascade=false 參數(shù)實現(xiàn),我們通過下面的例子來驗證:

$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap-parent
EOF
$ CM_UID=$(kubectl get configmap mymap-parent -o jsonpath="{.metadata.uid}")
$ cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: mymap-child
ownerReferences:
- apiVersion: v1
kind: ConfigMap
name: mymap-parent
uid: $CM_UID
EOF
$ kubectl delete --cascade=false configmap/mymap-parent
configmap "mymap-parent" deleted
$ kubectl get cm
NAME DATA AGE
mymap-child 0 107s

   ?

   --cascade=false 參數(shù)實際改變了父-子資源的刪除順序,k8s 中關(guān)于父-子資源刪除策略有以下三種:

  • Foreground: 子資源在父資源之前被刪除 (post-order)
  • Background: 父資源在子資源之前被刪除 (pre-order)
  • Orphan: 忽略所有者引用進(jìn)行刪除

下面這段內(nèi)容比較晦澀,沒太理解:

Keep in mind that when you delete an object and owner references have been specified, finalizers will be honored in the process.  This can result in trees of objects persisting, and you end up with a partial deletion.  At that point, you have to look at any existing owner references on your objects, as well as any finalizers, to understand what’s happening

強(qiáng)制刪除命名空間

有一種情況可能需要強(qiáng)制刪除命名空間:

如果您已經(jīng)刪除了一個命名空間,并刪除了它下面的所有對象,但名稱空間仍然存在,一般為 Terminating 狀態(tài)。則可以通過更新名稱空間的 finalize 屬性來強(qiáng)制刪除該名稱空間。

  • 會話 1
$ kubectl proxy
  • 會話 2
$ NAMESPACE_NAME=test
cat <<EOF | curl -X PUT \
127.0.0.1:8001/api/v1/namespaces/$NAMESPACE_NAME/finalize \
-H "Content-Type: application/json" \
--data-binary @-
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "$NAMESPACE_NAME"
},
"spec": {
"finalizers": null
}
}
EOF

我們應(yīng)該謹(jǐn)慎思考是否強(qiáng)制刪除命名空間,因為這樣做可能只刪除名稱空間,命名空間下的其他資源刪不完全,最終導(dǎo)致留下孤兒對象。比如資源對象 A 存在于 ddd 命名空間,此時若強(qiáng)制刪除 ddd 命名空間 , 且對象 A 又未被刪除,那么對象 A 便成了孤兒對象。

當(dāng)出現(xiàn)孤兒對象時,可以手動重新創(chuàng)建名稱空間,隨后可以手動清理和恢復(fù)該對象。

責(zé)任編輯:龐桂玉 來源: 奇妙的Linux世界
相關(guān)推薦

2022-09-05 08:26:29

Kubernetes標(biāo)簽

2024-06-26 00:22:35

2025-04-01 00:06:50

JavaK8sSpring

2022-04-29 11:13:08

K8s資源Linux

2022-04-22 13:32:01

K8s容器引擎架構(gòu)

2023-11-06 07:16:22

WasmK8s模塊

2023-11-07 08:23:05

2022-11-02 10:21:41

K8s pod運維

2023-12-01 15:46:01

Kubernetes容器

2023-11-24 17:51:18

Kubernetes云原生

2023-09-11 14:21:00

2024-06-12 13:21:06

2023-09-06 08:12:04

k8s云原生

2021-12-26 18:23:10

Kubernetes集群命令

2023-04-12 11:28:36

Kubernetes服務(wù)器

2024-05-10 08:00:48

K8soperatorGitHub

2024-09-26 18:04:02

2025-01-03 09:07:51

2022-07-11 10:51:25

Java 8OptionalNPE

2023-11-28 14:04:15

Kubernetes運維
點贊
收藏

51CTO技術(shù)棧公眾號