孔祥文 宋辰萱
(中國市政工程華北設計研究總院有限公司 天津市 300074)
PaaS(Platform as a Service)是云計算的重要組成部分,用戶可以通過PaaS 平臺完成應用的構建、部署、運維管理,而不需要自己搭建計算執行環境,如準備硬件資源、安裝操作系統等。而Kubernetes 正是云計算PaaS 領域的集大成者,是Google 公司設計發布的,旨在提供跨主機集群的自動部署、擴展以及運行應用程序容器的開源系統。IaaS(Infrastructure as a Service)系統提供給用戶的是虛擬機資源,而PaaS 負責應用的部署和運維,用戶只需要專注于應用的開發。
傳統的PaaS 系統主要由管理平臺、計算資源池和服務資源池三個部分組成:PaaS 管理平臺主要負責認證授權、應用自動化部署、運維監控等工作;應用運行在計算節點上,計算資源池提供應用所需要的完整運行環境,包括語言環境和應用框架等,一般基于Linux 的Cgroup 和Namespace 為應用提供資源隔離和限制;服務節點通過代理或接口為應用提供數據庫、緩存和存儲服務。傳統的PaaS 架構如圖1所示。
傳統PaaS 平臺也有很多局限性,用戶開發應用時所選擇的技術受限于平臺支持的開發語言、框架和中間件;無法支持復雜的分布式應用;應用與平臺鎖定,很難遷移到其他PaaS 平臺等。但隨著Docker 容器技術的迅速興起,PaaS 也迎來了新的挑戰和機遇。
虛擬化及容器化是云計算的兩大技術,Docker 中應用的就是容器技術。盡管容器技術出現很久,但卻是隨著Docker 容器平臺的出現才變得廣為人知。Docker 是第一個使得容器能夠在不同機器之間移植的系統,它不僅簡化了應用打包的過程,還將應用依賴的庫文件甚至是整個操作系統的文件系統都打包成一個簡單可移植的包,這個包能夠在任何運行Docker 服務的機器上使用。
通常所說的Docker 實際上是指Docker 引擎,它是Docker 公司容器平臺產品的核心部。Docker 引擎可以理解為一套輕量級應用運行時環境,應用及其依賴被隔離在相互獨立的運行環境里,共享同一個OS 內核,將這種環境形象地稱為“容器”。這種將多個應用部署在一臺主機以相互獨立的容器運行模式,在減少應用故障對其他應用影響的同時,還可以提高硬件資源利用率。
與容器相比,虛擬機通過模擬硬件環境,并啟動完整的操作系統為應用運行提供獨占環境,因此其中需要安裝Guest OS;而容器是主機操作系統上的進程虛擬化,容器鏡像中并不需要OS 內核,所以也不需要安裝Guest OS,只需要應用運行相關的庫和文件就可以了。相比與虛擬機實現,Docker 容器更輕量、更快捷。兩者的對比關系如圖2。
用戶使用Docker 的一般場景如下:根據鏡像標識從鏡像倉庫里下載鏡像到本地,Docker 引擎使用本地鏡像創建出多個相互隔離運行的容器。由于Docker 將應用和依賴文件都打包到了Docker鏡像里,用戶基于Docker 鏡像將應用部署并運行到隔離的Docker容器后,就不再依賴宿主機提供運行環境支持,從而實現了應用和PaaS 平臺解耦。這種機制為應用開發帶來了巨大便利,用戶向PaaS 平臺提交的不再是代碼,而是Docker 鏡像,PaaS 平臺也無須為應用準備各種運行時環境。新PaaS 平臺架構如圖3所示。
新PaaS 以Docker 容器為基礎,面向云化、微服務、DevOps等應用場景,支持大數據、分布式計算、深度學習等多種計算服務,集成開發、測試、部署流水線,成為一站式應用開發運行平臺。
在新PaaS 平臺上運行的生產應用會涉及多個容器,這些容器必須能夠跨多個主機部署運行,隨著數量的不斷累積,復雜性也隨之提高,Kubernetes 正是為解決這個問題而生的。借助Kubernetes,用戶可以構建多個容器的應用服務,跨主機調度、擴展這些容器、持續管理容器狀況。簡單來講,Kubernetes 將容器擴展成邏輯概念上的“容器集”(Pod),增加了一個容器分組抽象層,用戶通過選擇Kubernetes 工作負載運行容器,并為其提供網絡和存儲服務,同時Kubernetes 確保系統中運行正確數量的容器。Kubernetes 作為一個開源的軟件系統,為支撐PaaS 能力提供了如下功能:
根據資源需求以及其他相關約束條件,在不降低應用可用性的前提下對容器進行自動部署,基于工作負載盡力而為的特性,提高資源使用率以便節省更多資源。
支持根據CPU 或自定義監控指標的使用情況對應用程序容器進行自定義擴容或縮容。
Kubernetes 為容器可以為容器提供獨立的IP 地址,或針對一組相同應用程序容器提供虛擬VIP 和DNS 域名,以便用戶訪問Kubernetes 容器業務,并在這些容器間進行負載均衡。
如果容器啟動或運行失敗,Kubernetes 會重新創建失敗的容器;同時Kubernetes 也為用戶提供了容器檢查的自定義鉤子,Kubernetes 會根據鉤子的執行結果來決定是否對容器進行銷毀重建或負載均衡的摘除操作。

圖1

圖2

圖3

圖4
Kubernetes 通過定義不同的工作負載,支持部署運行無狀態應用、有狀態應用、一次性任務應用、周期性任務應用、節點daemon 應用等。
支持對一組應用程序容器進行逐步滾動更新的機制,對應用程序運行狀況進行監控以確保所有實例不會同時終止。如果在更新過程中出現問題,支持回滾更改。
支持應用配置資源與密鑰資源,用戶無需重新構建鏡像即可實現應用配置資源和密鑰資源更新。
Kubernetes 遵循微服務架構理念設計,實現了整個系統各個功能組件之間邊界清晰、部署簡單的模塊化,同時支持多種擴展機制,用戶可以方便地進行功能擴展和自定義實現。
Kubernetes 為容器管理提供了一個抽象層和一系列相關工具,支持大規模容器的編排與管理,確保應用程序的高可用和服務可移植性;同時Kubernetes 還可以更好地控制資源使用情況,如整個系統的CPU、內存和磁盤空間,在系統整體基礎資源不足時支持自動添加工作節點以完成集群的擴容[1]。圖4 展示了Kubernetes 的核心架構。
從圖4 中可以看到,整個Kubernetes 是由Master 節點和Node節點構成。
Master 節點是Kubernetes 集群的大腦,上面運行了API 服務、調度服務、控制器管理服務和Etcd 存儲服務。API 服務提供了基于Restful 的Web Service 接口,用于查詢或定義各種所需要的集群和狀態,API 服務內部有一套完備的安全機制。所有Kubernetes 集群對象的增刪改查操作只能通過訪問Kubernetes API 服務器來實現。Master 節點上的調度服務以Node 節點上實際Pod 為單位進行工作負載調度,用于為Pod 選擇合適的Node 來運行。控制器管理器是所有資源對象的自動化控制中心,用于管理各資源的控制器,用于進行故障檢測和自動化恢復的相關工作。Etcd 是一款分布式一致性的key-value 存儲,用于保存網絡配置和狀態信息。
Node 節點可以是物理機或虛擬機,承載了實際運行業務的容器,是Kubernetes 集群中的工作節點。Node 節點上運行了三個重要組件:kubelet、kube-proxy、容器引擎。kubelet 處理著master 和在其上運行的節點之間的所有通信,并負責創建、啟動和監視pod的運行。此外,kubelet 還會周期性地對配置的存活探針和就緒探針進行檢查,并在出現問題時啟動新實例。kube-proxy 是以pod 形式運行在節點上的網絡代理,負責代理UDP、TCP 數據包,維護主機上的網絡規則,并處理pod、主機和外部環境之間的數據包傳輸。容器引擎在Kubernetes 中也叫做容器運行時,負責從公有或私有鏡像倉庫中拉取鏡像,并根據這些鏡像運行容器。
使用Minikube 是運行Kubernetes 集群最簡單快捷的方法。Minikube 是一個構建單節點集群的工具,對于學習測試Kubernetes、開發本地應用都很有用。由于Linux 是目前業界廣泛使用的商業操作系統,以下內容著重介紹Linux 服務器上Kubernetes 的安裝配置過程[2]。
安裝Minikube:curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
&&chmod +x minikube
Minikube 安裝完成后,可以在本地啟動一個單節點的Kubernetes 集群:./minikube start
Kubernetes 機器組件啟動后,還需要使用kubectl 工具與啟動的Kubernetes 集群交互,kubectl 工具的安裝也很簡單,使用一條命令: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 中運行第一個應用:kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4,稍后可以看到應用已經被正常啟動了。
執行kubectl get deployments,查看啟動的應用controller,此時輸出結果類似于:
NAME READY UP-TO-DATE AVAILABLE AGE
hello-node 1/1 1 1 1m
執行kubectl get pods 查看啟動的應用實例,輸出結果類似于:
NAME READY STATUS RESTARTS AGE
hello-node-5f76cf6ccf-br9b5 1/1 Running 0 1m
從以上結果中可以看到在Kubernetes 系統中運行了一個應用實例,這個應用實例的名字為hello-node-5f76cf6ccf-br9b5。
Kubernetes 項目從一開始就沒有把Docker 作為整個架構的核心,而是將其作為最底層的一個容器運行時實現,Kubernetes 著重解決的場景:運行在大規模集群里的各種應用之間的關系,如何處理這些關系才是作業編排和管理系統最困難的地方。這些關系包括但不限于:Web 應用與數據庫之間的訪問關系、負載均衡和后端服務之間的代理關系、Web 應用與授權組件之間的調用關系。而對編排項目的需求是希望它能夠處理前面提到的所有類型的關系,甚至還要能夠支持未來可能出現的更多種類的關系。