從容器到調度:準備好這些 CRI 面試題
引言
這兩天也不知道分享什么好了,其實有很多面試題都可以分享,學習,今天的文章也可以讓你有更多的成長。
最后有面試群,大家有興趣可以加入。
開始
1. 什么是 CRI(Container Runtime Interface)?
CRI(Container Runtime Interface)是 Kubernetes 定義的一個接口,目的是為了實現容器的運行時抽象,使得 Kubernetes 能夠支持多種不同的容器運行時(如 Docker、containerd、CRI-O 等)。CRI 是 Kubernetes 的一個關鍵組件,它提供了一種標準化的方式來讓 Kubernetes 與不同的容器運行時交互。
? 容器運行時(Container Runtime): 負責創建和管理容器的組件,它直接與操作系統交互,執行容器的生命周期管理。
? CRI 的作用: 通過定義一個統一的接口,允許 Kubernetes 與容器運行時之間進行通信和交互,從而支持不同類型的容器運行時。
2. CRI 的常見實現有哪些?
常見的實現包括:
? Docker: 雖然 Docker 在 Kubernetes 中被逐漸替代,但它曾是最常用的容器運行時之一。Docker 支持通過 dockershim 實現與 Kubernetes 的 CRI 兼容。
? containerd: 這是一個由 Docker 提供的容器運行時,后成為獨立項目,并成為 Kubernetes 推薦的容器運行時之一。它提供了基礎的容器生命周期管理功能,如容器的創建、啟動、停止等。
? CRI-O: 這是一個專門為 Kubernetes 設計的容器運行時,遵循 CRI 規范。CRI-O 通過提供與 Kubernetes 的直接集成,簡化了容器運行時的功能,去除了 Docker 中的許多非必需功能。
? Frakti: 這是一個為 Kubernetes 提供容器和虛擬機支持的容器運行時,通過 KVM 提供虛擬化支持。
3. CRI 與 Docker 之間的關系是什么?
在 Kubernetes 中,Docker 以前通過 dockershim 提供了對 CRI 的支持,但隨著 Kubernetes 1.20 版本的發布,Docker 支持逐漸被棄用。原因是 Docker 不完全符合 Kubernetes 對容器運行時的要求,尤其是在性能和資源管理方面的靈活性。Kubernetes 推薦使用 containerd 或 CRI-O 來作為容器運行時。
? dockershim: Kubernetes 使用 dockershim 將 Docker 與 Kubernetes 連接在一起,使得 Kubernetes 能夠通過 CRI 與 Docker 進行通信。然而,dockershim 在 Kubernetes 1.24 中被完全移除,因此 Kubernetes 現在不再直接支持 Docker 作為容器運行時。
? containerd 和 CRI-O: 這兩個容器運行時符合 CRI 規范,因此可以直接與 Kubernetes 進行集成并作為容器運行時使用。
4. CRI 的工作流程是怎樣的?
CRI 的工作流程可以分為以下幾個步驟:
- Kubernetes 請求容器運行時: Kubernetes 向 CRI 發出請求,通過 CRI 調用容器運行時的接口(如創建、啟動、停止容器等)。
- CRI 調用容器運行時 API: CRI 通過容器運行時的 API 與容器運行時(如 containerd 或 CRI-O)進行交互,管理容器的生命周期。
- 容器運行時操作系統: 容器運行時與操作系統的內核進行交互,直接管理容器的進程和資源,啟動和停止容器。
- 返回結果給 Kubernetes: 容器運行時完成任務后,返回狀態或執行結果給 Kubernetes。
這個流程確保了 Kubernetes 可以在不同的容器運行時之間進行無縫切換。
5. Kubernetes 通過 CRI 啟動容器時,哪些信息是必需的?
當 Kubernetes 通過 CRI 啟動容器時,必須提供以下信息:
? 容器鏡像: 容器運行時需要知道要拉取并使用哪個鏡像。
? 容器的資源需求: 包括 CPU、內存等資源的限制。
? 網絡配置: 如容器的 IP 地址、端口映射等。
? 存儲卷: 容器可能需要掛載一些持久化存儲卷。
? 命令和參數: 容器啟動時需要執行的命令和參數。
? 容器運行時配置: 如環境變量、日志、PID 控制等配置項。
6. CRI 的接口包括哪些主要的功能?
CRI 提供了多個功能接口,主要包括:
容器創建和啟動:
? CreateContainer: 創建一個容器。
? StartContainer: 啟動一個已經創建的容器。
容器管理:
? StopContainer: 停止一個容器。
? RemoveContainer: 刪除一個容器。
容器狀態查詢:
? ContainerStatus: 獲取容器的當前狀態。
? ListContainers: 列出當前所有運行的容器。
容器日志:
? ContainerLogs: 獲取容器的日志。
容器的健康檢查:
? UpdateContainerResources: 更新容器的資源配置。
? ContainerStats: 獲取容器的資源使用情況,如 CPU、內存、磁盤等。
7. Kubernetes 支持哪些容器運行時?
Kubernetes 支持多種容器運行時,主要包括:
? Docker(通過 dockershim,已逐步棄用)
? containerd
? CRI-O
? Frakti(支持虛擬機容器)
? gVisor(提供額外的安全性,類似沙箱)
? Kata Containers(通過虛擬化實現容器)
從 Kubernetes 1.24 版本開始,Docker 支持逐漸被移除,Kubernetes 推薦使用 containerd 或 CRI-O 作為容器運行時。
8. 為什么 Kubernetes 不再推薦使用 Docker 作為容器運行時?
Kubernetes 不再推薦使用 Docker 作為容器運行時,主要原因有:
? 性能問題: Docker 包含了很多不必要的功能,Kubernetes 只需要容器運行時的基礎功能,如容器的創建、運行和停止,而 Docker 提供了很多額外的功能(如構建鏡像、網絡配置等),這增加了 Kubernetes 的復雜性。
? 復雜性: Docker 本身包含很多與 Kubernetes 無關的組件,如鏡像構建、Docker CLI 等,Kubernetes 只需要與容器運行時交互。containerd 和 CRI-O 是更加輕量和專注的容器運行時,它們去除了與容器編排無關的部分,更適合 Kubernetes 的需求。
? 維護問題: Docker 是一個完整的容器平臺,包含了從構建到運行的完整生命周期,而 containerd 和 CRI-O 僅專注于容器的運行時部分,避免了不必要的復雜性和依賴。
9. CRI 是如何與 Kubernetes 中的 kubelet 交互的?
kubelet 是 Kubernetes 的一個組件,負責與容器運行時交互,確保容器的生命周期管理。kubelet 通過 CRI 與容器運行時進行通信,以下是交互過程:
- 創建容器: kubelet 向 CRI 發起請求,要求創建容器。
- 啟動容器: kubelet 通過 CRI 啟動容器并進行管理。
- 監控容器: kubelet 通過 CRI 獲取容器的狀態、資源使用情況等信息。
- 容器健康檢查: kubelet 可以定期向容器運行時請求容器的健康檢查信息,并在容器失敗時采取恢復操作。
kubelet 作為 Kubernetes 節點的核心組件,利用 CRI 來實現容器的高效管理與調度。
10. CRI 是如何與 Kubernetes 中的 Pod 和容器生命周期管理交互的?
CRI(Container Runtime Interface)與 Kubernetes 中的 Pod 和容器生命周期管理緊密結合。Kubernetes 的 kubelet 通過 CRI 與容器運行時進行交互來管理容器的生命周期。主要交互步驟如下:
? Pod 創建: kubelet 通過 CRI 請求容器運行時創建容器。容器運行時會根據 Pod 的配置文件(如容器鏡像、資源限制等)啟動容器。
? 容器啟動: 一旦 Pod 被調度到節點,kubelet 會調用 CRI 中的 CreateContainer 和 StartContainer 接口來啟動容器。
? 資源管理: kubelet 會通過 CRI 獲取容器的資源使用情況(如 CPU、內存等),并根據 Pod 的資源請求進行調度和限制。
? 容器停止和刪除: kubelet 會通過 CRI 調用容器運行時的 StopContainer 和 RemoveContainer 接口,停止并刪除容器。
? 健康檢查: kubelet 使用 CRI 接口中的 ContainerStatus 和 ContainerLogs 來獲取容器的健康狀態,并進行故障恢復操作。
11. CRI-O 與 containerd 之間有什么區別,為什么 Kubernetes 推薦使用它們?
CRI-O 和 containerd 都是符合 CRI 規范的容器運行時,常用于 Kubernetes 集群中。它們的主要區別和 Kubernetes 推薦使用它們的原因如下:
12. 如何配置 Kubernetes 使用 CRI-O 作為容器運行時?
要將 Kubernetes 配置為使用 CRI-O 作為容器運行時,通常需要進行以下步驟:
- 安裝 CRI-O:安裝 CRI-O 并確保它在 Kubernetes 節點上運行。可以使用發行版的包管理工具(如 apt、yum)或直接從 GitHub 上安裝預編譯的二進制文件。
- 安裝 CRI-O 之后,啟動并確保它運行正常:
systemctl start crio
systemctl enable crio
- 配置 Kubernetes 使用 CRI-O: Kubernetes 的 kubelet 通過 --container-runtime 參數指定容器運行時。如果要使用 CRI-O,可以在 kubelet 配置中設置為 cri-o:
- 編輯 kubelet 的啟動配置文件(如 /etc/default/kubelet):
KUBELET_EXTRA_ARGS="--container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock"
- 如果你使用的是 kubeadm 來安裝 Kubernetes,可以通過 kubeadm 的配置文件進行配置:
apiServer:
extraArgs:
container-runtime: remote
container-runtime-endpoint: /var/run/crio/crio.sock
- 重啟 kubelet 服務: 配置完成后,重啟 kubelet 服務,使其使用 CRI-O 作為容器運行時:
systemctl restart kubelet
- 驗證配置: 使用以下命令驗證容器運行時配置是否正確:
kubectl get nodes -o wide
- 如果配置成功,kubelet 會使用 CRI-O 來管理容器。
13. CRI 在容器調度中的作用是什么?
CRI 在 Kubernetes 中的容器調度過程中起到了以下作用:
? 容器生命周期管理: CRI 負責容器的生命周期管理,包括容器的創建、啟動、停止和刪除等。當 Kubernetes 調度一個 Pod 到某個節點時,kubelet 會通過 CRI 啟動容器,并監控其健康狀態。
? 容器狀態監控: 通過 CRI,kubelet 能夠獲取容器的狀態和資源使用情況(如 CPU、內存等),并將這些信息反饋給 Kubernetes,以便進行調度決策。
? 資源分配與限制: CRI 協調容器資源(如內存、CPU、存儲等)的分配和限制。kubelet 會通過 CRI 來確保容器不會超出節點的資源配額。
? 容器健康檢查: CRI 提供了容器健康檢查接口,kubelet 可以定期檢查容器的健康狀態,并在容器失敗時進行重啟或遷移。
14. 什么是 Kubernetes 中的 kubelet 與 CRI 的交互方式?
在 Kubernetes 中,kubelet 是管理容器生命周期的關鍵組件,它與 CRI 容器運行時接口直接交互,確保容器的啟動、管理和停止等操作。kubelet 通過以下方式與 CRI 進行交互:
- 容器創建和啟動: kubelet 會向 CRI 請求創建和啟動容器。它將 Pod 的規范(如容器鏡像、資源要求等)傳遞給 CRI,CRI 根據這些信息啟動容器。
- 容器監控: kubelet 會定期通過 CRI 獲取容器的狀態、資源使用情況和健康狀況。基于這些數據,kubelet 會判斷容器是否需要重啟、停止或刪除。
- 容器日志: kubelet 可以通過 CRI 獲取容器的日志信息,并將日志記錄在 Kubernetes 的日志系統中,供用戶調試和監控。
- 健康檢查: kubelet 使用 CRI 的健康檢查功能來檢測容器的健康狀態,并根據結果決定是否需要重新調度容器。
- 容器停止與刪除: kubelet 會在容器運行完成后,通過 CRI 請求停止并刪除容器,釋放資源。
15. 如何在 Kubernetes 中實現容器的資源限制和 QoS(Quality of Service)?
在 Kubernetes 中,容器的資源限制是通過 Pod 的資源請求和限制來實現的。資源請求和限制會影響容器的 QoS 級別,具體步驟如下:
16. CRI-O 和 containerd 的性能優化和調優策略有哪些?
CRI-O 和 containerd 都是符合 CRI 規范的容器運行時,它們的性能優化和調優策略包括:
優化容器鏡像拉取
? 鏡像緩存: 通過鏡像緩存機制,減少重復拉取相同鏡像的次數。在 containerd 和 CRI-O 中,可以設置鏡像拉取的緩存策略,避免每次啟動時都需要從頭開始拉取鏡像。
? 鏡像代理: 使用鏡像代理服務(如 Harbor 或 Nexus)來緩存常用鏡像,減少對遠程鏡像倉庫的依賴,提升拉取速度。
容器調度優化
? 資源預留和限制: 在 containerd 或 CRI-O 配置中,合理設置容器的資源限制(如 CPU、內存、I/O)和優先級,避免因資源爭搶導致的容器性能下降。
? CPU 配額: 通過配置容器的 CPU 配額和親和性(cpu-shares, cpuset),確保容器在多節點集群中高效調度,減少 CPU 資源的浪費。
性能優化
? 存儲優化: 使用高效的存儲插件,如 overlay2 文件系統,減少容器 I/O 負擔,提高磁盤訪問速度。
? 網絡性能: 通過調整容器運行時的網絡配置(如使用 HostNetwork 模式),減少容器間的網絡開銷,優化網絡帶寬和延遲。
垃圾回收與清理
? 鏡像垃圾回收: 定期清理不再使用的鏡像和容器,釋放存儲空間,避免磁盤空間的浪費。
? 容器日志管理: 通過日志輪轉機制(如設置 max-size 和 max-file)避免日志文件過大,影響性能。
容器啟動優化
? 使用 Pod 優先級 和 調度策略 來確保關鍵服務能夠盡早啟動。
? 配置容器的 init 容器(初始化容器),避免主容器啟動時的阻塞,確保初始化任務并行執行。
17. 如何處理 Kubernetes 中的 CRI 運行時與容器運行時之間的兼容性問題?
Kubernetes 中的容器運行時和 CRI 的兼容性問題可能會在多種情況下出現,例如 Kubernetes 版本升級、容器運行時更新或配置不當等。處理這些問題的策略包括:
使用 kubelet 配置文件
? Kubernetes 提供了 kubelet 配置文件,其中包括關于 CRI 運行時的詳細配置項,如 --container-runtime、--container-runtime-endpoint、--image-service-endpoint 等。通過精確設置這些參數,可以確保 kubelet 與指定的容器運行時兼容。
版本匹配
? 確保 Kubernetes 版本和容器運行時的版本兼容。例如,containerd 和 CRI-O 的新版本可能會支持新的 CRI 特性,因此需要在 Kubernetes 中確保配置正確的 CRI 版本。
CRIO 和 containerd 的插件機制
? CRI-O 和 containerd 都提供了插件機制,可以通過加載不同的插件來擴展或修改容器運行時的行為。通過正確配置這些插件,可以解決與容器運行時的兼容性問題。
? 例如,containerd 使用 snapshotter 插件來處理文件系統層(如 overlay2 或 aufs),根據不同的文件系統來調整容器運行時的性能。
集成與測試
? 對于多容器運行時環境(例如同時使用 containerd 和 CRI-O),定期進行集成測試,確保 Kubernetes 和容器運行時之間的兼容性。在生產環境中,進行壓力測試來發現潛在的兼容性問題,并及時修復。
監控與日志
? 利用 Kubernetes 的日志系統和容器運行時日志,快速定位和解決容器運行時與 CRI 的兼容性問題。例如,使用 kubectl logs 查看容器日志,查看 kubelet 和 CRI-O、containerd 等日志,找到潛在的配置或兼容性問題。
18. 如何實現 CRI 與 Kubernetes 中的調度器(Scheduler)的高效集成?
為了確保 CRI 與 Kubernetes 調度器(Scheduler)高效集成,涉及多個方面的配置和優化:
資源請求與調度優化
? Kubernetes 調度器基于容器的資源請求(如 CPU、內存)來進行調度。CRI 需要向 kubelet 提供容器的資源請求信息,調度器根據這些信息將容器調度到適合的節點上。
? 為了實現高效調度,容器運行時(如 CRI-O 或 containerd)需要與 kubelet 緊密協作,確保容器的資源限制與請求正確地傳遞給調度器。
Pod Affinity/Anti-Affinity
? 在調度 Pod 時,使用 Pod Affinity 和 Anti-Affinity 配置來確保相關容器運行在相同節點或不同節點上。容器運行時通過支持節點親和性和拓撲配置,幫助調度器做出高效的決策。
調度策略與 QoS(Quality of Service)
? Kubernetes 中的 QoS 級別(如 Guaranteed、Burstable、BestEffort)直接影響容器的優先級。CRI 需要根據容器的 QoS 配置來優化資源的分配和管理。
? 對于關鍵業務服務,容器運行時應支持資源優先級的配置,確保這些容器能夠優先獲得資源。
動態資源調整與 Pod 重新調度
? Kubernetes 支持基于資源使用的動態調度,容器運行時通過 CRI 接口提供容器的實時資源使用數據,幫助調度器根據集群的負載動態調整容器調度。
? 例如,containerd 和 CRI-O 可以提供容器的實時資源使用情況,通過 CRI 接口將其反饋給 kubelet 和調度器,進而執行容器的遷移或重調度。
19. 如何在 CRI 中實現容器運行時的高可用性(HA)?
為了確保容器運行時的高可用性(HA),需要從以下幾個方面入手:
容器運行時的多節點部署
? 將 CRI 運行時的容器管理服務(如 containerd、CRI-O)部署在多個節點上,通過高可用集群架構來保證容器運行時的可用性。
? 配置集群級別的負載均衡,確保容器運行時的請求可以在集群內多個節點間分發,避免單點故障。
容器運行時的狀態同步
? 容器運行時應支持跨節點的狀態同步。例如,containerd 提供了對分布式存儲的支持,確保多個節點上容器的狀態信息一致,以便在節點發生故障時能夠恢復容器的運行狀態。
? 配置共享存儲卷(如 NFS、Ceph),確保容器的持久化數據在節點故障時能夠恢復。
故障恢復與自動重啟
? CRI 運行時可以通過支持容器的健康檢查和自動重啟機制來提高容器的可用性。kubelet 會監控容器狀態,通過 CRI 接口獲取容器健康狀況,自動重啟失敗的容器。
? 配置容器運行時的故障檢測機制,當容器出現故障或不可用時,及時重啟容器并將其恢復到預期狀態。
動態容器調度與節點擴展
? 配置 Kubernetes 的自動擴容功能,結合容器運行時的高可用性設置,當集群資源緊張時,自動擴展節點并將負載均衡到新節點上。
? 在容器運行時支持容器的動態遷移和調度,確保容器在集群中故障恢復時能夠快速遷移到其他節點。
20. 如何優化 CRI 中容器運行時的 I/O 性能?
優化容器運行時的 I/O 性能可以從以下幾個方面著手:
文件系統選擇
? 選擇高性能的存儲驅動,如 overlay2,該驅動提供了較高的文件系統性能,特別是在容器鏡像和容器數據的 I/O 操作時。
? 使用支持高性能 I/O 操作的存儲插件,如 device-mapper 和 btrfs。
存儲卷優化
? 對于需要高性能存儲的容器,使用本地存儲卷(如 local 存儲插件)可以減少 I/O 延遲,提供更高的吞吐量。
? 配置適當的卷類型,例如使用 NFS 協議的遠程存儲系統來支持共享存儲需求。
容器磁盤配額與分配
? 配置磁盤 I/O 限制(如 --blkio-weight)來確保容器不會因 I/O 操作過多而影響其他容器的性能。
? 使用 磁盤配額 來分配每個容器的磁盤空間,避免磁盤資源過度占用。
優化日志處理
? 對容器日志進行優化,避免過多的日志寫入影響容器性能。使用外部日志處理系統(如 Fluentd、ELK)來集中管理容器日志。
21. CRI 的配置文件通常位于哪里?如何修改其參數?
? 路徑:/etc/containerd/config.toml(containerd)或 /etc/crio/crio.conf(CRI-O)。
? 修改后重啟服務:
systemctl restart containerd # 或 crio
22. Kubernetes 1.24 移除了 dockershim,如何確保舊集群兼容 Docker?
方案:
? 使用 Mirantis Container Runtime(替代 dockershim)。
? 遷移到 containerd,并確保 Docker 容器鏡像兼容。
23. 如何通過 CRI 查看容器的底層日志?
ctr --namespace=k8s.io containers ls # 列出容器
ctr --namespace=k8s.io logs <容器ID>
crictl logs <容器ID>
24. 當 Pod 處于 ContainerCreating 狀態時,如何排查 CRI 相關問題?
步驟:
- 查看 Pod 事件:kubectl describe pod <pod-name>。
- 檢查容器運行時日志:
journalctl -u containerd # 或 crio
- 驗證鏡像拉取:crictl pull <image>。
- 如何限制容器運行時的資源使用(如 CPU、內存)?
a. Kubernetes 層面: 通過 Pod 的 resources 字段限制。
b.CRI 層面: 配置容器運行時的 Cgroups 參數(如 containerd 的 config.toml)。
25. 如何配置 containerd 使用私有鏡像倉庫?
修改 config.toml:
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."my-registry.com"]
endpoint = ["https://my-registry.com"]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.com".tls]
insecure_skip_verify = true # 跳過 TLS 驗證(可選)
26. CRI 與 OCI(Open Container Initiative)的關系是什么?
? CRI: 定義 Kubernetes 與容器運行時的交互接口。
? OCI: 定義容器鏡像和運行時的標準(如鏡像格式、運行時規范 runc)。
? 關系: CRI 兼容的運行時(如 containerd)通過 OCI 標準管理容器生命周期。
27. 如何優化 CRI 的性能以支持高密度容器部署?
? 啟用容器運行時緩存(如 containerd 的快照機制)。
? 調整并發拉取鏡像的線程數(max_concurrent_downloads)。
? 使用高性能存儲驅動(如 overlay2)。