關於容器眾說紛紜,你真的需要聽聽老王的
前言
容器技術目前的市場現狀是一家獨大、百花齊放。 關於容器技術,看看青雲QingCloud 王淵命(老王)是如何看待它的,本文來自他在青雲QingCloud 深圳站實踐課堂的演講。全文 2780字,閱讀時長約為 11 分鐘。
容器是什麼
容器的概念外延比較廣,討論的時候容易產生分歧,雖然大家都在說容器,但各自的角度不同,表達的具體內容也完全不一樣。總結來看容器有兩個視角,一是資源,二是應用。
一是從資源隔離的角度。容器技術經常被拿來跟虛擬化技術作對比,從技術角度來說,容器是一種跟VM 類似的資源隔離技術,它比 VM 的資源損耗小,但隔離性和安全性不如 VM ,等等。
二是從應用封裝的角度。Docker 之所以興起,原因在於其重點關注應用的標準化,而不是資源的隔離。Docker 的鏡像機制提供了一種更高級的通用的應用製品包,也就是大家說的集裝箱能力。原來各種操作系統或編程語言都有各自己的製品機制,各自的依賴管理,製品庫都不相同。應用從源碼打包,分發到製品庫,再部署到伺服器,很難抽象出一種通用的流程和機制。
而有了 Docker 的鏡像以及鏡像倉庫標準之後,這個流程終於可以標準化了。同時Docker 將進程的管理,比如啟動停止也標準化了。類似杯子、筐、集裝箱都是容器,它們的共同特點是能把雜物打包,標準化,方便運輸和定價。在此之上,容器可以做更高級的邏輯分裝和調度。
容器生態圈現狀
容器技術目前的市場現狀是一家獨大、百花齊放。容器的解決方案非常多,以 Docker 為首佔據了大部分的市場,此外還有各種解決方案如 Rocket、Mesos Universal container、LXC、Hyper Container 等。容器主流的調度系統 Kubernetes、Mesos和 Docker Swarm 是三足鼎立的狀態,他們各有優勢。Kubernetes 偏重於應用的抽象和規範的定義,Mesos關注可擴展性及資源混合部署,Swarm 關注於開發環境和線上環境的一體化,更方便使用。
可以看出,容器市場的競爭現已上升到調度層,這也是為什麼 Docker 把 Swarm 嵌在內部,使得Docker 不再是一個單機容器,而變成了調度系統的解決方案。
青雲QingCloud 容器解決方案
從資源視角和應用視角分析一下青雲QingCloud 提供的容器解決方案。
就資源視角來說,用戶希望 VM 能像 Docker 一樣,可對標準進程進行封裝,使得 VM 也是一個完整的操作系統。為延續用戶對VM 的操作體驗,青雲QingCloud 在統一的 IaaS平台上同時支持 VM(Virtual Machine 虛擬主機)與 CM(Container Machine 容器主機),使得用戶對虛擬化的部署習慣得以沿襲,同時還可享受容器資源輕量隔離的特點。
就應用視角來說,青雲QingCloud 支持容器編排系統,體現在兩方面:一是AppCenter 應用支持 Docker 鏡像,二是容器編排系統可以作為一個應用放在AppCenter 上。容器可以在 VM 之上部署集群,Mesos、Kubernetes、Swarm 也可以作為雲應用放在 AppCenter 之上,讓用戶可以自主選擇。
Kuberneteson QingCloud AppCenter
我們第一步做的是在 AppCenter 上部署 Kubernetes。為什麼選擇 Kubernetes 呢?主要是因為 Kubernetes 部署比較複雜,如果最為複雜的 Kubernetes 能夠在青雲QingCloud AppCenter 上運行,其他集群也一樣可以部署到 AppCenter 上。
QingCloud支持用戶一鍵部署 Kubernetes 集群,不僅解決了用戶很大的痛點,同時也驗證了 AppCenter 支持應用的廣泛性。
為此,我們解決了四大難題:容器調度系統的網路、數據本地存儲的讀取、容器平台與負載均衡器集成以及實現 Kubernetes 應用的彈性伸縮能力。
接下來整體介紹一下 Kubernetes。
Kubernetes 概覽
Kubernetes 集群包含兩種角色,一是 master, 二是 node,相當於 worker 或者 slave。Master 有三個主要的組件:
一是 API Server(APIs),其底層是分散式存儲(etcd),存儲集群所有的數據;
二是 Controller Manager,承擔了 master 的主要職能,管控所有的節點以及 Kubernetes 之上的 pod,service 等;
三是調度器 Scheduler,可以根據調度規則來分配節點最適合部署的位置。
如圖有兩個 Node,其上的 Kubelet 是節點的守護進程,用以管理 Node 上的所有 Pod。
Kubernetes 的 Pod 和 Docker Container 有點區別,這裡特殊說明下,Pod 里包含多個 Container。Kubernetes 這樣設計主要有兩方面原因:
1. 為了和 Docker 解耦。Docker 啟動時會先初始化網路,然後再啟動容器進程,因為很多應用啟動後如果沒有網路就會報錯。但 Kubernetes 想用自己的網路方案,就必須是先啟動容器,再創建網路。
於是 Kubernetes 會先啟動一個空進程(pause進程,啟動後就一直 sleep),佔據容器的一個命名空間,在網路、存儲創建出來後掛載到這個空容器上,然後才啟動用戶定義的容器,而這個容器直接復用 pause 容器的網路和存儲。
2. 通過 Pod 打包多個 Container,使之共享同一個生命周期。這樣的解決方案也非常有利於多個容器有強依賴關係的場景,比如 nginx 和 php-fpm 進程,比如 Kubernetes 的內置 dns 的多個組件,kube-dns 負責監聽 Kubernetes 的 service 變更,然後轉換成 dns 記錄,寫入到 dnsmasq 中。這種場景下,任何一個組件獨立存活都是沒有意義的。
Kubernetes 抽象概念
Kubernetes 的目標在於制定一個標準和規範,可以讓你來描述集群的架構,定義服務的最終狀態,它來幫助你的系統達到和維持在這個狀態。這個其實和 Puppet/Ansible 等配置管理工具的目的是一致的,只是配置管理工具只能做達到某個狀態,沒法實現維持到這個狀態(因為沒有動態的伸縮以及故障遷移等調度能力)。所以 Kubernetes 提出了許多抽象的概念,用來實現這種描述能力。如 Service、Job、ReplicaSet、Deployment等。
Kubernetes 網路設計
Kubernetes 對於網路有三點要求:一是容器之間可以直接互通,不需要 NAT;二是節點可以和容器直接互通,不需 NAT;三是容器看到自己的 IP 應該和其他容器看到的是一致的,即中間不能做IP轉換,避免複雜的分散式架構應用節點之間的連接複雜問題。Kubernetes 網路之 Cluster IP
Kubernetes 的 Service 概念大概是,一組服務有多個容器,通過一樣的埠運行,暴露出來的 IP 都是一樣的。通過一個松耦合的選擇器把後面的容器或者 Pod 全部歸納在這個 Service 之下。Cluster IP 是一個虛IP,可以自動分配,也可以指定。當用戶向這個 IP 的service port (比如例子中是 80) 發送數據的時候,iptables 會攔截這個數據包,然後把數據包隨機分發至其中一個 Pod。這相當於是內部的一種負載均衡器,但它是自動的,即定義Service 的時候,會自動創建一個輕量的負載均衡器。
同時,Kubernetes 內置了 dns 服務,每個 service 都會有一個和 service name 一樣的 dns 記錄,解析到 service 的 Cluster IP 上。這樣一來,就實現了服務之間依賴的解耦。當請求一個服務的時候,不需要知道服務後面 Pod 的真實 IP 是多少,只需要請求 Cluster IP 或者 DNS。
Kubernetes 之 Flannel
先想像一下,如果我們要自行實現一個容器的網路,每個主機上有一個 Docker 容器,並自行分配一個 DockerBridge 的 IP。這樣一來,如果在多個主機上啟動Docker 就會發現:
第一,它會產生 IP 衝突,怎麼解決這個 IP 衝突呢?首先得有一個機制協調,協調每個主機分別用什麼 IP。
第二,從某個主機里的容器發出來的數據包,它需要有一種轉發機制,確定這個包應該如何轉發到另外一個容器所在的主機上。
為了解決 IP 衝突,它首先需要 IP 分配策略,通過共享的 etcd 存儲。也就是說,Flannel 會給每個主機分配一個 IP 段,把它捆到 etcd 里,使得每一個主機都知道另外主機的 IP 段是多少。這樣就能確保 IP 不會衝突,使某個容器發出的數據能夠準確傳給對應主機的目標容器上,並且是通過 Kubernetes 分配 IP 的規則。
怎麼去轉發數據包呢?一種方法是通過 etcd 隧道,創建一個鏈接直接轉發數據包;還有一種方法是通過雲服務提供的路由規則,修改路由表即可。
Kubernetes 網路之 QingCloud
Kubernetes 的網路是如何發揮青雲QingCloud IaaS 層網路的優勢以及 SDN Passthrough(網路直通)的特性呢?
首先,一個主機可掛多個網卡,將一個網卡給這個主機,其他的網卡直接綁到容器里,使得在 VPC 環境中每個容器的 IP 和對應主機的 IP 是對等的。這樣一來,主機之間、主機和容器之間、容器之間可以實現互通,同時省去了 Flannel 解決方案的損耗。
其次,青雲QingCloud 的負載均衡器能感知到容器網路,而傳統的方案在內部還需要再做一層虛擬網路,IaaS 層的負載均衡器無法感知容器網路。
Kubernetes 存儲
容器的存儲解決方案是影射一個本地硬碟到容器中,本地硬碟的生命周期和容器是脫離的,容器刪了之後數據還在。但是當我們用調度系統的時候會發現,如果把容器從這個節點遷移到這個節點的時候,如果直接把本地硬碟路徑掛上去之後,數據就沒了,說明它的數據是遷移不過來的。
為此,Kubernetes 採用了分散式的存儲,比如 nfs、ceph、glusterfs,PersistentVolume plugin。
此外,Kubernetes 還提供了存儲插件,支持谷歌、AWS,以及青雲QingCloud(QingCloudStore) 。有了這些插件,用戶可以在主機上掛載一個硬碟,再將硬碟映射到容器。當容器從一個節點遷到另外一個節點的時候,這個硬碟也跟著遷過來,使得容器的數據實現遷移。
Kubernetes 存儲之 QingCloudStore
Kubernetes 有一個抽象的配置文件,配置文件標明 QingCloudStore,它可以關聯一個 volumeID。這種方式的缺點在於配置文件和資源是綁定的、強關聯的,配置文件用一次之後就不能用了,使得測試環境和現場環境不一樣。所以,為解決這個問題,需要在 Kubernetes 中聲明需要多大的空間、是否讀寫、什麼許可權、提供方是誰,再加上 StorageClass 的配置。
有了這樣的聲明之後有什麼好處呢?使得環境和具體的資源不綁定了,當集群發現該聲明還沒有滿足的情況下,它會自動創建一個盤,關聯到你的 Pod 上。當 Pod 刪除的時候,它會回收資源。這樣,實現了解耦。
Kubernetes 負載均衡器
Kubernetes 本身的負載均衡器提供了一種插件,讓雲服務商實現插件和 IaaS 層整合。因為最終用戶暴露的時候需要一個公網 IP,這個實現和各雲廠商的服務是息息相關的,而 Kubernetes 自己比較難直接提供這樣的服務,所以它就提供插件讓雲服務商去實現。
但是雲廠商的負載均衡器只能感知到節點主機這一層,對主機裡面的容器是無感的,所以大多數情況下只能把 Kubernetes 集群下所有的節點都掛載到 LoadBalancer之後。前面講到 Service 時說到,Kubernetes 為每一個 Service 都在所有主機上監聽一個隨機的埠,也就是 NodePort,這個請求會轉發到主機的隨機埠上,由隨機埠轉發到 ClusterIP 上,再由 ClusterIP 轉發到後面的容器,可以看出,這樣就多了幾層轉發。
如果負載均衡器能感知到容器的網路,就可以直接透傳請求到容器中。我們的負載均衡器後面直接掛在的是容器網卡,這樣就省去了幾層轉發。同時我們的支持公網和私網兩種 Load Balancer。因為一般不可能把所有的服務遷到 Kubernetes,有一部分遷進去了,有一部分服務可能在外面。這種情況下外部服務訪問不了Kubernetes Service 的 Cluster IP 和 DNS ,這個時候需要私網的 Load Balancer 去轉發這種請求。
Kubernetes 自動伸縮
Kubernetes 提供了本身一種機制,通過相應命令可自動增加 Pod 的節點數。但光有這一層伸縮是不夠的,部署 Kubernetes 集群的時候,節點數是提前規劃好的。當自動伸縮使 Kubernetes 容量達到上限的時候,就無法伸縮了。這個時候集群本身需要有自動伸縮的功能,當前只有谷歌雲實現了集群的伸縮能力。
當 Kubernetes 集群的資源不夠了,它會觸發一個事件,IaaS 層監聽這個事件,收到事件請求之後增加集群的節點。這樣就實現了業務應用層的自動伸縮以及 Kubernetes 資源池的伸縮。
『充電時間』上海、杭州、重慶、成都,讓你們久等了!實踐課堂馬上與你見面,還不報名?本次課程內容仍以技術實踐為主,以用戶場景為切入,主要圍繞QingCloud 的技術理念、功能特性和使用技巧展開,話題將涵蓋如何高效構建原生雲應用,雲端容器部署,微服務架構,應用感知,自動化運維等業內熱點話題。
報名鏈接:QingCloud 第3季實踐課堂報名表
推薦閱讀:
※Docker 鏡像優化與最佳實踐
※深度解析容器雲之 Kubernetes 應用與實踐
※為何 Kubernetes 如此受歡迎?
※很遺憾,我也不知道什麼是容器!
※2017中國容器技術使用情況有獎調查