從零開始入門 K8s

一、什麼是 Kubernetes

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

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

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

二、Kubernetes 有如下幾個核心的功能

  • 服務的發現與負載的均衡;

  • 容器的自動裝箱,我們也會把它叫做 scheduling,就是“調度”,把一個容器放到一個集羣的某一個機器上,Kubernetes 會幫助我們去做存儲的編排,讓存儲的聲明週期與容器的生命週期能有一個連接;

  • Kubernetes 會幫助我們去做自動化的容器的恢復。在一個集羣中,經常會出現宿主機的問題或者說是 OS 的問題,導致容器本身的不可用,Kubernetes 會自動地對這些不可用的容器進行恢復;

  • Kubernetes 會幫助我們去做應用的自動發佈與應用的回滾,以及與應用相關的配置密文的管理;

  • 對於 job 類型任務,Kubernetes 可以去做批量的執行;

  • 爲了讓這個集羣、這個應用更富有彈性,Kubernetes 也支持水平的伸縮。

下面,我們希望以三個例子跟大家更切實地介紹一下 Kubernetes 的能力。

 

1、調度

 

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

 

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

2、自動修復

 

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

 

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

3、水平伸縮

 

Kubernetes 有業務負載檢查的能力,它會監測業務上所承擔的負載,如果這個業務本身的 CPU 利用率過高,或者響應時間過長,它可以對這個業務進行一次擴容。

 

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

以上就是 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的調度執行操作的。

四、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 格式的。

下面有個例子:比如說,對於這個 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 這個概念,以及如何更好地去使用它。

 

五、以一個 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/

 

當大家安裝好之後,我會跟大家一起做一個例子,來做三件事情:

第一步,我們提交一個 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。

我們下面還是回到 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 架構;

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章