1. 容器編排技術(shù)
容器編排是指對(duì)多個(gè)容器的部署,管理和監(jiān)控。
之所以有容器編排技術(shù),其實(shí)是和業(yè)務(wù)量與系統(tǒng)復(fù)雜度與日俱增推動(dòng)服務(wù)部署的演進(jìn)方式息息相關(guān)的,下圖是服務(wù)部署方式的演進(jìn)過(guò)程。
更高效地利用系統(tǒng)資源、一致的運(yùn)行環(huán)境、更輕松的遷移和拓展等諸多優(yōu)點(diǎn),使容器部署方式越來(lái)越成為主流。
Docker 是開(kāi)源的被廣泛應(yīng)用的容器引擎,在實(shí)際生產(chǎn)環(huán)境中,在多臺(tái)物理主機(jī)中協(xié)調(diào)容器資源成為首要要解決的問(wèn)題,這一問(wèn)題被統(tǒng)稱為容器編排。
容器領(lǐng)域現(xiàn)階段爭(zhēng)論的重點(diǎn)也正在于為容器主機(jī)群管理提供怎樣的容器編排功能。
目前比較流行的容器編排工具包括 Docker Swarm,Kube.NETes 和 Mesos+Marathon。容器使用的最核心問(wèn)題也恰是容器編排及如何部署和管理容器。Docker Swarm,Kubernetes,Mesos+Marathon 都可用于容器的部署、管理以及實(shí)現(xiàn)容器的擴(kuò)容,但這三種編排工具著重處理的問(wèn)題和使用場(chǎng)景也是不同的。
2. 初識(shí) Kubernetes
2.1 Kubernetes 概述
Kubernetes 也簡(jiǎn)稱為 k8s,它可以提供?戶所需的容器部署,管理和擴(kuò)縮容等編排功能。
借助 Kubernetes 的編排功能,?戶可以構(gòu)建多個(gè)容器的應(yīng)?服務(wù),跨集群調(diào)度、擴(kuò)展這些容器,并長(zhǎng)期持續(xù)管理這些容器和檢測(cè)健康狀況 。
2.2 Kubernetes 能做什么?
Kubernetes 為?戶主要提供了以下功能:
- 服務(wù)發(fā)現(xiàn)和負(fù)載均衡:Kubernetes 可以使?DNS 名稱或集群的 IP 公開(kāi)容器,如果進(jìn)?容器的流量很?, Kubernetes 可以用負(fù)載均衡并均衡分配流量使服務(wù)穩(wěn)定。
- 存儲(chǔ)編排:Kubernetes 允許你?動(dòng)掛載選擇的存儲(chǔ)系統(tǒng),例如本地存儲(chǔ)、公共云提供商等。
- ?動(dòng)部署和回滾:你可以使?Kubernetes 描述已部署容器的所需狀態(tài),它可以以受控的速率將實(shí)際狀態(tài)更改為期望狀態(tài)。例如,你可以?動(dòng)化的方式來(lái)部署創(chuàng)建新容器, 刪除現(xiàn)有容器并將它們的所有資源?于新容器。
- ?動(dòng)完成裝箱計(jì)算:Kubernetes 允許你指定每個(gè)容器所需 CPU 和內(nèi)存(RAM)。 當(dāng)容 器指定了資源請(qǐng)求時(shí),Kubernetes 可以做出更好的決策來(lái)管理容器的資源。
- ?我修復(fù):Kubernetes 能重啟容器、替換容器、殺死不符合定義運(yùn)?狀況檢查的容器,并且這些功能對(duì)客戶端都是無(wú)感知的。
- 密鑰與配置管理:Kubernetes 允許你存儲(chǔ)和管理敏感信息,例如密碼、OAuth 令牌和 ssh 密鑰。 你可以在不重建容器鏡像的情況下部署和更新密鑰和應(yīng)?程序配置,也?需 在堆棧配置中暴露密鑰。
2.3 為什么是 Kubernetes?
回歸根本問(wèn)題:why Kubernetes?
- 可擴(kuò)展性
Kubernetes 具有很好的可擴(kuò)展性。K8s 內(nèi)置一組資源,例如 Pod,Deployment、StatefulSets、Secrets、ConfigMaps 等,用戶和開(kāi)發(fā)人員也可以以“Custom Resource Definition”的形式添加更多自定義資源。 Kubernetes 可擴(kuò)展性的另一種形式是開(kāi)發(fā)人員具有編寫(xiě)自己的能力 Operators 的能力,operator 允許用戶通過(guò)與 Kubernetes API 進(jìn)行對(duì)話來(lái)自動(dòng)管理 Custom Resource Definition。
- 強(qiáng)大的社區(qū)
Kubernetes 受歡迎的另一個(gè)重要方面是其強(qiáng)大的社區(qū)。Kubernetes 于 2015 年在 1.0 版本時(shí)就捐贈(zèng)給了與供應(yīng)商無(wú)關(guān)的基金會(huì),Kubernetes 是活躍在 Github 中前幾名的項(xiàng)目之一:占有在所有項(xiàng)目前 0.01%的排名。 隨著項(xiàng)目的推進(jìn),還有各種各樣的社區(qū) SIG(特殊興趣小組)針對(duì) Kubernetes 中的不同領(lǐng)域。他們不斷添加新功能,并使其對(duì)用戶更加友好。
- 技術(shù)與革新
Kubernetes 基于谷歌的 Borg 的開(kāi)源技術(shù),它累積了 Borg15 年輕人深耕細(xì)作的發(fā)展和生產(chǎn)實(shí)踐。 在過(guò)去的幾年中,Kubernetes 每年都有三到四個(gè)大小版本發(fā)布。引入的新功能的速度到目前也并未減慢,這些新功能使集群運(yùn)營(yíng)商在運(yùn)行各種不同的工作負(fù)載時(shí)具有更大的靈活性。軟件工程師也能擁有更多控件,以將其應(yīng)用程序直接部署到生產(chǎn)環(huán)境中。
3. Kubernetes 構(gòu)成與基本原理
3.1 Kubernetes 集群
上圖可以看到一個(gè)集群主要包括兩個(gè)部分:
- 一個(gè) Master 節(jié)點(diǎn),也稱為控制平?,是 Kubernetes 集群的?腦。
其中包括如下組件:
- Api server:是整個(gè)系統(tǒng)的對(duì)外接口,供客戶端和其它組件調(diào)用,相當(dāng)于“營(yíng)業(yè)廳”;
- Etcd:Api server 后臺(tái)數(shù)據(jù)存儲(chǔ),相當(dāng)于 Kubernetes 集群的數(shù)據(jù)中?;
- Scheduler:負(fù)責(zé)對(duì)集群內(nèi)部的資源進(jìn)行調(diào)度,相當(dāng)于“調(diào)度室”;
- Controller-manager:控制管理器,保證 Kubernetes 集群中的資源按照要求運(yùn)?。
- 一群 Node 節(jié)點(diǎn),也稱為 Worker 節(jié)點(diǎn) ,主要負(fù)責(zé) Pod 地運(yùn)?。
主要包括以下組件:
- Kubelet:負(fù)責(zé)與 Master 節(jié)點(diǎn)交互,進(jìn)?執(zhí)?具體的任務(wù);
- Kube-proxy:負(fù)責(zé) Kubernetes 集群中的負(fù)載均衡;
- Container-runtime:提供容器運(yùn)行環(huán)境,有 docker,rkt 或者其他容器實(shí)現(xiàn)標(biāo)準(zhǔn),負(fù)責(zé)容器的操作,啟動(dòng)或者關(guān)閉等;
- Pod:k8s 的最小調(diào)度單元,1 個(gè) pod 可以包含 1 個(gè)或多個(gè)容器,pod 可以理解為容器的集合。
3.2 Master 節(jié)點(diǎn)及運(yùn)行機(jī)制
我們知道了 Master 節(jié)點(diǎn)包括 Api Server、Scheduler、Controller manager、Etcd。
下面對(duì)這幾種組件一一做介紹。
- Api server
Kubernetes API Server 是集群的統(tǒng)一入口,各組件協(xié)調(diào)者,以 HTTP API 提供接口服務(wù),所有對(duì)象資源的增刪改查和監(jiān)聽(tīng)操作首先交給 API Server 處理,下一步再給 Etcd 存儲(chǔ)。
- Controller-manager
Controller-manager 是 Kubernetes 中的資源管理器。Kubernetes 集群中有很多
的資源,如 Node、Pod 副本、服務(wù)端點(diǎn) Endpoint、命名空間 namespace、服務(wù)賬號(hào)
ServiceAccount 等。Controller-manager 負(fù)責(zé)這些資源的管理,以保證這些資源實(shí)際運(yùn)?的狀態(tài)達(dá)到被期望的狀態(tài)。
- Etcd
Etcd 是一個(gè)高可用的鍵值存儲(chǔ)系統(tǒng),主要用于共享配置和服務(wù)發(fā)現(xiàn)。它使用 Go 語(yǔ)言編寫(xiě),并通過(guò) Raft 一致性算法處理日志復(fù)制以保證強(qiáng)一致性。
Etcd 可以理解為 Kubernetes 集群的數(shù)據(jù)中?,用于保存集群狀態(tài)信息,比如 Pod、Service 等對(duì)象信息。Etcd 主要和 Api server 交互比較多,Api server 接受操作命令后,會(huì)將信息存儲(chǔ)到 Etcd 中。從下文的 pod 的狀態(tài)流程可看到,Api server 構(gòu)建出完整的 Pod 信息,并將該信息存儲(chǔ)到 etcd 中。
- Scheduler
Scheduler 是 Kubernetes 集群中的調(diào)度器。Scheduler 的作?是將待調(diào)度的 Pod 按照特定的調(diào)度算法和調(diào)度策略綁定到集群中某個(gè)合適的 Node 上,并將綁定信息通過(guò)調(diào)?Api server 寫(xiě)?etcd 中。scheduler 在整個(gè)系統(tǒng)中承擔(dān)了承上啟下的重要功能,承上是指它負(fù)責(zé)接收 Controller manager 創(chuàng)建新的 Pod,為其安排一個(gè)落腳的目標(biāo) Node,啟下是指安置 Node 工作完成后,目標(biāo) Node 上的 kubelet 服務(wù)進(jìn)程接管 Scheduler 的后繼工作。
3.3 node 節(jié)點(diǎn)及運(yùn)行機(jī)制
Node 節(jié)點(diǎn)主要包括 Kubelet、Kube-proxy、Pod,其中最重要的也就是 Pod 了。
下邊我們來(lái)一一進(jìn)行介紹:
- Kubelet
kubelet 是 Master 在 Node 節(jié)點(diǎn)上的 Agent,每個(gè)節(jié)點(diǎn)都會(huì)啟動(dòng) kubelet 進(jìn)程,該進(jìn)程?于處理 Master 下發(fā)到本節(jié)點(diǎn)的任務(wù),管理 Pod 及 Pod 中的容器。每個(gè) kubelet 進(jìn)程都會(huì)在 Api server 上注冊(cè)節(jié)點(diǎn)信息,定期向 Master 匯報(bào)節(jié)點(diǎn)資源的使?情況,并監(jiān)控容器和節(jié)點(diǎn)資源。
kubelet 在啟動(dòng)時(shí)通過(guò) Api server 注冊(cè)節(jié)點(diǎn)信息,并定時(shí)向 Api server 發(fā)送節(jié)點(diǎn)的新信息,Api server 在接收到這些信息后,將這些信息寫(xiě)?etcd。kubelet 監(jiān)聽(tīng) etcd,所有針對(duì) Pod 的操作都會(huì)被 kubelet 監(jiān)聽(tīng)。如果發(fā)現(xiàn)有新的綁定到本節(jié)點(diǎn)的 Pod,則按照 Pod 清單的要求創(chuàng)建該 Pod。如果發(fā)現(xiàn)本地的 Pod 被修改,則 kubelet 會(huì)做出相應(yīng)的修改,?如在刪除 Pod 中的某個(gè)容器時(shí),會(huì)通過(guò)操作本地容器運(yùn)?時(shí)刪除該容器。
- Kube-proxy
在 Kubernetes 集群的每個(gè) Node 上都會(huì)運(yùn)??個(gè) kube-proxy 服務(wù)進(jìn)程,其核?功能是將到某個(gè) Service 的訪問(wèn)請(qǐng)求轉(zhuǎn)發(fā)到后端的多個(gè) Pod 實(shí)例上。kube-proxy 本質(zhì)上類似一個(gè)反向代理。我們可以把每個(gè)節(jié)點(diǎn)上運(yùn)行的 kube-proxy 看作 service 的透明代理兼負(fù)載均衡器。kube-proxy 也監(jiān)聽(tīng) api server 中 service 與 Endpoint 的信息, 通過(guò)配置的 iptables 規(guī)則,請(qǐng)求通過(guò) iptables 直接轉(zhuǎn)發(fā)給 pod。
- Pod
Pod 是最小部署單元,一個(gè) Pod 有一個(gè)或多個(gè)容器組成,Pod 中的容器共享存儲(chǔ)和網(wǎng)絡(luò),在同一臺(tái) Docker 主機(jī)上運(yùn)行。
pod 的構(gòu)成示意圖如下所示:
可以看到由一個(gè) pause 的根容器,加上一個(gè)或多個(gè)業(yè)務(wù)容器構(gòu)成。
kubernetes 中的 pause 容器主要為每個(gè)業(yè)務(wù)容器提供以下功能:
- PID 命名空間:Pod 中的不同應(yīng)用程序可以看到其他應(yīng)用程序的進(jìn)程 ID。
- 網(wǎng)絡(luò)命名空間:Pod 中的多個(gè)容器能夠訪問(wèn)同一個(gè) IP 和端口范圍。
- IPC 命名空間:Pod 中的多個(gè)容器能夠使用 System IPC 或 POSIX 消息隊(duì)列進(jìn)行通信。
- UTS 命名空間:Pod 中的多個(gè)容器共享一個(gè)主機(jī)名 Volumes(共享存儲(chǔ)卷)
Pod 里多個(gè)業(yè)務(wù)容器共享 pause 容器的網(wǎng)絡(luò)棧和 Volume 掛載卷。
正是由于業(yè)務(wù)容器共享這些資源,同一個(gè) Pod 里的容器之間僅需通過(guò) localhost 就能互相通信,所以他們之間通信和數(shù)據(jù)交換更為高效,在設(shè)計(jì)時(shí)我們可以充分利用這一特性將一組密切相關(guān)的服務(wù)進(jìn)程放入同一個(gè) Pod 中。
3.4 Pod 的數(shù)量和版本控制
ReplicationController 用來(lái)確保容器應(yīng)用的副本數(shù)始終保持在用戶定義的副本數(shù),即如果有容器異常退出,會(huì)自動(dòng)創(chuàng)建新的 Pod 來(lái)替代。
在新版本的 Kubernetes 中建議使用 ReplicaSet 來(lái)取代 ReplicationController ,ReplicaSet ReplicaSet 跟 ReplicationController 沒(méi)有本質(zhì)的不同,只是名字不一樣,并且 ReplicaSet 支持集合式的 selector。雖然 ReplicaSet 可以獨(dú)立使用,但一般還是建議使用 Deployment 來(lái)自動(dòng)管理 ReplicaSet,這樣就無(wú)需擔(dān)心跟其他機(jī)制的不兼容問(wèn)題。 Deployment 為 Pod 和 ReplicaSet 提供了一個(gè) 聲明式定義方法,用來(lái)替代以前的 ReplicationController 來(lái)方便的管理應(yīng)用。 Deployment 典型的場(chǎng)景:滾動(dòng)更新
Deployment 不僅可以滾動(dòng)更新,還可以進(jìn)行回滾,如何發(fā)現(xiàn)升級(jí)到 V2 版本后,發(fā)現(xiàn)服務(wù)不可用,可以回滾到 V1 版本。
3.5 Pod 的創(chuàng)建流程
以創(chuàng)建 Pod 為例,來(lái)理解 Kubernetes 中的各組件的運(yùn)?流程:
- 通過(guò) api server 向集群發(fā)起創(chuàng)建 Pod 的指令,api server 將 yaml 中的配置的屬性信息(metadata)寫(xiě)入 etcd 中。
- apiserver 觸發(fā) watch 機(jī)制準(zhǔn)備創(chuàng)建 pod,信息轉(zhuǎn)發(fā)給調(diào)度器 Scheduler,Scheduler 使用調(diào)度算法選擇 node,然后將 node 信息給 api server,api server 將綁定的 node 信息寫(xiě)入 etcd。
- api server 又通過(guò) watch 機(jī)制,調(diào)用 kubelet,指定 pod 信息,觸發(fā) docker run 命 令創(chuàng)建容器。
- 創(chuàng)建完成之后反饋給 kubelet, kubelet 又將 pod 的狀態(tài)信息給 api server, api server 又將 pod 的狀態(tài)信息寫(xiě)入 etcd。
- ?此 Pod 真正的創(chuàng)建完畢。如果因?yàn)槟承┰?Pod 出現(xiàn)了問(wèn)題,集群中的 controller-manager 會(huì)向 apiserver 發(fā)起創(chuàng)建的請(qǐng)求。
4. Kubernetes 的服務(wù)暴露
Pod 能創(chuàng)建成功了,也能很好的對(duì) Pod 做管理了,那么客戶端如何找出相應(yīng)的 Pod 調(diào)用其服務(wù)呢?
Kubernetes 支持多種服務(wù)暴露的方式。
下面介紹ClusterIP、NodePort和Ingress是三種廣泛使用的服務(wù)暴露方式。其中 ClusterIP 和 NodePort 方式屬于 Service 資源類型,Ingress 屬于 Ingress 資源類型。
4.1 Service—ClusterIP 服務(wù)暴露
Kubernetes 集群會(huì)為一組 Pod 分配對(duì)應(yīng)的集群 IP,同時(shí)產(chǎn)??個(gè)域名。集群內(nèi)部可以通過(guò)這集群 IP 或者域名訪問(wèn) Service 對(duì)應(yīng)的 Pod。
該類型只能在集群內(nèi)部訪問(wèn),也是默認(rèn)的 ServiceType。
apiVersion: v1kind: Servicespec: metadata: name: my-service selector: App: my-app type: ClusterIP ports: - name: http port: 80 targetPort: 8080 protocol: TCP
復(fù)制代碼
上面的示例定義了一個(gè) ClusterIP Service。ClusterIP 上端口 80 的流量將轉(zhuǎn)發(fā)到 Pod 上的 8080 端口 (targetPort 配置項(xiàng))上,攜帶 app: my-app標(biāo)簽的 Pod 將被添加到 Service 中作為作為服務(wù)的可用節(jié)點(diǎn)。
常見(jiàn)使用場(chǎng)景:
集群內(nèi)部服務(wù)的暴露。
4.2 Service—NodePort 服務(wù)暴露
NodePort 在固定端口號(hào)上公開(kāi)向集群外部暴露服務(wù),它允許從集群外部訪問(wèn)該服務(wù),在集群外部需要使用集群的 IP 地址和 NodePort 指定的端口才能訪問(wèn)。
創(chuàng)建 NodePort Service 將在集群中的每個(gè) Node 上開(kāi)放該端口。
創(chuàng)建 NodePort Service 的同時(shí)還會(huì)自動(dòng)創(chuàng)建一個(gè) ClusterIP 類型的 Service,NodePort 會(huì)將端口上的流量路由給 ClusterIP` 類型的 Service。
常見(jiàn)使用場(chǎng)景:
可以使用 NodePort 快速設(shè)置開(kāi)發(fā),測(cè)試環(huán)境的服務(wù)或在其上公開(kāi) TCP 或 UDP 服務(wù),但是對(duì)于公開(kāi) HTTP 服務(wù)來(lái)說(shuō) NodePort 不是一個(gè)的理想選擇,因?yàn)槠涫褂玫亩际欠?HTTP 標(biāo)準(zhǔn)的端口。
4.3 Ingress 服務(wù)暴露
Ingress 實(shí)際上是與 Service 完全不同的資源,算是 Service 上面的一層代理,通常在 Service 前使用 Ingress 來(lái)提供 HTTP 路由配置。它讓我們可以設(shè)置外部 URL、基于域名的虛擬主機(jī)、SSL 和負(fù)載均衡。
為了讓 Ingress 資源?作,集群必須有?個(gè)正在運(yùn)?的 Ingress 控制器。與 Controller-manager 控制器不同,Ingress 控制器不是隨集群?動(dòng)啟動(dòng)的,可以選擇不同外部組件來(lái)做 Ingress 控制器。
比如:Nginx-ingress,它使用 nginx 服務(wù)器作為反向代理來(lái)把流量路由給后面的 Service。
常見(jiàn)使用場(chǎng)景:
可以處理 http,https 請(qǐng)求的流量,并且可以處理多個(gè)域名的流量。一個(gè) IP 可以暴露多個(gè)應(yīng)用,支持同域名不同 uri,支持證書(shū)等功能。使用場(chǎng)景比較廣泛。
5. Kubernetes 在企業(yè)中的應(yīng)用
無(wú)論是中小型企業(yè),還是大型互聯(lián)網(wǎng)為了提高資源利用率,實(shí)現(xiàn)降本增效,利用 Kubernetes 構(gòu)建一套自動(dòng)化運(yùn)維環(huán)境已成為最佳選擇。
下圖是企業(yè)服務(wù)云平臺(tái)正在實(shí)現(xiàn)的云上架構(gòu)能力的一幅藍(lán)圖,其中服務(wù)容器化作為云平臺(tái)基礎(chǔ)中的基礎(chǔ)能力。在容器的編排和管理上最基礎(chǔ)能力上實(shí)現(xiàn)擴(kuò)容、限流等可操作 api 和日志、監(jiān)控等可觀測(cè)的 api。上層能力層可通過(guò)這些 api 提供服務(wù)構(gòu)建,部署,流量控制等功能。
可見(jiàn) Kubernetes 在整個(gè)架構(gòu)圖中重要的位置。
從容器編排管理的實(shí)現(xiàn)細(xì)節(jié)來(lái)看,如下圖,經(jīng)過(guò) 7 層負(fù)載,請(qǐng)求會(huì)打到一組 Ingress 控制器上,由于容器的 ip 會(huì)經(jīng)常變動(dòng),所以 Ingress 會(huì)向上屏蔽掉變動(dòng),到達(dá)了 Ingress 請(qǐng)求就由 Kubernetes 來(lái)控制了,Kubernetes 會(huì)將此請(qǐng)求路由到相應(yīng)服務(wù)的某個(gè) Pod 上,同一個(gè)服務(wù)會(huì)有多個(gè) Pod,這些 Pod 也會(huì)分部在不容物理機(jī)上。目前貝殼采用 Eureka 注冊(cè),每個(gè) Pod 對(duì)應(yīng)的服務(wù)節(jié)點(diǎn),都會(huì)在 Eureka 上注冊(cè), 如果服務(wù) A 需要調(diào)用服務(wù) B,則請(qǐng)求到服務(wù) A 的 pod 后,會(huì)從 Eureka 上尋找服務(wù) B 的 Pod 的節(jié)點(diǎn)(目前通過(guò) Eureka+DNS 來(lái)實(shí)現(xiàn))拿到上游服務(wù) Pod 信息后就直接調(diào)用服務(wù) B 某一個(gè) Pod 上的服務(wù)了。
希望今天的講解對(duì)大家有所幫助,謝謝!
Thanks for reading!