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

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)

分享創造快樂