天天看點

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

點選這裡檢視第一章:Kubernetes系統基礎 點選這裡檢視第三章:資源管理基礎

第2章:Kubernetes快速入門

Kubernetes叢集将所有節點上的資源都整合到一個大的虛拟資源池裡,以代替一個個單獨的伺服器,而後開放諸如CPU、記憶體和I/O這些基本資源用于運作其基本單元—Pod資源對象。Pod的容器中運作着隔離的任務單元,它們以Pod為原子機關,并根據其資源需求從虛拟資源池中為其動态配置設定資源。若可以将整個叢集類比為一台傳統的伺服器,那麼Kubernetes(Master)就好比是作業系統核心,其主要職責在于抽象資源并排程任務,而Pod資源對象就是那些運作于使用者空間中的程序。于是,傳統意義上的向單節點或叢集直接部署、配置應用的模型日漸式微,取而代之的是向Kubernetes的API Server送出運作Pod對象。

API Server是負責接收并響應用戶端送出任務的接口,使用者可使用諸如CLI工具(如kubectl)、UI工具(如Dashboard)或程式代碼(用戶端開發庫)發起請求,其中,kubectl是最為常用的互動式指令行工具。快速了解Kubernetes的辦法之一就是部署一個測試叢集,并嘗試測試使用它的各項基本功能。本章在簡單介紹核心資源對象後将嘗試使用kubectl建立Deployment和Service資源部署并暴露一個Web應用,以便讀者快速了解如何在Kubernetes系統上運作應用程式的核心任務。

2.1 Kubernetes的核心對象

API Server提供了RESTful風格的程式設計接口,其管理的資源是Kubernetes API中的端點,用于存儲某種API對象的集合,例如,内置Pod資源是包含了所有Pod對象的集合。資源對象是用于表現叢集狀态的實體,常用于描述應于哪個節點進行容器化應用、需要為其配置什麼資源以及應用程式的管理政策等,例如,重新開機、更新及容錯機制。另外,一個對象也是一種“意向記錄”—一旦建立,Kubernetes就需要一直確定對象始終存在。Pod、Deployment和Service等都是最常用的核心對象。

2.1.1 Pod資源對象

Pod資源對象是一種集合了一到多個應用容器、存儲資源、專用IP及支撐容器運作的其他選項的邏輯元件,如圖2-1所示。換言之,Pod代表着Kubernetes的部署單元及原子運作單元,即一個應用程式的單一運作執行個體,它通常由共享資源且關系緊密的一個或多個應用容器組成。

Kubernetes的網絡模型要求其各Pod對象的IP位址位于同一網絡平面内(同一IP網段),各Pod之間可使用其IP位址直接進行通信,無論它們運作于叢集内的哪個工作節點之上,這些Pod對象都像是運作于同一區域網路中的多個主機。

讀者可以将每個Pod對象想象成一個邏輯主機,它類似于現實世界中的實體主機或VM(Virtual Machine),運作于同一個Pod對象中的多個程序也類似于實體機或VM上獨立運作的程序。不過,Pod對象中的各程序均運作于彼此隔離的容器中,并于各容器間共享兩種關鍵資源:網絡和存儲卷。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門
  • 網絡(networking):每個Pod對象都會被配置設定一個叢集内專用的IP位址,也稱為Pod IP,同一Pod内部的所有容器共享Pod對象的Network和UTS名稱空間,其中包括主機名、IP位址和端口等。是以,這些容器間的通信可以基于本地回環接口lo進行,而與Pod外的其他元件的通信則需要使用Service資源對象的ClusterIP及其相應的端口完成。
  • 存儲卷(volume):使用者可以為Pod對象配置一組“存儲卷”資源,這些資源可以共享給其内部的所有容器使用,進而完成容器間資料的共享。存儲卷還可以確定在容器終止後被重新開機,甚至是被删除後也能確定資料不會丢失,進而保證了生命周期内的Pod對象資料的持久化存儲。

    一個Pod對象代表某個應用程式的一個特定執行個體,如果需要擴充應用程式,則意味着為此應用程式同時建立多個Pod執行個體,每個執行個體均代表應用程式的一個運作的“副本”(replica)。這些副本化的Pod對象的建立和管理通常由另一組稱之為“控制器”(Controller)的對象實作,例如,Deployment控制器對象。

建立Pod時,還可以使用Pod Preset對象為Pod注入特定的資訊,如Conf?igMap、Secret、存儲卷、卷挂載和環境變量等。有了Pod Preset對象,Pod模闆的建立者就無須為每個模闆顯式提供所有資訊,是以,也就無須事先了解需要配置的每個應用的細節即可完成模闆定義。這些内容将在後面的章節中予以介紹。

基于期望的目标狀态和各節點的資源可用性,Master會将Pod對象排程至某標明的工作節點運作,工作節點于指向的鏡像倉庫(image registry)下載下傳鏡像,并于本地的容器運作時環境中啟動容器。Master會将整個叢集的狀态儲存于etcd中,并通過API Server共享給叢集的各元件及用戶端。

2.1.2 Controller

Kubernetes叢集的設計中,Pod是有生命周期的對象。使用者通過手工建立或由Controller(控制器)直接建立的Pod對象會被“排程器”(Scheduler)排程至叢集中的某工作節點運作,待到容器應用程序運作結束之後正常終止,随後就會被删除。另外,節點資源耗盡或故障也會導緻Pod對象被回收。

但Pod對象本身并不具有“自愈”功能,若是因為工作節點甚至是排程器自身導緻了運作失敗,那麼它将會被删除;同樣,資源耗盡或節點故障導緻的回收操作也會删除相關的Pod對象。在設計上,Kubernetes使用“控制器”實作對一次性的(用後即棄)Pod對象的管理操作,例如,要確定部署的應用程式的Pod副本數量嚴格反映使用者期望的數目,以及基于Pod模闆來重建Pod對象等,進而實作Pod對象的擴縮容、滾動更新和自愈能力等。例如,某節點發生故障時,相關的控制器會将此節點上運作的Pod對象重新排程到其他節點進行重建。

控制器本身也是一種資源類型,它有着多種實作,其中與工作負載相關的實作如Replication Controller、Deployment、StatefulSet、DaemonSet、DaemonSet和Jobs等,也可統稱它們為Pod控制器。如圖2-2中的Deployment就是這類控制器的代表實作,是目前最常用的管理無狀态應用的Pod控制器。

Pod控制器的定義通常由期望的副本數量、Pod模闆和标簽選擇器(Label Selector)組成。Pod控制器會根據标簽選擇器對Pod對象的标簽進行比對檢查,所有滿足選擇條件的Pod對象都将受控于目前控制器并計入其副本總數,并確定此數目能夠精确反映期望的副本數。

需要注意的是,在實際的應用場景中,在接收到的請求流量負載顯著低于或接近于已有Pod副本的整體承載能力時,使用者需要手動修改Pod控制器中的期望副本數量以實作應用規模的擴容或縮容。不過,若叢集中部署了HeapSter或Prometheus一類的資源名額監控附件時,使用者還可以使用“HorizontalPodAutoscaler”(HPA)計算出合适的Pod副本數量,并自動修改Pod控制器中期望的副本數以實作應用規模的動态伸縮,提高叢集資源使用率,如圖2-3所示。

Kubernetes叢集中的每個節點都運作着cAdvisor以收集容器及節點的CPU、記憶體及磁盤資源的使用率名額資料,這些統計資料由Heapster聚合後可通過API Server通路。HorizontalPodAutoscaler基于這些統計資料監控容器健康狀态并做出擴充決策。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

   

      

圖2-2 Replication

Controller  

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

  

圖2-3 Horizontal Pod Autoscaler

2.1.3 Service

盡管Pod對象可以擁有IP位址,但此位址無法確定在Pod對象重新開機或被重建後保持不變,這會為叢集中的Pod應用間依賴關系的維護帶來麻煩:前端Pod應用(依賴方)無法基于固定位址持續跟蹤後端Pod應用(被依賴方)。于是,Service資源被用于在被通路的Pod對象中添加一個有着固定IP位址的中間層,用戶端向此位址發起通路請求後由相關的Service資源排程并代理至後端的Pod對象。

換言之,Service是“微服務”的一種實作,事實上它是一種抽象:通過規則定義出由多個Pod對象組合而成的邏輯集合,并附帶通路這組Pod對象的政策。Service對象挑選、關聯Pod對象的方式同Pod控制器一樣,都是要基于Label Selector進行定義,其示意圖如圖2-4所示。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-4 Service對象功能示意圖

Service IP是一種虛拟IP,也稱為Cluster IP,它專用于叢集内通信,通常使用專用的位址段,如“10.96.0.0/12”網絡,各Service對象的IP位址在此範圍内由系統動态配置設定。

叢集内的Pod對象可直接請求此類的Cluster IP,例如,圖2-4中來自pod client的通路請求即可以Service的Cluster IP作為目标位址,但叢集網絡屬于私有網絡位址,它們僅在叢集内部可達。将叢集外部的通路流量引入叢集内部的常用方法是通過節點網絡進行,實作方法是通過工作節點的IP位址和某端口(NodePort)接入請求并将其代理至相應的Service對象的Cluster IP上的服務端口,而後由Service對象将請求代理至後端的Pod對象的Pod IP及應用程式監聽的端口。是以,諸如圖2-4中的External Clients這種來自叢集外部的用戶端無法直接請求此Service提供的服務,而是需要事先經由某一個工作節點(如Node Y)的IP位址進行,這類請求需要兩次轉發才能到達目标Pod對象,是以在通信效率上必然存在負面影響。

事實上,NodePort會部署于叢集中的每一個節點,這就意味着,叢集外部的用戶端通過任何一個工作節點的IP位址來通路定義好的NodePort都可以到達相應的Service對象。此種場景中,如果存在叢集外部的一個負載均衡器,即可将使用者請求負載均衡至叢集中的部分或者所有節點。這是一種稱為“LoadBalancer”類型的Service,它通常是由Cloud Provider自動建立并提供的軟體負載均衡器,不過,也可以是由管理者手工配置的諸如F5 Big-IP一類的硬體裝置。

簡單來說,Service主要有三種常用類型:第一種是僅用于叢集内部通信的ClusterIP類型;第二種是接入叢集外部請求的NodePort類型,它工作于每個節點的主機IP之上;第三種是LoadBalancer類型,它可以把外部請求負載均衡至多個Node的主機IP的NodePort之上。此三種類型中,每一種都以其前一種為基礎才能實作,而且第三種類型中的LoadBalancer需要協同叢集外部的元件才能實作,并且此外部元件并不接受Kubernetes的管理。

2.1.4 部署應用程式的主體過程

Docker容器技術使得部署應用程式從傳統的安裝、配置、啟動應用程式的方式轉為于容器引擎上基于鏡像建立和運作容器,而Kubernetes又使得建立和運作容器的操作不必再關注其位置,并在一定程度上賦予了它動态擴縮容及自愈的能力,進而讓使用者從主機、系統及應用程式的維護工作中解脫出來。

用到某應用程式時,使用者隻需要向API Server請求建立一個Pod控制器,由控制器根據鏡像等資訊向API Server請求建立出一定數量的Pod對象,并由Master之上的排程器指派至標明的工作節點以運作容器化應用。此外,使用者一般還需要建立一個具體的Service對象以便為這些Pod對象建立起一個固定的通路入口,進而使得其用戶端能夠通過其服務名稱或ClusterIP進行通路,如圖2-5所示。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-5 應用程式簡單的部署示例

API Server的常用用戶端程式是Kubernetes系統自帶的指令行工具kubectl,它通過一衆子指令用于實作叢集及相關資源對象的管理操作,并支援直接指令式、指令式配置清單及聲明式配置清單等三種操作方式,特性豐富且功能強大。而需作為叢集附件額外部署的Dashboard則提供了基于Web界面的圖形用戶端,它是一個通用目的管理工具,與Kubernetes緊密內建,支援多級别使用者授權,能在一定程度上替代kubectl的大多數操作。

本章後面的篇幅将介紹在部署完成的Kubernetes叢集環境中如何快速部署如圖2-5所示的示例應用程式,并簡單說明如何完成對容器化應用的通路,以及如何進行應用規模的動态伸縮,并借此讓讀者了解kubectl指令的基本功能和用法。

2.2 部署Kubernetes叢集

Kubernetes系統可運作于多種平台之上,包括虛拟機、裸伺服器或PC等,例如本地主機或托管的雲端虛拟機。若僅用于快速了解或開發的目的,那麼讀者可直接于單個主機之上部署“僞”分布式的Kubernetes叢集,将叢集的所有元件均部署運作于單台主機上,著名的minukube項目可幫助使用者快速建構此類環境。如果要學習使用Kubernetes叢集的完整功能,則應該建構真正的分布式叢集環境,将Master和Node等部署于多台主機之上,主機的具體數量要按實際需求而定。另外,叢集部署的方式也有多種選擇,簡單的可以基于kubeadm一類的部署工具運作幾條指令即可實作,而複雜的則可以是從零開始手動建構叢集環境。

2.2.1 kubeadm部署工具

kubeadm是Kubernetes項目自帶的叢集建構工具,它負責執行建構一個最小化的可用叢集以及将其啟動等的必要基本步驟,簡單來講,kubeadm是Kubernetes叢集全生命周期的管理工具,可用于實作叢集的部署、更新/降級及拆除,如圖2-6所示。不過,在部署操作中,kubeadm僅關心如何初始化并啟動叢集,餘下的其他操作,例如安裝Kubernetes Dashboard、監控系統、日志系統等必要的附加元件則不在其考慮範圍之内,需要管理者按需自行部署。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-6 kubeadm功能示意圖

kubeadm內建了kubeadm init和kubeadm join等工具程式,其中kubeadm init用于叢集的快速初始化,其核心功能是部署Master節點的各個元件,而kubeadm join則用于将節點快速加入到指定叢集中,它們是建立Kubernetes叢集最佳實踐的“快速路徑”。另外,kubeadm token可于叢集建構後管理用于加入叢集時使用的認證令牌(token),而kubeadm reset指令的功能則是删除叢集建構過程中生成的檔案以重置回初始狀态。

kubeadm還支援管理初始引導認證令牌(Bootstrap Token),完成待加入的新節點首次聯系API Server時的身份認證(基于共享密鑰)。另外,它們還支援管理叢集版本的更新和降級操作。Kubernetes 1.8版本之前,kubeadm一直處于beta級别,并警告不能用于生産環境。不過,自1.9版本開始,其雖仍處于beta版本,但已經不再輸出警告資訊,而随着1.11版本釋出的kubeadm又得到了進一步的增強,它支援動态配置kubelet,通過增強的CRI內建支援動态探測以判定所用的容器引擎,并引入了幾個新的指令行工具,包括kubeadm conf?ig print-default、kubeadm conf?ig migrate、kubeadm conf?ig images pull和kubeadm upgrade node conf?ig等。總體來說,使用kubeadm部署Kubernetes叢集具有如下幾個方面的優勢。

  • 簡單易用:kubeadm可完成叢集的部署、更新和拆除操作,并且對新手使用者非常友好。
  • 适用領域廣泛:支援将叢集部署于裸機、VMware、AWS、Azure、GCE及更多環境的主機上,且部署過程基本一緻。
  • 富有彈性:1.11版中的kubeadm支援階段式部署,管理者可分為多個獨立步驟完成部署操作。
  • 生産環境可用:kubeadm遵循以最佳實踐的方式部署Kubernetes叢集,它強制啟用RBAC,設定Master的各元件間以及API Server與kublet之間進行認證及安全通信,并鎖定了kubelet API等。

    由此可見,kubeadm并非一鍵安裝類的解決方案,相反,它有着更宏大的目标,旨在成為一個更大解決方案的一部分,試圖為叢集建立和營運建構一個聲明式的API驅動模型,它将叢集本身視為不可變元件,而更新操作等同于全新部署或就地更新。目前,使用kubeadm部署叢集已經成為越來越多的Kubernetes工程師的選擇。

2.2.2 叢集運作模式

Kubernetes叢集支援三種運作模式:一是“獨立元件”模式,系統各元件直接以守護程序的方式運作于節點之上,各元件之間互相協作構成叢集,如圖2-7b所示;第二種是“靜态Pod模式”,除kubelet和Docker之外的其他元件(如etcd、kube-apiserver、kube-controller-manager和kube-scheduler等)都是以靜态Pod對象運作于Master主機之上的,如圖2-7a所示;第三種是Kubernetes的“自托管”(self-hosted)模式,它類似于第二種方式,将除了kubelet和Docker之外的其他元件運作為叢集之上的Pod對象,但不同的是,這些Pod對象托管運作在叢集自身之上受控于DaemonSet類型的控制器,而非靜态的Pod對象。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-7 Kubernetes叢集的運作模式(圖2-7a為靜态Pod模式)

使用kubeadm部署的Kubernetes叢集可運作為第二種或第三種模式,預設為靜态Pod對象模式,需要使用自托管模式時,kubeadm init指令使用“--features-gates=selfHosting”選項即可。第一種模式叢集的建構需要将各元件運作于系統之上的獨立守護程序中,其間需要用到的證書及Token等認證資訊也都需要手動生成,過程煩瑣且極易出錯;若有必要用到,則建議使用GitHub上合用的項目輔助進行,例如,通過ansible playbook進行自動部署等。

2.2.3 準備用于實踐操作的叢集環境

本書後面的篇幅中用到的測試叢集如圖2-8所示,該叢集由一個Master主機和三個Node主機組成,它基于kubeadm部署,除了kubelet和Docker之外其他的叢集元件都運作于Pod對象中。多數情況下,兩個或以上的獨立運作的Node主機即可測試分布式叢集的核心功能,是以其數量可按需定義,但兩個主機是模拟分布式環境的最低需求。生産實踐中,應該至少部署三個協同工作的Master節點以確定控制平面的服務可用性,不過,在測試環境中僅部署一個Master節點也是常見的選擇。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-8 Kubernetes叢集部署目标示意圖

各Node上采用的容器運作時環境為docker,後續的衆多容器的運作任務都将依賴于Docker Registry服務,包括DockerHub、GCR(Google Container Registry)和Quay等,甚至是私有的Registry服務,本書假設讀者對Docker容器技術有熟練的使用基礎。另外,本部署示例中使用的用于為Pod對象提供網絡功能的插件是f?lannel,其同樣以Pod對象的形式托管運作于Kubernetes系統之上。

具體的部署過程以及本書用到的叢集環境請參考附錄A,本章後續的操作都将依賴于根據其步驟部署完成的叢集環境,讀者需要根據其内容成功搭建出Kubernetes測試叢集後才能進行後面章節的學習。

2.2.4 擷取叢集環境相關的資訊

Kubernetes系統目前仍處于快速疊代階段,版本演進頻繁,讀者所部署的版本與本書中使用的版本或将有所不同,其功能特性也将存在一定程度的變動。是以,事先檢視系統版本,以及對比了解不同版本間的功能特性變動也将是不可或缺的步驟。當然,使用者也可選擇安裝與本書相同的系統版本。下面的指令顯示的是目前使用的用戶端及服務端程式版本資訊:

[root@master ~]# kubectl version --short=true
Client Version: v1.12.1
Server Version: v1.12.1      

Kubernetes系統版本變動時的ChangeLog可參考github.com站點上相關版本中的介紹。

Kubernetes叢集以及部署的附件CoreDNS等提供了多種不同的服務,用戶端通路這些服務時需要事先了解其通路接口,管理者可使用“kubectl cluster-info”指令擷取相關的資訊。

[root@master ~]# kubectl cluster-info
Kubernetes master is running at         https://172.16.0.70:6443               
CoreDNS is running at         https://172.16.0.70:6443/api/v1/namespaces/kube-system/          
services/kube-dns:dns/proxy</pre>           

一個功能完整的Kubernetes叢集應當具備的附加元件還包括Dashboard、Ingress Controller和Heapster(或Prometheus)等,後續章節中的某些概念将會依賴到這些元件,讀者可選擇在将要用到時再進行部署。

2.3 kubectl使用基礎與示例

Kubernetes API是管理其各種資源對象的唯一入口,它提供了一個RESTful風格的CRUD(Create、Read、Update和Delete)接口用于查詢和修改叢集狀态,并将結

果存儲于叢集狀态存儲系統etcd中。事實上,API server也是用于更新etcd中資源對象狀态的唯一途徑,Kubernetes的其他所有元件和用戶端都要通過它來完成查詢或修改操作,如圖2-9所示。從這個角度來講,它們都算得上是API server的用戶端。

任何RESTful風格API中的核心概念都是“資源”(resource),它是具有類型、關聯資料、同其他資源的關系以及可對其執行的一組操作方法的對象,它與對象式程式設計語言中的對象執行個體類似,兩者之間的重要差別在于RESTful API僅為資源定義了少量的标準方法(對應于标準HTTP的GET、POST、PUT和DELETE方法),而程式設計語言中的對象執行個體通常有很多方法。另外,資源可以根據其特性分組,每個組是同一類型資源的集合,它僅包含一種類型的資源,并且各資源間不存在順序的概念,集合本身也是資源。對應于Kubernetes中,Pod、Deployment和Service等都是所謂的資源類型,它們由相應類型的對象集合而成。

API Server通過認證(Authentication)、授權(Authorization)和準入控制(Admission Control)等來管理對資源的通路請求,是以,來自于任何用戶端(如kubectl、kubelet、kube-proxy等)的通路請求都必須事先完成認證之後方可進行後面的其他操作。API Server支援多種認證方式,用戶端可以使用指令行選項或專用的配置檔案(稱為kubeconf?ig)提供認證資訊。相關的内容将在後面的章節中給予詳細說明。

kubectl的核心功能在于通過API Server操作Kubernetes的各種資源對象,它支援三種操作方式,其中直接指令式(Imperative commands)的使用最為簡便,是了解Kubernetes叢集管理的一種有效途徑。

kubectl指令常用操作示例

為了便于讀者快速适應kubectl的指令操作,這裡給出幾個使用示例用于說明其基本使用方法。

1.建立資源對象

直接通過kubectl指令及相關的選項建立資源對象的方式即為直接指令式操作,例如下面的指令分别建立了名為nginx-deploy的Deployment控制器資源對象,以及名為nginx-svc的Service資源對象:

$ kubectl run nginx-deploy --image=nginx:1.12 --replicas=2
$ kubectl expose deployment/nginx --name=nginx-svc --port=80      

使用者也可以根據資源清單建立資源對象,即指令式對象配置檔案,例如,假設存在定義了Deployment對象的nginx-deploy.yaml檔案,和定義了Service對象的nginx-svc.yaml檔案,使用kubectl create指令即可進行基于指令式對象配置檔案的建立操作:

$ kubectl create -f nginx-deploy.yaml -f nginx-svc.yaml      

甚至還可以将建立交由kubectl自行确定,使用者隻需要聲明期望的狀态,這種方式稱為聲明式對象配置。例如,假設存在定義了Deployment對象的nginx-deploy.yaml檔案,以及定義了Service對象的nginx-svc.yaml檔案,那麼使用kubectl apply指令即可實作聲明式配置:

$ kubectl apply -f nginx-deploy.yaml -f nginx-svc.yaml      

本章後面的章節主要使用第一種資源管理方式,第二種和第三種方式将在後面的章節中展開講述。

2.檢視資源對象

運作着實際負載的Kubernetes系統上通常會存在多種資源對象,使用者可分類列出感興趣的資源對象及其相關的狀态資訊,“kubectl get”正是用于完成此類功能的指令。例如,列出系統上所有的Namespace資源對象,指令如下:

$ kubectl get namespaces      

使用者也可一次檢視多個資源類别下的資源對象,例如,列出預設名稱空間内的所有Pod和Service對象,并輸出額外資訊,可以使用如下形式的kubectl get指令:

$ kubectl get pods,services -o wide      

Kubernetes系統的大部分資源都隸屬于某個Namespace對象,預設的名稱空間為default,若需要擷取指定Namespace對象中的資源對象的資訊,則需要使用-n或--namespace指明其名稱。例如,列出kube-namespace名稱空間中擁有k8s-app标簽名稱的所有Pod對象:

$ kubectl get pods -l k8s-app -n kube-system      

3.列印資源對象的詳細資訊

每個資源對象都包含着使用者期望的狀态(Spec)和現有的實際狀态(Status)兩種狀态資訊,“kubectl get -o {yaml|josn}”或“kubectl describe”指令都能夠列印出指定資源對象的較長的描述資訊。例如,檢視kube-system名稱空間中擁有标簽component=kube-apiserver的Pod對象的資源配置清單(期望的狀态)及目前的狀态資訊,并輸出為yaml格式,指令如下:

$ kubectl get pods -l component=kube-apiserver -o yaml -n kube-system      

而“kubectl describe”指令還能顯示與目前對象相關的其他資源對象,如Event或Controller等。例如,檢視kube-system名稱空間中擁有标簽component=kube-apiserver的Pod對象的較長的描述資訊,可以使用下面的指令:

$ kubectl describe pods -l component=kube-apiserver -n kube-system      

這兩個指令都支援以“TYPE NAME”或“TYPE/NAME”的格式指定具體的資源對象,如“pods kube-apiserver-master.ilinux.io”或“pods/kube-apiserver-master.ilinux.io”,以了解特定資源對象的詳細屬性資訊及狀态資訊。

4.列印容器中的日志資訊

通常一個容器中僅會運作一個程序(及其子程序),此程序作為PID為1的程序接收并處理管理資訊,同時将日志直接輸出至終端中,而無須再像傳統的多程序系統環境那樣将日志儲存于檔案中,是以容器日志資訊的擷取一般要到其控制上進行。“kubectl logs”指令可列印Pod對象内指定容器的日志資訊,指令格式為“kubectl logs [-f]

-p

[-c CONTAINER] [options]”,若Pod對象内僅有一個容器,則-c選項及容器名為可選。例如,檢視名稱空間kube-system中僅有一個容器的Pod對象kube-apiserver-master.ilinux.io的日志:

$ kubectl logs kube-apiserver-master.ilinux.io -n kube-system      

為上面的指令添加“-f”選項,還能用于持續監控指定容器中的日志輸出,其行為類似于使用了-f選項的tail指令。

5.在容器中執行指令

容器的隔離屬性使得對其内部資訊的擷取變得不再直覺,這一點在使用者需要了解容器内程序的運作特性、檔案系統上的檔案及路徑布局等資訊時,需要穿透其隔離邊界進行。“kubectl exec”指令便是用于在指定的容器内運作其他應用程式的指令,例如,在kube-system名稱空間中的Pod對象kube-apiserver-master.ilinux.io上的唯一容器中運作ps指令:

$ kubectl exec kube-apiserver-master.ilinux.io -n kube-system -- ps      

注意,若Pod對象中存在多個容器,則需要以-c選項指定容器後再運作。

6.删除資源對象

使命已經完成或存在錯誤的資源對象可使用“kubectl delete”指令予以删除,不過,對于受控于控制器的對象來說,删除之後其控制器可能會重建出類似的對象,例如,Deployment控制器下的Pod對象在被删除時就會被重建。例如,删除預設名稱空間中名為nginx-svc的Service資源對象:

$ kubectl delete services nginx-svc      

下面的指令可用于删除kube-system名稱空間中擁有标簽“k8s-app=kube-proxy”的所有Pod對象:

$ kubectl delete pods -l app=monitor -n kube-system      

若要删除指定名稱空間中的所有的某類對象,可以使用“kubectl delete TYPE --all -n NS”指令,例如,删除kube-public名稱空間中的所有Pod對象:

$ kubectl delete pods --all -n kube-public      
另外,有些資源類型(如Pod),支援優雅删除的機制,它們有着預設的删除寬限期,不過,使用者可以在指令中使用--grace-period選項或--now選項來覆寫預設的寬限期。      

2.4 指令式容器應用編排

本節将使用示例鏡像“ikubernetes/myapp: v1”來示範容器應用編排的基礎操作:應用部署、通路、檢視、服務暴露和擴縮容等。一般說來,Kubernetes之上應用程式的基礎管理操作由如下幾個部分組成。

1)通過合用的Controller類的資源(如Deployment或ReplicationController)建立并管控Pod對象以運作特定的應用程式,如Nginx或tomcat等。無狀态(stateless)應用的部署和控制通常使用Deployment控制器進行,而有狀态應用則需要使用StatefulSet控制器。

2)為Pod對象建立Service對象,以便向用戶端提供固定的通路路徑,并借助于CoreDNS進行服務發現。

3)随時按需擷取各資源對象的簡要或詳細資訊,以了解其運作狀态。

4)如有需要,則手動對支援擴縮容的Controller元件進行擴容或縮容;或者,為支援HPA的Controller元件(如Deployment或ReplicationController)建立HPA資源對象以實作Pod副本數目的自動伸縮。

5)滾動更新:當應用程式的鏡像出現新版本時,對其執行更新操作;必要時,為Pod對象中的容器更新其鏡像版本;并可根據需要執行復原操作。

本節中的操作示例僅示範了前三個部分的功能,即應用的部署、服務暴露及相關資訊的檢視。應用的擴縮容、更新及復原等操作會在後面的章節中進行詳細介紹。

以下操作指令在任何部署了kubectl并能正常通路到Kubernetes叢集的主機上均可執行,包括叢集外的主機。複制master主機上的/etc/kubernetes/admin.conf至相關使用者主目錄下的.kube/conf?ig檔案即可正常執行,具體方法請參考kubeadm init指令結果中的提示。

2.4.1 部署應用(Pod)

在Kubernetes叢集上自主運作的Pod對象在非計劃内終止後,其生命周期即告結束,使用者需要再次手動建立類似的Pod對象才能確定其容器中的應用依然可得。對于Pod數量衆多的場景,尤其是對微服務業務來說,使用者必将疲于應付此類需求。Kubernetes的工作負載(workload)類型的控制器能夠自動確定由其管控的Pod對象按使用者期望的方式運作,是以,Pod的建立和管理大多都會通過這種類型的控制器來進行,包括Deployment、ReplicaSet、ReplicationController等。

1.建立Deployment控制器對象

“kubectl run”指令可于指令行直接建立Deployment控制器,并以--image選項指定的鏡像運作Pod中的容器,--dry-run選項可用于指令的測試運作,但并未真正執行資源對象的建立過程。例如,下面的指令要建立一個名為myapp的Deployment控制器對象,它使用鏡像ikubernetes/myapp: v1建立Pod對象,但僅在測試運作後即退出:

~]$ kubectl run myapp --image=ikubernetes/myapp:v1 --port=80 --replicas=1      
--dry-run           

NAME AGE

myapp

鏡像ikubernetes/myapp: v1中定義的容器主程序為預設監聽于80端口的Web服務程式Nginx,是以,如下指令使用“--port=80”來指明容器要暴露的端口。而“--replicas=1”選項則指定了目标控制器對象要自動建立的Pod對象的副本數量。确認測試指令無誤後,可移除“--dry-run”選項後再次執行指令以完成資源對象的建立:

~]$ kubectl run myapp --image=ikubernetes/myapp:v1 --port=80 --replicas=1
deployment.apps/myapp created      

建立完成後,其運作效果示意圖如圖2-10所示,它在default名稱空間中建立了一個名為myapp的Deployment控制器對象,并由它基于指定的鏡像檔案建立了一個Pod對象。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-10 Deployment對象myapp及其建立的Pod對象

kubectl run指令其他常用的選項還有如下幾個,它們支援使用者在建立資源對象時實作更多的控制,具體如下。

-l, --labels:為Pod對象設定自定義标簽。

--record:是否将目前的對象建立指令儲存至對象的Annotation中,布爾型資料,其值可為true或false。

--save-conf?ig:是否将目前對象的配置資訊儲存至Annotation中,布爾型資料,其值可為true或false。

--restart=Never:建立不受控制器管控的自主式Pod對象。

其他可用選項及使用方式可通過“kubectl run --help”指令擷取。資源對象建立完成後,通常需要了解其目前狀态是否正常,以及是否能夠吻合于使用者期望的目标狀态,相關的操作一般使用kubectl get、kubectl describe等指令進行。

2.列印資源對象的相關資訊

kubectl get指令可用于擷取各種資源對象的相關資訊,它既能夠顯示對象類型特有格式的簡要資訊,也能夠指定出格式為YAML或JSON的詳細資訊,或者使用Go模闆自定義要顯示的屬性及資訊等。例如,下面是檢視前面建立的Deployment對象的相關運作狀态的指令及其輸出結果:

~]$ kubectl get deployments
NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
myapp      1         1         1            1           1m      

上面指令的執行結果中,各字段的說明具體如下。

1)NAME:資源對象的名稱。

2)DESIRED:使用者期望由目前控制器管理的Pod對象副本的精确數量。

3)CURRENT:目前控制器已有的Pod對象的副本數量。

4)UP-TO-DATE:更新到最新版本定義的Pod對象的副本數量,在控制器的滾動更新模式下,它表示已經完成版本更新的Pod對象的副本數量。

5)AVAILABLE:目前處于可用狀态的Pod對象的副本數量,即可正常提供服務的副本數。

6)AGE:Pod的存在時長。

Deployment資源對象通過ReplicaSet控制器執行個體完成對Pod對象的控制,而非直接控制。另外,通過控制器建立的Pod對象都會被自動附加一個标簽,其格式為“run=”,例如,上面的指令所建立的Pod,會擁有“run=myapp”标簽。後面的章節對此會有較長的描述。

而此Deployment控制器建立的唯一Pod對象運作正常與否,其被排程至哪個節點運作,目前是否就緒等也是使用者在建立完成後應該重點關注的資訊。由控制器建立的Pod對象的名稱通常是以控制器名稱為字首,以随機字元為字尾,例如,下面指令輸出結果中的myapp-6865459dff-5nsjc:

$ kubectl get pods -o wide
NAME                     READY  STATUS   RESTARTS  AGE  IP          NODE
myapp-6865459dff-5nsjc   1/1    Running  0         3m   10.244.3.2  node03.      
ilinux.io</pre>           

上面指令的執行結果中,每一個字段均代表着Pod資源對象一個方面的屬性,除了NAME之外的其他字段及功用說明如下。

①READY:Pod中的容器程序初始化完成并能夠正常提供服務時即為就緒狀态,此字段用于記錄處于就緒狀态的容器數量。

②STATUS:Pod的目前狀态,其值可能是Pending、Running、Succeeded、Failed和Unknown等其中之一。

③RESTARTS:Pod對象可能會因容器程序崩潰、超出資源限額等原因發生故障問題而被重新開機,此字段記錄了它重新開機的次數。

④IP:Pod的IP位址,其通常由網絡插件自動配置設定。

⑤NODE:建立時,Pod對象會由排程器排程至叢集中的某節點運作,此字段即為節點的相關辨別資訊。

如果指定名稱空間中存在大量的Pod對象而使得類似如上指令的輸出結果存在太多的不相關資訊時,則可通過指定選項“-l run=myapp”進行Pod對象過濾,其僅顯示符合此标簽選擇器的Pod對象。

确認Pod對象已轉為“Running”狀态之後,即可于叢集中的任一節點(或其他Pod對象)直接通路其容器化應用中的服務,如圖2-11中節點NodeX上的用戶端程式Client,或者叢集上運作于Pod中的用戶端程式。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-11 通路Pod中容器化應用服務程式

例如,在叢集中任一節點上使用curl指令對位址為10.244.3.2的Pod對象myapp-6865459dff-5nsjc的80端口發起服務請求,指令及結果如下所示:

[ik8s@node03 ~]$ curl

http://10.244.3.2:80/

Hello MyApp | Version: v1 |

Pod Name

2.4.2 探查Pod及應用詳情

資源建立或運作過程中偶爾會因故出現異常,此時使用者需要充分擷取相關的狀态及配置資訊以便确定問題的所在。另外,在對資源對象進行建立或修改完成之後,也需要通過其詳細的狀态來了解操作成功與否。kubectl有多個子指令可用于從不同的角度顯示對象的狀态資訊,這些資訊有助于使用者了解對象的運作狀态、屬性詳情等資訊。

1)kubectl describe:顯示資源的詳情,包括運作狀态、事件等資訊,但不同的資源類型其輸出内容不盡相同。

2)kubectl logs:檢視Pod對象中容器輸出在控制台的日志資訊。在Pod中運作有多個容器時,需要使用選項“-c”指定容器名稱。

3)kubectl exec:在Pod對象某容器内運作指定的程式,其功能類似于“docker exec”指令,可用于了解容器各方面的相關資訊或執行必需的設定操作等,其具體功能取決于容器内可用的程式。

1.檢視Pod對象的較長的描述

下面給出的指令列印了此前由myapp建立的Pod對象的詳細狀态資訊,為了便于後續的多次引用,這裡先将其名稱儲存于變量POD_NAME中。指令的執行結果中省略了部分輸出:

~]$ POD_NAME=myapp-6865459dff-5nsjc
~]$ kubectl describe pods $POD_NAME
Name:               myapp-6865459dff-5nsjc
Namespace:          default
Priority:           0
PriorityClassName:  
Node:               node03.ilinux.io/172.16.0.68
……
Status:             Running
IP:                 10.244.3.2
Controlled By:      ReplicaSet/myapp-6865459dff
Containers:
  myapp:      
……           

……

Events:

Type Reason Age From Message

---- ------ ---- ---- -------

Normal Scheduled 55m default-scheduler Successfully assigned

default/myapp-6865459dff-5nsjc to node03.ilinux.io           

Normal Pulling 55m kubelet, node03.ilinux.io pulling image "ikubernetes/

myapp:v1"           

Normal Pulled 54m kubelet, node03.ilinux.io Successfully pulled image

"ikubernetes/myapp:v1"           

Normal Created 54m kubelet, node03.ilinux.io Created container

Normal Started 54m kubelet, node03.ilinux.io Started container

不同的需求場景中,使用者需要關注不同緯度的輸出,但一般來說,Events和Status字段會是重點關注的對象,它們分别代表了Pod對象運作過程中的重要資訊及目前狀态。上面指令執行結果中的不少字段都可以見名而知義,而且部分字段在前面介紹其他指令輸出時已經給出,還有一部分會在本書後面的篇幅中給予介紹。

2.檢視容器日志

Docker容器一般僅運作單個應用程式,其日志資訊将通過标準錯誤輸出等方式直接列印至控制台,“kubectl logs”指令即用于檢視這些日志。例如,檢視由Deployment控制器myapp建立的Pod對象的控制台日志,指令如下:

~]$ kubectl logs $POD_NAME
10.244.3.1 - - [……] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
……      

如果Pod中運作有多個容器,則需要在檢視日志時為其使用“-c”選項指定容器名稱。例如,當讀者所部署的是KubeDNS附件而非CoreDNS時,kube-system名稱空間内的kube-dns相關的Pod中同時運作着kubedns、dnsmasq和sidecar三個容器,如果要檢視kubedns容器的日志,需要使用類似如下的指令:

~]$ DNS_POD=$(kubectl get pods -o name -n kube-system | grep kube-dns)
~]$ kubectl logs $DNS_POD -c kubedns -n kube-system      

需要注意的是,日志檢視指令僅能用于列印存在于Kubernetes系統上的Pod中容器的日志,對于已經删除的Pod對象,其容器日志資訊将無從擷取。日志資訊是用于輔助使用者擷取容器中應用程式運作狀态的最有效的途徑之一,也是非常重要的排錯手段,是以通常需要使用集中式的日志伺服器統一收集存儲于各Pod對象中容器的日志資訊。

3.在容器中運作額外的程式

運作着非互動式程序的容器中,預設運作的唯一程序及其子程序啟動後,容器即進入獨立、隔離的運作狀态。對容器内各種詳情的了解需要穿透容器邊界進入其中運作其他的應用程式來進行,“kubectl exec”可以讓使用者在Pod的某容器中運作使用者所需要的任何存在于容器中的程式。在“kubectl logs”擷取的資訊不夠全面時,此指令可以通過在Pod中運作其他指定的指令(前提是容器中存在此程式)來輔助使用者擷取更多的資訊。一個更便捷的使用接口的方式是直接互動式運作容器中的某個Shell程式。例如,直接檢視Pod中的容器運作的程序:

~]$ kubectl exec $POD_NAME ps aux
PID   USER     TIME   COMMAND      
1 root       0:00 nginx: master process nginx -g daemon off;
8 nginx      0:00 nginx: worker process
9 root       0:00 ps aux</pre>           

如果Pod對象中運作了多個容器,那麼在程式運作時還需要使用“-c ”選項指定要于其内部運作程式的容器名稱。

若要進入容器的互動式Shell接口,可使用類似如下的指令,斜體部分表示在容器的互動式接口中執行的指令:

~]$ kubectl -it exec $POD_NAME /bin/sh
/ # hostname
myapp-6865459dff-5nsjc
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address       Foreign Address      State
tcp        0      0 0.0.0.0:80              0.0.0.0:*             LISTEN
/       

2.4.3 部署Service對象

簡單來說,一個Service對象可視作通過其标簽選擇器過濾出的一組Pod對象,并能夠為此組Pod對象監聽的套接字提供端口代理及排程服務。

1.建立Service對象

“kubectl expose”指令可用于建立Service對象以将應用程式“暴露”(expose)于網絡中。例如,下面的指令即可将myapp建立的Pod對象使用“NodePort”類型的服務暴露到叢集外部:

~]$ kubectl expose deployments/myapp --type="NodePort" --port=80 --name=myapp
service "myapp" exposed      

上面的指令中,--type選項用于指定Service的類型,而--port則用于指定要暴露的容器端口,目标Service對象的名稱為myapp。建立完成後,default名稱空間中的對象及其通信示意圖如圖2-12所示。

帶你讀《Kubernetes進階實戰》之二:Kubernetes快速入門

圖2-12 Service對象在Pod對象前端添加了一個固定通路層

下面通過運作于同一叢集中的Pod對象中的用戶端程式發起通路測試,來模拟圖2-12中的源自myapp Client Pod對象的通路請求。首先,使用kubectl run指令建立一個Pod對象,并直接接入其互動式接口,如下指令的-it組合選項即用于互動式打開并保持其shell指令行接口;而後通過wget指令對此前建立的Service對象的名稱發起通路請求,如下指令中的myapp即Service對象名稱,default即其所屬的Namespace對象的名稱:

$ kubectl run client --image=busybox --restart=Never -it -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -O - -q         http://myapp.default:80               
Hello MyApp | Version: v1 |         Pod Name          

建立時,Service對象名稱及其ClusterIP會由CoreDNS附件動态添加至名稱解析庫當中,是以,名稱解析服務在對象建立後即可直接使用。

類似于列出Deployment控制器及Pod對象的方式,“kubectl get services”指令能夠列出Service對象的相關資訊,例如下面的指令顯示了Service對象myapp的簡要狀态資訊:

~]$ kubectl get svc/myapp
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
myapp     NodePort   10.109.39.145           80:31715/TCP   5m      

其中,“PORT(s)”字段表明,叢集中各工作節點會捕獲發往本地的目标端口為31715的流量,并将其代理至目前Service對象的80端口,于是,叢集外部的使用者可以使用目前叢集中任一節點的此端口來請求Service對象上的服務。CLUSTER-IP字段為目前Service的IP位址,它是一個虛拟IP,并沒有配置于叢集中的任何主機的任何接口之上,但每個node之上的kube-proxy都會為CLUSTER-IP所在的網絡建立用于轉發的iptables或ipvs規則。此時,使用者可于叢集外部任一浏覽器請求叢集任一節點的相關端口來進行通路測試。

建立Service對象的另一種方式是使用“kubectl create service”指令,對應于每個類型,它分别有一個專用的子指令,例如“kubectl create service clusterip”和“kubectl create service nodeport”等,各指令在使用方式上也略有差別。

2.檢視Service資源對象的描述

“kubectl describe services”指令用于列印Service對象的詳細資訊,它通常包括Service對象的Cluster IP,關聯Pod對象時使用的标簽選擇器及關聯到的Pod資源的端點等,示例如下:

~]$ kubectl describe services myapp-svc
Name:                     myapp
Namespace:                default
Labels:                   run=myapp
Annotations:              
Selector:                 run=myapp
Type:                     NodePort
IP:                       10.109.39.145
Port:                       80/TCP
TargetPort:               80/TCP
NodePort:                   31715/TCP
Endpoints:                10.244.3.2:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                         

上面指令的執行結果輸出基本上可以做到見名而知義,此處需要特别說明的幾個字段具體如下:

1)Selector:目前Service對象使用的标簽選擇器,用于選擇關聯的Pod對象。

2)Type:即Service的類型,其值可以是ClusterIP、NodePort和LoadBalancer等其中之一。

3)IP:目前Service對象的ClusterIP。

4)Port:暴露的端口,即目前Service用于接收并響應請求的端口。

5)TargetPort:容器中的用于暴露的目标端口,由Service Port路由請求至此端口。

6)NodePort:目前Service的NodePort,它是否存在有效值與Type字段中的類型相關。

7)EndPoints:後端端點,即被目前Service的Selector挑中的所有Pod的IP及其端口。

8)Session Aff?inity:是否啟用會話粘性。

9)External Traff?ic Policy:外部流量的排程政策。

2.4.4 擴容和縮容

前面示例中建立的Deployment對象myapp僅建立了一個Pod對象,其所能夠承載的通路請求數量即受限于這單個Pod對象的服務容量。請求流量上升到接近或超出其容量之前,使用者可以通過Kubernetes的“擴容機制”來擴充Pod的副本數量,進而提升其服務容量。

簡單來說,所謂的“伸縮”(Scaling)就是指改變特定控制器上Pod副本數量的操作,“擴容”(scaling up)即為增加副本數量,而“縮容”(scaling down)則意指縮減副本數量。不過,無論是擴容還是縮容,其數量都需要由使用者明确給出。

Service對象内建的負載均衡機制可在其後端副本數量不止一個時自動進行流量分發,它還會自動監控關聯到的Pod的健康狀态,以確定僅将請求流量分發至可用的後端Pod對象。若某Deployment控制器管理包含多個Pod執行個體,則必要時使用者還可以為其使用“滾動更新”機制将其容器鏡像更新到新的版本或變更那些支援動态修改的Pod屬性。

使用kubectl run指令建立Deployment對象時,“--replicas=”選項能夠指定由該對象建立或管理的Pod對象副本的數量,且其數量支援運作時進行修改,并立即生效。“kubectl scale”指令就是專用于變動控制器應用規模的指令,它支援對Deployment資源對象的擴容和縮容操作。例如,如果要将myapp的Pod副本數量擴充為3個,則可以使用如下指令來完成:

~]$ kubectl scale deployments/myapp --replicas=3
deployment.extensions "myapp" scaled      

而後列出由myapp建立的Pod副本,确認其擴充操作的完成狀态。如下指令顯示出其Pod副本數量已經擴增至3個,其中包括此前的myapp-6865459dff-5nsjc:

~]$ kubectl get pods -l run=myapp
NAME                     READY    STATUS               RESTARTS    AGE
myapp-6865459dff-52j7t   0/1      ContainerCreating    0           53s
myapp-6865459dff-5nsjc   1/1      Running              0           2h
myapp-6865459dff-jz7t6   0/1      ContainerCreating    0           53s      

Deployment對象myapp規模擴充完成之後,default名稱空間中的資源對象及其關聯關系如圖2-13所示。

圖2-13 Deployment對象規模擴增完成

而後由“kubectl describe deployment”指令列印Deployment對象myapp的詳細資訊,了解其應用規模的變動及目前Pod副本的狀态等相關資訊。從下面的指令結果可以看出,其Pod副本數量的各項名額都已經轉換到了新的目标數量,而其事件資訊中也有相應的事件顯示其擴增操作已成功完成:

~]$ kubectl describe deployments/myapp
Name:                   myapp
……
Selector:               run=myapp
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0      
unavailable           

Type Reason Age From Message

---- ------ ---- ---- -------

Normal ScalingReplicaSet 2m deployment-controller Scaled up replica set

myapp-6865459dff to 3</pre>           

由myapp自動建立的Pod資源全都擁有同一個标簽選擇器“run=myapp”,是以,前面建立的Service資源對象myapp的後端端點也已經通過标簽選擇器自動擴充到了這3個Pod對象相關的端點,如下面的指令結果及圖2-13所示:

~]$ kubectl describe services/myapp
Name:                     myapp
……
Endpoints:                10.244.1.3:80,10.244.2.2:80,10.244.3.2:80
……      

回到此前建立的用戶端Pod對象client的互動式接口,對Service對象myapp反複發起測試請求,即可驗正其負載均衡的效果。由如下指令及其結果可以看出,它會将請求排程至後端的各Pod對象進行處理:

~]$ / # while true; do wget -O - -q         http://myapp.default:80/hostname.html;          
sleep 1; done           

myapp-6865459dff-jz7t6

myapp-6865459dff-52j7t

myapp-6865459dff-5nsjc

應用規模縮容的方式與擴容相似,隻不過是将Pod副本的數量調至比原來小的數字即可。例如,将myapp的Pod副本縮減至2個,可以使用如下指令進行:

~]$ kubectl scale deployments/myapp --replicas=2
deployment.extensions "myapp" scaled      

至此,功能基本完整的容器化應用已在Kubernetes上部署完成,即便是一個略複雜的分層應用也隻需要通過合适的鏡像以類似的方式就能部署完成。

2.4.5 修改及删除對象

成功建立于Kubernetes之上的對象也稱為活動對象(live object),其配置資訊(live object conf?iguration)由API Server儲存于叢集狀态存儲系統etcd中,“kubectl get TYPE NAME -o yaml”指令可擷取到相關的完整資訊,而運作“kubectl edit”指令可調用預設編輯器對活動對象的可配置屬性進行編輯。例如,修改此前建立的Service對象myapp的類型為ClusterIP,使用“kubectl edit service myapp”指令打開編輯界面後修改type屬性的值為ClusterIP,并删除NodePort屬性,然後儲存即可。對活動對象的修改将實時生效,但資源對象的有些屬性并不支援運作時修改,此種情況下,編輯器将不允許儲存退出。

有些指令是kubectl edit指令某一部分功能的二次封裝,例如,kubectl scale指令不過是專用于修改資源對象的replicas屬性值而已,它也同樣直接作用于活動對象。

不再有價值的活動對象可使用“kubectl delete”指令予以删除,需要删除Service對象myapp時,使用如下指令即可完成:

~]$ kubectl delete service myapp
service "myapp" deleted      

有時候需要清空某一類型下的所有對象,隻需要将上面指令對象的名稱換成“--all”選項便能實作。例如,删除預設名稱空間中所有的Deployment控制器的指令如下:

~]$ kubectl delete deployment --all
deployment.extensions "myapp" deleted      

需要注意的是,受控于控制器的Pod對象在删除後會被重建,删除此類對象需要直接删除其控制器對象。不過,删除控制器時若不想删除其Pod對象,可在删除指令上使用“--cascade=false”選項。

雖然直接指令式管理的相關功能強大且适合用于操縱Kubernetes資源對象,但其明顯的缺點是缺乏操作行為以及待運作對象的可信源。另外,直接指令式管理資源對象存在較大的局限性,它們在設定資源對象屬性方面提供的配置能力相當有限,而且還有不少資源并不支援指令操作進行建立,例如,使用者無法建立帶有多個容器的Pod對象,也無法為Pod對象建立存儲卷。是以,管理資源對象更有效的方式是基于儲存有對象配置資訊的配置清單來進行。

2.5 本章小結

本章着重介紹了Kubernetes的三個核心資源抽象Pod、Deployment和Service,并在介紹了kubectl的基本用法之後通過案例講解了如何在叢集中部署、暴露、通路及擴縮容容器化應用,具體如下。

Pod是運作容器化應用及排程的原子單元,同一個Pod中可同時運作多個容器,這些容器共享Mount、UTS及Network等Linux核心名稱空間,并且能夠通路同一組存儲卷。

Deployment是最常見的無狀态應用的控制器,它支援應用的擴縮容、滾動更新等操作,為容器化應用賦予了極具彈性的功能。

Service為彈性變動且存在生命周期的Pod對象提供了一個固定的通路接口,用于服務發現和服務通路。

kubectl是Kubernetes API Server最常用的用戶端程式之一,它功能強大,特性豐富,幾乎能夠完成除了安裝部署之外的所有管理操作。

繼續閱讀