<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          萬字警告 - k8s入門,理應(yīng)Pod先行!

          共 15822字,需瀏覽 32分鐘

           ·

          2021-04-26 17:55

          大家好,歡迎來到小菜個人 solo 學(xué)堂。在這里,知識免費(fèi),不吝吸收!關(guān)注免費(fèi),不吝動手!死鬼~看完記得給我來個三連哦!

          本文主要介紹 kubernetes中pod的使用

          如有需要,可以參考

          如有幫助,不忘 點(diǎn)贊 ?

          微信公眾號已開啟,小菜良記,沒關(guān)注的同學(xué)們記得關(guān)注哦!

          上篇文章我們說到如何搭建 k8s 集群,不知道看完的小伙伴有沒有自己去嘗試一下呢!

          不要讓貧窮扼殺了你學(xué) k8s 的興趣

          這篇我們本著善始善終的原則,繼續(xù)帶你搞明白 k8s 中的pod ,成為別人家的程序員~

          我們老樣子,先回顧下 k8s 中存在的幾種組件:

          那我們還得了解一下 k8s 中幾種常見的資源:

          • Master: 集群控制節(jié)點(diǎn),每個集群都至少需要一個 master 節(jié)點(diǎn)負(fù)責(zé)集群的管控
          • Node: 工作負(fù)載節(jié)點(diǎn),由 master 分配容器到這些 node 節(jié)點(diǎn)上,然后 node 節(jié)點(diǎn)上的docker 負(fù)責(zé)容器的運(yùn)行
          • Pod: kubernetes的最小控制單元,容器都是運(yùn)行在 pod 中的,一個pod中可以有 1 個或多個容器
          • Controller: 控制器,通過它來實(shí)現(xiàn)對 pod 的管理,比如啟動 pod,停止 pod,伸縮 pod 的數(shù)量等等
          • Service: pod 對外服務(wù)的統(tǒng)一入口,可以維護(hù)同一類的多個 pod
          • Label: 標(biāo)簽,用于對 pod 進(jìn)行分類,同一類的 pod 會擁有相同的標(biāo)簽
          • NameSpace: 命名空間,用來隔離 pod 的運(yùn)行環(huán)境

          這幾個概念先初步有個了解即可,接下來便是對每個概念展開說明的時候~那么,正片開始!

          Kubernetes

          一、資源管理

          在 kubernetes 中,所有的內(nèi)容都抽象為資源,用戶需要通過操作資源來管理 kubernetes

          關(guān)于對 資源管理 的理解,我們需要了解以下幾個概念:

          • kubernetes 本質(zhì)上是一個集群系統(tǒng),用戶可以在集群中部署各種服務(wù)

          • kubernetes 最小管理單元是 pod 而不是容器,所以我們需要將容器放在 pod 中運(yùn)行,而 pod 一般是由 pod控制器 進(jìn)行管理的

          • pod 提供服務(wù)后,我們需要借助 service 這個資源來實(shí)現(xiàn)訪問 pod 中的服務(wù)

          • pod 也支持?jǐn)?shù)據(jù)的持久化

          然后我們通過下面圖例梳理一下上面幾個概念:

          通過上面那張圖我們差不多就可以將 kubernetes 中的重點(diǎn)資源理解一遍了,大概明白每個資源在集群中起到的作用。

          我們有三種方式可以對資源對象進(jìn)行管理:

          • 命令式對象管理

          直接使用命令來操作 kubernetes 資源。例如:

          kubectl run nginx --image=nginx:1.19.0 -port=80
          • 命令式對象配置

          通過命令配置和配置文件來操作 kubernetes 資源。例如:

          kubectl create/patch -f nginx.yml
          • 聲明式對象配置

          通過 apply 命令和配置文件來操作 kubernetes 資源。例如:

          kubectl apply -f nginx.yml

          在 k8s 中我們一般使用 YAML 格式的文件來創(chuàng)建符合我們預(yù)期期望的 pod,這樣的 YAML 文件稱為資源清單。我們也比較鼓勵使用清單的方式來創(chuàng)建資源。

          如果我們使用 命令式對象管理,這種方式雖然比較簡單,可以直接創(chuàng)建一個 pod 出來,但是只能操作活動對象,無法進(jìn)行審計和跟蹤。

          命令式對象配置聲明式對象配置 在我們?nèi)粘V性趧?chuàng)建資源服務(wù)中是比較經(jīng)常用到。

          1)命令式對象管理

          kubectl 這個是 kubernetes 集群的命令行工具,通過 kubectl 能夠?qū)罕旧磉M(jìn)行管理,并能夠在集群上進(jìn)行容器化應(yīng)用的安裝部署。可以想象我們接下來的操作絕大部分都需要借助這個命令工具的幫助。

          我們之前也已經(jīng)使用過一次了:kubectl get nodes 。這個命令便是用來獲取集群中各個節(jié)點(diǎn)狀態(tài)的,那么不難想象,這個命令的語法:

          kubectl [command] [TYPE] [NAME] [flags]
          • **command:**指定對資源執(zhí)行的操作、例如:create、get、describe、delete...

          • TYPE: 指定資源類型。資源類型是大小寫敏感的,開發(fā)者能以單數(shù)、復(fù)數(shù)和縮寫的形式,例如:pod、pods、po

          • NAME: 指定資源的名稱。名稱也是大小寫敏感的,如果省略名稱,則會顯示所有的資源,例如 :kubectl get pods

          • flags: 指定可選的參數(shù)。例如:-s 、-server、-o ...

          k8s 支持的 command 有很多,我們可以跟 docker 一樣使用 kubectl --help 來獲取幫助文檔:

          文檔很多,當(dāng)然有些是常用的,有些是不常用的,小菜在這里給你們簡單分個類,下次有需要可以直接查看分類中的結(jié)果!

          命令分類

          1、 基礎(chǔ)命令

          名稱描述
          create通過文件名或標(biāo)準(zhǔn)輸入創(chuàng)建資源
          expose將一個資源公開為一個新的 Service
          run在集群中運(yùn)行一個特定的鏡像
          set在對象上設(shè)置特定的功能
          get顯示一個或多個資源
          edit使用默認(rèn)的編輯器編輯一個資源
          delete通過文件名、標(biāo)準(zhǔn)輸入、資源名稱或標(biāo)簽
          explain獲取文檔參考資料

          2、部署命令

          名稱描述
          rollout管理資源的發(fā)布
          rolling-update對給定的控制器進(jìn)行滾動更新
          scale擴(kuò)容或縮容 pod 數(shù)量,可對 Deployment、ReplicaSet、RC或Job 操作
          autoscale創(chuàng)建一個自動選擇擴(kuò)容或縮容并設(shè)置 pod 數(shù)量

          3、 集群管理命令

          名稱描述
          certificate修改證書資源
          cluster-info顯示集群信息
          top顯示資源使用情況,需要運(yùn)行 Heapster
          cordon標(biāo)記節(jié)點(diǎn)不可調(diào)度
          uncordon標(biāo)記節(jié)點(diǎn)可調(diào)度
          drain驅(qū)逐節(jié)點(diǎn)上的應(yīng)用,準(zhǔn)備下線維護(hù)
          taint修改節(jié)點(diǎn)的 taint 標(biāo)記

          4、故障\調(diào)試命令

          名稱描述
          describe顯示特定資源或資源組的詳細(xì)信息
          logs在一個 pod 中打印容器日志,如果 pod 中只有多個容器,容器名稱是可選的
          attach附加到一個運(yùn)行的容器
          exec執(zhí)行一個命令到容器中
          port-forward轉(zhuǎn)發(fā)一個或多個本地端口到一個 pod
          proxy運(yùn)行一個 proxy 到 kubernetes ApiServer
          cp拷貝文件或目錄到容器中
          auth檢查授權(quán)

          6、高級命令

          名稱描述
          apply通過文件名或標(biāo)準(zhǔn)輸入對資源應(yīng)用配置
          patch使用補(bǔ)丁修改、更新資源的字段
          replace通過文件名或標(biāo)準(zhǔn)輸入替換一個資源
          convert不同的API 版本之間轉(zhuǎn)換配置文件

          7、設(shè)置命令

          名稱描述
          label更新資源上的標(biāo)簽
          annotate更新資源上的標(biāo)簽
          completion用于實(shí)現(xiàn) kubectl 工具自動補(bǔ)全

          8、其他命令

          名稱描述
          api-versions打印受支持的 API 版本
          config修改 kubeconfig 文件(用于訪問 API,比如配置認(rèn)證信息)
          help獲取所有命令幫助
          plugin運(yùn)行一個命令行插件
          version打印客戶端和服務(wù)版本信息

          我們通過一些簡單的例子來簡單的認(rèn)識一下這個命令工具:

          2)資源清單

          不管是 命令式對象配置 還是 聲明式對象配置 我們都需要借助 yaml 資源清單創(chuàng)建。

          我們先來看看一個 pod controller(控制器)  的yaml 文件中有哪些內(nèi)容:

          上面便是一個完整的 deployment 資源配置清單。內(nèi)容很多,老樣子我們先混個眼熟,不是每個 deployment 都需要這么多的配置,以下便是必須存在的字段屬性介紹:

          名稱類型描述
          versionString屬于 k8s 哪一個API 版本或組
          kindString資源類型,如pod、deployment、service
          metadataObject元數(shù)據(jù)對象,嵌套字段
          metadata.nameString元數(shù)據(jù)對象的名字
          specObject定義容器的規(guī)范,創(chuàng)建的容器應(yīng)該有哪些特性
          spec.container[]List定義容器的列表
          spec.container[].nameString容器的名稱
          spec.container[].imageString定義要用到鏡像的名稱

          3)命令式對象配置

          我們結(jié)合以上必存的字段,可以簡單寫出一個 yaml (test.yaml) 文件:

          然后我們可以通過 命令式對象配置 的方式創(chuàng)建出一個 pod:

          kubectl create -f test.yaml

          4)聲明式對象配置

          聲明式對象配置命令式對象配置 很相似,但是這種方式都是基于 apply 這一個命令來進(jìn)行操作的。

          我們這邊復(fù)用一下上面創(chuàng)建的 test.yaml 文件

          kubectl apply -f test.yaml

          這種方式不能說是雞肋,它有它的特點(diǎn),比如說我們執(zhí)行完上述命令后再執(zhí)行一遍:

          kubectl apply -f tset.yaml

          可以發(fā)現(xiàn)是沒什么改動的,但是如果我們使用的是 create 來重復(fù)執(zhí)行兩遍呢?結(jié)果是報錯

          那么我們不難猜出 apply  這個命令就是對 createpatch 這兩個命令的結(jié)合:

          • 如果資源不存在,則執(zhí)行創(chuàng)建 等同于  create
          • 如果資源存在,則執(zhí)行更新 等同于 patch

          二、實(shí)戰(zhàn)入門

          接下來的階段便是我們針對 k8sNameSpace 和 Pod 資源展開說明了,小伙伴們打起精神了哦!

          image-20210414125544325

          1)Namespace

          Namespace(命名空間) 的作用便是用來實(shí)現(xiàn)多用戶之間的資源那個李的,通過將集群內(nèi)部的資源對象分配到不同的 Namespace 中,形成邏輯上的分組,便于不同分組在共享使用整個集群資源的同時被分別管理。默認(rèn)情況下,kubernetes 集群中的所有 pod 都是可以互相訪問的,但是有些時候我們不想出現(xiàn)這種情況,那就可以借助于 namespace

          在集群內(nèi)部有個默認(rèn)的Namespace - default ,我們創(chuàng)建資源的時候如果不指定 namespace,那么就會將該資源分配到該 default 的命名空間之下。

          [root@master test]# kubectl get namespace

          創(chuàng)建 Namespace 的方式也很簡單,通過以下指令便可創(chuàng)建:

          [root@master test]# kubectl create namespace aaa-test

          這樣子,我們就獲得了一個名稱為 aaa-test 的命名空間。或者我們也可以通過 命令式對象配置 的方式創(chuàng)建,先準(zhǔn)備一個 yaml 文件:

          apiVersion: v1
          kind: Namespace # yaml文件中大小寫敏感
          metadata:
            name:aaa-test  #命名空間的名稱

          然后執(zhí)行kubectl create -f namespace.yml, 這樣子我們同樣也可以獲得一個名稱為 aaa-test 的命名空間。

          然后我們就可以在資源創(chuàng)建的時候使用了:

          然后執(zhí)行 kubectl create -f nginx.yml,這樣子我們就可以獲取到一個 pod 資源,只有通過指定命名空間才能查看到我們的pod資源,這說明對其他用戶是隔離的:

          如果我們想刪除命名空間的話,可以使用指令:kubectl delete -f namespace.yml  或 kubectl delete ns ns名稱

          注: 如果將命名空間刪除,那么存在于該命名空間下的資源會全部被刪除

          2)Pod

          Pod 是 k8s 中可以創(chuàng)建和管理的最小單元,是資源對象模型中由用戶穿件或部署的最小資源對象模型,也是在 k8s 上運(yùn)行容器化應(yīng)用的資源對象。

          在使用 docker 的時候,我們清楚程序要運(yùn)行就必須部署在容器中,而在 k8s 中,我們?nèi)萜鞅仨毚嬖谂c pod 中,pod 就可以認(rèn)為是容器的封裝,一個 pod 可以存在一個或多個容器。

          ㈠ Pod 概念
          ① pod 特性

          1. 資源共享

          在一個pod 中,多個容器之間可以共享存儲和網(wǎng)絡(luò),相當(dāng)于一個邏輯意義上的主機(jī)。

          2.  生命周期短暫

          pod 是一個具有生命周期的組件,如果 pod 所在的節(jié)點(diǎn)發(fā)生故障,那么該節(jié)點(diǎn)上的pod 都會被調(diào)度到其他節(jié)點(diǎn)上,而調(diào)度后的pod是一個全新的 pod,與之前沒有任何關(guān)系。

          **3. 平坦的網(wǎng)絡(luò) **

          k8s 集群中的所有 pod 都在同一個網(wǎng)絡(luò)地址空間中,也就是說每個 pod 都可以通過其他 pod 的IP地址來實(shí)現(xiàn)訪問

          ② pod 分類
          • 普通 pod

          這種就是我們日常中經(jīng)常用到的。一旦被創(chuàng)建就會放入 etcd 中存儲,接著就會被調(diào)度到任一節(jié)點(diǎn)上運(yùn)行,當(dāng) Pod 里某個容器停止時,Kubernetes 會自動檢測到這個問題并且重新啟動這個 Pod 里某所有容器, 如果 Pod 所在的 Node 宕機(jī),則會將這個 Node 上的所有 Pod 重新調(diào)度到其它節(jié)點(diǎn)上。

          • 靜態(tài) pod

          靜態(tài)pod是由 kubelet 激進(jìn)型管理的僅存在于特定 node 節(jié)點(diǎn)上的,它們不能通過 API server 進(jìn)行管理,無法與 controller 控制器 進(jìn)行管理,并且 kubelet 也無法對其進(jìn)行健康檢測。

          ③ pod 聲明周期

          pod中有 5 中生命周期,我們都需要了解一下~

          狀態(tài)名稱描述
          PendingAPI Server已經(jīng)創(chuàng)建了 pod,但 pod 中的一個或多個容器的鏡像還沒有創(chuàng)建,包括鏡像下載過程
          RunningPod 內(nèi)所有容器都已創(chuàng)建,且至少一個容器處于運(yùn)行狀態(tài),正在啟動狀態(tài)或正在重啟狀態(tài)
          CompletedPod 內(nèi)所有容器均成功執(zhí)行退出,且不會再重啟
          FailedPod 內(nèi)所有容器都已退出,但至少一個容器退出失敗
          Unknown由于某種原因無法獲取 Pod 狀態(tài),例如網(wǎng)絡(luò)不通
          ④ pod重啟策略
          策略名稱描述
          Always當(dāng)容器失效時,有 kubelet 自動重啟該容器
          OnFailure當(dāng)容器停止運(yùn)行且退出碼不為0時,由 kubelet 自動重啟該容器
          Never不論容器運(yùn)行狀態(tài)如何,kubelet 都不會重啟該容器
          ⑤ pod 資源配置

          之前在 docker 我們有進(jìn)行測試沒有對 docker 資源進(jìn)行限額的時候,運(yùn)行一個 elasticSearch 鏡像的時候服務(wù)器直接卡死。那么在 docker 能做到資源限額,k8s 中自然也可以。

          Kubernetes 中可以設(shè)置限額的計算資源有 CPUMemory 兩種。Kubernetes 我們想要進(jìn)行配額限定需要設(shè)定兩個參數(shù):RequestLimits

          • Request:表示該資源最小的申請量,系統(tǒng)必須滿足要求
          • Limits:表示該資源最大允許使用量,不能超出這個量,當(dāng)容器試圖使用超過這個量的資源時,就會被 Kubernetes kill 掉并重啟

          上面表示一個 nginx 容器最少需要 0.25個CPU和 64 MB內(nèi)存,最多只能使用  0.5個CPU和 128 MB內(nèi)存。

          ㈡ pod 基操

          以下是一份 pod 的完整資源清單:

          這份清單大部分看起來會比較陌生,但是有部分關(guān)鍵屬性我們在上面已經(jīng)講過了,當(dāng)我們實(shí)際要用的時候如果記不起那么多我們可以使用指令 kubectl explain pod.xxx  的方式來查看每個屬性的含義,例如

          ① 簡單創(chuàng)建

          我們?nèi)绻胍獎?chuàng)建一個 pod ,只需要簡單準(zhǔn)備一份 test.yml 文件即可:

          然后通過 命令式對象配置 的指令 kubectl create -f test.yml 就可以獲取到一個含有 nginx 和 centos 容器的pod。然后我們通過指令kubectl get pod -n cbuc-test 查看當(dāng)前 pod 的狀態(tài)。

          docker 可以用 docker exec -it 進(jìn)入容器,k8s 也是類似此命令:

          kubectl exec -it pod名稱 -c 容器名稱 -n 命名空間 bash

          通過以上命令就可以進(jìn)入到我們的pod中

          如果 pod 中只有一個容器,-c 可以不用指定容器名稱

          ② 屬性說明

          上面我們已經(jīng)成功的創(chuàng)建了一個 pod,但是這只是一個簡單的 pod 配置,我們可以針對該 yaml 文件進(jìn)行擴(kuò)展~

          1. imagePullPolicy

          這個屬性用來設(shè)置鏡像拉取策略,在 k8s 中支持三種鏡像拉取策略:

          • Always: 總是從遠(yuǎn)程倉庫拉取鏡像
          • IfNotPresent: 本地有則使用本地鏡像,本地沒有則從遠(yuǎn)程倉庫拉取鏡像
          • Never: 只使用本地鏡像,從不去遠(yuǎn)程倉庫拉取,本地如果不存在就會報錯

          注意:

          如果鏡像號為指定版本號,則默認(rèn)策略為 :IfNotPresent

          如果鏡像號為 latest ,則默認(rèn)策略為:Always

          2. command

          command 是用于在 pod 中的容器初始化完畢之后運(yùn)行一個命令。

          我們在上面創(chuàng)建了一個 centos的pod,然后在pod初始化完成后,便會執(zhí)行 command 中的命令,我們可以通過 kubectl exec -it pod名稱 -n 命名空間 bash 然后進(jìn)入pod中查看 /mnt/test.txt

          或者我們可以在pod外部執(zhí)行命令:

          kubectl exec pod名稱 -n 命名空間 -c 容器名稱 -- shell命令

          3. args

          我們上面說到的 command 已經(jīng)可以完成啟動命令和傳遞參數(shù)的功能,但是我們 k8s 中還提供了一個 args 選項(xiàng),用于傳遞參數(shù)。k8s 中使用 command 和 args 兩個參數(shù)可以實(shí)現(xiàn)覆蓋 Dockerfile 中的 ENTRYPOINE 的功能。

          注意:

          1. 如果 command 和 args 均沒有寫,那么是使用 Dockerfile 的配置
          2. 如果 command 寫了,args 沒有寫,那么 Dockerfile 默認(rèn)的配置會被忽略,執(zhí)行輸入的 command
          3. 如果 command 沒寫,args 寫了, 那么 Dockerfile 中配置的 ENTRYPOINT 的命令會被執(zhí)行,使用當(dāng)前 args 的參數(shù)
          4. 如果 command 和 arg 都寫了,那么 Dockerfile 的配置就會被忽略,執(zhí)行 command 命令加上 args 參數(shù)

          4. env

          用于在 pod 中的容器設(shè)置環(huán)境變量

          進(jìn)入pod查看:

          5. ports

          ports 在 k8s 的屬性類型是 Object,我們可以通過 kubectl explain pod.spec.containers.ports 查看該對象下的屬性:

          我們從圖中可以發(fā)現(xiàn)該對象由5個屬性:

          • containerPort: 容器要監(jiān)聽的端口(0~65536)

          • hostIP: 要將外部端口綁定到主機(jī)IP(一般省略)

          • hostPort: 容器要在主機(jī)上公開的端口,如果設(shè)置,主機(jī)上只能運(yùn)行容器的一個副本(一般省略)

          • name: 端口名稱,如果指定,必須保證name 在pod中是唯一的

          • protocol: 端口協(xié)議,必須是 UDP、TCP或 SCTP,默認(rèn)為 TCP

          我們簡單看個 nginx 的例子:

          創(chuàng)建方式可以選擇 3 中創(chuàng)建方式任意一種,然后創(chuàng)建完成后我們可以通過 podIp+containerPort 來訪問到 nginx 資源

          6. resources

          容器中運(yùn)行的程序需要占用一定的資源(CPU和內(nèi)存),在運(yùn)行的時候如果不對某個容器的資源進(jìn)行限制,那么它可能會耗盡服務(wù)器的大量資源,防止這種情況的發(fā)生,k8s 中提供了 resource 屬性,對資源進(jìn)行限制。這個屬性下有兩個子選項(xiàng):

          • limits: 用于限制運(yùn)行容器的最大占用資源,當(dāng)容器占用資源超過 limit 時會被終止,并進(jìn)行重啟
          • requests:  用于設(shè)置容器需要的最小資源,如果環(huán)境資源不夠,容器將會無法啟動

          看個使用例子:

          • cpu: core數(shù),可以為整數(shù)或小數(shù)
          • memory: 內(nèi)存大小,可以使用 Gi, Mi, G,M 等形式
          ㈢ pod 擴(kuò)展
          ① 生命周期

          任何事物的創(chuàng)建過程都有屬于它自己的生命周期,而 pod 對象從創(chuàng)建到銷毀,這段的時間范圍便稱為 pod 的生命周期。生命周期一般包含下面幾個過程:

          運(yùn)行初始化容器 (init container) 過程

          運(yùn)行主容器 (main container)

          2.1 容器啟動后鉤子(post start),容器終止前鉤子(pre stop)

          2.2 容器存活性檢測(liveness probe),就緒性檢測(readiness probe)

          pod 終止過程

          在整個生命周期中,pod 也會相應(yīng)的出現(xiàn) 5 中狀態(tài),如下:

          • 掛起(Pending): apiServer 已經(jīng)創(chuàng)建 pod 資源對象,但它尚未被調(diào)度完成或者仍處于下載鏡像的過程中
          • 運(yùn)行中(Running): pod 已經(jīng)被調(diào)度至某節(jié)點(diǎn),并且所用容器都已經(jīng)被 kubelet 創(chuàng)建完成
          • 成功(Succeeded): pod 中的所有容器都已經(jīng)成功終止并且不會被重啟
          • 失敗(Failed): 所有容器都已經(jīng)終止,但至少有一個容器終止失敗,即容器返回了非 0 值的退出狀態(tài)
          • 未知(UnKnown): apiServer 無法獲取到 pod 對象的狀態(tài)信息,通常是因?yàn)榫W(wǎng)絡(luò)通信失敗導(dǎo)致的

          ⑴ pod 的創(chuàng)建過程

          kubernetes 啟動后,無論是 master 節(jié)點(diǎn) 亦或者 node 節(jié)點(diǎn),都會將自身的信息存儲到 etcd 數(shù)據(jù)庫中

          1. 用戶通過 kubectl 或其他 api 客戶端提交需要創(chuàng)建的 pod 信息給 apiServer
          2. apiServer  接收到信息后會生成 pod 對象信息,并存入 etcd 數(shù)據(jù)庫中,返回確認(rèn)消息給客戶端
          3. apiServer 開始反映 etcd 中 pod 對象的變化,其他組件會使用 watch 機(jī)制來跟蹤檢查 apiServer 上的變動
          4. scheduler 發(fā)現(xiàn)如果有新的 pod 對象需要創(chuàng)建,便會為 pod 分配主機(jī)并將結(jié)果回送至 apiServer
          5. node 節(jié)點(diǎn)上的 kubectl 發(fā)現(xiàn)有 pod 調(diào)度過來,會嘗試調(diào)用 docker 啟動容器,并將結(jié)果返回給 apiServer
          6. apiServer 將接收到的 pod 狀態(tài)信息存入 etcd

          ⑵ pod 的終止過程

          1. 用戶首先向 apiServer 發(fā)送刪除 pod 對象的命令
          2. apiServer 中的pod對象信息會隨著時間的推移而更新,在寬限期內(nèi)(默認(rèn)30s),pod 會被視為 dead 狀態(tài),并將 pod 標(biāo)記為 terminating 狀態(tài)
          3. kubelet 在監(jiān)控到 pod 對象轉(zhuǎn)為 terminating 狀態(tài)的同時啟動 pod 關(guān)閉過程
          4. 端點(diǎn)控制器監(jiān)控到 pod 對象的關(guān)閉行為時將其從所有匹配到此端點(diǎn)的 service 資源的端點(diǎn)列表中移除
          5. 如果當(dāng)前 pod 對象定義了 preStop 鉤子處理器,則在其標(biāo)記為 terminating 后即會以同步的方式啟動執(zhí)行
          6. pod 對象中的容器進(jìn)程接收到停止信號,并停止容器
          7. 寬限期結(jié)束后,如果 pod 中還存在仍在運(yùn)行的進(jìn)程,那么 pod 對象就會收到立即終止的信號
          8. kubelet 請求 apiServer 將此 pod 資源的寬限期設(shè)置為 0 從而完成刪除操作。

          ⑶ 初始化容器

          初始化容器,看名字也大致能夠猜到初始化容器是在 pod 主容器啟動之前要運(yùn)行的容器,主要是做一些主容器的前置工作。

          特征:

          • 初始化容器必須運(yùn)行完成直至結(jié)束,如果運(yùn)行失敗便會進(jìn)行重啟直至成功
          • 初始化容器必須按照順序執(zhí)行,只有前一個成功后,后一個才能執(zhí)行

          這里簡單看一個使用例子:

          我們在初始化容器中定義了一個 centos 容器,只有 ping 通對應(yīng)的地址才會啟動成功,已知當(dāng)前網(wǎng)絡(luò)能通 192.168.108.101

          可以看到,在初始化容器成功啟動的情況下,我們的 nginx 容器也能運(yùn)行成功,但是如果我們把 ping 的地址改一下,就會導(dǎo)致初始化容器啟動失敗,那么正常容器也是會啟動失敗的:

          ⑷ 鉤子函數(shù)

          不知道你對鉤子函數(shù)這個詞是否有一些了解~ 鉤子函數(shù)能夠感知自身生命周期中的事件,在相應(yīng)的時刻到來時就會運(yùn)行用戶指定的程序代碼。

          k8s 提供了兩個鉤子函數(shù),分別是啟動之后停止之前

          • post start:容器創(chuàng)建之后執(zhí)行。如果失敗了會重啟容器
          • pre stop: 容器終止之前執(zhí)行。執(zhí)行完成之后容器將成功終止,在其完成之前會阻塞刪除容器的操作

          那么鉤子函數(shù)有了,我們該如何定義這個函數(shù)呢?在 k8s 中鉤子函數(shù)支持使用三種方式定義動作:

          • exec 命令

          在容器中執(zhí)行一次命令,如果命令執(zhí)行的退出碼為0,則認(rèn)為程序正常,否則反之。

          • tcpSocket

          將會嘗試訪問一個用戶容器的端口,如果能夠建立這條連接,則認(rèn)為程序正常,否則不正常

          • httpGet

          調(diào)用容器內(nèi)Web應(yīng)用的URL,如果返回的狀態(tài)碼在200和399之間,則認(rèn)為程序正常,否則不正常

          ② 容器探測

          容器探測是用來檢測容器中的應(yīng)用實(shí)例是否正常工作,是保障業(yè)務(wù)可用性的一種傳統(tǒng)機(jī)制。如果經(jīng)過探測,實(shí)例的狀態(tài)不符合預(yù)期結(jié)果,那么 k8s 就會把這個實(shí)例刪除。在 k8s 中也支持了兩種探針來實(shí)現(xiàn)容器探測:

          • liveness probes: 存活性探針,用于檢測應(yīng)用實(shí)例當(dāng)前是否處于正常運(yùn)行狀態(tài),如果不是,k8s 會重啟容器
          • readiness probe: 就緒性探針,用于檢測應(yīng)用實(shí)例當(dāng)前是否可以接受請求,如果不能,k8s不會轉(zhuǎn)發(fā)流量

          注意:

          livenessProbe 決定了容器是否需要重啟

          readinessProbe 決定了是否將請求轉(zhuǎn)發(fā)給容器

          這兩種探針支持的檢測方式與上面生命周期檢測的方式一樣:

          • exec 命令
          • TCPSocket
          • httpGet
          ③ 重啟策略

          容器探測 檢測出容器有問題后, k8s 就會對容器所在的 pod 進(jìn)行重啟,而這些重啟的定義便是由 pod 自身的重啟策略決定的,pod 的重啟策略有如下3種:

          • Always: 容器失效時,自動重啟該容器(默認(rèn)值)

          • OnFailure: 容器終止運(yùn)行且退出碼不為0時重啟

          • Never: 不論狀態(tài)為何,都不重啟該容器

          首次需要重啟的容器會立即進(jìn)行重啟,如果隨后還需要重啟,那么kubectl 便會延遲一段時間后才進(jìn)行,反復(fù)重啟的操作延遲時長為 10s,20s,30s,40s,80s,160s和300s,其中300s是最大的延遲時長

          ㈣ pod 調(diào)度

          上面說到過默認(rèn)情況下,pod 在哪個 Node 節(jié)點(diǎn)上運(yùn)行是由 Scheduler組件采用相應(yīng)的算法計算出來的,這個過程是不受人工控制的。但是在實(shí)際的使用場景中我們有時候想要控制某些pod到達(dá)某些節(jié)點(diǎn)上,而針對于這種需求,k8s 當(dāng)然也是可以滿足的~ 在 k8s 中它提供了 4 中調(diào)度方式:

          • 自動調(diào)度:scheduler 組件計算運(yùn)行在哪個node節(jié)點(diǎn)上
          • 定向調(diào)度: 由用戶自定義,需要用到 NodeNameNodeSelector  屬性
          • 親和性調(diào)度: 由用戶自定義,需要用到 NodeAffinity、PodAffinity、PodAntiAffinity 屬性
          • 污點(diǎn)容忍調(diào)度: 由用戶自定義,需要用到 Taints、Toleration屬性
          ① 定向調(diào)度

          我們可以利用 nodeName 或者 nodeSelector 來標(biāo)記 pod 需要調(diào)度到期望的 node 節(jié)點(diǎn)上。這里的標(biāo)記是強(qiáng)制性,不管 node 節(jié)點(diǎn)有沒有宕機(jī),都會往這個節(jié)點(diǎn)上面調(diào)度,因此如果node節(jié)點(diǎn)宕機(jī)的話,就會導(dǎo)致 pod 運(yùn)行失敗。

          • NodeName

          這個屬性用于強(qiáng)制約束將 Pod 調(diào)度到指定名稱的 node節(jié)點(diǎn)上,這種方式,其實(shí)就是直接跳過 scheduler 的調(diào)度邏輯。

          上面已經(jīng)準(zhǔn)備了一個 pod 的yaml文件,我們創(chuàng)建看下是否能夠調(diào)度到我們想要的節(jié)點(diǎn)上

          可以看到 pod 節(jié)點(diǎn)已經(jīng)成功的調(diào)度到名稱為 node02 的節(jié)點(diǎn)上了

          • NodeSelector

          這個屬性是用于將 pod 調(diào)度到添加了指定標(biāo)簽上的 node 節(jié)點(diǎn)上(k8s 中資源可以打標(biāo)簽,我們一樣可以對 node 節(jié)點(diǎn)打標(biāo)簽)。它是通過 k8s 的 label-selector 機(jī)制實(shí)現(xiàn)的,就是說在 pod 創(chuàng)建之前,會由 scheduler 的使用 MatchNodeSelector 的調(diào)度策略進(jìn)行 label 匹配,找出目標(biāo) node,然后將 pod 調(diào)度到目標(biāo)節(jié)點(diǎn),該匹配規(guī)則也是屬于強(qiáng)制約束。

          測試:

          首先對 node 節(jié)點(diǎn)打上標(biāo)簽:

          kubectl label nodes node02 app=node-dev

          查看是否打成功:

          然后準(zhǔn)備一份 pod yaml文件:

          然后我們創(chuàng)建后查看:

          ② 親和度調(diào)度

          上面介紹的定向調(diào)度是屬于強(qiáng)制性約束,如果沒有滿足的node節(jié)點(diǎn)供運(yùn)行的話,pod 就是啟動失敗,這樣子就很大地限制了它的使用場景。所以我們接下來介紹的 親和度調(diào)度 (Affinity) 便是用來解決這種問題的。

          它是通過配置的形式,實(shí)現(xiàn)優(yōu)先選擇滿足條件的 Node 進(jìn)行調(diào)度,如果有就調(diào)度到對應(yīng)節(jié)點(diǎn),如果沒有,也可以調(diào)度到不滿足條件的節(jié)點(diǎn)上,這樣可以使調(diào)度更加靈活

          Affinity分為三大類:

          • nodeAffinity(node親和性)

          node為目標(biāo),解決 pod 可以調(diào)度到哪些 node 的問題

          這個屬性中又存在 requiredDuringSchedulingIgnoredDuringExecution (硬限制)preferredDuringSchedulingIgnoredDuringExecution (軟限制) 兩種

          Ⅰ、requiredDuringSchedulingIgnoredDuringExecution (硬限制)

          這個限制和上面說到的定向調(diào)度有點(diǎn)像,只選擇滿足條件的 node 節(jié)點(diǎn)進(jìn)行調(diào)度,使用例子如下:

          上面我們創(chuàng)建了一個 pod,會在標(biāo)簽 keyapp,且valuenode-pro 或 node-test 的節(jié)點(diǎn)上選擇,但是并不存在具備這個標(biāo)簽的節(jié)點(diǎn),因此這個pod 一直處于掛起的狀態(tài)~

          我們上面看到了一個新的屬性 matchExpressions,這個是用來編寫關(guān)系表達(dá)式的,具體使用方法如下:

          - matchExpressions:
            - key: app # 匹配存在標(biāo)簽的key為 app 的節(jié)點(diǎn)
              operator: Exists
            - key: app # 匹配標(biāo)簽的key為 app ,且value是"xxx"或"yyy"的節(jié)點(diǎn)
              operator: In
              values: ["xxx","yyy"]
            - key: app # 匹配標(biāo)簽的key為 app, 且value大于"xxx"的節(jié)點(diǎn)
              operator: Gt
              values: "xxx"

          Ⅱ、 preferredDuringSchedulingIgnoredDuringExecution (軟限制)

          上面已經(jīng)了解到了 硬限制 的使用,軟限制 的使用如下,我們直接來看 yaml 文件:

          這邊可以看到雖然不存在滿足條件的node,但是也是可以成功運(yùn)行pod 的,只是調(diào)度到了不滿足條件的 node 上!

          我們來總結(jié)一下硬限制和軟限制的用法:

          • podAffinity(pod 親和性)

          以 pod 為目標(biāo),解決pod可以和哪些已存在的pod部署在同一個拓?fù)溆蛑械膯栴}。

          podAffinity 同樣也存在 硬限制 和 軟限制 ,我們接下來直接看下如何配置:

          image-20210423130432962

          上面便是 podAffinity 硬限制的yaml文件,除了眼熟的屬性之外,我們還看到了一個新的屬性 topologyKey,那么這個屬性是用來干嘛的呢?

          topologyKey 用于指定調(diào)度時作用域:

          • 如果值為 kubernetes.io/hostname ,說明是以 node 節(jié)點(diǎn)為區(qū)分范圍
          • 如果值為 kubernetes.io/os, 則以 node 節(jié)點(diǎn)的操作系統(tǒng)來區(qū)分

          了解完硬限制的編寫,軟限制也是與上面 node親和度的用法相似,這里不再贅訴~

          • podAntiAffinity(pod反親和性)

          以pod 為目標(biāo),解決pod不能和哪些已存在的pod部署在同一個拓?fù)溆蛑械膯栴}。

          這個使用就是和上面基本一致了,就是和 podAffinity 要求反著來就是了,屬性名換個就完事了~

          這個yaml文件代表的含義便是選擇不和標(biāo)簽帶有 app=test01app=test02 的pod "共處一室"。同樣存在硬限制和軟限制的配置

          親和性反親和性 的使用場景

          親和性: 如果兩個應(yīng)用交互頻繁,那就有必要利用親和性讓兩個應(yīng)用盡可能的靠近,可以減少因?yàn)榫W(wǎng)絡(luò)通信而帶來的性能損耗

          反親和性: 當(dāng)應(yīng)用采用多副本部署的時候,有必要采用反親和性讓各個應(yīng)用實(shí)例打散分布在各個 node 上,這樣可以提高服務(wù)的高可用性

          ③ 污點(diǎn)(Taint)

          我們先來看下目前 pod 存在于每個節(jié)點(diǎn)的情況,

          是否發(fā)現(xiàn)了一個問題,那就是 pod 基本都分布在了 node 節(jié)點(diǎn)上,而 master 節(jié)點(diǎn)卻沒有運(yùn)行任何pod。而這個原因便是和我們要講到的污點(diǎn) 有關(guān)系了!

          我們前面說到的調(diào)度都是站在 pod 的角度,讓 pod 選擇 node 進(jìn)行運(yùn)行,而污點(diǎn)很好的進(jìn)行了反轉(zhuǎn)。讓node節(jié)點(diǎn)決定讓哪些pod可以調(diào)度過來!

          Node 可以設(shè)置 污點(diǎn) ,設(shè)置上 污點(diǎn) 之后,就會和 pod 之間形成了一種排斥關(guān)系。這種關(guān)系存在的意義便是可以拒絕 pod 調(diào)度進(jìn)來,也可以將已經(jīng)存在的 pod 驅(qū)逐出去。

          污點(diǎn)格式: key=value:effect

          keyvalue 是污點(diǎn)的標(biāo)簽,而 effect 則是用來描述污點(diǎn)的作用,支持三種功能定義:

          • PreferNoSchedule

          k8s將盡量避免把 Pod 調(diào)度到具有該污點(diǎn)的 node 節(jié)點(diǎn)上,除非沒有其他節(jié)點(diǎn)可以調(diào)度。(盡量不要來,除非沒辦法)

          • NoScheduler

          k8s 將不會把 Pod 調(diào)度到具有該污點(diǎn)的 node 節(jié)點(diǎn)上,但不會影響當(dāng)前 Node 上已經(jīng)存在的 pod。(新的不要來,在這的就別動了)

          • NoExecute

          k8s 將不會把 Pod 調(diào)度到具有該污點(diǎn)的 node 節(jié)點(diǎn)上,同時也會將 Node 上已經(jīng)存在的 Pod 驅(qū)逐。(新的不要來,在這的趕緊走)

          設(shè)置污點(diǎn)命令如下:

          # 設(shè)置污點(diǎn)
          kubectl taint nodes node01 key=value:effect

          #
           去除污點(diǎn)
          kubectl taint nodes node01 key:effect-

          #
           去除所有污點(diǎn)
          kubectl taint nodes node01 key-

          而 k8s中的 master節(jié)點(diǎn)之所以沒有運(yùn)行任何pod,那便是因?yàn)?master 節(jié)點(diǎn)上已經(jīng)存在了污點(diǎn):

          ④ 容忍(Toleration)

          上面說到如果 node 節(jié)點(diǎn)存在污點(diǎn),那么pod就會無法調(diào)度。那如果 pod 有時候就是想 "厚著臉皮",哪怕你存在污點(diǎn),也不嫌棄的想要調(diào)度進(jìn)去有沒有辦法解決呢?

          k8s 也是想到了這種情況的存在,因此便有了一個 容忍 的屬性!

          污點(diǎn)就是拒絕,容忍就是忽略,Node 通過污點(diǎn)來拒絕 pod 調(diào)度上去,pod 通過容忍忽略拒絕

          我們先給 node01 打上 NoExecute 的污點(diǎn),然后我們再給 pod 添加容忍,看下是否能夠成功調(diào)度上去

          pod yaml:

          通過添加容忍后,我們可以發(fā)現(xiàn)pod 在 node01 的節(jié)點(diǎn)上成功運(yùn)行了,說明容忍成功~

          容忍的配置信息如下:

          tolerations:
          - key   # 對應(yīng)著要容忍的污點(diǎn)的鍵,空意味著匹配所有的鍵
            value  # 對應(yīng)著要容忍的污點(diǎn)值
            operator # key-value 的運(yùn)算符,支持 Equal 和 Exists(默認(rèn))
            effect    # 對應(yīng)污點(diǎn)的effect,空意味著匹配所有的影響
            tolerationSeconds  # 容忍時間,當(dāng) effect 為NoExecute 時生效,表示 pod 在Node上的停留時間

          關(guān)于 k8s 中 pod 的介紹到這里就結(jié)束啦~個人覺得還是挺詳細(xì)的,如果能夠認(rèn)真看下來,相信對 pod 已經(jīng)有足夠了解了。但是你認(rèn)為 k8s 到這里就結(jié)束了嗎?那肯定不會的,礙于篇幅,所以其他資源組件留到下一節(jié)介紹~請動動小手,點(diǎn)點(diǎn)關(guān)注不迷路。路漫漫,小菜與你一同求索!

          今天的你多努力一點(diǎn),明天的你就能少說一句求人的話!

          我是小菜,一個和你一起學(xué)習(xí)的男人。 ??

          微信公眾號已開啟,小菜良記,沒關(guān)注的同學(xué)們記得關(guān)注哦!


          瀏覽 55
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  夜夜爱欧美 | 日逼综合 | 麻豆91在线 | 亚洲a免费观看 | 亚洲AV无码成人精品国产网站 |