天天看點

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

Kubernetes核心技術系列 點選這裡檢視第二章:Kubernetes快速入門 點選這裡檢視第三章:資源管理基礎

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

Kubernetes藝術

馬永亮 著

前  言

為什麼要寫這本書

作為置身于IT技術領域多年的實踐者和教育者,我們一直盼望着行業迎來這樣一個時刻:異構的IT基礎設施環境所造成的開發和部署系統應用紛繁複雜的局面終于迎來了終結者,開發人員無須再考慮複雜多樣的運作環境下軟體程式的移植問題,運維人員不用再手動解決運作環境中元件間的依賴關系等,進而讓各自的核心職責都回歸到開發和保證系統穩定運作本身。終于,以Docker為首的容器技術為此帶來了基礎保障,并在容器編排技術的支撐下塵埃落定,甚至連IT管理者心心念念多年的DevOps文化運動也借此找到了易于落地的實作方案。于是,系統運作割據多年的局面終于将走向天下一統。

盡管距Kubernetes 1.0的釋出不過三四年的光景,但其如今的影響力在IT技術領域完全算得上空前絕後,目前,一衆大小公司都在使用或正籌劃使用這一IT技術發展史上可能最為成功的開源項目。Linux軟體基金會的常務董事Jim Zemlin在Google Cloud Next 17大會上曾表示,Kubernetes是“雲時代的Linux”。的确,Kubernetes應該是開源世界有史以來疊代最快的項目,而且在幾乎所有需要采用容器技術的場景裡成為占統治地位的解決方案,其發展速度恐怕也僅有Linux核心項目可堪匹敵。2018年3月,Kubernetes成為CNCF旗下“畢業”的第一個項目,并榮獲2018年 OSCON最具影響力獎項。

目前,Kubernetes保持着每年釋出四個重要版本的節奏,版本的每次更新都會引入數個新特性。這種快速疊代的機制在為使用者不斷帶來驚喜的同時,也給他們在學習和使用上造成了一些困擾:相關領域的可參考書籍仍不豐富,網際網路上可以得到的衆多文檔并非源于同一個版本,以及厘清脈絡拼湊成完整的知識架構所需的時間成本較大。是以,我在課程以及直接或間接參與生産或測試環境的傳遞之餘便萌生了撰寫一本Kubernetes入門、進階與實戰的書籍的想法,将自己學習和使用的經驗總結、沉澱并分享給更多有此需求的技術同行,幫助大家快速找到入門路徑,降低時間成本,并迅速投入測試和生産之用。

的确,在寫作過程中,Kubernetes這種快速疊代的機制,以及每每引入的新特性,在小驚喜之餘帶給筆者更多的卻是真真切切的夢魇般的恐懼感:在一年多的寫作時間裡,許多章節幾易其稿,卻也依然無法確定能夠涵蓋即将成為核心功能的特性,于是沮喪感幾度如影随形,直到自我安慰着“基礎的核心特性基本不會發生大的變動,隻要能幫助讀者弄清楚Kubernetes系統的基礎架構及核心工作邏輯就算工夫沒有白費”之後方才釋然。于是便有了這本力圖盡量多地包羅Kubernetes系統目前主流特性及實踐路徑的入門和進階之書、工具之書。

本書特色

本書緻力于幫助容器編排技術的初級和中級使用者循序漸進地了解與使用Kubernetes系統,是以本書的編寫充分考慮到初學者進入新知識領域時的茫然,采用由淺入深、提綱挈領、再由點到面的方式講解每一個知識細節。對于每個知識點,不僅介紹了其概念和用法,還分析了為什麼要有這個概念,實作的方式是什麼,背後的邏輯為何,等等,使讀者不僅能知其然,還能知其是以然。

本書不僅要帶領讀者入門,更是一本可以随時動手加以驗證的實踐手冊,而且對于部分重要的内容還會專門一步步地給出具體的實操案例,幫助讀者在實踐中升華對概念的了解。本書幾乎涵蓋了應用Kubernetes系統的所有主流知識點,它甚至可以作為計劃考取CKA認證的讀者的配套參考圖書。

讀者對象

雲計算工程師

運維工程師

系統開發工程師

程式架構師

計劃考取CKA認證的人員

其他對容器編排感興趣的人員

如何閱讀本書

閱讀使用本書之前,讀者需要具備Docker容器技術的基礎使用能力。本書邏輯上共分為五大部分,15章。

第一部分(第1~2章),介紹Kubernetes系統的基礎概念及其基本應用。

第1章介紹容器編排系統出現的背景,以及Kubernetes系統的功能、特性、核心概念、系統元件及應用模型。

第2章講解Kubernetes的核心對象,以及直接使用指令管理資源對象的快速入門技巧。

第二部分(第3~6章),介紹核心資源類型及其應用。

第3章介紹資源管理模型、陳述式與聲明式資源管理接口,并通過指令對比說明兩種操作方式的不同之處。

第4章介紹Pod資源的常用配置、生命周期、存儲狀态和就緒狀态檢測,以及計算資源的需求及限制等。

第5章介紹Pod控制器資源類型,重點講解了控制無狀态應用的ReplicaSet、Deployment、DaemonSet控制器,并介紹了Job和CronJob控制器。

第6章介紹Service和Ingress資源類型,涵蓋Service類型、功用及其實作,以及Ingress控制器、Ingress資源的種類及其實作,并通過案例詳細說明了Ingress資源的具體使用方式。

第三部分(第7~9章),介紹存儲卷及StatefulSet控制器。

第7章主要介紹存儲卷類型及常見存儲卷的使用方式、PV和PVC出現的原因及應用,以及存儲類資源的應用和存儲卷的動态供給。

第8章介紹使用一等資源類型Conf?igMap和Secret為容器應用提供配置及敏感資訊的方式。

第9章主要介紹有狀态應用的Pod控制器資源StatefulSet,包括基礎應用、動态擴縮容及更新機制等。

第四部分(第10~11章),介紹安全相關的話題,主要涉及認證、授權、準入控制、網絡模型與網絡政策。

第10章重點講解認證方式、Service Account和TLS認證、授權插件類型及RBAC,并于章節的最後介紹LimitRanger、ResourceQuota和PodSecurityPolicy三種類型的準入控制器及相關的資源類型。

第11章主要介紹網絡插件基礎及f?lannel的三種後端實作與應用、借助Canal插件實作網絡政策的方式,以及Calico網絡插件的基礎使用。

第五部分(第12~15章),介紹Kubernetes系統的進階話題。

第12章介紹Pod資源的排程政策及進階排程方式的應用,包括節點親和、Pod資源親和以及基于污點和容忍度的排程。

第13章介紹系統資源的擴充方式,包括自定義資源類型、自定義資源對象、自定義API及控制器、Master節點的高可用、基于Kubernetes的PaaS系統等話題。

第14章介紹資源名額、自定義名額、監控系統及HPA控制器的應用。

第15章介紹簡化應用管理的工具Helm,并基于Helm介紹如何為Kubernetes系統提供統一的日志收集與管理工具棧EFK。

精彩導讀

第1章:Kubernetes系統基礎

近十幾年來,IT領域新技術、新概念層出不窮,例如DevOps、微服務(Microservice)、容器(Container)、雲計算(Cloud Computing)和區塊鍊(Blockchain)等,直有“亂花漸欲迷人眼”之勢。另外,出于業務的需要,IT應用模型也在不斷地變革,例如,開發模式從瀑布式(Waterfall)到靈活(Agile)再到精益(Lean),甚至是與QA和Operations融合的DevOps,應用程式架構從單體(monolithic)模型到分層模型再到微服務,部署及打包方式從面向實體機到虛拟機再到容器,應用程式的基礎架構從自建機房到托管再到雲計算,等等,這些變革使得IT技術應用的效率大大提升,同時卻以更低的成本傳遞更高品質的産品。

尤其是以Docker為代表的容器技術的出現,終結了DevOps中傳遞和部署環節因環境、配置及程式本身的不同而造成的動辄幾種甚至十幾種部署配置的困境,将它們統一在容器鏡像(image)之上。如今,越來越多的企業或組織開始選擇以鏡像檔案作為傳遞載體。容器鏡像之内直接包含了應用程式及其依賴的系統環境、庫、基礎程式等,進而能夠在容器引擎上直接運作。于是,IT運維工程師(operator)無須關注開發應用程式的程式設計語言、環境配置等,甚至連業務邏輯本身也不必過多關注,而隻需要掌握容器管理的單一工具鍊即可。

部署的複雜度雖然降低了,但以容器格式運作的應用程式間的協同卻成了一個新的亟待解決的問題,這種需求在微服務架構中表現得尤為明顯。結果,以Kubernetes為代表的容器編排系統應需而生。

1.1 容器技術概述

容器是一種輕量級、可移植、自包含的軟體打包技術,它使得應用程式可以在幾乎任何地方以相同的方式運作。軟體開發工程師在自己筆記本上建立并測試完成的容器,無須任何修改就能夠在生産系統的虛拟機、實體機或雲主機上運作。

容器由應用程式本身和它的環境依賴(庫和其他應用程式)兩部分組成,并在主控端(Host)作業系統的使用者空間中運作,但與作業系統的其他程序互相隔離,它們的實作機制有别于諸如VMWare、KVM和Xen等實作方案的傳統虛拟化技術。容器與虛拟機的對比關系如圖1-1所示。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-1 容器和虛拟機對比

由于同一個主控端上的所有容器都共享其底層作業系統(核心空間),這就使得容器在體積上要比傳統的虛拟機小得多。另外,啟動容器無須啟動整個作業系統,是以容器部署和啟動的速度更快,開銷更小,也更容易遷移。事實上,容器賦予了應用程式超強的可移植能力。

1.1.1 容器技術的功用

IT系統在架構上已經疊代數十年之久,其環境複雜程度日趨加重,直有積重難返之勢。現如今,應用程式開發人員通常需要同時使用多種服務建構,并要架構IT資訊系統,涉及MQ、Cache和DB等,且很可能要部署到不同的環境中,如實體伺服器、虛拟伺服器、私有雲或公有雲之上。這些不同的主機或許還有着不同的系統環境,如RHEL、Debian或SUSE等Linux發行版,甚至是UNIX、Windows等。

結果,一方面應用程式包含了多種服務,每種服務均可能存在依賴的庫和軟體包;另一方面存在多種部署環境,而服務在運作時又可能需要動态遷移到不同的環境中。于是,各種服務和環境通過排列組合産生了一個大部署矩陣。應用程式開發工程師在編寫代碼時需要考慮不同的運作環境,而運維工程師則需要為不同的服務和平台配置環境。對他們雙方來說,這都必将是一項困難而艱巨的任務。

幸運的是,貨運系統的集裝箱機制為解決這個難題提供了有效的借鑒方案。Docker正是将集裝箱思想運用到軟體打包上,為代碼提供了一個基于容器的标準化運輸系統。Docker可以将幾乎任何應用程式及其依賴的運作環境都打包成一個輕量級、可移植、自包含的容器,并能夠運作于支援Docker容器引擎的所有作業系統之上。簡言之,容器的優勢主要表現在以下兩個方面。

  • 應用程式開發工程師:“一次建構,到處運作”(Build Once,Run Anywhere)。容器意味着環境隔離和可重複性,開發人員隻需為應用建立一個運作環境,并将其打包成容器便可在各種部署環境上運作,并與它所在的主控端環境隔離。
  • 運維工程師:“一次配置,運作所有”(Conf?igure Once,Run Anything)。一旦配置好标準的容器運作時環境,伺服器就可以運作任何容器,這使得運維人員的工作變得更高效、一緻和可重複。容器消除了開發、測試、生産環境的不一緻性。

1.1.2 容器簡史

容器技術的概念最初出現在2000年,當時稱為FreeBSD jail,這種技術可将FreeBSD系統分區為多個子系統(也稱為Jail)。2001年,通過Jacques Gélinas的VServer項目,隔離環境的實施理念進入了Linux領域。

Jail的目的是讓程序在經過修改的chroot環境中建立,而不會脫離和影響整個系統—chroot環境對檔案系統、網絡和使用者的通路都實作了虛拟化。然而,Jail在實施方面存在着不少的局限性,當它與Namespaces和CGroups等技術結合在一起之後,才讓這種隔離方法從構想變為了現實。後來,Linux容器項目(LXC)又為其添加了一些使用者常用的工具、模闆、庫和語言綁定,進而較好地改善了使用者使用容器技術時的體驗。

Docker在LXC項目的基礎上,從檔案系統、網絡互聯到程序隔離等方面對容器技術進行了進一步的封裝,極大地簡化了容器的建立和維護過程,進而促進了容器技術的大流行。Docker最初是由dotCloud公司創始人Solomon Hykes在法國期間發起的一個公司内部項目,并于2013年3月以Apache 2.0授權協定開源,其項目代碼托管于GitHub之上。雖然其最初的實作是基于LXC項目的,但Docker在後來的0.7版本轉為使用自行開發的libcontainer容器引擎,而1.11版本又将其換作了runC和containerd。

在2017年4月舉行的DockerCon上,Docker公司将GitHub上原本隸屬于Docker組織的Docker項目直接轉移到了一個新的名為Moby的組織下,并将其重命名為Moby項目。

1.1.3 Docker的功能限制

Docker本身非常适合用于管理單個容器,不過,一旦開始使用越來越多的容器封裝和運作應用程式,必将會導緻其管理和編排變得越來越困難。最終,使用者不得不對容器實施分組,以便跨所有容器提供網絡、安全、監控等服務。于是,以Kubernetes為代表的容器編排系統應運而生。

真正的生産型應用會涉及多個容器,這些容器必須跨多個伺服器主機進行部署。Kubernetes可以提供所需的編排和管理功能,以便使用者針對這些工作負載輕松完成大規模容器部署。而且,借助于Kubernetes的編排功能,使用者可以建構出跨多個容器的應用服務,并且可以實作跨叢集排程、擴充容器,以及長期持續管理這些容器的健康狀況等。使用中,Kubernetes還需要與網絡、存儲、安全性、監控及其他服務進行整合,以提供全面的容器基礎架構,如圖1-2所示。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-2 容器與容器編排(來源:RedHat Inc.)

Kubernetes利用容器的擴縮容機制解決了許多常見的問題,它将容器歸類到一起,形成“容器集”(Pod),為分組的容器增加了一個抽象層,用于幫助使用者排程工作負載(workload),并為這些容器提供所需的聯網和存儲等服務。Kubernetes的其他部分可幫助使用者在這些Pod之間達成負載均衡,同時確定運作正确數量的容器,以充分支援實際的工作負載。

1.2 Kubernetes概述

盡管公開面世不過短短數年時間,Kubernetes業已成為容器編排領域事實上的标準,其近一兩年的發展狀态也在不斷地驗證着Urs H?lzle曾經的斷言:無論是公有雲、私有雲抑或混合雲,Kubernetes都将作為一個為任何應用、任何環境提供的容器管理架構而無處不在。

1.2.1 Kubernetes簡史

Kubernetes(來自希臘語,意為“舵手”或“飛行員”)由Joe Beda、Brendan Burns和Craig McLuckie創立,而後Google的其他幾位工程師,包括Brian Grant和Tim Hockin等加盟共同研發,并由Google在2014年首次對外宣布。Kubernetes的開發和設計都深受Google内部系統Borg的影響,事實上,它的許多頂級貢獻者之前也是Borg系統的開發者。

Borg是Google内部使用的大規模叢集管理系統,久負盛名。它建構于容器技術之上,目的是實作資源管理的自動化,以及跨多個資料中心的資源使用率最大化。2015年4月,Borg論文《Large-scale cluster management at Google with Borg》伴随Kubernetes的高調宣傳被Google首次公開,人們終于有緣得窺其全貌。

事實上,正是由于誕生于容器世家Google,并站在Borg這個巨人的肩膀之上,充分受益于Borg過去十數年間積累的經驗和教訓,Kubernetes甫一面世就立即廣受關注和青睐,并迅速稱霸了容器編排技術領域。很多人将Kubernetes視為Borg系統的一個開源實作版本,在Google内部,Kubernetes的原始代号曾經是Serven of Nine,即星際迷航中友好的“Borg”角色,它辨別中的舵輪有七個輪輻就是對該項目代号的緻意,如圖1-3所示。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

Kubernetes v1.0于2015年7月21日釋出,緊随其後,Google與Linux基金會合作組建了Cloud Native Computing Foundation(雲原生計算基金會,簡稱為CNCF),并将Kubernetes作為種子技術予以提供。這之後,Kubernetes進入了版本快速疊代期,從此不斷地融入着新功能,如Federation、Network Policy API、RBAC、CRD和CSI,等等,并增加了對Windows系統的支援。

2017年可謂是容器生态發展史上具有裡程碑意義的一年。這一年,AWS、Azure和Alibaba Cloud都相繼在其原有容器服務上新增了對Kubernetes的支援,而Docker官方也在2017年10月宣布同時支援Swarm和Kubernetes編排系統。這一年,RKT容器派系的CoreOS舍棄掉自己的排程工具Fleet,将其商用平台Tectonic的重心轉移至Kubernetes。這一年,Mesos也于9月宣布了對Kubernetes的支援,其平台使用者可以安裝、擴充和更新多個生産級的Kubernetes叢集。這一年,Rancher Labs推出了其2.0版本的容器管理平台并宣布all-in Kubernetes,放棄了其内置多年的容器編排系統Cattle。類似的故事依然在進行,并且必将在一個時期内持續上演。

1.2.2 Kubernetes特性

Kubernetes是一種用于在一組主機上運作和協同容器化應用程式的系統,旨在提供可預測性、可擴充性與高可用性的方法來完全管理容器化應用程式和服務的生命周期的平台。使用者可以定義應用程式的運作方式,以及與其他應用程式或外部世界互動的途徑,并能實作服務的擴容和縮容,執行平滑滾動更新,以及在不同版本的應用程式之間排程流量以測試功能或復原有問題的部署。Kubernetes提供了接口和可組合的平台原語,使得使用者能夠以高度的靈活性和可靠性定義及管理應用程式。簡單總結起來,它具有以下幾個重要特性。

(1)自動裝箱

建構于容器之上,基于資源依賴及其他限制自動完成容器部署且不影響其可用性,并通過排程機制混合關鍵型應用和非關鍵型應用的工作負載于同一節點以提升資源使用率。

(2)自我修複(自愈)

支援容器故障後自動重新開機、節點故障後重新排程容器,以及其他可用節點、健康狀态檢查失敗後關閉容器并重新建立等自我修複機制。

(3)水準擴充

支援通過簡單指令或UI手動水準擴充,以及基于CPU等資源負載率的自動水準擴充機制。

(4)服務發現和負載均衡

Kubernetes通過其附加元件之一的KubeDNS(或CoreDNS)為系統内置了服務發現功能,它會為每個Service配置DNS名稱,并允許叢集内的用戶端直接使用此名稱發出通路請求,而Service則通過iptables或ipvs内建了負載均衡機制。

(5)自動釋出和復原

Kubernetes支援“灰階”更新應用程式或其配置資訊,它會監控更新過程中應用程式的健康狀态,以確定它不會在同一時刻殺掉所有執行個體,而此過程中一旦有故障發生,就會立即自動執行復原操作。

(6)密鑰和配置管理

Kubernetes的Conf?igMap實作了配置資料與Docker鏡像解耦,需要時,僅對配置做出變更而無須重新建構Docker鏡像,這為應用開發部署帶來了很大的靈活性。此外,對于應用所依賴的一些敏感資料,如使用者名和密碼、令牌、密鑰等資訊,Kubernetes專門提供了Secret對象為其解耦,既便利了應用的快速開發和傳遞,又提供了一定程度上的安全保障。

(7)存儲編排

Kubernetes支援Pod對象按需自動挂載不同類型的存儲系統,這包括節點本地存儲、公有雲服務商的雲存儲(如AWS和GCP等),以及網絡存儲系統(例如,NFS、iSCSI、GlusterFS、Ceph、Cinder和Flocker等)。

(8)批量處理執行

除了服務型應用,Kubernetes還支援批處理作業及CI(持續內建),如果需要,一樣可以實作容器故障後恢複。

1.2.3 Kubernetes概念和術語

Kubernetes使用共享網絡将多個實體機或虛拟機彙集到一個叢集中,在各伺服器之間進行通信,該叢集是配置Kubernetes的所有元件、功能和工作負載的實體平台。叢集中一台伺服器(或高可用部署中的一組伺服器)用作Master,負責管理整個叢集,餘下的其他機器用作Worker Node(早期版本中也稱為Minion),它們是使用本地和外部資源接收和運作工作負載的伺服器,如圖1-4所示。叢集中的這些主機可以是實體伺服器,也可以是虛拟機(包括IaaS雲端的VPS)。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-4:Kubernetes

(1)Master

Master是叢集的網關和中樞,負責諸如為使用者和用戶端暴露API、跟蹤其他伺服器的健康狀态、以最優方式排程工作負載,以及編排其他元件之間的通信等任務,它是使用者或用戶端與叢集之間的核心聯絡點,并負責Kubernetes系統的大多數集中式管控邏輯。單個Master節點即可完成其所有的功能,但出于備援及負載均衡等目的,生産環境中通常需要協同部署多個此類主機。Master節點類似于蜂群中的蜂王。

(2)Node

Node是Kubernetes叢集的工作節點,負責接收來自Master的工作指令并根據指令相應地建立或銷毀Pod對象,以及調整網絡規則以合理地路由和轉發流量等。理論上講,Node可以是任何形式的計算裝置,不過Master會統一将其抽象為Node對象進行管理。Node類似于蜂群中的工蜂,生産環境中,它們通常數量衆多。

Kubernetes将所有Node的資源集結于一處形成一台更加強大的“伺服器”,如圖1-5所示,在使用者将應用部署于其上時,Master會使用排程算法将其自動指派至某個特定的Node運作。在Node加入叢集或從叢集中移除時,Master也會按需重新編排影響到的Pod(容器)。于是,使用者無須關心其應用究竟運作于何處。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-5 Node組成的虛拟資源池

從抽象的視角來講,Kubernetes還有着衆多的元件來支撐其内部的業務邏輯,包括運作應用、應用編排、服務暴露、應用恢複等,它們在Kubernetes中被抽象為Pod、Service、Controller等資源類型,下面列出了幾個較為常用的資源抽象。

(1)Pod

Kubernetes并不直接運作容器,而是使用一個抽象的資源對象來封裝一個或者多個容器,這個抽象即為Pod,它也是Kubernetes的最小排程單元。同一Pod中的容器共享網絡名稱空間和存儲資源,這些容器可經由本地回環節口lo直接通信,但彼此之間又在Mount、User及PID等名稱空間上保持了隔離。盡管Pod中可以包含多個容器,但是作為最小排程單元,它應該盡可能地保持“小”,即通常隻應該包含一個主容器,以及必要的輔助型容器(sidecar),如圖1-6所示。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-6:Pod

(2)資源标簽

标簽(Label)是将資源進行分類的辨別符,資源标簽其實就是一個鍵值型(key/values)資料。标簽旨在指定對象(如Pod等)辨識性的屬性,這些屬性僅對使用者存在特定的意義,對Kubernetes叢集來說并不直接表達核心系統語義。标簽可以在對象建立時附加其上,并能夠在建立後的任意時間進行添加和修改。一個對象可以擁有多個标簽,一個标簽也可以附加于多個對象(通常是同一類對象)之上,如圖1-7所示。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-7 Kubernetes資源标簽

(3)标簽選擇器

标簽選擇器(Selector)全稱為“Label Selector”,它是一種根據Label來過濾符合條件的資源對象的機制。例如,将附有标簽“role: backend”的所有Pod對象挑選出來歸為一組就是标簽選擇器的一種應用,如圖1-8所示。使用者通常使用标簽對資源對象進行分類,而後使用标簽選擇器挑選出它們,例如将其建立為某Service的端點。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-8 标簽選擇器

(4)Pod控制器

盡管Pod是Kubernetes的最小排程單元,但使用者通常并不會直接部署及管理Pod對象,而是要借助于另一類抽象—控制器(Controller)對其進行管理。用于工作負載的控制器是一種管理Pod生命周期的資源抽象,它們是Kubernetes上的一類對象,而非單個資源對象,包括ReplicationController、ReplicaSet、Deployment、StatefulSet、Job等。以圖1-9中所示的Deployment控制器為例,它負責確定指定的Pod對象的副本數量精确符合定義,否則“多退少補”。使用控制器之後就不再需要手動管理Pod對象了,使用者隻需要聲明應用的期望狀态,控制器就會自動對其進行程序管理。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-9 Deployment控制器示意圖

(5)服務資源(Service)

Service是建立在一組Pod對象之上的資源抽象,它通過标簽選擇器標明一組Pod對象,并為這組Pod對象定義一個統一的固定通路入口(通常是一個IP位址),若Kubernetes叢集存在DNS附件,它就會在Service建立時為其自動配置一個DNS名稱以便用戶端進行服務發現。到達Service IP的請求将被負載均衡至其後的端點—各個Pod對象之上,是以Service從本質上來講是一個四層代理服務。另外,Service還可以将叢集外部流量引入到叢集中來。

(6)存儲卷

存儲卷(Volume)是獨立于容器檔案系統之外的存儲空間,常用于擴充容器的存儲空間并為它提供持久存儲能力。Kubernetes叢集上的存儲卷大體可分為臨時卷、本地卷和網絡卷。臨時卷和本地卷都位于Node本地,一旦Pod被排程至其他Node,此種類型的存儲卷将無法通路到,是以臨時卷和本地卷通常用于資料緩存,持久化的資料則需要放置于持久卷(persistent volume)之上。

(7)Name和Namespace

名稱(Name)是Kubernetes叢集中資源對象的辨別符,它們的作用域通常是名稱空間(Namespace),是以名稱空間是名稱的額外的限定機制。在同一個名稱空間中,同一類型資源對象的名稱必須具有唯一性。名稱空間通常用于實作租戶或項目的資源隔離,進而形成邏輯分組,如圖1-10所示。建立的Pod和Service等資源對象都屬于名稱空間級别,未指定時,它們都屬于預設的名稱空間“default”。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-10 名稱空間

(8)Annotation

Annotation(注解)是另一種附加在對象之上的鍵值類型的資料,但它擁有更大的資料容量。Annotation常用于将各種非辨別型中繼資料(metadata)附加到對象上,但它不能用于辨別和選擇對象,通常也不會被Kubernetes直接使用,其主要目的是友善工具或使用者的閱讀及查找等。

(9)Ingress

Kubernetes将Pod對象和外部網絡環境進行了隔離,Pod和Service等對象間的通信都使用其内部專用位址進行,如若需要開放某些Pod對象提供給外部使用者通路,則需要為其請求流量打開一個通往Kubernetes叢集内部的通道,除了Service之外,Ingress也是這類通道的實作方式之一。

1.3 Kubernetes叢集元件

一個典型的Kubernetes叢集由多個工作節點(worker node)和一個叢集控制平面(control plane,即Master),以及一個叢集狀态存儲系統(etcd)組成。其中Master節點負責整個叢集的管理工作,為叢集提供管理接口,并監控和編排叢集中的各個工作節點。各節點負責以Pod的形式運作容器,是以,各節點需要事先配置好容器運作依賴到的所有服務和資源,如容器運作時環境等。Kubernetes的系統架構如圖1-11所示。

Master節點主要由apiserver、controller-manager和scheduler三個元件,以及一個用于叢集狀态存儲的etcd存儲服務組成,而每個Node節點則主要包含kubelet、kube-proxy及容器引擎(Docker是最為常用的實作)等元件。此外,完整的叢集服務還依賴于一些附加元件,如KubeDNS等。

1.3.1 Master元件

Kubernetes的叢集控制平面由多個元件組成,這些元件可統一運作于單一Master節點,也可以以多副本的方式同時運作于多個節點,以為Master提供高可用功能,甚至還可以運作于Kubernetes叢集自身之上。Master主要包含以下幾個元件。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-11 Kubernetes系統元件

(1)API Server

API Server負責輸出RESTful風格的Kubernetes API,它是發往叢集的所有REST操作指令的接入點,并負責接收、校驗并響應所有的REST請求,結果狀态被持久存儲于etcd中。是以,API Server是整個叢集的網關。

(2)叢集狀态存儲(Cluster State Store)

Kubernetes叢集的所有狀态資訊都需要持久存儲于存儲系統etcd中,不過,etcd是由CoreOS基于Raft協定開發的分布式鍵值存儲,可用于服務發現、共享配置以及一緻性保障(如資料庫主節點選擇、分布式鎖等)。是以,etcd是獨立的服務元件,并不隸屬于Kubernetes叢集自身。生産環境中應該以etcd叢集的方式運作以確定其服務可用性。

etcd不僅能夠提供鍵值資料存儲,而且還為其提供了監聽(watch)機制,用于監聽和推送變更。Kubernetes叢集系統中,etcd中的鍵值發生變化時會通知到API Server,并由其通過watch API向用戶端輸出。基于watch機制,Kubernetes叢集的各元件實作了高效協同。

(3)控制器管理器(Controller Manager)

Kubernetes中,叢集級别的大多數功能都是由幾個被稱為控制器的程序執行實作的,這幾個程序被內建于kube-controller-manager守護程序中。由控制器完成的功能主要包括生命周期功能和API業務邏輯,具體如下。

  • 生命周期功能:包括Namespace建立和生命周期、Event垃圾回收、Pod終止相關的垃圾回收、級聯垃圾回收及Node垃圾回收等。
  • API業務邏輯:例如,由ReplicaSet執行的Pod擴充等。

    (4)排程器(Scheduler)

Kubernetes是用于部署和管理大規模容器應用的平台,根據叢集規模的不同,其托管運作的容器很可能會數以千計甚至更多。API Server确認Pod對象的建立請求之後,便需要由Scheduler根據叢集内各節點的可用資源狀态,以及要運作的容器的資源需求做出排程決策,其工作邏輯如圖1-12所示。另外,Kubernetes還支援使用者自定義排程器。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-12 Kubernetes排程器

1.3.2 Node元件

Node負責提供運作容器的各種依賴環境,并接受Master的管理。每個Node主要由以下幾個元件構成。

(1)Node的核心代理程式kubelet

kubelet是運作于工作節點之上的守護程序,它從API Server接收關于Pod對象的配置資訊并確定它們處于期望的狀态(desired state,後文不加差別地稱之為“目标狀态”)。kubelet會在API Server上注冊目前工作節點,定期向Master彙報節點資源使用情況,并通過cAdvisor監控容器和節點的資源占用狀況。

(2)容器運作時環境

每個Node都要提供一個容器運作時(Container Runtime)環境,它負責下載下傳鏡像并運作容器。kubelet并未固定連結至某容器運作時環境,而是以插件的方式載入配置的容器環境。這種方式清晰地定義了各元件的邊界。目前,Kubernetes支援的容器運作環境至少包括Docker、RKT、cri-o和Fraki等。

(3)kube-proxy

每個工作節點都需要運作一個kube-proxy守護程序,它能夠按需為Service資源對象生成iptables或ipvs規則,進而捕獲通路目前Service的ClusterIP的流量并将其轉發至正确的後端Pod對象。

1.3.3 核心附件

Kubernetes叢集還依賴于一組稱為“附件”(add-ons)的元件以提供完整的功能,它們通常是由第三方提供的特定應用程式,且托管運作于Kubernetes叢集之上,如圖1-11所示。下面列出的幾個附件各自為叢集從不同角度引用了所需的核心功能。

  • KubeDNS:在Kubernetes叢集中排程運作提供DNS服務的Pod,同一叢集中的其他Pod可使用此DNS服務解決主機名。Kubernetes自1.11版本開始預設使用CoreDNS項目為叢集提供服務注冊和服務發現的動态名稱解析服務,之前的版本中用到的是kube-dns項目,而SkyDNS則是更早一代的項目。
  • Kubernetes Dashboard:Kubernetes叢集的全部功能都要基于Web的UI,來管理叢集中的應用甚至是叢集自身。
  • Heapster:容器和節點的性能監控與分析系統,它收集并解析多種名額資料,如資源使用率、生命周期事件等。新版本的Kubernetes中,其功能會逐漸由Prometheus結合其他元件所取代。
  • Ingress Controller:Service是一種工作于傳統層的負載均衡器,而Ingress是在應用層實作的HTTP(s)負載均衡機制。不過,Ingress資源自身并不能進行“流量穿透”,它僅是一組路由規則的集合,這些規則需要通過Ingress控制器(Ingress Controller)發揮作用。目前,此類的可用項目有Nginx、Traef?ik、Envoy及HAProxy等。

1.4 Kubernetes網絡模型基礎

雲計算的核心是虛拟化技術,網絡虛拟化技術又是其最重要的組成部分,用于在實體網絡上虛拟多個互相隔離的虛拟網絡,實作網絡資源切片,提高網絡資源使用率,實作彈性化網絡。Kubernetes作為容器雲技術棧中的容器編排元件,必然需要在多租戶(名稱空間)的基礎上實作彈性網絡管理,這也是“基礎設施即代碼”的要求之一。

1.4.1 網絡模型概述

Kubernetes的網絡中主要存在四種類型的通信:同一Pod内的容器間通信、各Pod彼此之間的通信、Pod與Service間的通信,以及叢集外部的流量同Service之間的通信。Kubernetes為Pod和Service資源對象分别使用了各自的專用網絡,Pod網絡由Kubernetes的網絡插件配置實作,而Service的網絡則由Kubernetes叢集予以指定。為了提供更靈活的解決方式,Kubernetes的網絡模型需要借助于外部插件實作,它要求任何實作機制都必須滿足以下需求。

所有Pod間均可不經NAT機制而直接通信。

所有節點均可不經NAT機制而直接與所有容器通信。

容器自己使用的IP也是其他容器或節點直接看到的位址。換句話講,所有Pod對象都位于同一平面網絡中,而且可以使用Pod自身的位址直接通信。

Kubernetes使用的網絡插件必須能為Pod提供滿足以上要求的網絡,它需要為每個Pod配置至少一個特定的位址,即Pod IP。Pod IP位址實際存在于某個網卡(可以是虛拟裝置)上,而Service的位址卻是一個虛拟IP位址,沒有任何網絡接口配置此位址,它由kube-proxy借助iptables規則或ipvs規則重新定向到本地端口,再将其排程至後端Pod對象。Service的IP位址是叢集提供服務的接口,也稱為Cluster IP。

Pod網絡及其IP由Kubernetes的網絡插件負責配置和管理,具體使用的網絡位址可在管理配置網絡插件時指定,如10.244.0.0/16網絡。而Cluster網絡和IP則是由Kubernetes叢集負責配置和管理,如10.96.0.0/12網絡。

總結起來,Kubernetes叢集至少應該包含三個網絡,如圖1-13中的網絡環境所示。一個是各主機(Master、Node和etcd等)自身所屬的網絡,其位址配置于主機的網絡接口,用于各主機之間的通信,例如,Master與各Node之間的通信。此位址配置于Kubernetes叢集建構之前,它并不能由Kubernetes管理,管理者需要于叢集建構之前自行确定其位址配置及管理方式。第二個是Kubernetes叢集上專用于Pod資源對象的網絡,它是一個虛拟網絡,用于為各Pod對象設定IP位址等網絡參數,其位址配置于Pod中容器的網絡接口之上。Pod網絡需要借助kubenet插件或CNI插件實作,該插件可獨立部署于Kubernetes叢集之外,亦可托管于Kubernetes之上,它需要在建構Kubernetes叢集時由管理者進行定義,而後在建立Pod對象時由其自動完成各網絡參數的動态配置。第三個是專用于Service資源對象的網絡,它也是一個虛拟網絡,用于為Kubernetes叢集之中的Service配置IP位址,但此位址并不配置于任何主機或容器的網絡接口之上,而是通過Node之上的kube-proxy配置為iptables或ipvs規則,進而将發往此位址的所有流量排程至其後端的各Pod對象之上。Service網絡在Kubernetes叢集建立時予以指定,而各Service的位址則在使用者建立Service時予以動态配置。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-13 Kubernetes網絡環境

CNI是指容器網絡接口(Container Network Interface),是由CNCF(Cloud Native Computing Foundation)維護的項目,其由一系列的用于編寫配置容器網絡插件的規範和庫接口(libcni)組成,支援衆多插件項目。後文對此有詳細說明。

1.4.2 叢集上的網絡通信

Kubernetes叢集的用戶端大體可以分為兩類:API Server用戶端和應用程式(運作為Pod中的容器)用戶端,如圖1-14所示。第一類用戶端通常包含人類使用者和Pod對象兩種,它們通過API Server通路Kubernetes叢集完成管理任務,例如,管理叢集上的各種資源對象。第二類用戶端一般也包含人類使用者和Pod對象兩種,它們的通路目标是Pod上運作于容器中的應用程式提供的各種具體的服務,如redis或nginx等,不過,這些通路請求通常要經由Service或Ingress資源對象進行。另外,第二類用戶端的通路目标對象的操作要經由第一類用戶端建立和配置完成後才能進行。

帶你讀《Kubernetes進階實戰》之一:Kubernetes系統基礎

圖1-14 Kubernetes用戶端及其類型

通路API Server時,人類使用者一般借助于指令行工具kubectl或圖形UI(例如Kubernetes Dashboard)進行,也可通過程式設計接口進行通路,包括REST API。通路Pod中的應用時,其通路方式要取決于Pod中的應用程式,例如,對于運作Nginx容器的Pod來說,其最常用工具自然是浏覽器。

管理者(開發人員或運維人員)使用Kubernetes叢集的常見操作包括通過控制器建立Pod,在Pod的基礎上建立Service供第二類用戶端通路,更新Pod中的應用版本(更新和復原)以及對應用規模進行擴容或縮容等,另外還有叢集附件管理、存儲卷管理、網絡及網絡政策管理、資源管理和安全管理等,這些内容将在後面的章節中展開。不過,這一切的前提是要先建構出一個可用的Kubernetes叢集,這一内容将在第2章中着重講述。

1.5 本章小結

本章介紹了Kubernetes的曆史、功用、特性及其相關的核心概述和術語,并簡單描述了其架構及其各關鍵元件,以及叢集網絡中的常見通信方式,具體如下。

  • Kubernetes叢集主要由Master和Node兩類節點組成。
  • Master主要包含API Server、controller-manager、Scheduler和etcd幾個元件,其中API Server是整個叢集的網關。
  • Node主要由kubelet、kube-proxy和容器引擎等元件構成,kubelet是Kubernetes叢集的工作于節點之上的代理元件。

    完整的Kubernetes叢集還需要部署有CoreDNS(或KubeDNS)、Prometheus(或HeapSter)、Dashboard和Ingress Controller幾個附加元件。

Kubernetes的網絡中主要存在四種類型的通信:同一Pod内的容器間通信、各Pod間的通信、Pod與Service間的通信,以及叢集外部的流量同Service之間的通信。