如果我們想要構建和運行一個現代的云基礎設施,那么理解Docker和Kubernetes是必不可少的。本文主要給大家介紹Docker和Kubernetes技術以及它們之間的區別和聯系。
一、Docker
1.1 容器(Container)簡介
容器是打包軟件的一種方式,包括打包應用程序的所有代碼、庫和依賴關系等。它們提供了一個輕量級的虛擬環境,可以將一組進程和資源(如內存、CPU、磁盤等)與主機和任何其他容器隔離。隔離保證了容器內的任何進程都不能看到容器外的任何進程或資源。
1.2 Docker原理
linux下的容器技術使用了Linux的內核機制:namespace (ipc、uts、mount、pid、network和user) 和cgroups (在現有內核實例之上提供抽象層,以創建類似于虛擬機的隔離環境)。其中,namespace實現了對內核全局資源的隔離;而cgroup則用來限制、控制和統計一組進程及將來的子進程所使用的物理資源,包括cpu, memory, disk等。
1.2.1 namespace
namespace是Linux內核的一個特性,它對內核資源進行分組,以便一組進程看到一組資源,同時另一組進程看到另一組資源。也就是說內核資源被包裝在namespace中,并且它們只對運行在同一個namespace中的進程可見,對其他namespace中的進程不可見。目前namespace支持的類型包括以下六種:
我們依次來介紹以下他們的作用:
(1)NET:
NET namespace為容器提供系統網絡協議的視圖(如IP地址、路由表、端口號等)。基于此,不同容器都有各自獨立的網絡協議棧視圖,如網絡接口、IP地址、端口、路由表等。
(2)PID(Process ID):
PID namespace為容器提供它們自己的進程視圖,包括一個獨立的init (PID 1),它是所有進程的祖先。基于此,不同容器都有各自的PID為1的init進程。
(3)MNT:
MNT namespace為容器提供了系統上的“文件系統掛載”視圖。因此,不同的容器中,可以看到不同的文件系統層次結構視圖,且可以獨立操作(讀寫)而互不影響。
(4)UTS (UNIX Timesharing System):
UTS namespace允許容器擁有自己的主機名和NIS域名,它們獨立于其他容器和主機系統。
(5)IPC(Interprocess Communication):
IPC namespace負責在每個容器內運行的進程之間隔離IPC資源。
(6)USER:
USER namespace 用于在每個容器中隔離用戶。它的功能是允許不同的容器擁有不同的UID(用戶ID)和GID(組ID)范圍視圖。
我們來總結一下,當Docker創建一個容器時,它會創建新的以上六種namespace的實例,然后把該容器中的所有進程放到這些namespace之中,使得容器這個父進程只對自己創建的子進程有感知,而對于宿主機的和其他容器創建的進程一無所知,從而產生一種它就是一個獨立的系統的“錯覺”。
1.2.2 cgroups
control groups這是一個Linux內核特性,用于隔離和管理不同的資源,如CPU、內存、磁盤I/O、網絡等的消耗。 cgroups還可以確保單個容器不會耗盡其中某一個資源,從而避免整個系統的崩潰。
1.3 Docker的組成
一個完整的Docker系統由以下6個部分組成,分別是:
Docker Client:
這是CLI(命令行接口)工具,用于配置Docker并與之交互。每當開發人員或用戶運行docker命令(內部封裝了Docker Client)時,Docker Client就會將這些命令發送到docker守護進程(dockerd), dockerd會負責執行這些具體的命令。
Docker Daemon:
這是作為docker守護進程運行的Docker服務器。這個守護進程偵聽API請求并管理Docker對象(images、containers、networks和volumes)。守護進程還可以與其他守護進程通信來管理Docker服務。
Images(鏡像):
Images是用于創建Docker容器的只讀模板或者快照。這些Images可以從鏡像倉庫獲取。鏡像倉庫分為公有鏡像倉庫和私有鏡像倉庫。Docker Hub 是市面上主流的公有鏡像倉庫。除了公有鏡像倉庫以外,很多企業為了節省網絡帶寬和提高鏡像資源使用率,也會配置自己的私有鏡像倉庫,提供給企業內部員工使用。
Docker file:
Docker file用來創建Docker Image。具體Docker file的語法大家可以參考相關的文檔。
Containers(容器):
容器是鏡像的運行實例。我們可以通過docker命令進行如下操作:
- 創建、運行、停止、移動或者刪除容器
- 將容器連接到一個或多個網絡(Network)
- 向容器添加存儲(Volume)
- 根據容器的當前狀態創建新的鏡像(Image)
Docker Registries:
Docker Registries用來保存和管理容器鏡像。Docker Hub是任何人都可以使用的公共的Docker Register,默認情況下Docker被配置為在Docker Hub上尋找鏡像。當我們使用docker pull或docker run命令時,所需的鏡像就會從我們配置的Docker Register拉取到本地。當我們使用docker push命令時,我們自己的鏡像會被推到我們配置的Docker Register。
1.4 Docker的優勢
(1)可以在云平臺之間無縫遷移你的應用
(2)消除環境的不一致
(3)高效的分發你的應用
(4)易于擴展應用程序
(5)輕量級
(6)啟動速度快
(7)易于維護
正是docke的以上特性和優勢,docker獲得了越來越多的開發者的青睞。然而,隨著應用程序越來越復雜,單個應用程序跨越和使用多個容器越發平常,如何協調和管理這些容器成為一個棘手的問題:
- 多個容器之間如何協調和調度?
- 應用程序中的不同的容器之間如何彼此通訊?
- 多個容器執行個體的規模如何調整?
而要解決這些問題,就需要借助Kubernetes了。
二、kubernetes
2.1 Kubernetes簡介
Kubernetes是由google在2014年開源的生產級別的容器編排系統。Kubernetes不僅是一個容器編排系統,還是一個微服務或者云原生(彈性伸縮)的平臺, Kubernetes提供了服務注冊與發現、負載均衡、服務自愈、橫向擴展、日志監控、集群自愈和容錯、彈性伸縮、存儲卷掛載的能力。
2.2 Kubernetes的架構
一個 Kubernetes 集群由一組被稱作節點的機器組成。節點分為主節點和工作節點。每個集群至少要有一個主節點和工作節點。
主節點管理集群中的工作節點和 Pod 。多個主節點用于為集群提供故障轉移和高可用性。工作節點負責托管應用程序組件中的 Pod。
這張圖表展示了包含所有相互關聯組件的 Kubernetes 集群。
Control Plane Components(控制平面組件): Control Plane Components組件提供了集群的控制平面,它們負責集群的全局活動,包括:調度、檢測和響應集群事件等功能(例如,當不滿足部署的replicas字段時,啟動新的pod)
- kube-apiserver: kube-apiserver是主節點上負責提供 Kubernetes API 服務的組件,它是 Kubernetes 控制面的前端。kube-apiserver用于控制集群的所有REST命令的入口點。它處理REST請求、驗證它們并執行相應的業務邏輯。kube-apiserver 在設計上考慮了水平擴縮的需要。 換言之,通過部署多個實例可以實現擴縮。
- etcd: etcd 是兼具一致性和高可用性的key-value數據庫,可以作為保存 Kubernetes 所有集群數據的后臺數據庫。
- Controller-manager: Controller-manager運行Contrller來處理集群中的常規任務。這些控制器包括:節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應。副本控制器(Replication Controller): 負責為系統中的每個副本控制器對象維護正確數量的 Pod。端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)。服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的namespace創建默認帳戶和 API 訪問令牌
從邏輯上講,每個控制器都是一個單獨的進程,但是為了降低復雜性,它們都被編譯到同一個可執行文件,并在一個進程中運行。
- Scheduler: 該組件負責監視那些新創建的未指定運行節點的 Pod,并選擇節點讓 Pod 在上面運行。Scheduler組件的調度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規范、數據位置等。
- cloud-controller-manager:cloud-controller-manager是 kubernetes 1.8 的 alpha 特性。在未來的kubernetes版本中,這是將 Kubernetes 與任何其他云集成的最佳方式。cloud-controller-manager允許您將集群鏈接到cloud provider的API中,并將與云平臺交互的組件與僅與集群交互的組件分離開來。當然了,如果你在自己的環境中運行 Kubernetes,或者在本地計算機中運行學習環境, 所部署的環境中不需要cloud-controller-manager。
Node Components: Node組件運行在每個節點上,負責維護運行的pods并為它們提供Kubernetes運行時環境。
- kubelet: kubelet 接收一組通過各類機制提供給它的 PodSpecs,確保這些 PodSpecs 中描述的容器處于運行狀態且健康。kubelet 不會管理不是由 Kubernetes 創建的容器。
- kube-proxy: Kube-proxy是集群中每個節點上運行的網絡代理。kube-proxy 維護節點上的網絡規則。這些網絡規則允許從集群內部或外部的網絡會話與 Pod 進行網絡通信。如果操作系統提供了數據包過濾層并可用的話,kube-proxy會通過它來實現網絡規則。否則,kube-proxy 僅轉發流量本身。
- Container runtime: Container runtime是負責運行容器的軟件。Kubernetes 支持多個容器運行環境: Docker、 containerd、cri-o、 rktlet 以及任何實現 Kubernetes CRI (容器運行環境接口)的軟件。但近年來,Docker 已發展成為默認的容器運行環境。
2.3 Kubernetes的優勢
Kubernetes 為您提供:
- 服務發現和負載均衡
- Kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,如果到容器的流量很大,Kubernetes 可以負載均衡并分配網絡流量,從而使部署穩定。
- 存儲編排
- Kubernetes 允許您自動掛載您選擇的存儲系統,例如本地存儲、公共云提供商等。
- 自動部署和回滾
- 您可以使用 Kubernetes 描述已部署容器的期待狀態,它可以以受控的速率將實際狀態更改為所需狀態。例如,您可以自動化 Kubernetes 來為您的部署創建新容器,刪除現有容器并將它們的所有資源用于新容器。
- 自動二進制打包
- Kubernetes 允許您指定每個容器所需 CPU 和內存(RAM)。當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。
- 自我修復
- Kubernetes 可以重新啟動失敗的容器、替換容器、殺死不響應用戶定義的運行狀況檢查的容器,并且在準備好服務之前不將其通告給客戶端。
- 密鑰與配置管理
- Kubernetes 允許您存儲和管理敏感信息,例如密碼、OAuth 令牌和 ssh 密鑰。您可以在不重建容器鏡像的情況下部署和更新密鑰和應用程序配置,也無需在應用配置中暴露密鑰。
三、Kubernetes和Docker比較
談到 Kubernetes 與 Docker 的比較時,往往會落入“非此即彼”的陷阱:應該使用 Kubernetes 還是 Docker?
事實上,不必進行選擇,Kubernetes 和 Docker 基本上是不同的兩種技術。事實上,如果一定要比較,將 Kubernetes 與 Docker Swarm 進行比較更為恰當。
Kubernetes 與 Docker 之間的根本區別在于,Kubernetes 旨在跨群集運行,而 Docker 在單個節點上運行。Docker讓你只需編寫一次代碼即可在任何地方運行;而 Kubernetes 則讓你可從單一控制界面協調和管理所有容器資源。這有助于跨運行容器的所有 Kubernetes 節點實現聯網、負載均衡、安全性和縮放。Kubernetes 還具有命名空間等內置隔離機制,使你可以按訪問權限等對容器資源進行分組。這些結構使 IT 部門更易于為開發人員提供自助式資源訪問權限,并且即使在最復雜的微服務體系結構上,開發人員也可以在不模擬其開發環境中的整個應用程序的情況下進行協作。
簡而言之,結合使用 Kubernetes 和 Docker 可以:
- 使你的基礎結構更加可靠,并使應用程序更具高可用性。
- 使你的應用程序更具可縮放性。如果你的應用開始逐漸產生越來越多的負載,并且需要橫向擴展才能提供更好的用戶體驗,則只需啟動更多容器或向 Kubernetes 群集添加更多節點即可。
參考資料:
https://kubernetes.io/docs/concepts/overview/components/
https://azure.microsoft.com/zh-cn/topic/kubernetes-vs-docker/