本文已發布超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 中的鑑識容器檢查點
鑑識容器檢查點建立基於 Userspace 中的檢查點/還原 (CRIU),並允許建立正在運行的容器的狀態副本,而無需容器知道它正在被建立檢查點。容器的副本可以被分析並在沙箱環境中多次還原,而原始容器不會意識到這一點。鑑識容器檢查點建立作為 Kubernetes v1.25 中的 Alpha 功能引入。
它是如何運作的?
在 CRIU 的幫助下,可以對容器進行檢查點建立和還原。CRIU 已整合到 runc、crun、CRI-O 和 containerd 中,並且 Kubernetes 中實作的鑑識容器檢查點建立使用了這些現有的 CRIU 整合。
為何這很重要?
借助 CRIU 和相應的整合,可以取得磁碟上關於正在運行的容器的所有資訊和狀態,以供日後進行鑑識分析。鑑識分析可能對於檢查可疑容器非常重要,而無需停止或影響它。如果容器真的受到攻擊,攻擊者可能會偵測到檢查容器的嘗試。建立檢查點並在沙箱環境中分析容器,提供了在不讓原始容器和可能的攻擊者意識到檢查的情況下檢查容器的可能性。
除了鑑識容器檢查點建立用例之外,也可以將容器從一個節點遷移到另一個節點,而不會遺失內部狀態。特別是對於具有較長初始化時間的狀態ful 容器,從檢查點還原可能會在重新啟動後節省時間,或實現更快的啟動時間。
我該如何使用容器檢查點建立?
此功能位於功能閘道之後,因此請確保先啟用 ContainerCheckpoint
閘道,然後才能使用此新功能。
執行階段也必須支援容器檢查點建立
containerd:支援目前正在討論中。請參閱 containerd pull request #6965 以取得更多詳細資訊。
CRI-O:v1.25 支援鑑識容器檢查點建立。
搭配 CRI-O 的使用範例
若要搭配 CRI-O 使用鑑識容器檢查點建立,則需要使用命令列選項 --enable-criu-support=true
啟動執行階段。對於 Kubernetes,您需要啟用 ContainerCheckpoint
功能閘道來執行叢集。由於檢查點建立功能由 CRIU 提供,因此也必須安裝 CRIU。通常 runc 或 crun 依賴 CRIU,因此會自動安裝。
同樣重要的是要提到,在撰寫本文時,檢查點建立功能在 CRI-O 和 Kubernetes 中被視為 Alpha 級功能,並且安全影響仍在考量中。
一旦容器和 Pod 正在運行,就可以建立檢查點。檢查點建立目前僅在 kubelet 層級公開。若要對容器建立檢查點,您可以在該容器運行的節點上運行 curl
,並觸發檢查點
curl -X POST "https://localhost:10250/checkpoint/namespace/podId/container"
對於命名空間為 default 中名為 counters 的 Pod 內名為 counter 的容器,kubelet API 端點可透過以下方式存取
curl -X POST "https://localhost:10250/checkpoint/default/counters/counter"
為了完整起見,以下 curl
命令列選項是必要的,以使 curl
接受 kubelet 的自我簽署憑證並授權使用 kubelet checkpoint
API
--insecure --cert /var/run/kubernetes/client-admin.crt --key /var/run/kubernetes/client-admin.key
觸發此 kubelet API 將請求從 CRI-O 建立檢查點。CRI-O 從您的低階執行階段 (例如,runc
) 請求檢查點。看到該請求後,runc
會調用 criu
工具來執行實際的檢查點建立。
檢查點建立完成後,檢查點應可在 /var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar
中取得
然後,您可以使用該 tar 存檔在其他地方還原容器。
在 Kubernetes 外部還原已建立檢查點的容器 (使用 CRI-O)
使用檢查點 tar 存檔,可以在 Kubernetes 外部的 CRI-O 沙箱實例中還原容器。為了在還原期間獲得更好的使用者體驗,我建議您使用來自 main CRI-O GitHub 分支的最新版本 CRI-O。如果您使用的是 CRI-O v1.25,則需要手動建立某些 Kubernetes 在啟動容器之前會建立的目錄。
在 Kubernetes 外部還原容器的第一步是使用 crictl 建立 Pod 沙箱
crictl runp pod-config.json
然後,您可以將先前建立檢查點的容器還原到新建立的 Pod 沙箱中
crictl create <POD_ID> container-config.json pod-config.json
您需要在 container-config.json
中指定先前建立的檢查點存檔的路徑,而不是在登錄檔中指定容器映像
{
"metadata": {
"name": "counter"
},
"image":{
"image": "/var/lib/kubelet/checkpoints/<checkpoint-archive>.tar"
}
}
接下來,運行 crictl start <CONTAINER_ID>
以啟動該容器,然後應該運行先前建立檢查點的容器的副本。
在 Kubernetes 內部還原已建立檢查點的容器
若要直接在 Kubernetes 中還原先前建立檢查點的容器,則必須將檢查點存檔轉換為可以推送到登錄檔的映像。
一種可能的轉換本機檢查點存檔的方法包括以下步驟,並借助 buildah
newcontainer=$(buildah from scratch)
buildah add $newcontainer /var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar /
buildah config --annotation=io.kubernetes.cri-o.annotations.checkpoint.name=<container-name> $newcontainer
buildah commit $newcontainer checkpoint-image:latest
buildah rm $newcontainer
產生的映像未標準化,僅適用於 CRI-O。請將此映像格式視為 Pre-Alpha。目前正在進行 討論,以標準化此類檢查點映像的格式。請務必記住,只有在啟動 CRI-O 時使用 --enable-criu-support=true
,此尚未標準化的映像格式才有效。使用 CRIU 支援啟動 CRI-O 的安全性影響尚不清楚,因此應謹慎使用此功能和映像格式。
現在,您需要將該映像推送到容器映像登錄檔。例如
buildah push localhost/checkpoint-image:latest container-image-registry.example/user/checkpoint-image:latest
若要還原此檢查點映像 (container-image-registry.example/user/checkpoint-image:latest
),則需要在 Pod 的規格中列出該映像。以下是一個範例 manifest
apiVersion: v1
kind: Pod
metadata:
namePrefix: example-
spec:
containers:
- name: <container-name>
image: container-image-registry.example/user/checkpoint-image:latest
nodeName: <destination-node>
Kubernetes 將新 Pod 排程到節點上。該節點上的 kubelet 指示容器執行階段 (在本範例中為 CRI-O) 根據指定為 registry/user/checkpoint-image:latest
的映像建立並啟動容器。CRI-O 偵測到 registry/user/checkpoint-image:latest
是對檢查點資料的參考,而不是容器映像。然後,CRI-O 不會執行建立和啟動容器的通常步驟,而是提取檢查點資料並從指定的檢查點還原容器。
該 Pod 中的應用程式將繼續運行,就像未建立檢查點一樣;在容器內,應用程式的外觀和行為就像任何其他正常啟動而非從檢查點還原的容器一樣。
透過這些步驟,可以將在一個節點上運行的 Pod 替換為在不同節點上運行的等效新 Pod,而不會遺失該 Pod 中容器的狀態。
我該如何參與?
您可以透過多種方式聯繫 SIG Node
延伸閱讀
請參閱後續文章 鑑識容器分析,以了解如何分析容器檢查點的詳細資訊。