歡迎光臨
每天分享高質量文章

Kubernetes新手快速入門指南

Kubernetes現已成為在私有雲,公共雲以及混合雲環境中大規模部署容器化應用程式的事實標準。業內最大的幾家公有雲平臺AWS,Google Cloud,Azure,IBM Cloud以及Oracle Cloud現已提供Kubernetes託管服務。幾年前,RedHat完全重寫了他們的Openshift實現以適配Kubernetes,並且和Kubernetes社群一起合作實現了下一代容器平臺。在Kubernetes變得受歡迎後不久,Mesosphere便將Kubernetes的主要功能(如容器分組,改寫網路,4層路由,secret管理等)整合到他們的容器平臺DC/OS中。DC/OS還將Kubernetes作為一個和Marathon相似的容器排程器整合進來。Pivotal最近推出了基於Kubernetes的Pivotal Container Service(PKS),用於在Pivotal Cloud Foundry上部署第三方服務,直到目前為止,還有很多其他組織和技術廠商處在一個加速適配它的階段。
Kubernetes專案創立於2014年,它的背後是擁有在谷歌執行生產工作負載超過十年經驗的谷歌內部容器叢集管理平臺Borg和Omega。在我看來,它讓使用者更加方便去適配一些新興的軟體架構樣式(如微服務,無伺服器功能,服務網格和事件驅動應用程式),並且為整個雲原生系統生態鋪平了道路。最重要的是,它的雲不相關性的設計使得容器化的應用程式無需經過任何修改便可以跑在任何平臺上。如今,大型企業的部署可以使用Kubernetes的生態系統,而從長遠來看,任何中小型企業也可以透過使用Kubernetes節省大量的基礎設施和維護成本。在這篇文章裡,我將會介紹到Kubernetes整體上的架構,其應用程式的部署模型,服務發現和負載平衡,內部/外部路由分離,持久捲的使用,在節點上部署守護行程,部署有狀態的分散式系統,執行後臺作業,部署資料庫,配置管理,憑據管理,滾動更新,自動伸縮以及包管理。


Kubernetes架構

這個接近完美的叢集管理器採取的基本設計決策之一是能夠部署在虛擬機器上執行的現有應用程式,而無需對應用程式程式碼做出任何修改。從整體上來說,任何在虛擬機器上執行的應用程式都可以透過簡單地容器化其元件的方式部署在Kubernetes上。這是透過其核心功能實現的:容器分組,容器編排,改寫網路,基於4層虛擬IP路由系統的容器間路由,服務發現,對執行守護程式的支援,部署有狀態的應用程式元件,而且最重要的是,它還能夠透過擴充套件容器編排器以支援複雜的編排要求。
從一個相對宏觀的層面來講,Kubernetes提供了一組動態可擴充套件的主機,用於承載執行工作負載的容器,並使用一組稱為master的管理主機,提供用於管理整個容器基礎設施的API。工作負載可能包括長期執行的服務,批處理作業和執行在特定容器主機上的守護程式。所有容器主機使用改寫網路連線在一起以提供容器間的路由。部署在Kubernetes上的應用程式在叢集網路是可以動態發現的,而且可以透過傳統的負載均衡器暴露到外部網路。叢集管理器的狀態存放在高度分散式組織的k/v儲存裡,該儲存執行在master實體上。
Kubernetes scheduler將始終確保每個應用程式元件都是經過健康檢查的,提供高可用的服務,當副本數量設定為多個時,每個實體在多個主機上進行排程,並且如果其中一個主機變為不可用時,所有在該臺主機上執行的容器都會被排程到剩餘的其他主機。Kubernetes提供的一項迷人功能是兩級自動擴縮。首先,透過使用一個叫做Horizontal Pod Autoscaler(Pod自動水平擴縮器)的資源,它可以為使用者提供容器的自動擴縮功能,該資源將會監視資源的消耗並相應地擴充套件所需的容器數量。其次,它可以根據資源需求新增或刪除主機來擴充套件容器叢集本身。 此外,隨著叢集聯盟(cluster federation)功能的引入,它甚至可以使用單個API端點管理一組Kubernetes叢集,這些叢集甚至可能跨越多個資料中心。
以上只是Kubernetes所提供的開箱即用的功能的概覽。在接下來的幾節裡,本人將為你介紹Kubernetes的核心功能,並說明使用者該如何設計自己的軟體應用,以便能夠立即部署在上面。

應用部署模型

上圖展示的是Kubernetes宏觀層面的應用程式部署模型。它使用一個叫做ReplicaSet的資源來編排容器。我們不妨將ReplicaSet視為基於YAML或基於JSON的一個元資料檔案,該檔案裡定義了容器映象,埠,副本數,啟用執行狀況檢查(health check),存活狀況檢查(liveness health check),環境變數,掛載捲以及建立和管理容器所需的一些安全規則。在Kubernetes上,容器總是以所謂Pods的形式成組建立,它是Kubernetes的一個元資料定義或者說是一個資源。每個pod允許在使用了Linux namespace,cgroup和其他核心功能的容器之間共享檔案系統,網路介面和作業系統使用者。ReplicaSet可以由另外一個名為Deployments的高階資源管理,它被設計用於提供滾動更新和處理回滾等功能。
透過執行下麵這樣一條簡單的CLI命令,使用者便可以透過定義一個deployment,在Kubernetes上部署一個容器化的應用程式:

kubectl run <application-name> --image=<container-image> --port=<port-no>
執行上述CLI命令後,它將使用給定的容器映象建立一個Deployment宣告,一個副本集以及一個採用了指定容器映象的Pod;新增一個應用名的選擇器標簽。根據當前的設計,由此建立的每個pod將會擁有兩個容器,一個用於指定的應用程式元件,另外一個即所謂的pause容器,用於連線網路介面。
服務發現 & 負載均衡

Kubernetes的一個關鍵特性便是由SkyDNS和4層虛擬IP路由系統提供的服務發現和內部路由模型。這些功能可以為面向service的應用請求提供內部路由。可以使用叢集網路裡的service對透過副本集建立的一組pod提供負載平衡。service使用選擇器標簽連線到pod。每個service都將會分配一個唯一的IP地址,一個由它的名稱派生出的主機名,並且將會以round robin的方式路由pods的請求。這些service甚至可以為可能需要支援會話親和性的應用程式提供基於IP雜湊的路由機制。service可以指定一組埠,而針對指定的service定義的一系列屬性將會以相同的形式同樣應用到所有埠上。因此,如果只是某個給定埠需要支援會話親和性,而所有的其他埠只需要round robin的方式路由的情況下,可能需要用到多個service。
service內部工作原理
Kubernetes service背後是透過一個叫做kube-proxy的元件實現。kube-proxy實體執行在每個節點上,並提供了三種代理樣式:userspace,iptables和IPVS。目前的預設值是iptables。
在第一種代理樣式下,userspace,kube-proxy本身將充當代理伺服器的角色,並且將被一條iptable規則接受的請求代理到後端pod。在這種樣式下,kube-proxy將在使用者空間中執行,並且將會在訊息流上額外增加一跳(hop)。在iptables中,kube-proxy將建立一個iptable規則集合,用於將來自客戶端的入口請求在網路層面直接轉發到後端pod的埠上,而不會在中間額外增加一跳。這種代理樣式比第一種樣式快得多,因為它是在核心空間中操作而不是在中間增加一臺額外的代理伺服器。
第三種代理樣式是在Kubernetes v1.8中新增的,它和第二種代理樣式非常相似,該樣式使用的是基於IPVS的虛擬伺服器來路由請求,而無需用到iptable規則。IPVS是一個傳輸層的負載均衡功能,可以在基於Netfilter的Linux核心中使用,並且提供了一組負載均衡演演算法。在iptables上使用IPVS的主要原因是在使用iptables時同步代理規則帶來的效能開銷。當建立數千個service時,更新iptable規則需要相當長的時間,相比之下,使用IPVS只需幾毫秒。此外,IPVS使用雜湊表線性的掃描iptables來查詢代理規則。有關介紹IPVS代理樣式的更多資訊,請參閱華為在KubeCon 2017上的“Scaling Kubernetes to Support 50,000 Services”[1]簡報。


內外路由分離

Kubernetes service可以透過兩種主流方式暴露給外部網路。第一種是使用節點埠(node port),透過暴露節點上的動態埠,這些埠會將流量轉發到service埠。第二種是使用一個ingress controller配置的負載均衡器,它將會連線到同一個改寫網路並將請求代理給service。ingress controller是一個後臺行程,它可以跑在容器裡,該容器將會監聽Kubernetes API,根據指定的一組ingress動態配置並重新載入給定的負載均衡器。一個ingress定義了一組基於service的主機名及背景關係路徑的路由規則。
一旦透過執行kubectl run命令,在Kubernetes上跑起來應用後,我們可以透過一個負載均衡器將其暴露給外部網路,如下所示:

kubectl expose deployment name> --type=LoadBalancer --name=name>
上述命令將建立一個負載均衡器型別的service,並且使用在POD建立之初建立的選擇器標簽對映到相同的一組pod。這樣一來,根據Kubernetes叢集不同的配置方式,一個負載均衡器型別的service將會在底層基礎設施上創建出來,透過service或直接路由的形式將請求轉發到指定的一組pod。
持久捲用法

需要在檔案系統上持久化儲存資料的應用程式可以使用捲將儲存裝置掛載到臨時容器,這和虛擬機器的使用方式類似。Kubernetes巧妙地重新設計了這一概念,透過引入一個所謂的持久捲宣告(PVC)的中間資源,在物理儲存裝置和容器之間做瞭解耦。一個PVC定義了磁碟大小,磁碟型別(ReadWriteOnce,ReadOnlyMany,ReadWriteMany),並將儲存裝置動態連結到在pod中定義了的捲。該系結過程可以使用PV這樣一個靜態的形式,也可以使用一個持久化儲存的provider動態實現。在這兩種方法裡,捲將一對一地連結到PV,並且取決於其配置,給定的資料即便pod被終止也將會被保留。根據使用的磁碟型別,多個pod將能夠連線到同一磁碟併進行讀/寫。
支援ReadWriteOnce的磁碟將只能連線到單個pod,並且無法同時在多個pod之間共享。但是,支援ReadOnlyMany的磁碟將能夠在只讀樣式下同時在多個pod之間共享。相反地,顧名思義,支援ReadWriteMany的磁碟可以連線到多個pod,以便在讀寫樣式下共享資料。 Kubernetes提供了一系列的捲外掛,用於支援公有雲平臺上可用的儲存服務,例如AWS EBS,GCE Peristent Disk,Azure File,Azure Disk和許多其他眾所周知的儲存系統,如NFS,Glusterfs,Cinder等。


在節點上部署守護程式

Kubernetes提供了一個名為DaemonSets的資源,用於在每個Kubernetes節點上以守護行程的形式執行pod的副本。DaemonSets的一些用例如下:
  • 需要部署到每個節點上提供持久化儲存的叢集儲存守護程式(如glusterd,ceph)。

  • 需要在每個節點上執行的監控容器宿主機的節點監控守護程式,例如Prometheus Node Exporter。

  • 需要在每個節點上執行的,用作採集容器及Kubernetes元件日誌的日誌採集守護程式,例如fluentd或是logstash。

  • 需要在一組節點上執行的提供外部路由的ingress controll pod。


部署有狀態的分散式系統

容器化應用程式最艱巨的任務之一莫過於設計有狀態分散式元件部署架構的流程。無狀態元件可以很容易地進行容器化,因為它們可能沒有預定的啟動順序,叢集要求,點對點的TCP連線,唯一的網路識別符號,優雅的啟動和終止需求等。像資料庫,大資料分析系統,分散式k/v儲存以及訊息代理這樣的系統,可能擁有需要支援上述這些功能的複雜分散式架構。Kubernetes引入了StatefulSets資源來解決這些複雜的需求。
從整體上來說,StatefulSets類似於ReplicaSet,除了提供處理pod的啟動順序的能力,唯一地標識每個pod以保留其狀態之外,它還同時提供以下特性:
  • 穩定,唯一的網路識別符號。

  • 穩定,持久化的儲存。

  • 有序,優雅的部署和擴容。

  • 有序,優雅的刪除和終止。

  • 有序,自動地滾動更新。

這裡面的“穩定”指的是在跨pod重新排程時它將會保留網路識別符號和持久化儲存。如上圖所示,唯一的網路識別符號可以透過使用headless service提供。Kubernetes提供了一些StatefulSets的示例,包括以分散式的形式部署Cassandra以及Zookeeper。


執行後臺任務

除了ReplicaSet和StatefulSets之外,Kubernetes還提供了兩個額外的控制器,用於在後臺執行稱為Jobs和CronJobs的工作負載。Jobs和CronJobs之間的區別在於Jobs執行一次即終止,而CronJobs會按照與標準Linux cron作業類似的給定時間間隔定期地執行。
部署資料庫

由於存在對叢集,點對點連線,複製同步,灰度,備份管理等需求,在容器平臺上部署資料庫用於生產環境將會比部署應用程式稍微困難一些。正如之前所提到的那樣,Statefulsets專門為解決此類複雜需求而設計,而如今已經有一些在Kubernetes上執行PostgreSQL和MongoDB叢集的方案。YouTube的資料庫集群系統Vitess現如今已經是一個CNCF專案,對於在Kubernetes上大規模灰度執行MySQL是一個很好的選擇。說是如此,我們最好註意一下,這些方案目前仍然處於非常早期的開發階段,而如果現有的生產級別資料庫系統,仍然可用於給定的基礎架構,例如AWS上的RDS,GCP上的Cloud SQL,或是內部按需部署的資料庫叢集,考慮到安裝的複雜性以及維護成本,選擇這其中的一種方案可能更合適些。


配置管理

容器通常使用環境變數來引數化它們的執行時配置。但是,常見的企業應用程式往往使用大量的配置檔案為一個指定的部署提供所需的靜態配置。Kubernetes則提供了一個絕妙的辦法,使用名為ConfigMaps的一種簡單資源來管理此類配置檔案,而無需將它們打包到容器映象裡。可以透過執行以下CLI命令,使用目錄,檔案或文字值建立ConfigMaps:

kubectl create configmap <map-name> <data-source>
# map-name: name of the config map
# data-source: directory, file or literal value
建立ConfigMap後,可以透過捲的形式將其掛載到pod。透過這種松耦合的架構,一個已經在執行的系統的配置可以透過更新相關的ConfigMaps的方式無縫更新,而其滾動更新的執行流程這塊我將在下一節中詳細說明。值得一提的是,ConfigMaps現在不支援巢狀的目錄結構;因此,如果應用程式的巢狀目錄結構中存放有配置檔案的話,則需要為每一個目錄層級建立一個ConfigMap。
憑證管理

與ConfigMaps類似,Kubernetes提供了另一種名為Secrets的寶貴資源,用於管理密碼,OAuth令牌和ssh金鑰等敏感資訊。否則,在已執行的系統上更新該資訊可能需要重建容器映象。
可以使用以下方式建立用於管理基本身份驗證憑據的金鑰:

# write credentials to two files
$ echo -n 'admin' > ./username.txt
$ echo -n '1f2d1e2e67df' > ./password.txt
# create a secret
$ kubectl create secret generic app-credentials --from-file=./username.txt --from-file=./password.txt
建立secret後,pod可以使用環境變數或掛載捲的方式來讀取它。類似地,可以使用相同的方法將任何其他型別的敏感資訊註入到pod中。
滾動更新

上面這個動畫描述瞭如何使用藍/綠部署的方法為已經執行的應用程式釋出應用程式更新,而無需任何宕機成本。這是Kubernetes提供的另一個重磅功能,它允許應用程式不費吹灰之力即可無縫地釋出安全更新和向後相容的變更。如果變更不向後相容,則可能需要使用單獨的部署定義手動執行藍/綠部署。
這一方案允許透過一條簡單的CLI命令,發起一個部署以更新容器映象:
$ kubectl set image deployment/name> <container-name>=<container-image-name>:<new-version>

一旦發起部署,可以透過如下方式檢查部署進度的狀態:
$ kubectl rollout status deployment/Waiting for rollout to finish: 2 out of 3 new replicas have been updated...deployment "" successfully rolled out

使用相同的CLI命令kubectl set image deployment,可以讓部署更新回滾到之前的狀態。
自動擴縮

Kubernetes允許使用ReplicaSet或Deployments手動調整pod數量。這可以透過執行如下CLI命令來實現:

kubectl scale --replicas=<desired-instance-count> deployment/<application-name>
如上圖所示,可以透過向Deployment新增另一個名為Horizontal Pod Autoscaler(HPA)的資源來擴充套件此功能,以便根據實際資源使用情況動態擴縮容器。HPA將透過資源指標的API監視每個pod的資源使用情況,並通知Deployment相應地更改ReplicaSet的副本數。Kubernetes使用高檔延遲(upscale delay)和縮減延遲(downscale delay)來避免某些情況下頻繁的資源使用波動而可能導致的顛簸。目前,HPA僅支援基於CPU的使用情況進行擴充套件。如果有必要的話,還可以透過Custom Metrics API加入自定義指標,這具體視應用程式的自然屬性而定。
包管理

Kubernetes社群發起了一個單獨的專案,為Kubernetes實現了一個稱為Helm的包管理器。它允許使用者使用一個名為Chart的資源模板化並打包Kubernetes資源,比如Deployment,Service,ConfigMap,Ingress等,並允許在安裝時使用輸入引數配置它們。更重要的是,它允許在使用依賴項實現包的安裝時復用現有圖表。Helm儲存庫可以託管在公有雲或私有雲環境中,用於管理應用程式的Chart。Helm提供了一個CLI,用於從給定的Helm儲存庫裡安裝應用程式到指定的Kubernetes環境中。
一些眾所周知的軟體應用程式的各種穩定Helm圖表可以在它的Github儲存庫[2]中找到,也可以在中心化的Helm伺服器中找到:Kubeapps Hub[3]。


小結

Kubernetes的設計源自於Google內部大規模執行容器化應用程式十多年來積累的經驗。它已經被一些頂級的公有雲廠商和技術廠商採用,並且在撰寫本文時正在被更多的軟體廠商和企業所接受。 它甚至促成了2015年雲原生計算基金會(CNCF)的成立,並且是第一個在CNCF下畢業的專案,隨後開始了同其他與容器相關的專案一起精簡容器生態系統的道路,如CNI,Containerd,Envoy,Fluentd,gRPC,Jagger,Linkerd,Prometheus,rkt和Vitess。 Kubernetes受歡迎並得到如此認可的關鍵原因可能源自其完美的設計,與行業領導者的合作,其開源屬性,以及始終對創意和貢獻持開放態度的精神。
相關連結:
  1. https://docs.google.com/presentation/d/1BaIAywY2qqeHtyGZtlyAp89JIZs59MZLKcFLxKE6LyM/edit#slide=id.p3

  2. https://github.com/kubernetes/charts/tree/master/stable

  3. https://hub.kubeapps.com/

原文連結:https://dzone.com/articles/a-beginners-guide-to-kubernetes

Kubernetes專案實戰訓練營

Kubernetes專案實戰訓練將於2018年8月17日在深圳開課,3天時間帶你係統掌握Kubernetes本次培訓包括:Docker介紹、Docker映象、網路、儲存、容器安全;Kubernetes架構、設計理念、常用物件、網路、儲存、網路隔離、服務發現與負載均衡;Kubernetes核心元件、Pod、外掛、微服務、雲原生、Kubernetes Operator、叢集災備、Helm等,點選下方圖片檢視詳情。

贊(0)

分享創造快樂