孔祥文 宋辰萱
(中國(guó)市政工程華北設(shè)計(jì)研究總院有限公司 天津市 300074)
PaaS(Platform as a Service)是云計(jì)算的重要組成部分,用戶可以通過PaaS 平臺(tái)完成應(yīng)用的構(gòu)建、部署、運(yùn)維管理,而不需要自己搭建計(jì)算執(zhí)行環(huán)境,如準(zhǔn)備硬件資源、安裝操作系統(tǒng)等。而Kubernetes 正是云計(jì)算PaaS 領(lǐng)域的集大成者,是Google 公司設(shè)計(jì)發(fā)布的,旨在提供跨主機(jī)集群的自動(dòng)部署、擴(kuò)展以及運(yùn)行應(yīng)用程序容器的開源系統(tǒng)。IaaS(Infrastructure as a Service)系統(tǒng)提供給用戶的是虛擬機(jī)資源,而PaaS 負(fù)責(zé)應(yīng)用的部署和運(yùn)維,用戶只需要專注于應(yīng)用的開發(fā)。
傳統(tǒng)的PaaS 系統(tǒng)主要由管理平臺(tái)、計(jì)算資源池和服務(wù)資源池三個(gè)部分組成:PaaS 管理平臺(tái)主要負(fù)責(zé)認(rèn)證授權(quán)、應(yīng)用自動(dòng)化部署、運(yùn)維監(jiān)控等工作;應(yīng)用運(yùn)行在計(jì)算節(jié)點(diǎn)上,計(jì)算資源池提供應(yīng)用所需要的完整運(yùn)行環(huán)境,包括語(yǔ)言環(huán)境和應(yīng)用框架等,一般基于Linux 的Cgroup 和Namespace 為應(yīng)用提供資源隔離和限制;服務(wù)節(jié)點(diǎn)通過代理或接口為應(yīng)用提供數(shù)據(jù)庫(kù)、緩存和存儲(chǔ)服務(wù)。傳統(tǒng)的PaaS 架構(gòu)如圖1所示。
傳統(tǒng)PaaS 平臺(tái)也有很多局限性,用戶開發(fā)應(yīng)用時(shí)所選擇的技術(shù)受限于平臺(tái)支持的開發(fā)語(yǔ)言、框架和中間件;無法支持復(fù)雜的分布式應(yīng)用;應(yīng)用與平臺(tái)鎖定,很難遷移到其他PaaS 平臺(tái)等。但隨著Docker 容器技術(shù)的迅速興起,PaaS 也迎來了新的挑戰(zhàn)和機(jī)遇。
虛擬化及容器化是云計(jì)算的兩大技術(shù),Docker 中應(yīng)用的就是容器技術(shù)。盡管容器技術(shù)出現(xiàn)很久,但卻是隨著Docker 容器平臺(tái)的出現(xiàn)才變得廣為人知。Docker 是第一個(gè)使得容器能夠在不同機(jī)器之間移植的系統(tǒng),它不僅簡(jiǎn)化了應(yīng)用打包的過程,還將應(yīng)用依賴的庫(kù)文件甚至是整個(gè)操作系統(tǒng)的文件系統(tǒng)都打包成一個(gè)簡(jiǎn)單可移植的包,這個(gè)包能夠在任何運(yùn)行Docker 服務(wù)的機(jī)器上使用。
通常所說的Docker 實(shí)際上是指Docker 引擎,它是Docker 公司容器平臺(tái)產(chǎn)品的核心部。Docker 引擎可以理解為一套輕量級(jí)應(yīng)用運(yùn)行時(shí)環(huán)境,應(yīng)用及其依賴被隔離在相互獨(dú)立的運(yùn)行環(huán)境里,共享同一個(gè)OS 內(nèi)核,將這種環(huán)境形象地稱為“容器”。這種將多個(gè)應(yīng)用部署在一臺(tái)主機(jī)以相互獨(dú)立的容器運(yùn)行模式,在減少應(yīng)用故障對(duì)其他應(yīng)用影響的同時(shí),還可以提高硬件資源利用率。
與容器相比,虛擬機(jī)通過模擬硬件環(huán)境,并啟動(dòng)完整的操作系統(tǒng)為應(yīng)用運(yùn)行提供獨(dú)占環(huán)境,因此其中需要安裝Guest OS;而容器是主機(jī)操作系統(tǒng)上的進(jìn)程虛擬化,容器鏡像中并不需要OS 內(nèi)核,所以也不需要安裝Guest OS,只需要應(yīng)用運(yùn)行相關(guān)的庫(kù)和文件就可以了。相比與虛擬機(jī)實(shí)現(xiàn),Docker 容器更輕量、更快捷。兩者的對(duì)比關(guān)系如圖2。
用戶使用Docker 的一般場(chǎng)景如下:根據(jù)鏡像標(biāo)識(shí)從鏡像倉(cāng)庫(kù)里下載鏡像到本地,Docker 引擎使用本地鏡像創(chuàng)建出多個(gè)相互隔離運(yùn)行的容器。由于Docker 將應(yīng)用和依賴文件都打包到了Docker鏡像里,用戶基于Docker 鏡像將應(yīng)用部署并運(yùn)行到隔離的Docker容器后,就不再依賴宿主機(jī)提供運(yùn)行環(huán)境支持,從而實(shí)現(xiàn)了應(yīng)用和PaaS 平臺(tái)解耦。這種機(jī)制為應(yīng)用開發(fā)帶來了巨大便利,用戶向PaaS 平臺(tái)提交的不再是代碼,而是Docker 鏡像,PaaS 平臺(tái)也無須為應(yīng)用準(zhǔn)備各種運(yùn)行時(shí)環(huán)境。新PaaS 平臺(tái)架構(gòu)如圖3所示。
新PaaS 以Docker 容器為基礎(chǔ),面向云化、微服務(wù)、DevOps等應(yīng)用場(chǎng)景,支持大數(shù)據(jù)、分布式計(jì)算、深度學(xué)習(xí)等多種計(jì)算服務(wù),集成開發(fā)、測(cè)試、部署流水線,成為一站式應(yīng)用開發(fā)運(yùn)行平臺(tái)。
在新PaaS 平臺(tái)上運(yùn)行的生產(chǎn)應(yīng)用會(huì)涉及多個(gè)容器,這些容器必須能夠跨多個(gè)主機(jī)部署運(yùn)行,隨著數(shù)量的不斷累積,復(fù)雜性也隨之提高,Kubernetes 正是為解決這個(gè)問題而生的。借助Kubernetes,用戶可以構(gòu)建多個(gè)容器的應(yīng)用服務(wù),跨主機(jī)調(diào)度、擴(kuò)展這些容器、持續(xù)管理容器狀況。簡(jiǎn)單來講,Kubernetes 將容器擴(kuò)展成邏輯概念上的“容器集”(Pod),增加了一個(gè)容器分組抽象層,用戶通過選擇Kubernetes 工作負(fù)載運(yùn)行容器,并為其提供網(wǎng)絡(luò)和存儲(chǔ)服務(wù),同時(shí)Kubernetes 確保系統(tǒng)中運(yùn)行正確數(shù)量的容器。Kubernetes 作為一個(gè)開源的軟件系統(tǒng),為支撐PaaS 能力提供了如下功能:
根據(jù)資源需求以及其他相關(guān)約束條件,在不降低應(yīng)用可用性的前提下對(duì)容器進(jìn)行自動(dòng)部署,基于工作負(fù)載盡力而為的特性,提高資源使用率以便節(jié)省更多資源。
支持根據(jù)CPU 或自定義監(jiān)控指標(biāo)的使用情況對(duì)應(yīng)用程序容器進(jìn)行自定義擴(kuò)容或縮容。
Kubernetes 為容器可以為容器提供獨(dú)立的IP 地址,或針對(duì)一組相同應(yīng)用程序容器提供虛擬VIP 和DNS 域名,以便用戶訪問Kubernetes 容器業(yè)務(wù),并在這些容器間進(jìn)行負(fù)載均衡。
如果容器啟動(dòng)或運(yùn)行失敗,Kubernetes 會(huì)重新創(chuàng)建失敗的容器;同時(shí)Kubernetes 也為用戶提供了容器檢查的自定義鉤子,Kubernetes 會(huì)根據(jù)鉤子的執(zhí)行結(jié)果來決定是否對(duì)容器進(jìn)行銷毀重建或負(fù)載均衡的摘除操作。
圖1
圖2
圖3
圖4
Kubernetes 通過定義不同的工作負(fù)載,支持部署運(yùn)行無狀態(tài)應(yīng)用、有狀態(tài)應(yīng)用、一次性任務(wù)應(yīng)用、周期性任務(wù)應(yīng)用、節(jié)點(diǎn)daemon 應(yīng)用等。
支持對(duì)一組應(yīng)用程序容器進(jìn)行逐步滾動(dòng)更新的機(jī)制,對(duì)應(yīng)用程序運(yùn)行狀況進(jìn)行監(jiān)控以確保所有實(shí)例不會(huì)同時(shí)終止。如果在更新過程中出現(xiàn)問題,支持回滾更改。
支持應(yīng)用配置資源與密鑰資源,用戶無需重新構(gòu)建鏡像即可實(shí)現(xiàn)應(yīng)用配置資源和密鑰資源更新。
Kubernetes 遵循微服務(wù)架構(gòu)理念設(shè)計(jì),實(shí)現(xiàn)了整個(gè)系統(tǒng)各個(gè)功能組件之間邊界清晰、部署簡(jiǎn)單的模塊化,同時(shí)支持多種擴(kuò)展機(jī)制,用戶可以方便地進(jìn)行功能擴(kuò)展和自定義實(shí)現(xiàn)。
Kubernetes 為容器管理提供了一個(gè)抽象層和一系列相關(guān)工具,支持大規(guī)模容器的編排與管理,確保應(yīng)用程序的高可用和服務(wù)可移植性;同時(shí)Kubernetes 還可以更好地控制資源使用情況,如整個(gè)系統(tǒng)的CPU、內(nèi)存和磁盤空間,在系統(tǒng)整體基礎(chǔ)資源不足時(shí)支持自動(dòng)添加工作節(jié)點(diǎn)以完成集群的擴(kuò)容[1]。圖4 展示了Kubernetes 的核心架構(gòu)。
從圖4 中可以看到,整個(gè)Kubernetes 是由Master 節(jié)點(diǎn)和Node節(jié)點(diǎn)構(gòu)成。
Master 節(jié)點(diǎn)是Kubernetes 集群的大腦,上面運(yùn)行了API 服務(wù)、調(diào)度服務(wù)、控制器管理服務(wù)和Etcd 存儲(chǔ)服務(wù)。API 服務(wù)提供了基于Restful 的Web Service 接口,用于查詢或定義各種所需要的集群和狀態(tài),API 服務(wù)內(nèi)部有一套完備的安全機(jī)制。所有Kubernetes 集群對(duì)象的增刪改查操作只能通過訪問Kubernetes API 服務(wù)器來實(shí)現(xiàn)。Master 節(jié)點(diǎn)上的調(diào)度服務(wù)以Node 節(jié)點(diǎn)上實(shí)際Pod 為單位進(jìn)行工作負(fù)載調(diào)度,用于為Pod 選擇合適的Node 來運(yùn)行??刂破鞴芾砥魇撬匈Y源對(duì)象的自動(dòng)化控制中心,用于管理各資源的控制器,用于進(jìn)行故障檢測(cè)和自動(dòng)化恢復(fù)的相關(guān)工作。Etcd 是一款分布式一致性的key-value 存儲(chǔ),用于保存網(wǎng)絡(luò)配置和狀態(tài)信息。
Node 節(jié)點(diǎn)可以是物理機(jī)或虛擬機(jī),承載了實(shí)際運(yùn)行業(yè)務(wù)的容器,是Kubernetes 集群中的工作節(jié)點(diǎn)。Node 節(jié)點(diǎn)上運(yùn)行了三個(gè)重要組件:kubelet、kube-proxy、容器引擎。kubelet 處理著master 和在其上運(yùn)行的節(jié)點(diǎn)之間的所有通信,并負(fù)責(zé)創(chuàng)建、啟動(dòng)和監(jiān)視pod的運(yùn)行。此外,kubelet 還會(huì)周期性地對(duì)配置的存活探針和就緒探針進(jìn)行檢查,并在出現(xiàn)問題時(shí)啟動(dòng)新實(shí)例。kube-proxy 是以pod 形式運(yùn)行在節(jié)點(diǎn)上的網(wǎng)絡(luò)代理,負(fù)責(zé)代理UDP、TCP 數(shù)據(jù)包,維護(hù)主機(jī)上的網(wǎng)絡(luò)規(guī)則,并處理pod、主機(jī)和外部環(huán)境之間的數(shù)據(jù)包傳輸。容器引擎在Kubernetes 中也叫做容器運(yùn)行時(shí),負(fù)責(zé)從公有或私有鏡像倉(cāng)庫(kù)中拉取鏡像,并根據(jù)這些鏡像運(yùn)行容器。
使用Minikube 是運(yùn)行Kubernetes 集群最簡(jiǎn)單快捷的方法。Minikube 是一個(gè)構(gòu)建單節(jié)點(diǎn)集群的工具,對(duì)于學(xué)習(xí)測(cè)試Kubernetes、開發(fā)本地應(yīng)用都很有用。由于Linux 是目前業(yè)界廣泛使用的商業(yè)操作系統(tǒng),以下內(nèi)容著重介紹Linux 服務(wù)器上Kubernetes 的安裝配置過程[2]。
安裝Minikube:curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
&&chmod +x minikube
Minikube 安裝完成后,可以在本地啟動(dòng)一個(gè)單節(jié)點(diǎn)的Kubernetes 集群:./minikube start
Kubernetes 機(jī)器組件啟動(dòng)后,還需要使用kubectl 工具與啟動(dòng)的Kubernetes 集群交互,kubectl 工具的安裝也很簡(jiǎn)單,使用一條命令:curl -LO
https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl &&chmod +x kubectl
然后,在Kubernetes 中運(yùn)行第一個(gè)應(yīng)用:kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4,稍后可以看到應(yīng)用已經(jīng)被正常啟動(dòng)了。
執(zhí)行kubectl get deployments,查看啟動(dòng)的應(yīng)用controller,此時(shí)輸出結(jié)果類似于:
NAME READY UP-TO-DATE AVAILABLE AGE
hello-node 1/1 1 1 1m
執(zhí)行kubectl get pods 查看啟動(dòng)的應(yīng)用實(shí)例,輸出結(jié)果類似于:
NAME READY STATUS RESTARTS AGE
hello-node-5f76cf6ccf-br9b5 1/1 Running 0 1m
從以上結(jié)果中可以看到在Kubernetes 系統(tǒng)中運(yùn)行了一個(gè)應(yīng)用實(shí)例,這個(gè)應(yīng)用實(shí)例的名字為hello-node-5f76cf6ccf-br9b5。
Kubernetes 項(xiàng)目從一開始就沒有把Docker 作為整個(gè)架構(gòu)的核心,而是將其作為最底層的一個(gè)容器運(yùn)行時(shí)實(shí)現(xiàn),Kubernetes 著重解決的場(chǎng)景:運(yùn)行在大規(guī)模集群里的各種應(yīng)用之間的關(guān)系,如何處理這些關(guān)系才是作業(yè)編排和管理系統(tǒng)最困難的地方。這些關(guān)系包括但不限于:Web 應(yīng)用與數(shù)據(jù)庫(kù)之間的訪問關(guān)系、負(fù)載均衡和后端服務(wù)之間的代理關(guān)系、Web 應(yīng)用與授權(quán)組件之間的調(diào)用關(guān)系。而對(duì)編排項(xiàng)目的需求是希望它能夠處理前面提到的所有類型的關(guān)系,甚至還要能夠支持未來可能出現(xiàn)的更多種類的關(guān)系。