概述
本章總共有7個小節, 首先我們要知道Kubernetes的定義, 接著透過叢集架構了解K8s的設計, 使用容器化技術是否存在著某些妥協, 需要考量的點有哪些? 我們也看看與K8s相關的開源專案或類似的技術, 當然, 高科技往往是過去所有相關技術的積累而成, 我們也來看看K8s的歷史與演進,是否有哪些包袱或困難需要被解決? 所以, 跟著介紹K8s的架構與術語, 行話肯定要聽的懂嘛, 你說是不是勒? 最後, 稍稍微的介紹幾個與K8s 相關的工具及CNCF 雲原生的開源專案,未來若是需要尋找適合的工具, 知道CNCF就也知道該往何處去找尋解決方案.
2.1 Kubernetes(K8s)的定義
- 容器編排平台
- kubernetes 專案的解釋, kubernetes 是一個開源軟體用來自動化部屬, 拓展, 及管理容器化的應用程式
- 簡單使用來管理容器, 並將叢集複雜之處整合起來, 方便使用者
- 來自google 的專案 borg
- K8S的特性是開源且易於拓展, 各大軟體或服務商都有自己發行的kubernetes 版本, 例如: AWS的EKS, GCP的GKE, Azure的 AKS等等
- 到底怎麼念? 來自希臘文 κνβερνητης, 意思就是領航員或是舵手, 就也是為什麼會看到代表 K8S的符號是一個舵.
- 我們通常會稱呼kubernetes 為K8S. 英文是Kate’s, 我們之後在文章中會用K8S代替kubernetes.
在筆記型電腦上運行容器相對簡單, 如使用Docker, 但是跨多個主機連接容器、擴展它們、在不停機的情況下部署應用程序以及在多個方面服務探索(service discovery)上可能很變得困難起來。
Kubernetes 從一開始就通過一組原語和強大的開放和可擴展 API 解決了這些挑戰。對!K8S後面就是一大堆API的相互溝通, 聽到這裡, 是否增加了學習K8S的信心了呢? 使用API的方式來添加新對象(components)和控制器的能力允許根據各種生產需求輕鬆定制。
Kubernetes 這個開源專案, 是根據一個建立在谷歌 2015 年的 borg 項目經驗之上。
在虛擬機在數據中心普及之前,谷歌的基礎設施開始達到大規模,而容器為高效打包集群提供了顆粒度的解決方案。使用集群和管理分佈式應用程序的效率一直是 Google 挑戰的核心。 使用容器時, 整個開發設計的理念跟方向跟虛擬機器時期十分不同, 從前的設計偏向一體化(monolith), 使用容器時更偏向微服務 (microservice). 我們會在後面的章節,更了解或更習慣使用容器跟K8S來管理應用程式(application)及服務(service).
2.2 叢集(cluster)的架構
- 微服務
- 解耦合的設計
- 專為瞬態(transient)而打造
- API call 調用驅動
- YAML 到 JSON,Kubernetes是用 Go 語言打造而成 (其實Docker也是)
部署容器和使用 Kubernetes, 對於IT人員或研發同仁來說, 可能需要改變部署應用程序的開發和系統管理方法因為 Kubernetes 使用的是微服務的設計。
在傳統環境中,應用程序(例如 Web 服務器)將是放置在專用服務器上的一體化(monolithic)的應用程式. 隨著網絡流量的增加,應用程序將被調整併可能轉移到越來越大的硬體上。料想幾年後,為了滿足當前的網絡流量需求,可能已經進行了大量客製化硬體。
我們試想一下會發生什麼事情, 當流量長大會需要更大的機器, 那會不會有極限呢? Google 的流量大到不得不考慮這個問題, 一體化的設計無法滿足未來google服務的拓展, 也會受限在硬體之上, 所以誕生了Borg, 進而實踐微服務的設計取代一體化的設計.
如果大家對Kubernetes的發展歷史有興趣的話, 可以看看下表:
接續上面提到如何解耦一體化設計, 我們從Kubernetes的微服務管理設計角度來看, 使用它來部署大量小型服務器或微服務來解決相同的問題,而不是使用大型服務器。
若是客戶端來的高流量需求造成服務器進程(process)死亡並需要被替換,從而導致臨時需要部署服務器,若是使用微服務的方式, 因為它瞬態的特性, 更可以解耦原來龐大的服務器架構, 將服務(service)建立在微服務上, 不僅所需時間更短, 作業系統的利用率更高, 也能簡單設計出高可用性架構.
所以,傳統應用程序被解耦成多個專用的微服務或代理所取代。 依據這樣的設計, 我們需要在每個服務前面掛上一個代理(proxy), 若後端任何服務有問題的話, 可以被叢集內其他的服務替換.
此外,Kubernetes 上的通信完全由 API 調用驅動,因此具有靈活性。集群配置信息以 JSON 格式存儲在 etcd 中,但最常由社區用 YAML 編寫。 Kubernetes 代理在持久化到數據庫之前將 YAML 轉換為 JSON。
2.3 adoption 採用容器
在沒有容器的時代, 跨平台建置環境, 基本上是讓工程師哀鴻遍野的痛苦要求. 導入容器後, 建置環境變得容易許多, 開發團隊用的環境, 測試團隊用的環境, 線上production 的環境, 除了使用機器大小可能不同, 容器封裝都可以減輕建置環境的負擔, 也不用擔心哪個相依的程式沒有安裝到, 容器技術真的是讓人不愛都難.
這邊就要特別提一下 Docker的座右銘(motto), 容器提供了一種很好的方式來打包、運送和運行應用程序
A good summary of what Docker does is included in its very own motto: Build, Ship, Run.
其實後來Docker 改成 Build, Share, Run.不過本質上來說, Share的概念跟ship to anywhere 是很相似的, 對於開發者來說都是好事一樁.
Build - Docker allows you to compose your application from microservices, without worrying about inconsistencies between development and production environments, and without locking into any platform or language.
Ship - Docker lets you design the entire cycle of application development, testing, and distribution, and manage it with a consistent user interface.
Run - Docker offers you the ability to deploy scalable services securely and reliably on a wide variety of platforms.
由於容器,開發人員的體驗得到了極大的提升。容器(尤其是 Docker)使開發人員能夠輕鬆構建容器鏡像(conatiner image),通過 Docker 註冊表共享鏡像的簡單性,並提供強大的用戶體驗來管理容器。
然而,大規模管理容器和設計基於微服務原則的分佈式應用程式可能具有挑戰性, 只有用Docker可能無法滿足分散式架構的所有場景。
明智的第一步是決定使用持續集成/持續交付 (CI/CD) 管道來構建、測試和驗證容器映像。例如:使用 https://www.spinnaker.io、https://www.jenkins.io 和 https://helm.sh 等工具以及其他可能的工具會很有幫助, 而且這將有助於應對動態環境的挑戰。
然後,您需要一組機器作為運行容器的基礎架構。您還需要一個系統來啟動您的容器,在出現故障時監視它們並根據需要進行更換。容器的滾動更新(rolling update)和輕鬆回滾(rollback)是一項重要功能,最終在不再需要時將其拆除。
所有這些操作都需要靈活、可擴展且易於使用的網絡和存儲。當容器在任何工作節點上啟動時,網絡必須將資源加入其他容器,同時仍保持流量不受其他容器的影響。我們還需要一個存儲結構,以無縫的方式提供和保持或回收存儲。
雖然 Kubernetes 解決了這些問題,但採用的最大挑戰之一是在容器內運行的應用程序本身。它們需要被編寫或重寫,才能真正成為瞬態的架構。
在使用Kubernetes時, 我們會將應用程式做成分散式的架構, 讓服務具有高可用性. 以這樣的前提下, 一個值得思考的好問題:如果您要部署 Chaos Monkey,它可以隨時終止任何容器,您的客戶會注意到嗎?
除了kubernetes之外, 還有其他的選項嗎? 其實是有的, 下面介紹幾個.
-
Docker Swarm 是 Docker Inc. 的解決方案。它最近經過重新架構,基於 SwarmKit, 嵌入 Docker 引擎。 https://github.com/docker/swarmkit
-
Apache Mesos 是一個數據中心調度器,它可以通過使用框架來運行容器。Marathon是可讓您編排容器的框架。 https://mesosphere.github.io/marathon/
-
Vagrant 和 Consul 的製造商 HashiCorp 的 Nomad 是另一種管理容器化應用程序的解決方案。 Nomad 調度在 Jobs 中定義的任務。它有一個 Docker 驅動程序,可讓您將正在運行的容器定義為任務。 https://www.nomadproject.io/
-
Rancher 是一個與容器編排器無關的系統,它為管理應用程序提供了一個單一的玻璃界面。它支持 Mesos、Swarm、Kubernetes,以及它的原生系統 Cattle。從 2.0 開始,牛已被 Kubernetes 取代。 http://rancher.com
-
crossplane 是一個開源的 Kubernetes 插件,可以使用 kubectl 配置和管理基礎設施、服務和應用。它的意義在使用 Kubernetes 風格的 API 統一了雲基礎設施和應用程序的管理。該項目是由 Upbound 公司和 Rook 項目的創始人於 2018 年 12 月發起,開源社區主要參與者來自微軟、阿里巴巴、Gitlab、紅帽等。
如果大家有興趣所有的容器管理排程的開源專案, 也可以到CNCF的網站參考點我
Kubernetes (K8s)的歷史與傳承
Kubernetes 與其他系統的主要區別在於它的傳承。 Kubernetes 的靈感來自 Borg,Borg 是 Google 用來管理其應用程序(例如 Gmail、Apps、GCE)的內部系統。
谷歌將他們從編寫和操作 Borg 超過 15 年的寶貴經驗傾注到 Kubernetes 中,這使得 Kubernetes 在必須決定使用什麼系統來管理容器時成為一個安全的選擇。雖然它是一個強大的工具,但它是秘密和內部的,但 Kubernetes 當前增長的一部分正在使其更容易使用和處理 Google 數據中心中沒有的工作負載。
Borg 啟發了當前的數據中心系統,以及當今容器運行時中使用的底層技術。谷歌在 2007 年為 Linux 內核貢獻了 cgroups;它限制了process 集合使用的資源。 cgroup 和 Linux 命名空間(namespace)都是當今容器(包括 Docker)的核心。
當 Borg 還是個秘密時,Mesos 的靈感來自於與google的討論。事實上,Mesos 構建了一個多級調度器,旨在更適切地使用數據中心集群。
Kubernetes 開源且被CNCF管理之後, 讓更多人可以投入並貢獻在Kubernetes 專案之上, 幾乎是每3-6個月就會有一個版本更新, 若你對貢獻Kubernetes也有興趣的話, 也可以到github 上關注這個開源專案 按這裡
2.4 Kubernetes(K8s)的架構
以kubernetes 的叢集來看, 主要分成兩種組件:
- 控制平台 (control plane)
- 工作節點 (woker node)
當我們創建一個 Kubernetes (K8S) 意味著我們創建了一個叢集(cluster), 而叢集(cluster) 的意思是有一組控制平台(control plane) 及 至少一個的工作機節點(worker node), 在這些工作節點上可以運行容器化的應用(application) 並且由 控制平台(control plane)進行管理. 當我們自行建置 Kubernetes 叢集, 每個叢集至少要有一個工作機節點.
工作機節點上運行容器化應用的組件稱之為 Pod, 一個Pod上可以跑一個或多個容器(container). 透過控制台(control plane)的管理, 我們可以把同一個容器化的服務透過部署(deployment)機制跑在不同的Pod及工作節點之上, 提供高可用性(High Availability) 及故障移轉 (fault-tolerance)
那Kubernetes 到底是如何完成上述的方式來完成部署的呢? 這個時候我們必須來了解在控制平台與工作節點上的所有組件. 我們來讀一下下面這句十分經典的句子, 有助於我們了解Kubernetes的設計.
Kubernetes is not just API-driven, but is API-centric.
這句話是K8S界的大牛Brian Grant在他的Kubernetes Resource Model 文章中說的, 其實講的非常的貼切, 在上圖中你看到所有的元件溝通都是通過API驅動, 讓我們注意一下這些箭頭都指向何處? 眼尖的同學早已發現, 沒錯! 就是 Kube-api-server, 也是我們要介紹的第一個組件.
-
kube-api-server - 控制平台(control plane)的中心就是 api-server,它實現了系統所有 API 的通用功能。用戶客戶端和實現 Kubernetes 業務邏輯的組件(稱為控制器)與相同的 API 交互。這些 API 類似於 REST,主要支持(主要是)持久資源上的 CRUD 操作。所有持久的集群狀態都存儲在 etcd 鍵值存儲的一個或多個實例中。
-
kubelet - 每個運行容器的節點都會有kubelet, 它通常是systemd的process, 而不是一個容器. kubelet 接收運行容器的請求,管理任何必要的資源,並與容器引擎一起在本地節點上管理它們。本地容器引擎可以是 Docker、cri-o、containerd 或其他的CRI (container Runtime Interface)
-
kube-proxy - 創建和管理網絡規則,以將網絡上的容器暴露給其他容器或外部世界. 它其實就是一個跑在各個工作節點(node) 的網路代理(network proxy), 整體的運行在Pod之上, 並且用來實現一部分的Kubernetes Service 的概念. kube-proxy 維護各個節點上的網路規則, 這些規則允許叢集內部或外部的網路與Pod間進行網路通信.
-
kube-scheduler - 將運行容器的pod規範轉發給API,並找到合適的節點來運行這些容器。 又或者說, scheduler 負責監控新創建的Pods 但仍未指定運行的工作節點(Node), 安排工作節點讓Pod可以運行在其之上. 調度決策的考慮因素包含單個Pod 或 多個Pods (Pod 的集合)所需要的資源, 如: 硬體, 軟體, 部署策略/限制/規範, 工作負載間的干擾 (inter-workload interference)及最終期限 (deadlines).
-
etcd - 是具有高可用性及一致性的鍵值(key-value) 資料庫, 用來保存K8S叢集數據的後台資料庫. 管理etcd 可能會因為環境建置情況, 我們會需要操作 etcd的備份及還原資料
-
control manager - 是Kubernetes 的大腦由 kube-controller-manager 和 cloud-controller-manager 组成. 它的運作機制是通過API-server監控整個叢集的狀態, 並且確保集群上的運作符合預期
- kube-controller-manager - 每個控制器(controller)其實都是一個單獨的程序(process), 但是為了降低複雜性, 它們都被編譯到同一個可執行的文件, 並在一個程序中運行. 這些控制器(controller)包含下面幾種:
- 節點控制器 node controller - node 發生故障時, 需要發出通報
- 任務控制器 job controller - 監測一次性任務的Job 對象, 然後創建Pods來運行任務直到完成任務.
- 端點控制器 end-point controller - 加入端點的對象也就是串接 Service 與 Pods
- 服務帳戶與令牌控制器 service account & token controller - 為新建立的命名空間(namespace)創建對應的默認帳戶及訪問令牌
- cloud-controller-manager - 僅運行在特定的雲平台, 若是本地運行Kubernetes, 所部署的環境不需要考慮之.
- kube-controller-manager - 每個控制器(controller)其實都是一個單獨的程序(process), 但是為了降低複雜性, 它們都被編譯到同一個可執行的文件, 並在一個程序中運行. 這些控制器(controller)包含下面幾種:
2.5 Kubernetes(K8s)的術語
- Pod
- Namespace
- Operator/Controller/Watch-loop
- ReplicaSet
- Deployment
- DaemonSet
- Jobs
- Service
- Label
- Taint
- Toleration
- Annotation
我們已經知道kubernetes 是一個容器編排的平台, 用以部署及管理容器. 這些容器並非直接被管理, 而是被放在一個更大的物件之上, 我們稱這個物件為 Pod. 一個Pod可以包含一個或多個容器, 並且互享分享命名空間(Namespace), IP Address, 儲存空間等等.
Kubernetes 利用命名空間(namespace)來確實清楚化辨析不同的物件(objects), 用來管理資源 (resource control) 或 多用戶(multi-tenant) 的場景. Kubernetes 上的物件(objects)有些是cluster 層級的, 而有些是命名空間層級的. 一旦物件是命名空間層級的, 若要與這種pod 進行溝通的話, 需要透過 "service"來達成. 若是很難想像Namespace的話, 你可以把Namespace的概念想像成社區大樓每個住戶的房號. 不住在同一個房間的人, 要跟管理員要求一個服務(service)來做彼此間的通信.
若想要知道使用的物件是namespace層級的,還是cluster 層級的, 可以透過這個指令得知 kubectl get api-resources
, 第四個欄位(Namespaced)若為true, 則是namespace層級的. 反之, 則是cluster 層級的.
Kubernetes 編排(orchestration)平台通過一系列監視循環 (watch-loops))進行管理。透過每個查詢 kube-apiserver 的特定對象狀態,然後修改對象直到聲明的狀態與當前狀態匹配。這些控制器被編譯到 kube-controller-manager 中,但你也可以使用自定義資源定義(CRD customer resource definition)添加其他控制器。
容器的基礎的部署方式是使用deployment, Deployment 不直接與 pod 一起使用。相反,它管理 ReplicaSet, ReplicaSet 是一個操作符 (operator),它將根據 podspec 創建或終止 pod。 podspec 被發送到 kubelet,然後 kubelet 與容器引擎交互,下載並提供所需的資源,然後生成或終止容器,直到狀態與規範匹配。 下圖再次說明了Kubernetes watch-loops 的操作模式.
DeploymentReplicaSetpod
Service 操作符會向端點操作符(endpoint operator)請求現有的 IP 地址和信息,並將根據label標籤管理網絡連接。service用於在 Pod、命名空間(namespace)和集群(cluster)外部之間進行通信。除了其他默認操作符之外,還有 Jobs 和 CronJobs 來處理單個或重複性任務。
除了Service需要使用標籤(label), 為了可以更輕鬆地管理數百個節點上的數千個 Pod,我們也可以使用Label標籤,即成為對像元數據(metadata)一部分的任意字符串, 然後可以在檢查或更改對象的狀態時使用這些,而無需知道具體的名稱或 UID。
另外節點可以有污點(taint)來阻止 Pod 分配,除非 Pod 在其元數據中具有容忍度(tolerance)。
元數據(metadata)中還有用於註釋(annotation)的空間,這些註釋保留在對像中但不用作選擇器(selector)。這些信息可以被容器、第三方代理或其他工具使用。 後續使用雲服務或第三方工具時, 會很常注意到註釋(annotation)被廣泛地運用.
2.6 Kubernetes Tools
-
Minikube, Kind, K3s - 他們都是可以在你的筆記型電腦建置K8S的好用工具, 功能上這三種可能會跟kubernetes 發行的正式版本上有支援度的差異. 但是在開發或學習K8S是一個免費簡單的好工具.
-
kubeadm - 這是協助我們建立K8S叢集的好工具, 簡化了許多流程.
-
kubectl - 這個是整個CKA training或是未來操作K8s不能沒有的命令列, 功能非常的豐富.
-
helm - 就像是mac 上的brew 或是 ubuntu 上的apt, 作用是工具包的管理, 它可以被使用在K8S上來部署更新移除應用程式. 也可以使用Helm的values.yaml檔案, 來客製化你需要的設定, 是一個在K8s上非常好用的工具.
-
kompose - 它的功能就是能把docker-compose 轉換成K8s 所需要的yaml檔案用以部署容器
-
lens - 用來監控k8s叢集的圖形化工具, 需要將prometheus 服務啟動.
2.7 CNCF 下的Kubernetes 開源專案管理
Kubernetes 是使用 Apache License 許可的開源專案。 2015 年 7 月,當 Kubernetes 達到 v1.0 版本時,谷歌將 Kubernetes 捐贈給了 Linux 基金會內一個新成立的合作項目, 這個項目被命名為雲原生計算基金會(CNCF)。
CNCF 不僅僅是關於 Kubernetes, 它也是解決雲原生(cloud native)應用程式(即專門為雲環境編寫的應用程序)面臨的特定問題的開源軟件的管理機構, 現在CNCF的Landscape有關雲原生的專案非常非常的多. 有興趣的, 可以點這裡
CNCF 有許多合作的企業成員,例如 Cisco、Cloud Foundry Foundation、AT&T、Box、Goldman Sachs 等。
參考資料
2.7 Lab
- 查看目前kubernetes 的最新版本 這裏
- 查看目前kubernetes 的issues 這裏
- Service 是透過哪個K8s的物件來管理網路連接? (endpoint)
- Taint 的作用是防止pod 被部署在某一個node之上, 可以透過哪一個組件允許pod被放在有taint的node上面?(toleration)
- 哪一個K8s 物件是被執行在systemd之上?(kubelet)
- K8s的組件有control-manager, scheduler, etcd, kube-proxy, kubelet, api-server. 那個別的功能是?(請看內文)
- kubeadm 的功用是? (安裝k8s套件)
- helm 的功用是? (協助部署複雜的應用程序)