1. 程式人生 > >容器、容器叢集管理平臺與Kubernetes技術漫談_Kubernetes中文社群

容器、容器叢集管理平臺與Kubernetes技術漫談_Kubernetes中文社群

文章由作者投稿:

高慶,百悟科技  高階運維工程師

本文源自一次技術選型的工作中所收集、整理、調研和撰寫的技術資料,釋出於2018年11月12日。

我們為什麼使用容器?

我們為什麼使用虛擬機器(雲主機)? 為什麼使用物理機? 這一系列的問題並沒有一個統一的標準答案。因為以上幾類技術棧都有自身最適用的場景,在最佳實踐之下,它們分別都是不可替代的。 原本沒有虛擬機器,所有型別的業務應用都直接跑在物理主機上面,計算資源和儲存資源都難於增減,要麼就是一直不夠用,要麼就一直是把過剩的資源浪費掉,所以後來我們看到大家越來越多得使用虛擬機器(或雲主機),物理機的使用場景被極大地壓縮到了像資料庫系統這樣的特殊型別應用上面。

原本也沒有容器,我們把大部分的業務應用跑在虛擬機器(或雲主機)上面,把少部分特殊型別的應用仍然跑在物理主機上面。但現在所有的虛擬機器技術方案,都無法迴避兩個主要的問題,一個問題是虛擬化Hypervisor管理軟體本身的資源消耗與磁碟IO效能降低,另一個是虛擬機器仍然還是一個獨立的作業系統,對很多型別的業務應用來說都顯得太重了,導致我們在處理虛擬機器的擴縮容與配置管理工作時效率低下。所以,我們後來發現了容器的好處,所有業務應用可以直接執行在物理主機的作業系統之上,可以直接讀寫磁碟,應用之間通過計算、儲存和網路資源的名稱空間進行隔離,為每個應用形成一個邏輯上獨立的“容器作業系統”。除此之外,容器技術還有以下優點:簡化部署、多環境支援、快速啟動、服務編排、易於遷移。

容器技術的一些缺點:仍然不能做到徹底的安全隔離,技術棧複雜度飈升,尤其是在應用了容器叢集技術之後。所以如果只是小規模的使用,做實驗或測試是可以的,上生產環境需要三思而後行。

容器與容器叢集技術的演進

容器技術的演進路線

注:上圖取自《容器技術及其應用白皮書[v1.0]》

容器叢集技術的演進

上圖描述了容器技術的演進,此後的近三年來的容器技術演進發展為主要是以容器叢集技術為中心,如下所示。

容器的執行原理與基本元件

Docker容器主要基於以下三個關鍵技術實現的: – Namespaces – Cgroups技術 – Image映象

容器引擎 容器引擎(Engine)或者容器執行時(Runtime)是容器系統的核心,也是很多人使用“容器”這個詞語的指代物件。容器引擎能夠建立和執行容器,而容器的定義一般是以文字方式儲存的,比如 Dockerfile。

  • Docker Engine :目前最流行的容器引擎,也是業界的事實標準。
  • Rkt:CoreOS 團隊推出的容器引擎,有著更加簡單的架構,一直作為 Docker 的直接競爭對手存在,是 kubernetes 排程系統支援的容器引擎之一。
  • containerd:這個新的Daemon是對Docker內部元件的一個重構以便支援OCI規範,containerd 主要職責是映象管理(映象、元資訊等)、容器執行(呼叫最終執行時元件執行),向上為 Docker Daemon 提供了 gRPC 介面,向下通過 containerd-shim 結合 runC,使得引擎可以獨立升級。
  • docker-shim:shim 通過呼叫 containerd 啟動 docker 容器,所以每啟動一個容器都會起一個新的docker-shim程序。docker-shim是通過指定的三個引數:容器id,boundle目錄和執行時(預設為runC)來呼叫runC的api建立一個容器。
  • runC :是 Docker 按照開放容器格式標準(OCF, Open Container Format)制定的一種具體實現,實現了容器啟停、資源隔離等功能,所以是可以不用通過 docker 引擎直接使用runC執行一個容器的。也支援通過改變引數配置,選擇使用其他的容器執行時實現。RunC可以說是各大CaaS廠商間合縱連橫、相互妥協的結果,

注:RunC在各個CaaS廠商的推動下在生產環境得到廣泛的應用。Kubernetes目前基本只支援RunC容器,對於Docker超出其容器抽象層之外的功能,一概不支援。同樣,Mesos也通過其Unified Containerizer只支援RunC容器,目前還支援Docker,但是未來的規劃是隻支援Unified Containerizer。CF也通過Garden只支援RunC,不支援Docker超出RunC之前的功能。

為什麼在容器的啟動或執行過程中需要一個 docker-containerd-shim 程序呢? 其目的有如下幾點: – 它允許容器執行時(即 runC)在啟動容器之後退出,簡單說就是不必為每個容器一直執行一個容器執行時(runC) – 即使在 containerd 和 dockerd 都掛掉的情況下,容器的標準 IO 和其它的檔案描述符也都是可用的 – 向 containerd 報告容器的退出狀態

rkt與containerd的區別是什麼? 一個主要的不同之處是,rkt作為一個無守護程序的工具(daemonless tool),可以用來在生產環境中,整合和執行那些特別的有關鍵用途的容器。舉個例子,CoreOS Container Linux使用rkt來以一個容器映象的方式執行Kubernetes的agent,即kublet。更多的例子包括在Kubernetes生態環境中,使用rkt來用一種容器化的方式掛載volume。這也意味著rkt能被整合進並和Linux的init系統一起使用,因為rkt自己並不是一個init系統。kubernets支援容器進行部署,其所支援的容器不只是僅僅侷限於docker,CoreOS的rkt也是容器玩家之一,雖然跟docker比起來還是明顯處於絕對下風,但有競爭總要好過沒有。

容器編排和管理系統

容器是很輕量化的技術,相對於物理機和虛機而言,這意味著在等量資源的基礎上能創建出更多的容器例項出來。一旦面對著分佈在多臺主機上且擁有數百套容器的大規模應用程式時,傳統的或單機的容器管理解決方案就會變得力不從心。另一方面,由於為微服務提供了越來越完善的原生支援,在一個容器叢集中的容器粒度越來越小、數量越來越多。在這種情況下,容器或微服務都需要接受管理並有序接入外部環境,從而實現排程、負載均衡以及分配等任務。 簡單而高效地管理快速增漲的容器例項,自然成了一個容器編排系統的主要任務。

容器叢集管理工具能在一組伺服器上管理多容器組合成的應用,每個應用叢集在容器編排工具看來是一個部署或管理實體,容器叢集管理工具全方位為應用叢集實現自動化,包括應用例項部署、應用更新、健康檢查、彈性伸縮、自動容錯等等。 容器編排和管理系統的分層結構圖

容器編排和管理系統界的主要選手 – Kubernetes:Google 開源的容器管理系統,起源於內部歷史悠久的 Borg 系統。因為其豐富的功能被多家公司使用,其發展路線注重規範的標準化和廠商“中立”,支援底層不同的容器執行時和引擎(比如 Rkt),逐漸解除對 Docker 的依賴。Kubernetes的核心是如何解決自動部署,擴充套件和管理容器化(containerized)應用程式。目前該專案在github上Star數量為43k。 – Docker Swarm: 在 Docker 1.2 版本後將 Swarm 整合在了 Docker 引擎中。使用者能夠輕鬆快速搭建出來 docker 容器叢集,幾乎完全相容 docker API 的特性。目前該專案在github上Star數量為5.3k。 – Mesosphere Marathon:Apache Mesos 的排程框架目標是成為資料中心的作業系統,完全接管資料中心的管理工作。Mesos理念是資料中心作業系統(DCOS),為了解決IaaS層的網路、計算和儲存問題,所以Mesos的核心是解決物理資源層的問題。Marathon是為Mesosphere DC/OS和Apache Mesos設計的容器編排平臺。目前該專案在github上Star數量為3.7k。

注:國內外有很多公司在從事基於上面三個基礎技術平臺的創新創業,為企業提供增值服務,其中做得不錯的如Rancher,其產品可以同時相容 kubernetes、mesos 和 swarm 集群系統,此外還有很多商用解決方案,如OpenShift。

中國市場的表現 在中國市場,2017 年 6 月 Kubernetes 中國社群 K8SMeetup 曾組織了國內首個針對中國容器開發者和企業使用者的調研。近 100 個受訪使用者和企業中給我們帶來了關於 Kubernetes 在中國落地狀況的一手調查資料顯示: – 在容器編排工具中,Kubernetes佔據了70%市場份額,此外是Mesos約11%,Swarm不足7%; – 在中國受訪企業使用者中,Kubernetes 平臺上執行的應用型別非常廣泛,幾乎包括了除hadoop大資料技術棧以外的各種型別應用; – 中國受訪企業執行 Kubernetes 的底層環境分佈顯示,29%的客戶使用裸機直接執行容器叢集,而在包括OpenStack、VMWare、阿里雲和騰訊雲在內的泛雲平臺上執行容器叢集服務的客戶佔到了60%;

關於CNCF基金會

主要的容器技術廠商(包括 Docker、CoreOS、Google、Mesosphere、RedHat 等)成立了 Cloud Native Computing Foundation (CNCF) 。 CNCF對雲原生的定義是: – 雲原生技術幫助公司和機構在公有云、私有云和混合雲等新型動態環境中,構建和執行可彈性擴充套件的應用。雲原生的代表技術包括容器、服務網格、微服務、不可變基礎設施和宣告式API。 – 這些技術能夠構建容錯性好、易於管理和便於觀察的鬆耦合系統。結合可靠的自動化手段,雲原生技術可以使開發者輕鬆地對系統進行頻繁並可預測的重大變更。 – 雲原生計算基金會(CNCF)致力於培育和維護一個廠商中立的開源生態系統,來推廣雲原生技術。我們通過將最前沿的模式普惠,讓這些創新為大眾所用。

下圖是截止2018.11的CNCF部分雲原生專案列表:

  • 雲原生以容器為核心技術,分為執行時(Runtime)和 Orchestration 兩層,Runtime 負責容器的計算、儲存、網路;Orchestration 負責容器叢集的排程、服務發現和資源管理。

Kubernetes的核心元件

Kubernetes的核心元件示意圖

  • etcd是Kubernetes的儲存狀態的分散式資料庫,採用raft協議作為一致性演算法(raft協議原理可參見一個動畫演示http://thesecretlivesofdata.com/raft/)。
  • API Server元件主要提供認證與授權、執行一組准入控制器以及管理API版本等功能,通過REST API向外提供服務,允許各類元件建立、讀取、寫入、更新和監視資源(Pod, Deployment, Service等)。
  • Scheduler元件,根據叢集資源和狀態選擇合適的節點用於建立Pod。
  • Controller Manager元件,實現ReplicaSet的行為。
  • Kubelet元件,負責監視繫結到其所在節點的一組Pod,並且能實時返回這些Pod的執行狀態。

建立Pod的整個流程時序圖

容器網路

容器的大規模使用,也對網路提供了更高的要求。網路的不靈活也是很多企業的短板,目前也有很多公司和專案在嘗試解決這些問題,希望提出容器時代的網路方案。 Docker採用外掛化的網路模式,預設提供bridge、host、none、overlay、macvlan和Network plugins這幾種網路模式,執行容器時可以通過–network引數設定具體使用那一種模式。

– bridge:這是Docker預設的網路驅動,此模式會為每一個容器分配Network Namespace和設定IP等,並將容器連線到一個虛擬網橋上。如果未指定網路驅動,這預設使用此驅動。 – host:此網路驅動直接使用宿主機的網路。

– none:此驅動不構造網路環境。採用了none 網路驅動,那麼就只能使用loopback網路裝置,容器只能使用127.0.0.1的本機網路。

– overlay:此網路驅動可以使多個Docker daemons連線在一起,並能夠使用swarm服務之間進行通訊。也可以使用overlay網路進行swarm服務和容器之間、容器之間進行通訊,

– macvlan:此網路允許為容器指定一個MAC地址,允許容器作為網路中的物理裝置,這樣Docker daemon就可以通過MAC地址進行訪問的路由。對於希望直接連線網路網路的遺留應用,這種網路驅動有時可能是最好的選擇。

– Network plugins:可以安裝和使用第三方的網路外掛。可以在Docker Store或第三方供應商處獲取這些外掛。

在預設情況,Docker使用bridge網路模式。

容器網路模型(CNM)

CNM在2015年由Docker引入,CNM有IP 地址管理(IPAM)和網路外掛功能。IPAM外掛可以建立IP地址池並分配,刪除和釋放容器IP。網路外掛API用於建立/刪除網路,並從網路中新增/刪除容器。

容器網路介面(CNI)

CNI誕生於2015年4月,由CoreOS公司推出,CNI是容器中的網路系統外掛,它使得類似Kubernetes之類的管理平臺更容易的支援IPAM、SDN或者其它網路方案。CNI實現的基本思想為:Contianer runtime在建立容器時,先建立好network namespace,這在實際操作過程中,首先創建出來的容器是Pause容器。之後呼叫CNI外掛為這個netns配置網路,最後在啟動容器內的程序。

CNI Plugin負責為容器配置網路,包括兩個基本介面: – 配置網路:AddNetwork(net NetworkConfig, rt RuntimeConf) (types.Result, error) – 清理網路:DelNetwork(net NetworkConfig, rt RuntimeConf) error

每個CNI外掛只需實現兩種基本操作:建立網路的ADD操作,和刪除網路的DEL操作(以及一個可選的VERSION檢視版本操作)。所以CNI的實現確實非常簡單,把複雜的邏輯交給具體的Network Plugin實現。

Kubernetes CNI 外掛

  • Flannel:CoreOS 開源的網路方案,為 kubernetes 設計,它的功能是讓叢集中的不同節點主機建立的Docker容器都具有全叢集唯一的虛擬IP地址。Flannel的底層通訊協議的可選餘地有很多,比如UDP、VXlan、AWS VPC等等,不同協議實現下的網路通訊效率相差較多,預設為使用UDP協議,部署和管理簡單。目前為止,還不支援k8s的Network Policy。
  • Calico:一個純三層的網路解決方案,使用 BGP 協議進行路由,可以整合到 openstack 和 docker。Calico節點組網可以直接利用資料中心的網路結構(無論是L2或者L3),不需要額外的NAT,隧道或者Overlay Network,網路通訊效能好。Calico基於iptables還提供了豐富而靈活的網路Policy,保證通過各個節點上的ACLs來提供Workload的多租戶隔離、安全組以及其他可達性限制等功能。如果企業生產環境可以開啟BGP協議,可以考慮calico bgp方案。不過在現實中的網路並不總是支援BGP路由的,因此Calico也設計了一種IPIP模式,使用Overlay的方式來傳輸資料。
  • Weave Net:weaveworks 給出的網路的方案,使用 vxlan 技術通過Overlay網路實現的, 支援網路的隔離和安全,安裝和使用都比較簡單。
  • Contiv: 思科開源,相容CNI模型以及CNM模型,支援 VXLAN 和 VLAN 方案,配置較複雜。支援Tenant,支援租戶隔離,支援多種網路模式(L2、L3、overlay、cisco sdn solution)。Contiv帶來的方便是使用者可以根據容器例項IP直接進行訪問。
  • Canal:基於 Flannel 和 Calico 提供 Kubernetes Pod 之間網路防火牆的專案。
  • Cilium:利用 Linux 原生技術提供的網路方案,支援 L7 和 L3、L4 層的訪問策略。
  • Romana:Panic Networks 推出的網路開源方案,基於 L3 實現的網路連通,因此沒有 Overlay 網路帶來的效能損耗,但是隻能通過 IP 網段規劃來實現租戶劃分。

從理論上說,這些CNI工具的網路速度應該可以分為3個速度等級。 最快的是Romana、Gateway模式的Flannel、BGP模式的Calico。 次一級的是IPIP模式的Calico、Swarm的Overlay網路、VxLan模式的Flannel、Fastpath模式的Weave。 * 最慢的是UDP模式的Flannel、Sleeve模式的Weave。

Flannel

  • UDP封包使用了Flannel自定義的一種包頭協議,資料是在Linux的使用者態進行封包和解包的,因此當資料進入主機後,需要經歷兩次核心態到使用者態的轉換。網路通訊效率低且存在不可靠的因素。
  • VxLAN封包採用的是內建在Linux核心裡的標準協議,因此雖然它的封包結構比UDP模式複雜,但由於所有資料裝、解包過程均在核心中完成,實際的傳輸速度要比UDP模式快許多。Vxlan方案在做大規模應用時複雜度會提升,故障定位分析複雜。
  • Flannel的Gateway模式與Calico速度相當,甚至理論上還要快一點。Flannel的Host-Gateway模式,在這種模式下,Flannel通過在各個節點上的Agent程序,將容器網路的路由資訊刷到主機的路由表上,這樣一來所有的主機就都有整個容器網路的路由資料了。Host-Gateway的方式沒有引入像Overlay中的額外裝包解包操作,完全是普通的網路路由機制,它的效率與虛擬機器直接的通訊相差無幾。Host-Gateway的模式就只能用於二層直接可達的網路,由於廣播風暴的問題,這種網路通常是比較小規模的。路由網路對現有網路裝置影響比較大,路由器的路由表有空間限制,一般是兩三萬條,而容器的大部分應用場景是執行微服務,數量集很大。

Flannel網路通訊原理示意圖

各CNI網路外掛的功能對比:

容器儲存

因為容器存活時間很短的特點,容器的狀態(儲存的資料)必須獨立於容器的生命週期,也因為此,容器的儲存變得非常重要。 – Ceph:分散式儲存系統,同時支援塊儲存、檔案儲存和物件儲存,發展時間很久,穩定性也得到了驗證。之前在 OpenStack 社群被廣泛使用,目前在容器社群也是很好的選項。 – GlusterFS:RedHat 旗下的產品,部署簡單,擴充套件性強。 – 商業儲存:DELL EMC,NetApp等 – CSI(Container Storage Interface):定義雲應用排程平臺和各種儲存服務介面的專案,核心的目標就是儲存 provider 只需要編寫一個 driver,就能整合到任何的容器平臺上。 – Rook:基於 Ceph 作為後臺儲存技術,深度整合到 Kubernetes 容器平臺的容器專案,因為選擇了 Ceph 和 Kubernetes 這兩個都很熱門的技術,並且提供自動部署、管理、擴充套件、升級、遷移、災備和監控等功能

Kubernetes支援的儲存型別

  • awsElasticBlockStore
  • azureDisk
  • azureFile
  • cephfs
  • configMap
  • csi
  • downwardAPI
  • emptyDir
  • fc (fibre channel)
  • flocker
  • gcePersistentDisk
  • gitRepo (deprecated)
  • glusterfs
  • hostPath
  • iscsi
  • local
  • nfs
  • persistentVolumeClaim
  • projected
  • portworxVolume
  • quobyte
  • rbd
  • scaleIO
  • secret
  • storageos
  • vsphereVolume

Kubernetes以in-tree plugin的形式來對接不同的儲存系統,滿足使用者可以根據自己業務的需要使用這些外掛給容器提供儲存服務。同時相容使用者使用FlexVolume和CSI定製化外掛。 在這裡插入圖片描述

一般來說,Kubernetes中Pod通過如下三種方式來訪問儲存資源: – 直接訪問 – 靜態provision – 動態provision(使用StorageClass動態建立PV)

服務發現

容器和微服務的結合創造了另外的熱潮,也讓服務發現成功了熱門名詞。可以輕鬆擴充套件微服務的同時,也要有工具來實現服務之間相互發現的需求。 DNS 伺服器監視著建立新 Service 的 Kubernetes API,從而為每一個 Service 建立一組 DNS 記錄。 如果整個叢集的 DNS 一直被啟用,那麼所有的 Pod應該能夠自動對 Service 進行名稱解析。在技術實現上是通過kubernetes api監視Service資源的變化,並根據Service的資訊生成DNS記錄寫入到etcd中。dns為叢集中的Pod提供DNS查詢服務,而DNS記錄則從etcd中讀取。 – kube-dns:kube-dns是Kubernetes中的一個內建外掛,目前作為一個獨立的開源專案維護。Kubernetes DNS pod 中包括 3 個容器:kube-dns,sidecar,dnsmasq – CoreDNS:CoreDNS是一套靈活且可擴充套件的權威DNS伺服器,作為CNCF中的託管的一個專案,自k8s 1.11 版本起被正式作為叢集DNS附加選項,且在使用者使用kubeadm時預設生效。提供更好的可靠性、靈活性和安全性,可以選擇使用CoreDNS替換Kubernetes外掛kube-dns。

狀態資料儲存

目前主要有三種工具,大部分的容器管理系統也都是同時可以支援這三種工具。 – etcd:CoreOS 開源的分散式 key-value 儲存,通過 HTTP/HTTPS 協議提供服務。etcd 只是一個 key-value 儲存,預設不支援服務發現,需要三方工具來整合。kubernetes 預設使用 etcd 作為儲存。 – ZooKeeper:Hadoop 的一個子專案,本來是作為 Hadoop 叢集管理的資料儲存,目前也被應用到容器領域,開發語言是 Java。 – Consul:HashiCorp 開發的分散式服務發現和配置管理工具

這些工具的主要作用就是保證這個叢集的動態資訊能統一儲存,並保證一致性,這樣每個節點和容器就能正確地獲取到叢集當前的資訊。

健康檢查

Kubernetes提供兩種型別的健康檢查,支援進行三種類型的探測:HTTP、Command和TCP。 – Readiness探針旨在讓Kubernetes知道您的應用何時準備好其流量服務。 Kubernetes確保Readiness探針檢測通過,然後允許服務將流量傳送到Pod。 如果Readiness探針開始失敗,Kubernetes將停止向該容器傳送流量,直到它通過。 – Liveness探針讓Kubernetes知道你的應用程式是活著還是死了。 如果你的應用程式還活著,那麼Kubernetes就不管它了。 如果你的應用程式已經死了,Kubernetes將刪除Pod並啟動一個新的替換它。

容器監控

我們習慣於在兩個層次監控:應用以及執行它們的主機。現在由於容器處在中間層,以及 Kubernetes 本身也需要監控,因此有 4 個不同的元件需要監控並且蒐集度量資訊。 1)cAdvisor + InfluxDB + Grafana:一個簡單的跨多主機的監控系統Cadvisor:將資料,寫入InfluxDBInfluxDB :時序資料庫,提供資料的儲存,儲存在指定的目錄下Grafana :提供了WEB控制檯,自定義查詢指標,從InfluxDB查詢資料,並展示。 2)Heapster + InfluxDB + Grafana:Heapster是一個收集者,將每個Node上的cAdvisor的資料進行彙總,然後導到InfluxDB,支援從Cluster、Node、Pod的各個層面提供詳細的資源使用情況。Heapster:在Kubernetes叢集中獲取Metrics和事件資料,寫入InfluxDB,Heapster收集的資料比cAdvisor多,而且儲存在InfluxDB的也少。InfluxDB:時序資料庫,提供資料的儲存,儲存在指定的目錄下。Grafana:提供了WEB控制檯,自定義查詢指標,從InfluxDB查詢資料,並展示。 3)Prometheus+Grafana:Prometheus是個集DB、Graph、Statistics、Alert 於一體的監控工具。提供多維資料模型(時序列資料由metric名和一組key/value組成)和在多維度上靈活的查詢語言(PromQl),提供了很高的寫入和查詢效能。對記憶體佔用量大,不依賴分散式儲存,單主節點工作,所以不具有高可用性,支援pull/push兩種時序資料採集方式。

考慮到Prometheus在擴充套件性和高可用方面的缺點,在超大規模應用時可以考察下thanos這樣的面向解決Prometheus的長時間資料儲存與服務高可用解決方案的開源專案:https://github.com/improbable-eng/thanos

容器叢集的四個監控層次

映象 registry

映象 registry 是儲存映象的地方,可以方便地在團隊、公司或者世界各地分享容器映象,也是執行容器最基本的基礎設施。 – Docker Registry:Docker 公司提供的開源映象伺服器,也是目前最流行的自建 registry 的方案 – Harbor:企業級的映象 registry,提供了許可權控制和圖形介面

參考資料