超詳細 Kubernetes 初學者指南
來自專欄 KubernetesMeetup 社區
原文作者:Imesh Gunaratne
翻譯:夏天技術校對:星空下的文仔
Kubernetes 已成為在私有雲、公有雲和混合雲環境中大規模部署容器化應用的事實標準。AWS、Google Cloud、Azure、IBM Cloud 和 Oracle Cloud 等幾個最大的公有雲平台都可以為 Kubernetes 提供託管服務。
幾年前,Red Hat 用 Kubernetes 完全替代了自己的 OpenShift 實施方案,並與 Kubernetes 社區合作推出了下一代容器平台。Mesosphere 在 Kubernetes 流行起來後迅速將 Kubernetes 的關鍵特性,如容器分組,重疊網路,4 層路由,Secrets 等集成到它們的容器平台 DC / OS 中。DC / OS 還將 Kubernetes 與 Marathon 整合為一個容器編排系統。Pivotal 最近推出了基於 Kubernetes 的 Pivotal Container Service(PKS),用於在 Pivotal Cloud Foundry 上部署第三方服務……時至今日,仍然有許多組織和技術提供商正在跟隨 Kubernetes 發展的腳步對產品進行相應調整。
2014 年,Kubernetes 走入人們的視野 。它整合了谷歌內部容器集群管理系統 Borg 和 Omega 優勢,汲取了谷歌大規模應用容器技術十幾年經驗 。在我看來, Kubernetes 讓人們對於諸如微服務,serverless 功能,Service Mesh 和 Event-driven 應用程序等新興軟體架構模式的適應變得容易,並為構建整個雲原生生態鋪平了道路。最重要的是,其 cloud agnostic 設計讓容器化應用程序無需對應用程序代碼進行任何更改,就可以在任何平台上運行。當前 Kubernetes 主要用在大型企業部署場景下,但從長遠來看,中小型企業也可以應用 Kubernetes 節省大量的基礎設施和維護成本。
接下來,我將在文中介紹 Kubernetes 的高級架構,應用程序部署模型,服務發現和負載均衡,內部/外部路由分離、persistent volume 的使用,部署節點守護程序,部署有狀態分散式系統,作業後台運行,部署資料庫,配置管理,憑證管理,滾動更新,自動縮放和包管理。
Kubernetes 架構
這個集群管理器的基本設計策略之一就是,無需更改應用程序代碼,就能部署在虛擬機上運行的現有應用程序。另外,任何運行在虛擬機上的應用程序都可以通過容器化組件在 Kubernetes 上實現部署。這是通過容器分組、容器編排、覆蓋網路、基於第 4 層虛擬 IP、服務發現、支持守護程序運行、部署有狀態應用程序組件、以及擴展容器編排系統這些核心功能實現的。
另外,Kubernetes 可以提供一組可動態擴展的主機,可以應用容器運行 workload,並使用一組稱為 master 的管理主機來提供管理整個容器基礎架構的 API。這些 workload 包括長期運行服務 ,批處理作業和容器主機的守護程序。為了提供容器到容器的路由,所有容器主機都用覆蓋網路連接在一起。部署在 Kubernetes 上的應用程序在集群網路中是動態可見的,並可通過傳統負載均衡器向外部網路暴露。集群管理器的狀態存儲在一個高度分布的 key/value 存儲(etcd)中,該存儲在 master 上運行。Kubernetes 調度程序可以確保每個應用程序組件都已進行健康檢查,可提供高可用。當副本的數量設置大於 1 時,多個主機中的實例都會被調度。如果其中一個主機不可用,那麼運行在該主機上的所有容器,都可能被任一主機調度。
Kubernetes 的迷人功能之一就是提供兩級自動縮放。首先,可以使用一個名為 Horizontal Pod Autoscaler 的資源來自動調整容器,它可以監視資源消耗並對所需容器數量進行相應地調整。其次,它可以通過添加和刪除主機的方式,根據資源需求擴展容器集群。此外,通過引入集群聯合功能,Horizontal Pod Autoscaler 甚至可以使用單個 API 端點跨多個數據中心管理 Kubernetes 集群。
這只是 Kubernetes 「開箱即用」眾多功能的冰山一角。接下來,我將介紹 Kubernetes 的核心功能,並詳解應該如何設計並部署你的軟體應用程序。
應用程序部署模型
上圖是 Kubernetes 上高級應用程序部署模型。它使用 ReplicaSet 來編排容器。我們可以將 ReplicaSet 視為基於 YAML 或基於 JSON 的元數據文件,該文件可以定義容器鏡像、埠、副本數量、激活狀況檢查、活動狀況檢查、環境變數、數據掛載和創建並管理容器需要的安全規則。
容器在 Kubernetes 上以組的形式創建,被稱為 Pod,它是 Kubernetes 的一個元數據定義或資源。每個 Pod 都可以通過 Linux namespace,cgroup 和其他內核功能在容器之間共享文件系統、網路介面以及操作系統用戶。而 ReplicaSets 可以由一個叫做 Deployment 的高級資源進行管理,Deployment 提供用於滾動更新和處理其回滾的功能。
通過執行下面這樣一條簡單的 CLI 命令,就可以在 Kubernetes 上部署容器化的應用程序了。
一旦執行上述 CLI 命令,給定容器鏡像將創建一個部署定義,一個副本集和一個 pod; 另外使用應用程序名稱將添加一個 selector label。由此創建的每個 pod 將有兩個容器,一個用於給定的應用程序組件,另一個叫做 Pause 用於連接網路介面。
服務發現與負載均衡
Kubernetes 的主要功能之一,是使用 SkyDNS 和 4 層虛擬 IP 路由系統,提供服務發現和內部路由模型。這些功能為要求使用 service 的應用程序提供了內部路由。通過副本集創建的一組 Pod 可以使用集群網路內的 service 進行負載均衡。service 用選擇器標籤(selector labels)連接到 Pod。每個 service 會分到一個唯一的 IP 地址,和一個由其名稱派生的主機名,並以循環的方式在 Pod 中路由請求。該 service 甚至還能為需要會話關聯的應用程序提供基於 IP 的路由機制。一個 service 可以定義一個埠集合,為給定 service 定義的屬性將以相同的方式應用於所有埠。因此,在一個場景中,只需要一個給定埠的會話關聯,在該埠中所有其他埠都需要使用基於輪詢的路由,這可能要用到多個 service。
Service 如何在內部工作?
Kubernetes service 使用一個名為 kube-proxy 的組件來實現。每個節點中都有一個 kube-proxy 實例。Kube-proxy 有三種代理模式:Userspace,iptables 和 IPVS。當前的默認模式是 iptables。
在第一種代理模式下,userspace,kube-proxy 本身充當代理伺服器,由 iptables 規則接受的請求委託給後端 Pod。在這種模式下,kube-proxy 將在 userspace 中運行,並增加一個跳轉到信息流。在 iptables 中,kube-proxy 創建一組 iptables 規則,用於將來自客戶端的傳入請求直接轉發到網路層上的後端 Pod 埠,而無需在中間添加額外的跳轉。這個代理模式比第一種模式快得多,因為它無需在中間添加額外代理伺服器,直接在 kernel space 中運行。
Kubernetes v1.8 版本增加了第三種代理模式,與第二種代理模式非常相似,它不用 iptables 規則而是使用基於 IPVS 的虛擬伺服器來路由請求。IPVS 是一種傳輸層負載均衡功能,可在基於 Netfilter 的 Linux kernel 中運行,並提供一組負載均衡演算法。通過 iptables 使用 IPVS 是因為使用 iptables 可以同步代理規則的性能開銷。當創建數千個服務時,與 IPVS 的幾毫秒相比,更新 iptables 規則需要相當長的時間。此外,IPVS 使用 hash table 來查找通過 iptables 進行順序掃描的代理規則。
內/外路由分離
Kubernetes service 可以通過兩種主要方式暴露於外部網路。第一種方法是通過暴露節點上的動態埠來使用節點埠,將流量轉發到服務埠。第二種方法是通過使用 ingress controller 配置負載均衡器, ingress controller 可以通過連接到相同的覆蓋網路將請求委託給 service。 Ingress controller 是一個後台進程,它可以運行在監聽 Kubernetes API 的容器中,根據給定的一組 ingress 動態地配置並重新載入給定的負載均衡器。Ingress 基於使用服務的 hostname 和 context paths 來定義路由規則。
一旦使用 kubectl run 命令將應用程序部署到 Kubernetes 上,它就可以通過負載均衡器暴露給外部網路,如下所示:上述命令將創建一個負載均衡器類型的 service,並將創建該 Pod 時生成的相同選擇器標籤(selector label )將其映射到 Pod。因此,根據 Kubernetes 集群的配置方式,基礎架構上的負載均衡器服務將通過 service 或直接為給定的 Pod 路由請求而創建。
Persistent Volumes 的使用
需要在文件系統上保留數據的應用程序可以使用 volume 將存儲設備掛載到臨時容器中,這與虛擬機使用 volumes 的方式類似。Kubernetes 通過引入稱為 persistent volume claims(PVC)的中間資源,將物理存儲設備與容器進行鬆散耦合。PVC 定義了磁碟大小,磁碟類型(ReadWriteOnce,ReadOnlyMany,ReadWriteMany)並且可以將存儲設備動態地連接到某個 Pod 定義的 volume 上 。綁定過程既可以使用 PV 靜態處理,也可以動態地使用 persistent storage provider 。在這兩種方法中,volume 將一對一地連接到一個 PV,這取決於配置,因為即使該 Pod 被終止,數據也將被保留。根據所使用的磁碟類型,多個 Pod 將能夠連接到相同的磁碟並進行讀取或寫入。
支持 ReadWriteOnce 的磁碟只能連接到一個 Pod,並且不能同時在多個 Pod 中共享。但是,支持 ReadOnlyMany 的磁碟可以在只讀模式下同時在多個 Pod 中共享。顧名思義,具有ReadWriteMany 支持的磁碟可以連接到多個 Pod,以讀寫模式共享數據。Kubernetes 提供了一系列 volume plugins,用於支持 AWS EBS,GCE 持久性磁碟,Azure File,Azure Disk 以及其他眾所周知的存儲系統(如 NFS,Glusterfs,Cinder 等)等公有雲平台上提供的存儲服務。
在節點部署守護程序
Kubernetes 提供了一個名為 DaemonSets 的資源,用於在每個 Kubernetes 節點中將守護進程的副本作為後台進程運行。DaemonSet 的一些用例如下所示:
- 集群存儲守護程序,如 glusterd,ceph 要部署在每個節點上以提供持久性存儲;
- 節點監視守護進程,如 Prometheus 節點可導出程序,將在每個節點上運行,以監視容器主機;
- 日誌收集守護程序,如 fluentd 或 logstash ,在每個節點上運行以收集容器和 Kubernetes 組件日誌;
- Ingress controller pod 將在一組節點上運行,以提供外部路由。
部署有狀態分散式系統
容器化應用程序最困難的任務之一,就是設計有狀態分散式組件的部署體系結構。由於無狀態組件可能沒有預定義的啟動順序、集群要求、點對點 TCP 連接、唯一的網路標識符、正常的啟動和終止要求等,因此可以很容易地進行容器化。諸如資料庫,大數據分析系統,分散式 key/value 存儲和 message brokers 可能有複雜的分散式體系結構,都可能用到上述功能。Kubernetes 引入了 StatefulSets 資源來支持這種複雜的需求。
StatefulSets 類似於 ReplicaSets,但是它可以處理 Pod 的啟動順序,為保留每個 Pod 的狀態設置唯一標識,同時具有以下功能:
- Stable,唯一的網路標識符
- Stable,持久化的存儲
- Ordered,優雅的部署和縮放
- Ordered,優雅的刪除和終止
- Ordered,自動滾動更新Stable 指的是將網路標識符和持久存儲跨 Pod 重新調度。如上圖所示,使用 headless services 提供唯一的網路標識符。Kubernetes 提供了以分散式方式部署 Cassandra 和 Zookeeper 的 StatefulSets 示例。
運行後台作業
除了 ReplicaSets 和 StatefulSets 之外,Kubernetes 還提供了兩個額外的控制器,用於在後台運行稱為 Jobs 和 CronJobs 的 workload 。 Job 和 CronJobs 之間的區別在於,Job 執行一次並終止,而 CronJobs 與標準 Linux cron job 類似,根據給定時間間隔周期性執行。
部署資料庫
由於大家對集群化、點對點連接、主從複製、分區、管理備份等都有要求,因此在容器平台上部署資料庫以供生產使用比部署應用程序要困難的多。如前所述,StatefulSets 專門應付這種複雜要求,而在 Kubernetes 上運行 PostgreSQL 和 MongoDB 集群有幾個相應選項。
YouTube 的資料庫集群系統 Vitess 現在是一個 CNCF 項目,對於在 Kubernetes 上大規模運行 MySQL 來說,它是一個很好的選擇。值得注意的是,這些選項還處於非常早期的階段,如果現有的生產級資料庫系統可用於給定的基礎架構,例如 AWS 上的 RDS,GCP 上的 Cloud SQL 或內部部署資料庫集群考慮到安裝複雜性和維護開銷,選擇其中一種選擇可能會更好。
配置管理
容器通常使用環境變數來對其運行時配置進行參數化。但是,典型的企業應用程序使用大量的配置文件來提供給定部署所需的靜態配置。Kubernetes 提供了一種稱為 ConfigMaps 的簡單資源來管理此類配置文件的方法,無需將它們捆綁到容器鏡像中。只需要使用以下 CLI 命令可以使用目錄,文件或 literal values 創建 ConfigMaps:
一旦創建 ConfigMap 後,可以使用 volume mount 將其掛載到一個容器。藉助這種鬆散耦合的體系結構,只需更新相關的 ConfigMap 並執行滾動更新程序就可以無縫地更新已運行系統的配置,我將在下一節中對其進行解釋。注意 ConfigMaps 目前不支持嵌套文件夾; 因此,如果應用程序的嵌套目錄結構中有可用的配置文件,則需要為每個目錄級別創建一個 ConfigMap。
憑證管理
與 ConfigMaps 類似,Kubernetes 提供了另一個好功能,稱為 Secrets,用於管理敏感信息,如密碼,OAuth 令牌和 ssh 密鑰。否則,在已經運行的系統上更新該信息可能需要重建容器鏡像。
使用以下方法可以創建一個 Secret 來管理基本身份驗證憑據:一旦創建了 secret,就可以使用環境變數或 volume mounts 通過 Pod 進行讀取。當然,其他類型的敏感信息也可以使用相同的方法注入到 Pod 中。
滾動更新
上面的動畫說明了如何通過使用藍/綠部署方法為已經運行的應用程序進行滾動更新,而不會導致系統停機。這是 Kubernetes 的另一個非常棒的功能,應用程序可以無縫地推出安全更新和向後兼容的更改。如果更改不向後兼容,則可能需要使用單獨的部署定義執行手動藍/綠部署。
此方法允許使用簡單的 CLI 命令執行卷展欄更新容器鏡像:
一旦執行了 rollout,可以按照以下方式檢查 rollout 過程的狀態:
使用相同的 CLI 命令 kubectl set image deployment ,可以將更新回滾到以前的狀態。
自動縮放
Kubernetes 允許使用 ReplicaSets 或 Deployments 手動縮放 Pod。如上圖所示,可以通過向部署添加另一個名為 Horizontal Pod Autoscaler(HPA)的資源來擴展此功能,以根據實際資源使用情況動態縮放 Pod。HPA 將通過資源度量 API 監視每個 Pod 的資源使用情況,並通知部署相應地更改副本集的副本計數。Kubernetes 使用高級延遲和低級延遲來避免由於某些情況下頻繁資源使用波動而可能發生的波動。目前,HPA 僅支持基於 CPU 使用率的擴展。如果需要,還可以通過根據應用程序的性質自定義指標 API 插入自定義指標。
包管理
Kubernetes 社區啟動了一個單獨的項目來實施 Kubernetes 的管理器(Package Manager),名為 Helm。Kubernetes 資源(如 deployment,service,configmap,ingress 等)可以使用 chart 進行模板化和打包,在安裝時使用輸入參數對它們進行配置。更重要的是,它允許在使用依賴關係實現安裝包時重用現有圖表。
Helm 庫可以託管在公有和私有雲環境中,用於管理應用程序圖表。Helm 提供了一個 CLI,用於將來自給定 Helm repo 的應用程序安裝到選定的 Kubernetes 環境中。大家可以在 Github repo 和 central Helm server——Kubeapps Hub 找到這個眾所周知的軟體應用程序 Helm 圖表。
Kubernetes 結合 Google 大規模運行容器應用程序十年經驗。目前,它已經被最大的公有雲供應商和技術提供商所採用。在撰寫本文時,它正在被更多的軟體供應商和企業所接受。Kubernetes 在 2015 年開源並衍生出 Cloud Native Computing Foundation (CNCF),最近成為基金會旗下首個畢業的項目。CNCF 也開始整合容器生態系統以及其他與容器相關的項目,如 CNI,Containerd,Envoy ,Fluentd,gRPC,Jagger,Linkerd,Prometheus,rkt 和 Vitess。Kubernetes 之所以受到各大組織的歡迎和認可,其關鍵原因首先是它的完美設計,其次就是其開源的特性、與業界領袖的合作的熱情以及始終對創意和貢獻保持開放的態度。
原文鏈接:https://dzone.com/articles/a-beginners-guide-to-kubernetes
推薦閱讀:
※數人云架構師:微服務體系中的K8S&Mesos調度與服務發現
※Kubernetes 1.9發布:年度更新這些評論亮了!
※Kubernetes v1.7新特性解析-Secret加密存儲
※Heptio 發布 Contour 項目
TAG:Kubernetes | OpenStack | 容器 |