從零開始入門 K8s| 阿里技術專家詳解 K8s 核心概念

做者| 阿里巴巴資深技術專家、CNCF 9個 TCO 之一 李響node

1、什麼是 Kubernetes

Kubernetes,從官方網站上能夠看到,它是一個工業級的容器編排平臺。Kubernetes 這個單詞是希臘語,它的中文翻譯是「舵手」或者「飛行員」。在一些常見的資料中也會看到「ks」這個詞,也就是「K8s」,它是經過將 8 個字母「ubernete 」替換爲「8」而致使的一個縮寫。nginx

Kubernetes 爲何要用「舵手」來命名呢?你們能夠看一下這張圖:sql

 

這是一艘載着一堆集裝箱的輪船,輪船在大海上運着集裝箱奔波,把集裝箱送到它們該去的地方。咱們以前其實介紹過一個概念叫作 container,container 這個英文單詞也有另外的一個意思就是「集裝箱」。Kubernetes 也就藉着這個寓意,但願成爲運送集裝箱的一個輪船,來幫助咱們管理這些集裝箱,也就是管理這些容器。後端

這個就是爲何會選用 Kubernetes 這個詞來表明這個項目的緣由。更具體一點地來講:Kubernetes 是一個自動化的容器編排平臺,它負責應用的部署、應用的彈性以及應用的管理,這些都是基於容器的。api

2、Kubernetes 有以下幾個核心的功能:

  • 服務的發現與負載的均衡;
  • 容器的自動裝箱,咱們也會把它叫作 scheduling,就是「調度」,把一個容器放到一個集羣的某一個機器上,Kubernetes 會幫助咱們去作存儲的編排,讓存儲的聲明週期與容器的生命週期能有一個鏈接;
  • Kubernetes 會幫助咱們去作自動化的容器的恢復。在一個集羣中,常常會出現宿主機的問題或者說是 OS 的問題,致使容器自己的不可用,Kubernetes 會自動地對這些不可用的容器進行恢復;
  • Kubernetes 會幫助咱們去作應用的自動發佈與應用的回滾,以及與應用相關的配置密文的管理;
  • 對於 job 類型任務,Kubernetes 能夠去作批量的執行;
  • 爲了讓這個集羣、這個應用更富有彈性,Kubernetes 也支持水平的伸縮。

下面,咱們但願以三個例子跟你們更切實地介紹一下 Kubernetes 的能力。微信

一、調度網絡

Kubernetes 能夠把用戶提交的容器放到 Kubernetes 管理的集羣的某一臺節點上去。Kubernetes 的調度器是執行這項能力的組件,它會觀察正在被調度的這個容器的大小、規格。架構

好比說它所須要的 CPU以及它所須要的 memory,而後在集羣中找一臺相對比較空閒的機器來進行一次 placement,也就是一次放置的操做。在這個例子中,它可能會把紅顏色的這個容器放置到第二個空閒的機器上,來完成一次調度的工做。app

 

二、自動修復負載均衡

Kubernetes 有一個節點健康檢查的功能,它會監測這個集羣中全部的宿主機,當宿主機自己出現故障,或者軟件出現故障的時候,這個節點健康檢查會自動對它進行發現。

下面 Kubernetes 會把運行在這些失敗節點上的容器進行自動遷移,遷移到一個正在健康運行的宿主機上,來完成集羣內容器的一個自動恢復。

 

 

三、水平伸縮

Kubernetes 有業務負載檢查的能力,它會監測業務上所承擔的負載,若是這個業務自己的 CPU 利用率太高,或者響應時間過長,它能夠對這個業務進行一次擴容。

好比說在下面的例子中,黃顏色的過分忙碌,Kubernetes 就能夠把黃顏色負載從一份變爲三份。接下來,它就能夠經過負載均衡把原來打到第一個黃顏色上的負載平均分到三個黃顏色的負載上去,以此來提升響應的時間。

 

 

以上就是 Kubernetes 三個核心能力的簡單介紹。

3、Kubernetes 的架構

Kubernetes 架構是一個比較典型的二層架構和 server-client 架構。Master 做爲中央的管控節點,會去與 Node 進行一個鏈接。

全部 UI 的、clients、這些 user 側的組件,只會和 Master 進行鏈接,把但願的狀態或者想執行的命令下發給 Master,Master 會把這些命令或者狀態下發給相應的節點,進行最終的執行。

 

Kubernetes 的 Master 包含四個主要的組件:API Server、Controller、Scheduler 以及 etcd。以下圖所示:

 

  • API Server:顧名思義是用來處理 API 操做的,Kubernetes 中全部的組件都會和 API Server 進行鏈接,組件與組件之間通常不進行獨立的鏈接,都依賴於 API Server 進行消息的傳送;
  • Controller:是控制器,它用來完成對集羣狀態的一些管理。好比剛剛咱們提到的兩個例子之中,第一個自動對容器進行修復、第二個自動進行水平擴張,都是由 Kubernetes 中的 Controller 來進行完成的;
  • Scheduler:是調度器,「調度器」顧名思義就是完成調度的操做,就是咱們剛纔介紹的第一個例子中,把一個用戶提交的 Container,依據它對 CPU、對 memory 請求大小,找一臺合適的節點,進行放置;
  • etcd:是一個分佈式的一個存儲系統,API Server 中所須要的這些原信息都被放置在 etcd 中,etcd 自己是一個高可用系統,經過 etcd 保證整個 Kubernetes 的 Master 組件的高可用性。

咱們剛剛提到的 API Server,它自己在部署結構上是一個能夠水平擴展的一個部署組件;Controller 是一個能夠進行熱備的一個部署組件,它只有一個 active,它的調度器也是相應的,雖然只有一個 active,可是能夠進行熱備。

Kubernetes 的架構:Node

Kubernetes 的 Node 是真正運行業務負載的,每一個業務負載會以 Pod 的形式運行。等一下我會介紹一下 Pod 的概念。一個 Pod 中運行的一個或者多個容器,真正去運行這些 Pod 的組件的是叫作 kubelet,也就是 Node 上最爲關鍵的組件,它經過 API Server 接收到所須要 Pod 運行的狀態,而後提交到咱們下面畫的這個 Container Runtime 組件中。

 

在 OS 上去建立容器所須要運行的環境,最終把容器或者 Pod 運行起來,也須要對存儲跟網絡進行管理。Kubernetes 並不會直接進行網絡存儲的操做,他們會靠 Storage Plugin 或者是網絡的 Plugin 來進行操做。用戶本身或者雲廠商都會去寫相應的 Storage Plugin 或者 Network Plugin,去完成存儲操做或網絡操做。

在 Kubernetes 本身的環境中,也會有 Kubernetes 的 Network,它是爲了提供 Service network 來進行搭網組網的。(等一下咱們也會去介紹「service」這個概念。)真正完成 service 組網的組件的是 Kube-proxy,它是利用了 iptable 的能力來進行組建 Kubernetes 的 Network,就是 cluster network,以上就是 Node 上面的四個組件。

Kubernetes 的 Node 並不會直接和 user 進行 interaction,它的 interaction 只會經過 Master。而 User 是經過 Master 向節點下發這些信息的。Kubernetes 每一個 Node 上,都會運行咱們剛纔提到的這幾個組件。

下面咱們以一個例子再去看一下 Kubernetes 架構中的這些組件,是如何互相進行 interaction 的。

 

用戶能夠經過 UI 或者 CLI 提交一個 Pod 給 Kubernetes 進行部署,這個 Pod 請求首先會經過 CLI 或者 UI 提交給 Kubernetes API Server,下一步 API Server 會把這個信息寫入到它的存儲系統 etcd,以後 Scheduler 會經過 API Server 的 watch 或者叫作 notification 機制獲得這個信息:有一個 Pod 須要被調度。

這個時候 Scheduler 會根據它的內存狀態進行一次調度決策,在完成此次調度以後,它會向 API Server report 說:「OK!這個 Pod 須要被調度到某一個節點上。」

這個時候 API Server 接收到此次操做以後,會把此次的結果再次寫到 etcd 中,而後 API Server 會通知相應的節點進行此次 Pod 真正的執行啓動。相應節點的 kubelet 會獲得這個通知,kubelet 就會去調 Container runtime 來真正去啓動配置這個容器和這個容器的運行環境,去調度 Storage Plugin 來去配置存儲,network Plugin 去配置網絡。

這個例子咱們能夠看到:這些組件之間是如何相互溝通相互通訊,協調來完成一次Pod的調度執行操做的。

4、Kubernetes 的核心概念與它的 API

核心概念

第一個概念:Pod

Pod 是 Kubernetes 的一個最小調度以及資源單元。用戶能夠經過 Kubernetes 的 Pod API 生產一個 Pod,讓 Kubernetes 對這個 Pod 進行調度,也就是把它放在某一個 Kubernetes 管理的節點上運行起來。一個 Pod 簡單來講是對一組容器的抽象,它裏面會包含一個或多個容器。

好比像下面的這幅圖裏面,它包含了兩個容器,每一個容器能夠指定它所須要資源大小。好比說,一個核一個 G,或者說 0.5 個核,0.5 個 G。

固然在這個 Pod 中也能夠包含一些其餘所須要的資源:好比說咱們所看到的 Volume 卷這個存儲資源;好比說咱們須要 100 個 GB 的存儲或者 20GB 的另一個存儲。

 

在 Pod 裏面,咱們也能夠去定義容器所須要運行的方式。好比說運行容器的 Command,以及運行容器的環境變量等等。Pod 這個抽象也給這些容器提供了一個共享的運行環境,它們會共享同一個網絡環境,這些容器能夠用 localhost 來進行直接的鏈接。而 Pod 與 Pod 之間,是互相有 isolation 隔離的。

第二個概念:Volume

Volume 就是卷的概念,它是用來管理 Kubernetes 存儲的,是用來聲明在 Pod 中的容器能夠訪問文件目錄的,一個卷能夠被掛載在 Pod 中一個或者多個容器的指定路徑下面。

而 Volume 自己是一個抽象的概念,一個 Volume 能夠去支持多種的後端的存儲。好比說 Kubernetes 的 Volume 就支持了不少存儲插件,它能夠支持本地的存儲,能夠支持分佈式的存儲,好比說像 ceph,GlusterFS ;它也能夠支持雲存儲,好比說阿里雲上的雲盤、AWS 上的雲盤、Google 上的雲盤等等。

 

第三個概念:Deployment

Deployment 是在 Pod 這個抽象上更爲上層的一個抽象,它能夠定義一組 Pod 的副本數目、以及這個 Pod 的版本。通常你們用 Deployment 這個抽象來作應用的真正的管理,而 Pod 是組成 Deployment 最小的單元。

Kubernetes 是經過 Controller,也就是咱們剛纔提到的控制器去維護 Deployment 中 Pod 的數目,它也會去幫助 Deployment 自動恢復失敗的 Pod。

好比說我能夠定義一個 Deployment,這個 Deployment 裏面須要兩個 Pod,當一個 Pod 失敗的時候,控制器就會監測到,它從新把 Deployment 中的 Pod 數目從一個恢復到兩個,經過再去新生成一個 Pod。經過控制器,咱們也會幫助完成發佈的策略。好比說進行滾動升級,進行從新生成的升級,或者進行版本的回滾。

 

第四個概念:Service

Service 提供了一個或者多個 Pod 實例的穩定訪問地址。

好比在上面的例子中,咱們看到:一個 Deployment 可能有兩個甚至更多個徹底相同的 Pod。對於一個外部的用戶來說,訪問哪一個 Pod 其實都是同樣的,因此它但願作一次負載均衡,在作負載均衡的同時,我只想訪問某一個固定的 VIP,也就是 Virtual IP 地址,而不但願得知每個具體的 Pod 的 IP 地址。

咱們剛纔提到,這個 pod 自己可能 terminal go(終止),若是一個 Pod 失敗了,可能會換成另一個新的。

對一個外部用戶來說,提供了多個具體的 Pod 地址,這個用戶要不停地去更新 Pod 地址,當這個 Pod 再失敗重啓以後,咱們但願有一個抽象,把全部 Pod 的訪問能力抽象成一個第三方的一個 IP 地址,實現這個的 Kubernetes 的抽象就叫 Service。

實現 Service 有多種方式,Kubernetes 支持 Cluster IP,上面咱們講過的 kuber-proxy 的組網,它也支持 nodePort、 LoadBalancer 等其餘的一些訪問的能力。

 

第五個概念:Namespace

Namespace 是用來作一個集羣內部的邏輯隔離的,它包括鑑權、資源管理等。Kubernetes 的每一個資源,好比剛纔講的 Pod、Deployment、Service 都屬於一個 Namespace,同一個 Namespace 中的資源須要命名的惟一性,不一樣的 Namespace 中的資源能夠重名。

Namespace 一個用例,好比像在阿里巴巴,咱們內部會有不少個 business units,在每個 business units 之間,但願有一個視圖上的隔離,而且在鑑權上也不同,在 cuda 上面也不同,咱們就會用 Namespace 來去給每個 BU 提供一個他所看到的這麼一個看到的隔離的機制。

 

Kubernetes 的 API

下面咱們介紹一下 Kubernetes 的 API 的基礎知識。從 high-level 上看,Kubernetes API 是由 HTTP+JSON 組成的:用戶訪問的方式是 HTTP,訪問的 API 中 content 的內容是 JSON 格式的。

Kubernetes 的 kubectl 也就是 command tool,Kubernetes UI,或者有時候用 curl,直接與 Kubernetes 進行溝通,都是使用 HTTP + JSON 這種形式。

下面有個例子:好比說,對於這個 Pod 類型的資源,它的 HTTP 訪問的路徑,就是 API,而後是 apiVesion: V1, 以後是相應的 Namespaces,以及 Pods 資源,最終是 Podname,也就是 Pod 的名字。

 

若是咱們去提交一個 Pod,或者 get 一個 Pod 的時候,它的 content 內容都是用 JSON 或者是 YAML 表達的。上圖中有個 yaml 的例子,在這個 yaml file 中,對 Pod 資源的描述也分爲幾個部分。

第一個部分,通常來說會是 API 的 version。好比在這個例子中是 V1,它也會描述我在操做哪一個資源;好比說個人 kind 若是是 pod,在 Metadata 中,就寫上這個 Pod 的名字;好比說 nginx,咱們也會給它打一些 label,咱們等下會講到 label 的概念。在 Metadata 中,有時候也會去寫 annotation,也就是對資源的額外的一些用戶層次的描述。

比較重要的一個部分叫作 Spec,Spec 也就是咱們但願 Pod 達到的一個預期的狀態。好比說它內部須要有哪些 container 被運行;好比說這裏面有一個 nginx 的 container,它的 image 是什麼?它暴露的 port 是什麼?

當咱們從 Kubernetes API 中去獲取這個資源的時候,通常來說在 Spec 下面會有一個項目叫 status,它表達了這個資源當前的狀態;好比說一個 Pod 的狀態多是正在被調度、或者是已經 running、或者是已經被 terminates,就是被執行完畢了。

剛剛在 API 之中,咱們講了一個比較有意思的 metadata 叫作「label」,這個 label 能夠是一組 KeyValuePair。

好比下圖的第一個 pod 中,label 就多是一個 color 等於 red,即它的顏色是紅顏色。固然你也能夠加其餘 label,好比說 size: big 就是大小,定義爲大的,它能夠是一組 label。

這些 label 是能夠被 selector,也就是選擇器所查詢的。這個能力實際上跟咱們的 sql 類型的 select 語句是很是類似的,好比下圖中的三個 Pod 資源中,咱們就能夠進行 select。name color 等於 red,就是它的顏色是紅色的,咱們也能夠看到,只有兩個被選中了,由於只有他們的 label 是紅色的,另一個 label 中寫的 color 等於 yellow,也就是它的顏色是黃色,是不會被選中的。

 

經過 label,kubernetes 的 API 層就能夠對這些資源進行一個篩選,那這些篩選也是 kubernetes 對資源的集合所表達默認的一種方式。

例如說,咱們剛剛介紹的 Deployment,它多是表明一組的 Pod,它是一組 Pod 的抽象,一組 Pod 就是經過 label selector 來表達的。固然咱們剛纔講到說 service 對應的一組 Pod,就是一個 service 要對應一個或者多個的 Pod,來對它們進行統一的訪問,這個描述也是經過 label selector 來進行 select 選取的一組 Pod。

因此能夠看到 label 是一個很是核心的 kubernetes API 的概念,咱們在接下來的課程中也會着重地去講解和介紹 label 這個概念,以及如何更好地去使用它。

5、以一個 demo 結尾

最後一部分,我想以一個例子來結束,讓你們跟我一塊兒來嘗試一個 kubernetes,在嘗試 Kubernetes 以前,我但願你們能在本機上安裝一下 Kubernetes,安裝一個 Kubernetes 沙箱環境。

安裝這個沙箱環境,主要有三個步驟:

  • 首先須要安裝一個虛擬機,來在虛擬機中啓動 Kubernetes。咱們會推薦你們利用 virtualbox 來做爲虛擬機的運行環境;

安裝 VirtualBox: https://www.virtualbox.org/wiki/Downloads

  • 其次咱們須要在虛擬機中啓動 Kubernetes,Kubernetes 有一個很是有意思的項目,叫 minikube,也就是啓動一個最小的 local 的 Kubernetes 的一個環境。

minikube 咱們推薦使用下面寫到的阿里雲的版本,它和官方 minikube 的主要區別就是把 minikube 中所須要的 Google 上的依賴換成國內訪問比較快的一些鏡像,這樣就方便了你們的安裝工做;

安裝 MiniKube(中國版): https://yq.aliyun.com/articles/221687

  • 最後在安裝完 virtualbox 和 minikube 以後,你們能夠對 minikube 進行啓動,也就是下面這個命令。

啓動命令:minikube start —vm-driver virtualbox

若是你們不是 Mac 系統,其餘操做系統請訪問下面這個連接,查看其它操做系統如何安裝 minikube 沙箱環境。

https://kubernetes.io/docs/tasks/tools/install-minikube/

當你們安裝好以後,我會跟你們一塊兒作一個例子,來作三件事情:

1.提交一個 nginx deployment;

kubectl apply -f https://k8s.io/examples/application/deployment.yaml

2.升級 nginx deployment;

kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml

3.擴容 nginx deployment。

kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml

第一步,咱們提交一個 nginx 的 Deployment,而後對這個 Deployment 進行一次版本升級,也就是改變它中間 Pod 的版本。最後咱們也會嘗試對 nginx 進行一次擴容,進行一次水平的伸縮,下面就讓你們一塊兒跟我來嘗試這三個操做吧。

首先,咱們先看一下 minikube 的 status,能夠看到 kubelet master 和 kubectl 都是配置好的。

 

下一步咱們利用 kubectl 來看一下這個集羣中節選的狀態,能夠看到這個master 的節點已是running狀態:

 

咱們就以這個爲節點,下面咱們嘗試去看一下如今集羣中 Deployment 這個資源:

 

能夠看到集羣中沒有任何的 Deployment,咱們能夠利用 watch 這個語義去看集羣中 Deployment 這個資源的變化狀況。

下面咱們去作剛纔想要的三個操做:第一個操做是去建立一個 Deployment。能夠看到下面第一個圖,這是一個 API 的 content,它的 kind 是 Deployment,name 是 nginx-deployment, 有圖中它的 replicas 數目是2,它的鏡像版本是 1.7.9。

 
![](https://intranetproxy.alipay.com/skylark/lark/0/2019/png/168324/1564386046039-12c5b5d6-0c39-4029-9fac-a56f95999fc0.png#align=left&display=inline&height=108&originHeight=96&originWidth=149&size=0&status=done&width=167)![](https://intranetproxy.alipay.com/skylark/lark/0/2019/png/168324/1564386046103-5f491536-2800-4dad-aec7-a4865820f5a5.png#align=left&display=inline&height=484&originHeight=578&originWidth=468&size=0&status=done&width=392)

咱們下面仍是回到 kubectl 這個 commnd 來執行此次 Deployment 的真正的操做。咱們能夠看到一個簡單的操做,就會去讓 Deployment 不停地生成副本。

 

Deployment 副本數目是 2 個,下面也能夠 describe 一下如今的 Deployment 的狀態。咱們知道以前是沒有這個 Deployment 的,如今咱們去 describe 這個 nginx-deployment。

下圖中能夠看到:有一個 nginx-deployment 已經被生成了,它的 replicas 數目也是咱們想要的、selector 也是咱們想要的、它的 image 的版本也是 1.7.9。還能夠看到,裏面的 deployment-controller 這種版本控制器也是在管理它的生成。

 

下面咱們去升級這個 Deployment 版本,首先下載另一個 yaml 文件 deployment-update.yaml,能夠看到這裏面的 image 自己的版本號從 1.7.9 升級到 1.8。

 

接下來咱們從新 apply 新的 deployment-update 這個 yaml 文件。

能夠看到,在另外一邊的屏幕上顯示出了這個 Deployment 升級的一些操做,最終它的 up-to-date 值從 0 變成了 2,也就是說全部的容器都是最新版本的,全部的 Pod 都是最新版本的。咱們也能夠 discribe 具體去看一下是否是全部 Pod 的版本都被更新了,能夠看到這個 image 的版本由 1.7.9 真正更新到了 1.8。

最後,咱們也能夠看到 controller 又執行了幾回新的操做,這個控制器維護了整個 Deployment 和 Pod 狀態。

 

最後咱們演示一下給 Deployment 作水平擴張,下載另外一個 yaml 文件 deployment-scale.yaml,這裏面的 replicas 數目已經從 2 改爲了 4。

 

回到最開始的窗口,用 kubectl 去 apply 這個新的 deployment-scale.yaml 文件,在另一個窗口上能夠看到,當咱們執行了 deployment-scale 操做以後,它的容器 Pod 數目從 2 變成了 4。咱們能夠再一次 describ 一下當前集羣中的 deployment 的狀況,能夠看到它的 replicas 的數目從 2 變到了 4,同時也能夠看到 controller 又作了幾回新的操做,這個 scale up 成功了。

 

最後,讓咱們利用 delete 操做把咱們剛纔生成的 Deployment 給刪除掉。kubectl delete deployment,也是剛纔咱們自己的 deployment name,當咱們把它刪除掉以後,咱們今天全部的操做就完成了。

咱們再去從新 get 這個 Deployment,也會顯示這個資源再也不存在,這個集羣又回到了最開始乾淨的狀態。

 

本文總結

本文咱們關注了 Kubernetes 的核心概念以及 Kubernetes 的架構設計,主要有如下內容:

  • Kubernetes 是一個自動化的容器編排平臺,它負責應用的部署、應用的彈性以及應用的管理,這些都是基於容器的;
  • Kubernetes 架構是一個比較典型的二層架構和 server-client 架構;

阿里巴巴雲原生微信公衆號(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,作最懂雲原生開發者的技術公衆號。

原文連接

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索