中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

國家企業(yè)信用信息公示系統(tǒng)官網(wǎng)(全國)阿里seo排名優(yōu)化軟件

國家企業(yè)信用信息公示系統(tǒng)官網(wǎng)(全國),阿里seo排名優(yōu)化軟件,如何辦寬帶,綠色環(huán)保材料網(wǎng)站模板文章目錄 Kubernetes之Pod詳解一、Pod介紹pod結(jié)構(gòu)pod定義 二、Pod配置pod基本配置鏡像拉取策略啟動命令環(huán)境變量端口設(shè)置資源配額 三、Pod生命周期創(chuàng)建和終止初始化容器鉤子函數(shù)容器探測重啟策略 四、Pod調(diào)度定向調(diào)度NodeNameNodeSelector 親和性調(diào)度NodeAffinityPodAffinityPo…

文章目錄

  • Kubernetes之Pod詳解
    • 一、Pod介紹
        • pod結(jié)構(gòu)
        • pod定義
    • 二、Pod配置
        • pod基本配置
        • 鏡像拉取策略
        • 啟動命令
        • 環(huán)境變量
        • 端口設(shè)置
        • 資源配額
    • 三、Pod生命周期
        • 創(chuàng)建和終止
        • 初始化容器
        • 鉤子函數(shù)
        • 容器探測
        • 重啟策略
    • 四、Pod調(diào)度
        • 定向調(diào)度
          • NodeName
          • NodeSelector
        • 親和性調(diào)度
          • NodeAffinity
          • PodAffinity
          • PodAntiAffinity
    • 五、污點和容忍
        • 污點(Taints)
        • 容忍(Toleration)

Kubernetes之Pod詳解

一、Pod介紹

pod結(jié)構(gòu)

在這里插入圖片描述

Pod 是 kubernetes 中最小的資源管理組件,Pod 也是最小化運行容器化應(yīng)用的資源對象。一個 Pod 代表著集群中運行的一個進程。kubernetes 中其他大多數(shù)組件都是圍繞著 Pod 來進行支撐和擴展 Pod 功能的,例如用于管理 Pod 運行的 StatefulSet 和 Deployment 等控制器對象,用于暴露 Pod 應(yīng)用的 Service 和 Ingress 對象,為 Pod 提供存儲的 PersistentVolume 存儲資源對象等。

每個Pod中都可以包含一個或者多個容器,這些容器可以分為兩類:

  • 用戶程序所在的容器,數(shù)量可多可少

  • Pause容器,這是每個Pod都會有的一個根容器,它的作用有兩個:

    可以以它為依據(jù),評估整個Pod的健康狀態(tài)

    可以在根容器上設(shè)置Ip地址,其它容器都此Ip(Pod IP),以實現(xiàn)Pod內(nèi)部的網(wǎng)路通信

    這里是Pod內(nèi)部的通訊,Pod的之間的通訊采用虛擬二層網(wǎng)絡(luò)技術(shù)來實現(xiàn),我們當(dāng)前環(huán)境用的是Flannel
    

pod定義

下面是Pod的資源清單:

apiVersion: v1     #必選,版本號,例如v1
kind: Pod         #必選,資源類型,例如 Pod
metadata:         #必選,元數(shù)據(jù)name: string     #必選,Pod名稱namespace: string  #Pod所屬的命名空間,默認為"default"labels:           #自定義標(biāo)簽列表- name: string                 
spec:  #必選,Pod中容器的詳細定義containers:  #必選,Pod中容器列表- name: string   #必選,容器名稱image: string  #必選,容器的鏡像名稱imagePullPolicy: [ Always|Never|IfNotPresent ]  #獲取鏡像的策略 command: [string]   #容器的啟動命令列表,如不指定,使用打包時使用的啟動命令args: [string]      #容器的啟動命令參數(shù)列表workingDir: string  #容器的工作目錄volumeMounts:       #掛載到容器內(nèi)部的存儲卷配置- name: string      #引用pod定義的共享存儲卷的名稱,需用volumes[]部分定義的的卷名mountPath: string #存儲卷在容器內(nèi)mount的絕對路徑,應(yīng)少于512字符readOnly: boolean #是否為只讀模式ports: #需要暴露的端口庫號列表- name: string        #端口的名稱containerPort: int  #容器需要監(jiān)聽的端口號hostPort: int       #容器所在主機需要監(jiān)聽的端口號,默認與Container相同protocol: string    #端口協(xié)議,支持TCP和UDP,默認TCPenv:   #容器運行前需設(shè)置的環(huán)境變量列表- name: string  #環(huán)境變量名稱value: string #環(huán)境變量的值resources: #資源限制和請求的設(shè)置limits:  #資源限制的設(shè)置cpu: string     #Cpu的限制,單位為core數(shù),將用于docker run --cpu-shares參數(shù)memory: string  #內(nèi)存限制,單位可以為Mib/Gib,將用于docker run --memory參數(shù)requests: #資源請求的設(shè)置cpu: string    #Cpu請求,容器啟動的初始可用數(shù)量memory: string #內(nèi)存請求,容器啟動的初始可用數(shù)量lifecycle: #生命周期鉤子postStart: #容器啟動后立即執(zhí)行此鉤子,如果執(zhí)行失敗,會根據(jù)重啟策略進行重啟preStop: #容器終止前執(zhí)行此鉤子,無論結(jié)果如何,容器都會終止livenessProbe:  #對Pod內(nèi)各容器健康檢查的設(shè)置,當(dāng)探測無響應(yīng)幾次后將自動重啟該容器exec:         #對Pod容器內(nèi)檢查方式設(shè)置為exec方式command: [string]  #exec方式需要制定的命令或腳本httpGet:       #對Pod內(nèi)個容器健康檢查方法設(shè)置為HttpGet,需要制定Path、portpath: stringport: numberhost: stringscheme: stringHttpHeaders:- name: stringvalue: stringtcpSocket:     #對Pod內(nèi)個容器健康檢查方式設(shè)置為tcpSocket方式port: numberinitialDelaySeconds: 0       #容器啟動完成后首次探測的時間,單位為秒timeoutSeconds: 0          #對容器健康檢查探測等待響應(yīng)的超時時間,單位秒,默認1秒periodSeconds: 0           #對容器監(jiān)控檢查的定期探測時間設(shè)置,單位秒,默認10秒一次successThreshold: 0failureThreshold: 0securityContext:privileged: falserestartPolicy: [Always | Never | OnFailure]  #Pod的重啟策略nodeName: <string> #設(shè)置NodeName表示將該Pod調(diào)度到指定到名稱的node節(jié)點上nodeSelector: obeject #設(shè)置NodeSelector表示將該Pod調(diào)度到包含這個label的node上imagePullSecrets: #Pull鏡像時使用的secret名稱,以key:secretkey格式指定- name: stringhostNetwork: false   #是否使用主機網(wǎng)絡(luò)模式,默認為false,如果設(shè)置為true,表示使用宿主機網(wǎng)絡(luò)volumes:   #在該pod上定義共享存儲卷列表- name: string    #共享存儲卷名稱 (volumes類型有很多種)emptyDir: {}       #類型為emtyDir的存儲卷,與Pod同生命周期的一個臨時目錄。為空值hostPath: string   #類型為hostPath的存儲卷,表示掛載Pod所在宿主機的目錄path: string                #Pod所在宿主機的目錄,將被用于同期中mount的目錄secret:          #類型為secret的存儲卷,掛載集群與定義的secret對象到容器內(nèi)部scretname: string  items:     - key: stringpath: stringconfigMap:         #類型為configMap的存儲卷,掛載預(yù)定義的configMap對象到容器內(nèi)部name: stringitems:- key: stringpath: string
#小提示:
#   在這里,可通過一個命令來查看每種資源的可配置項
#   kubectl explain 資源類型         查看某種資源可以配置的一級屬性
#   kubectl explain 資源類型.屬性     查看屬性的子屬性[root@master ~]# kubectl explain pod
KIND:     Pod
VERSION:  v1
FIELDS:apiVersion   <string>kind <string>metadata     <Object>spec <Object>status       <Object>[root@master ~]# kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1
RESOURCE: metadata <Object>
FIELDS:annotations  <map[string]string>clusterName  <string>creationTimestamp    <string>deletionGracePeriodSeconds   <integer>deletionTimestamp    <string>finalizers   <[]string>generateName <string>generation   <integer>labels       <map[string]string>managedFields        <[]Object>name <string>namespace    <string>ownerReferences      <[]Object>resourceVersion      <string>selfLink     <string>uid  <string>

在kubernetes中基本所有資源的一級屬性都是一樣的,主要包含5部分:

  • apiVersion 版本,由kubernetes內(nèi)部定義,版本號必須可以用 kubectl api-versions 查詢到
  • kind 類型,由kubernetes內(nèi)部定義,版本號必須可以用 kubectl api-resources 查詢到
  • metadata 元數(shù)據(jù),主要是資源標(biāo)識和說明,常用的有name、namespace、labels等
  • spec 描述,這是配置中最重要的一部分,里面是對各種資源配置的詳細描述
  • status 狀態(tài)信息,里面的內(nèi)容不需要定義,由kubernetes自動生成

在上面的屬性中,spec是接下來研究的重點,繼續(xù)看下它的常見子屬性:

  • containers <[]Object> 容器列表,用于定義容器的詳細信息
  • nodeName 根據(jù)nodeName的值將pod調(diào)度到指定的Node節(jié)點上
  • nodeSelector 根據(jù)NodeSelector中定義的信息選擇將該Pod調(diào)度到包含這些label的Node 上
  • hostNetwork 是否使用主機網(wǎng)絡(luò)模式,默認為false,如果設(shè)置為true,表示使用宿主機網(wǎng)絡(luò)
  • volumes <[]Object> 存儲卷,用于定義Pod上面掛在的存儲信息
  • restartPolicy 重啟策略,表示Pod在遇到故障的時候的處理策略


二、Pod配置

這一節(jié)主要是pod.spec.containers的屬性,這也是pod配置中最為關(guān)鍵的一項配置。

[root@master ~]# kubectl explain pod.spec.containers
KIND:     Pod
VERSION:  v1
RESOURCE: containers <[]Object>   # 數(shù)組,代表可以有多個容器
FIELDS:name  <string>     # 容器名稱image <string>     # 容器需要的鏡像地址imagePullPolicy  <string> # 鏡像拉取策略 command  <[]string> # 容器的啟動命令列表,如不指定,使用打包時使用的啟動命令args     <[]string> # 容器的啟動命令需要的參數(shù)列表env      <[]Object> # 容器環(huán)境變量的配置ports    <[]Object>     # 容器需要暴露的端口號列表resources <Object>      # 資源限制和資源請求的設(shè)置

先創(chuàng)建一個名稱空間用于實驗使用

//創(chuàng)建一個名為lcwanf的名稱空間
[root@master ~]# kubectl create namespace lcwanf
namespace/lcwanf created
[root@master ~]# kubectl get namespace
NAME              STATUS   AGE
default           Active   4d22h
kube-flannel      Active   4d21h
kube-node-lease   Active   4d22h
kube-public       Active   4d22h
kube-system       Active   4d22h
lcwanf            Active   3s      #用于實驗用的名稱空間
[root@master ~]# 

pod基本配置

創(chuàng)建一個pod-httpd.yaml文件,內(nèi)容如下

//編寫資源文件
[root@master ~]# vim pod-httpd1.yaml
[root@master ~]# cat pod-httpd1.yaml 
apiVersion: v1
kind: Pod
metadata:name: httpd1namespace: lcwanflabels:user: wanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.2- name: tomcatimage: lcwanf/tomcat-meinv:v1.0
[root@master ~]# 

上面定義了一個簡單的pod配置,里面有兩個容器:

  • httpd:用的是我自己制作的鏡像,上傳在我的docker官方鏡像倉庫
  • tomcat:也是用的我自己制作的鏡像,上傳在我的docker官方鏡像倉庫

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-httpd1.yaml 
pod/httpd1 created
[root@master ~]# //查看pod狀況
# READY 2/2 : 表示當(dāng)前Pod中有2個容器,2個都準(zhǔn)備就緒
# RESTARTS  : 重啟次數(shù),此時為0;如果容器故障了,Pod會一直重啟故障容器試圖恢復(fù)它
[root@master ~]# kubectl get -f pod-httpd1.yaml 
NAME    READY   STATUS    RESTARTS   AGE
httpd1   2/2     Running   0          2m
[root@master ~]# # 可以通過describe查看內(nèi)部的詳情
//查看pod詳細信息
[root@master ~]# kubectl describe pod httpd1 -n lcwanf
(省略)

鏡像拉取策略

imagePullPolicy,用于設(shè)置鏡像拉取策略,kubernetes支持配置三種拉取策略:

  • Always:總是從遠程倉庫拉取鏡像(一直遠程下載)
  • IfNotPresent:本地有則使用本地鏡像,本地沒有則從遠程倉庫拉取鏡像(本地有就本地 本地沒遠程下載)
  • Never:只使用本地鏡像,從不去遠程倉庫拉取,本地沒有就報錯 (一直使用本地)

默認值說明:

如果鏡像tag為具體版本號, 默認策略是:IfNotPresent

如果鏡像tag為:latest(最終版本) ,默認策略是always


創(chuàng)建應(yīng)該pod-imagepullpolicy.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-imagepullpolicy.yaml
[root@master ~]# cat pod-imagepullpolicy.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-imagepullpolicynamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.2imagePullPolicy: Never # 用于設(shè)置鏡像拉取策略- name: tomcatimage: lcwanf/tomcat-meinv:v1.0
[root@master ~]# 

上面定義了一個新的pod,其中httpd這個容器的鏡像拉取規(guī)則是Never(只使用本地鏡像,從不去遠程倉庫拉取,本地沒有就報錯 :一直使用本地)

創(chuàng)建資源并查看

//創(chuàng)建之前,先修改pod-imagepullpolicy.yaml文件里面的這個內(nèi)容把httpd這個容器的鏡像的版本從lcwanf/apache:v0.2改為lcwanf/apache:v0.1因為前面的操作拉取過lcwanf/apache:v0.2這個版本的鏡像,所以本地是有這個鏡像的換成lcwanf/apache:v0.1后,本地肯定是沒有這個鏡像的,再加上配置了拉取鏡像規(guī)則為Never,只使用本地鏡像,所以這個httpd的容器是運行不起來的
[root@master ~]# vim pod-imagepullpolicy.yaml 
[root@master ~]# cat pod-imagepullpolicy.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-imagepullpolicynamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1     //版本已經(jīng)修改imagePullPolicy: Never- name: tomcatimage: lcwanf/tomcat-meinv:v1.0
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-imagepullpolicy.yaml 
pod/pod-imagepullpolicy created//查看資源
--READY為1/2,證明確實有一個容器運行失敗
[root@master ~]# kubectl get -f pod-imagepullpolicy.yaml 
NAME                  READY   STATUS              RESTARTS   AGE
pod-imagepullpolicy   1/2     ErrImageNeverPull   0          3s//查看詳細信息,發(fā)現(xiàn)確實是httpd這個容器運行失敗報錯顯示:容器鏡像“l(fā)cwanf/apache:v0.1”不存在,pull策略為Never
[root@master ~]# kubectl describe -f pod-imagepullpolicy.yaml 
(省略)
Warning(省略)Container image "lcwanf/apache:v0.1" is not present with pull policy of Never//刪除創(chuàng)建的資源
[root@master ~]# kubectl delete -f pod-imagepullpolicy.yaml 
pod "pod-imagepullpolicy" deleted
[root@master ~]# //修改拉取鏡像策略為Always,我的docker官方鏡像倉庫里面是有l(wèi)cwanf/apache:v0.1這個版本的所以會去自動拉取
[root@master ~]# vim pod-imagepullpolicy.yaml 
[root@master ~]# cat pod-imagepullpolicy.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-imagepullpolicynamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1imagePullPolicy: Always   #改為Always:總是從遠程倉庫拉取鏡像- name: tomcatimage: lcwanf/tomcat-meinv:v1.0
[root@master ~]# //重新創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-imagepullpolicy.yaml 
pod/pod-imagepullpolicy created
[root@master ~]# //查看資源,正常運行
[root@master ~]# kubectl get -f pod-imagepullpolicy.yaml 
NAME                  READY   STATUS    RESTARTS   AGE
pod-imagepullpolicy   2/2     Running   0          23s
[root@master ~]# 

啟動命令

command,用于在pod中的容器初始化完畢之后運行一個命令。


創(chuàng)建一個pod-command.yaml文件,不定義啟動命令,內(nèi)容如下:

//編寫資源文件,沒有定義啟動命令
[root@master ~]# vim pod-command.yaml
[root@master ~]# cat pod-command.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-commandnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1- name: busyboximage: busybox:1.30
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-command.yaml 
pod/pod-command created//查看資源,會發(fā)現(xiàn)一直有一個容器運行失敗,通過詳細查看發(fā)現(xiàn)是busybox這個容器有問題
[root@master ~]# kubectl get -f pod-command.yaml 
NAME          READY   STATUS             RESTARTS      AGE
pod-command   1/2     CrashLoopBackOff   2 (12s ago)   40s
[root@master ~]# //刪除此資源

是什么原因?qū)е逻@個容器的故障呢?原來busybox并不是一個程序,而是類似于一個工具類的集合,kubernetes集群啟動管理后,它會自動關(guān)閉。解決方法就是讓其一直在運行,這就用到了command配置。

修改pod-command.yaml文件,給busybox容器定義啟動命令,內(nèi)容如下:

//修改資源文件
[root@master ~]# vim pod-command.yaml 
[root@master ~]# cat pod-command.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-commandnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1- name: busyboximage: busybox:1.30command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done;"]
[root@master ~]# 

解釋下上面命令的意思:

“/bin/sh”,“-c”, 使用sh執(zhí)行命令

touch /tmp/hello.txt; 創(chuàng)建一個/tmp/hello.txt 文件

while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中寫入當(dāng)前時間

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-command.yaml 
pod/pod-command created
[root@master ~]# //查看資源,兩個容器都正常運行了
[root@master ~]# kubectl get -f pod-command.yaml 
NAME          READY   STATUS    RESTARTS   AGE
pod-command   2/2     Running   0          25s
[root@master ~]# //進入busybox這個容器里面去,查看命令運行情況
# 補充一個命令: kubectl exec  pod名稱 -n 命名空間 -it -c 容器名稱 /bin/sh  在容器內(nèi)部執(zhí)行命令
# 使用這個命令就可以進入某個容器的內(nèi)部,然后進行相關(guān)操作了
# 比如,可以查看txt文件的內(nèi)容
[root@master ~]# kubectl exec pod-command -n lcwanf -it -c busybox /bin/sh / -- tail -f /tmp/hello.txt
08:07:50
08:07:53
08:07:56
08:07:59
08:08:02
08:08:05
08:08:08
08:08:11
08:08:14
08:08:17
(省略)
//命令一直在運行
特別說明:通過上面發(fā)現(xiàn)command已經(jīng)可以完成啟動命令和傳遞參數(shù)的功能,為什么這里還要提供一個args選項,用于傳遞參數(shù)呢?這其實跟docker有點關(guān)系,kubernetes中的command、args兩項其實是實現(xiàn)覆蓋Dockerfile中ENTRYPOINT的功能。1 如果command和args均沒有寫,那么用Dockerfile的配置。2 如果command寫了,但args沒有寫,那么Dockerfile默認的配置會被忽略,執(zhí)行輸入的command3 如果command沒寫,但args寫了,那么Dockerfile中配置的ENTRYPOINT的命令會被執(zhí)行,使用當(dāng)前args的參數(shù)4 如果command和args都寫了,那么Dockerfile的配置被忽略,執(zhí)行command并追加上args參數(shù)

環(huán)境變量

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


創(chuàng)建一個pod-env.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-env.yaml
[root@master ~]# cat pod-env.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-envnamespace: lcwanf
spec:containers:- name: busyboximage: busybox:1.30command: ["/bin/sh","-c","while true;do /bin/echo $(date +%T);sleep 60; done;"]env: # 設(shè)置環(huán)境變量列表- name: "username"value: "admin"- name: "password"value: "123456"
[root@master ~]# 

定義了兩個環(huán)境變量:

username:admin

password:123456


創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-env.yaml 
pod/pod-env created
[root@master ~]# //查看資源
[root@master ~]# kubectl get -f pod-env.yaml 
NAME      READY   STATUS    RESTARTS   AGE
pod-env   1/1     Running   0          24s
[root@master ~]# //進入容器,輸出環(huán)境變量
[root@master ~]# kubectl exec pod-env -n lcwanf -c busybox -it /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo $username
admin
/ # echo $password
123456
/ # exit
[root@master ~]# //注意,這里有一個警告信息kubectl exec [POD] [COMMAND]...,意思是此命令語法將在以后的版本中刪除,現(xiàn)在不影響使用

這種方式不是很推薦,推薦將這些配置單獨存儲在配置文件中,這種方式將在后面介紹。


端口設(shè)置

容器的端口設(shè)置,也就是containers的ports選項。

[root@master ~]# kubectl explain pod.spec.containers.ports
KIND:     Pod
VERSION:  v1
RESOURCE: ports <[]Object>
FIELDS:name         <string>  # 端口名稱,如果指定,必須保證name在pod中是唯一的     containerPort<integer> # 容器要監(jiān)聽的端口(0<x<65536)hostPort     <integer> # 容器要在主機上公開的端口,如果設(shè)置,主機上只能運行容器的一個副本(一般省略) hostIP       <string>  # 要將外部端口綁定到的主機IP(一般省略)protocol     <string>  # 端口協(xié)議。必須是UDP、TCP或SCTP。默認為“TCP”。

創(chuàng)建一個pod-ports.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-ports.yaml
[root@master ~]# cat pod-ports.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-portsnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports: # 設(shè)置容器暴露的端口列表- name: httpd-portcontainerPort: 80protocol: TCP
[root@master ~]# 

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-ports.yaml 
pod/pod-ports created
[root@master ~]# //查看
[root@master ~]# kubectl get -f pod-ports.yaml 
NAME        READY   STATUS    RESTARTS   AGE
pod-ports   1/1     Running   0          17s
[root@master ~]# //以yaml格式查看
# 在下面可以明顯看到配置信息
[root@master ~]# kubectl get pod pod-ports -n lcwanf -o yaml
(省略)
spec:containers:- image: lcwanf/apache:v0.1imagePullPolicy: IfNotPresentname: httpdports:- containerPort: 80name: httpd-portprotocol: TCP
(省略)

訪問容器中的程序需要使用的是Podip:containerPort


資源配額

容器中的程序要運行,肯定是要占用一定資源的,比如cpu和內(nèi)存等,如果不對某個容器的資源做限制,那么它就可能吃掉大量資源,導(dǎo)致其它容器無法運行。針對這種情況,kubernetes提供了對內(nèi)存和cpu的資源進行配額的機制,這種機制主要通過resources選項實現(xiàn),他有兩個子選項:

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

可以通過上面兩個選項設(shè)置資源的上下限。


創(chuàng)建一個pod-resources.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-resources.yaml
[root@master ~]# cat pod-resources.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-resourcesnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1resources:          # 資源配額limits:           # 限制資源(上限)cpu: "2"        # CPU限制,單位是core數(shù)memory: "10Gi"  # 內(nèi)存限制requests:         # 請求資源(下限)cpu: "1"        # CPU限制,單位是core數(shù)memory: "10Mi"  # 內(nèi)存限制
[root@master ~]# 

在這對cpu和memory的單位做一個說明:

cpu:core數(shù),可以為整數(shù)或小數(shù)

memory: 內(nèi)存大小,可以使用Gi、Mi、G、M等形式

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-resources.yaml 
pod/pod-resources created
[root@master ~]# //查看,運行是成功的
[root@master ~]# kubectl get -f pod-resources.yaml 
NAME            READY   STATUS    RESTARTS   AGE
pod-resources   1/1     Running   0          18s
[root@master ~]# //編輯pod,修改resources.requests.memory的值為10Gi(內(nèi)存下限為10Gi)我這臺實驗用的虛擬機的內(nèi)存為4G,肯定不滿足,所以容器肯定起不來//先刪除資源
[root@master ~]# kubectl delete -f pod-resources.yaml 
pod "pod-resources" deleted//修改資源文件的resources.requests.memory的值為10Gi
[root@master ~]# vim pod-resources.yaml 
[root@master ~]# cat pod-resources.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-resourcesnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1resources:        limits:           cpu: "2"       memory: "10Gi" requests:       cpu: "1"       memory: "10Gi" #修改為10Gi
[root@master ~]# //再次創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-resources.yaml 
pod/pod-resources created
[root@master ~]# //查看容器,是Pending狀態(tài),無法正常運行
[root@master ~]# kubectl get -f pod-resources.yaml 
NAME            READY   STATUS    RESTARTS   AGE
pod-resources   0/1     Pending   0          14s
[root@master ~]# //查看pod詳情會發(fā)現(xiàn),如下提示
[root@master ~]# kubectl describe  -f pod-resources.yaml 
(省略)
Warning  FailedScheduling  60s   default-scheduler  0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 Insufficient memory. preemption: 0/3 nodes are available: 1 Preemption is not helpful for scheduling, 2 No preemption victims found for incoming pod..


三、Pod生命周期

我們一般將pod對象從創(chuàng)建至終的這段時間范圍稱為pod的生命周期,它主要包含下面的過程:

  • pod創(chuàng)建過程
  • 運行初始化容器(init container)過程
  • 運行主容器(main container)
    • 容器啟動后鉤子(post start)、容器終止前鉤子(pre stop)
    • 容器的存活性探測(liveness probe)、就緒性探測(readiness probe)
  • pod終止過程

在這里插入圖片描述

在整個生命周期中,Pod會出現(xiàn)5種狀態(tài)相位),分別如下:

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

創(chuàng)建和終止

pod的創(chuàng)建過程

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

在這里插入圖片描述

pod的終止過程

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

初始化容器

初始化容器是在pod的主容器啟動之前要運行的容器,主要是做一些主容器的前置工作,它具有兩大特征:

  1. 初始化容器必須運行完成直至結(jié)束,若某初始化容器運行失敗,那么kubernetes需要重啟它直到成功完成
  2. 初始化容器必須按照定義的順序執(zhí)行,當(dāng)且僅當(dāng)前一個成功之后,后面的一個才能運行

初始化容器有很多的應(yīng)用場景,下面列出的是最常見的幾個:

  • 提供主容器鏡像中不具備的工具程序或自定義代碼
  • 初始化容器要先于應(yīng)用容器串行啟動并運行完成,因此可用于延后應(yīng)用容器的啟動直至其依賴的條件得到滿足

接下來做一個案例,模擬下面這個需求:

假設(shè)要以主容器來運行httpd,但是要求在運行httpd之前先要能夠連接上mysql和redis所在服務(wù)器

為了簡化測試,事先規(guī)定好mysql(192.168.179.81)和redis(192.168.179.82)服務(wù)器的地址

創(chuàng)建一個pod-resources.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-initcontainer.yaml
[root@master ~]# cat pod-initcontainer.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-initcontainernamespace: lcwanf
spec:containers:- name: main-containerimage: lcwanf/apache:v0.1ports: - name: httpd-portcontainerPort: 80initContainers:- name: test-mysqlimage: busybox:1.30command: ['sh', '-c', 'until ping 192.168.179.81 -c 1 ; do echo waiting for mysql...; sleep 2; done;']- name: test-redisimage: busybox:1.30command: ['sh', '-c', 'until ping 192.168.179.82 -c 1 ; do echo waiting for reids...; sleep 2; done;']
[root@master ~]# 

initContainers中的,test-mysql和test-redis這兩個初始化容器的cmd中要ping的IP地址現(xiàn)在是不存在的,所以這兩個容器是無法運行起來的。那么主容器httpd自然也不會運行起來

創(chuàng)建資源和查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-initcontainer.yaml 
pod/pod-initcontainer created
[root@master ~]# //查看資源
--沒有運行成功
[root@master ~]# kubectl get -f pod-initcontainer.yaml 
NAME                READY   STATUS     RESTARTS   AGE
pod-initcontainer   0/1     Init:0/2   0          21s
[root@master ~]# //詳細查看pod狀態(tài)
--發(fā)現(xiàn)pod卡在啟動第一個初始化容器過程中,后面的容器不會運行
[root@master ~]# kubectl describe pod  pod-initcontainer -n lcwanf
(省略)
Events:Type    Reason     Age   From               Message----    ------     ----  ----               -------Normal  Scheduled  72s   default-scheduler  Successfully assigned lcwanf/pod-initcontainer to node2Normal  Pulled     71s   kubelet            Container image "busybox:1.30" already present on machineNormal  Created    71s   kubelet            Created container test-mysqlNormal  Started    71s   kubelet            Started container test-mysql//動態(tài)查看pod
--暫時沒有什么變化
[root@master ~]# kubectl get pods pod-initcontainer -n lcwanf -w
NAME                READY   STATUS     RESTARTS   AGE
pod-initcontainer   0/1     Init:0/2   0          3m49s//然后新打開一個終端,給網(wǎng)卡添加上192.168.179.81和192.168.179.82這兩個IP
[root@master ~]# yum -y install net-tools
[root@master ~]# ifconfig ens160:1 192.168.179.81 netmask 255.255.255.0 up
[root@master ~]# ifconfig ens160:2 192.168.179.82 netmask 255.255.255.0 up//回到正在動態(tài)查看pod的終端繼續(xù)查看變化
--因為添加了對應(yīng)的IP地址,所以兩個初始化容器可以正常運行,那么主容器也可以創(chuàng)建成功了
[root@master ~]# kubectl get pods pod-initcontainer -n lcwanf -w
NAME                READY   STATUS     RESTARTS   AGE
pod-initcontainer   0/1     Init:0/2   0          3m49s
pod-initcontainer   0/1     Init:1/2   0          19m
pod-initcontainer   0/1     PodInitializing   0          19m
pod-initcontainer   1/1     Running           0          19m//查看pod,正常運行
[root@master ~]# kubectl get -f pod-initcontainer.yaml 
NAME                READY   STATUS    RESTARTS   AGE
pod-initcontainer   1/1     Running   0          20m
[root@master ~]# 

鉤子函數(shù)

鉤子函數(shù)能夠感知自身生命周期中的事件,并在相應(yīng)的時刻到來時運行用戶指定的程序代碼。

kubernetes在主容器的啟動之后和停止之前提供了兩個鉤子函數(shù):

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

鉤子處理器支持使用下面三種方式定義動作:

  • Exec命令:在容器內(nèi)執(zhí)行一次命令

    ……
    lifecycle:postStart: exec:command:- cat- /tmp/healthy
    ……
    
  • TCPSocket:在當(dāng)前容器嘗試訪問指定的socket

    ……      
    lifecycle:postStart:tcpSocket:port: 8080
    ……
    
  • HTTPGet:在當(dāng)前容器中向某url發(fā)起http請求

    ……
    lifecycle:postStart:httpGet:path: / #URI地址port: 80 #端口號host: 192.168.179.15 #主機地址scheme: HTTP #支持的協(xié)議,http或者https
    ……
    

演示exec方式的鉤子函數(shù)的使用:

創(chuàng)建一個pod-hook-exec.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-hook-exec.yaml
[root@master ~]# cat pod-hook-exec.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-hook-execnamespace: lcwanf
spec:containers:- name: main-containerimage: lcwanf/apache:v0.1ports:- name: httpd-portcontainerPort: 80lifecycle:postStart: exec: # 在容器啟動的時候執(zhí)行一個命令,修改掉httpd的默認首頁內(nèi)容command: ["/bin/sh", "-c", "echo this is test > /usr/local/apache/htdocs/index.html"]preStop:exec: # 在容器停止之前停止nginx服務(wù)command: ["/usr/local/apache/bin/apachectl","stop"]
[root@master ~]# 

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-hook-exec.yaml 
pod/pod-hook-exec created
[root@master ~]# //查看pod
[root@master ~]# kubectl get -f pod-hook-exec.yaml -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-hook-exec   1/1     Running   0          28s   10.244.1.31   node1   <none>           <none>
[root@master ~]# //訪問pod
--內(nèi)容確實是修改后的
[root@master ~]# curl 10.244.1.31
this is test
[root@master ~]# 

容器探測

容器探測用于檢測容器中的應(yīng)用實例是否正常工作,是保障業(yè)務(wù)可用性的一種傳統(tǒng)機制。如果經(jīng)過探測,實例的狀態(tài)不符合預(yù)期,那么kubernetes就會把該問題實例" 摘除 ",不承擔(dān)業(yè)務(wù)流量。kubernetes提供了兩種探針來實現(xiàn)容器探測,分別是:

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

livenessProbe 決定是否重啟容器,readinessProbe 決定是否將請求轉(zhuǎn)發(fā)給容器。

上面兩種探針目前均支持三種探測方式:

  • Exec命令:在容器內(nèi)執(zhí)行一次命令,如果命令執(zhí)行的退出碼為0,則認為程序正常,否則不正常

    ……
    livenessProbe:exec:command:- cat- /tmp/healthy
    ……
    
  • TCPSocket:將會嘗試訪問一個用戶容器的端口,如果能夠建立這條連接,則認為程序正常,否則不正常

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

    ……
    livenessProbe:httpGet:path: / #URI地址port: 80 #端口號host: 127.0.0.1 #主機地址scheme: HTTP #支持的協(xié)議,http或者https
    ……
    

以liveness probes為例,做幾個演示:

方式一:Exec

創(chuàng)建一個pod-liveness-exec.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-liveness-exec.yaml
[root@master ~]# cat pod-liveness-exec.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-execnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports: - name: httpd-portcontainerPort: 80livenessProbe:exec:command: ["/bin/cat","/tmp/hello.txt"] # 執(zhí)行一個查看文件的命令(此文件不存在)
[root@master ~]# 

容器啟動時會執(zhí)行查看/tmp/hello.txt這個文件,但是這個文件是不存在的,所以這條命令會失敗
那么這個容器也不會運行成功

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-liveness-exec.yaml 
pod/pod-liveness-exec created
[root@master ~]# //查看資源
--現(xiàn)在暫時是正常狀態(tài),其實不是正常狀態(tài)
[root@master ~]# kubectl get -f pod-liveness-exec.yaml 
NAME                READY   STATUS    RESTARTS     AGE
pod-liveness-exec   1/1     Running   1 (8s ago)   38s//詳細查看
[root@master ~]# kubectl describe pods pod-liveness-exec -n lcwanf
Events:Type     Reason     Age                   From               Message----     ------     ----                  ----               -------Normal   Scheduled  21m                   default-scheduler  Successfully assigned lcwanf/pod-liveness-exec to node1Normal   Created    19m (x4 over 21m)     kubelet            Created container httpdNormal   Started    19m (x4 over 21m)     kubelet            Started container httpdNormal   Killing    19m (x3 over 20m)     kubelet            Container httpd failed liveness probe, will be restartedWarning  Unhealthy  19m (x10 over 21m)    kubelet            Liveness probe failed: cat: /tmp/hello.txt: No such file or directoryWarning  BackOff    6m12s (x54 over 18m)  kubelet            Back-off restarting failed container httpd in pod pod-liveness-exec_lcwanf(dcac7987-fef7-497c-afaf-8e609b1ce6aa)Normal   Pulled     75s (x11 over 21m)    kubelet            Container image "lcwanf/apache:v0.1" already present on machine# 觀察上面的信息就會發(fā)現(xiàn)httpd容器啟動之后就進行了健康檢查
# 檢查失敗之后(要查看的文件是不存在的文件,所以檢查失敗)
# 容器被kill掉,然后嘗試進行重啟(這是重啟策略的作用,在下一小節(jié))
# 稍等一會之后,再觀察pod信息,就可以看到RESTARTS不再是0,而是一直增長//再次查看pod,容器運行失敗了
[root@master ~]# kubectl get pods pod-liveness-exec -n lcwanf
NAME                READY   STATUS             RESTARTS         AGE
pod-liveness-exec   0/1     CrashLoopBackOff   11 (2m58s ago)   23m
[root@master ~]# //刪除資源
[root@master ~]# kubectl delete -f pod-liveness-exec.yaml## 修改成一個存在的文件,比如/usr/local/apache/htdocs/index.html,再試,結(jié)果就正常了......//修改資源文件
[root@master ~]# vim pod-liveness-exec.yaml
[root@master ~]# cat pod-liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-execnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports: - name: httpd-portcontainerPort: 80livenessProbe:exec:command: ["/bin/cat","/usr/local/apache/htdocs/index.html"] //修改為一個存在的文件
[root@master ~]# //重新創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-liveness-exec.yaml
pod/pod-liveness-exec created
[root@master ~]# //查看資源
[root@master ~]# kubectl get -f pod-liveness-exec.yaml
NAME                READY   STATUS    RESTARTS   AGE
pod-liveness-exec   1/1     Running   0          14s
[root@master ~]# //詳細查看pod,沒有任何報錯
[root@master ~]# kubectl describe pods pod-liveness-exec -n lcwanf
(省略)
Events:Type    Reason     Age   From               Message----    ------     ----  ----               -------Normal  Scheduled  39s   default-scheduler  Successfully assigned lcwanf/pod-liveness-exec to node1Normal  Pulled     40s   kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal  Created    40s   kubelet            Created container httpdNormal  Started    40s   kubelet            Started container httpd

方式二:TCPSocket

創(chuàng)建一個pod-liveness-tcpsocket.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-liveness-tcpsocket.yaml
[root@master ~]# cat pod-liveness-tcpsocket.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-tcpsocketnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports: - name: httpd-portcontainerPort: 80livenessProbe:tcpSocket:port: 8080 # 嘗試訪問8080端口(錯誤的端口)
[root@master ~]# 

容器啟動時會執(zhí)行訪問8080,但是這個8080是錯誤的,所以這個訪問會失敗
那么這個容器也不會運行成功

創(chuàng)建資源并查看

Events:Type     Reason     Age               From               Message----     ------     ----              ----               -------Normal   Scheduled  65s               default-scheduler  Successfully assigned lcwanf/pod-liveness-tcpsocket to node2Normal   Pulled     5s (x3 over 65s)  kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal   Created    5s (x3 over 65s)  kubelet            Created container httpdNormal   Started    5s (x3 over 64s)  kubelet            Started container httpdWarning  Unhealthy  5s (x6 over 55s)  kubelet            Liveness probe failed: dial tcp 10.244.2.36:8080: connect: connection refusedNormal   Killing    5s (x2 over 35s)  kubelet            Container httpd failed liveness probe, will be restarted
[root@master ~]# kubectl describe -f pod-liveness-tcpsocket.yaml//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-liveness-tcpsocket.yaml
pod/pod-liveness-tcpsocket created
[root@master ~]# //查看資源
--現(xiàn)在暫時是正常狀態(tài),其實不是正常狀態(tài)
[root@master ~]# kubectl get -f pod-liveness-tcpsocket.yaml
NAME                     READY   STATUS    RESTARTS   AGE
pod-liveness-tcpsocket   1/1     Running   0          25s
[root@master ~]# //詳細查看pod情況
[root@master ~]# kubectl describe -f pod-liveness-tcpsocket.yaml
(省略)
Events:Type     Reason     Age               From               Message----     ------     ----              ----               -------Normal   Scheduled  65s               default-scheduler  Successfully assigned lcwanf/pod-liveness-tcpsocket to node2Normal   Pulled     5s (x3 over 65s)  kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal   Created    5s (x3 over 65s)  kubelet            Created container httpdNormal   Started    5s (x3 over 64s)  kubelet            Started container httpdWarning  Unhealthy  5s (x6 over 55s)  kubelet            Liveness probe failed: dial tcp 10.244.2.36:8080: connect: connection refusedNormal   Killing    5s (x2 over 35s)  kubelet            Container httpd failed liveness probe, will be restarted
# 觀察上面的信息,發(fā)現(xiàn)嘗試訪問8080端口,但是失敗了
# 稍等一會之后,再觀察pod信息,就可以看到RESTARTS不再是0,而是一直增長//再次查看pod,容器運行失敗了
[root@master ~]# kubectl get -f pod-liveness-tcpsocket.yaml
NAME                     READY   STATUS             RESTARTS     AGE
pod-liveness-tcpsocket   0/1     CrashLoopBackOff   4 (4s ago)   2m34s
[root@master ~]# //刪除資源
[root@master ~]# kubectl delete -f pod-liveness-tcpsocket.yaml
pod "pod-liveness-tcpsocket" deleted
[root@master ~]# ## 接下來,修改成一個可以訪問的端口,比如80,再試,結(jié)果就正常了......//修改資源文件,將測試端口修改為一個正確的端口
[root@master ~]# vim pod-liveness-tcpsocket.yaml
[root@master ~]# cat pod-liveness-tcpsocket.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-tcpsocketnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports: - name: httpd-portcontainerPort: 80livenessProbe:tcpSocket:port: 80
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-liveness-tcpsocket.yaml
pod/pod-liveness-tcpsocket created
[root@master ~]# //查看pod
[root@master ~]# kubectl get -f pod-liveness-tcpsocket.yaml
NAME                     READY   STATUS    RESTARTS   AGE
pod-liveness-tcpsocket   1/1     Running   0          19s
[root@master ~]# //詳細查看pod,沒有任何報錯
(省略)
Events:Type    Reason     Age   From               Message----    ------     ----  ----               -------Normal  Scheduled  39s   default-scheduler  Successfully assigned lcwanf/pod-liveness-tcpsocket to node2Normal  Pulled     39s   kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal  Created    39s   kubelet            Created container httpdNormal  Started    39s   kubelet            Started container httpd
[root@master ~]# kubectl describe -f pod-liveness-tcpsocket.yaml

方式三:HTTPGet

創(chuàng)建一個pod-liveness-httpget.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-liveness-httpget.yaml
[root@master ~]# cat pod-liveness-httpget.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-httpgetnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports:- name: httpd-portcontainerPort: 80livenessProbe:httpGet:  # 其實就是訪問http://127.0.0.1:80/hello  scheme: HTTP #支持的協(xié)議,http或者httpsport: 80 #端口號path: /hello #URI地址(錯誤的URI地址)
[root@master ~]# 

容器啟動時會執(zhí)行訪問http://127.0.0.1:80/hello ,但是這個URI地址是錯誤的,所以這個訪問會失敗,那么這個容器也不會運行成功

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-liveness-httpget.yaml 
pod/pod-liveness-httpget created
[root@master ~]# //查看資源
--現(xiàn)在暫時是正常狀態(tài),其實不是正常狀態(tài)
[root@master ~]# kubectl get -f pod-liveness-httpget.yaml 
NAME                   READY   STATUS    RESTARTS   AGE
pod-liveness-httpget   1/1     Running   0          19s
[root@master ~]# //詳細查看pod
[root@master ~]# kubectl describe -f pod-liveness-httpget.yaml 
(省略)
Events:Type     Reason     Age                From               Message----     ------     ----               ----               -------Normal   Scheduled  46s                default-scheduler  Successfully assigned lcwanf/pod-liveness-httpget to node1Normal   Pulled     16s (x2 over 46s)  kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal   Created    16s (x2 over 46s)  kubelet            Created container httpdNormal   Started    16s (x2 over 46s)  kubelet            Started container httpdNormal   Killing    16s                kubelet            Container httpd failed liveness probe, will be restartedWarning  Unhealthy  6s (x4 over 36s)   kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
[root@master ~]# # 觀察上面信息,嘗試訪問路徑,但是未找到,出現(xiàn)404錯誤
# 稍等一會之后,再觀察pod信息,就可以看到RESTARTS不再是0,而是一直增長//再次查看pod,容器運行失敗了
[root@master ~]# kubectl get -f pod-liveness-httpget.yaml 
NAME                   READY   STATUS             RESTARTS     AGE
pod-liveness-httpget   0/1     CrashLoopBackOff   4 (5s ago)   2m35s
[root@master ~]# //刪除資源
[root@master ~]# kubectl delete -f pod-liveness-httpget.yaml 
pod "pod-liveness-httpget" deleted
[root@master ~]# ## 修改成一個可以訪問的路徑path,比如/,再試,結(jié)果就正常了......//修改資源文件,把URL地址改為正確的地址。
[root@master ~]# vim pod-liveness-httpget.yaml
[root@master ~]# cat pod-liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-httpgetnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports:- name: httpd-portcontainerPort: 80livenessProbe:httpGet:  scheme: HTTPport: 80path: /   #直接訪問根目錄
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-liveness-httpget.yaml
pod/pod-liveness-httpget created
[root@master ~]# //查看pod
[root@master ~]# kubectl get -f pod-liveness-httpget.yaml
NAME                   READY   STATUS    RESTARTS   AGE
pod-liveness-httpget   1/1     Running   0          93s
[root@master ~]# //查看pod詳細信息,沒有任何報錯
[root@master ~]# kubectl describe -f pod-liveness-httpget.yaml
(省略)
Events:Type    Reason     Age   From               Message----    ------     ----  ----               -------Normal  Scheduled  2m3s  default-scheduler  Successfully assigned lcwanf/pod-liveness-httpget to node2Normal  Pulled     2m2s  kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal  Created    2m2s  kubelet            Created container httpdNormal  Started    2m2s  kubelet            Started container httpd
[root@master ~]# 

擴展:

至此,已經(jīng)使用liveness Probe演示了三種探測方式,但是查看livenessProbe的子屬性,會發(fā)現(xiàn)除了這三種方式,還有一些其他的配置,在這里一并解釋下:

[root@master ~]# kubectl explain pod.spec.containers.livenessProbe
FIELDS:exec <Object>  tcpSocket    <Object>httpGet      <Object>initialDelaySeconds  <integer>  # 容器啟動后等待多少秒執(zhí)行第一次探測timeoutSeconds       <integer>  # 探測超時時間。默認1秒,最小1秒periodSeconds        <integer>  # 執(zhí)行探測的頻率。默認是10秒,最小1秒failureThreshold     <integer>  # 連續(xù)探測失敗多少次才被認定為失敗。默認是3。最小值是1successThreshold     <integer>  # 連續(xù)探測成功多少次才被認定為成功。默認是1

下面稍微配置兩個,演示下效果即可:

[root@master ~]# more pod-liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-httpgetnamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports:- name: httpd-portcontainerPort: 80livenessProbe:httpGet:scheme: HTTPport: 80 path: /initialDelaySeconds: 30 # 容器啟動后30s開始探測timeoutSeconds: 5 # 探測超時時間為5s

重啟策略

在上一節(jié)中,一旦容器探測出現(xiàn)了問題,kubernetes就會對容器所在的Pod進行重啟,其實這是由pod的重啟策略決定的,pod的重啟策略有 3 種,分別如下:

  • Always :容器失效時,自動重啟該容器,這也是默認值。
  • OnFailure : 容器終止運行且退出碼不為0時重啟
  • Never : 不論狀態(tài)為何,都不重啟該容器

重啟策略適用于pod對象中的所有容器,首次需要重啟的容器,將在其需要時立即進行重啟,隨后再次需要重啟的操作將由kubelet延遲一段時間后進行,且反復(fù)的重啟操作的延遲時長以此為10s、20s、40s、80s、160s和300s,300s是最大延遲時長。


創(chuàng)建一個pod-restartpolicy.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-restartpolicy.yaml
[root@master ~]# cat pod-restartpolicy.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-restartpolicynamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1ports:- name: httpd-portcontainerPort: 80livenessProbe:httpGet:scheme: HTTPport: 80path: /hello   # 錯誤的URL地址restartPolicy: Never # 設(shè)置重啟策略為Never
[root@master ~]# 

探測規(guī)則中定義了錯誤的URL地址,所以容器會啟動失敗,pod會自己重啟嘗試修復(fù)

但是又因為定義了重啟策略為Never(從不),所以當(dāng)容器啟動失敗時,不會重啟容器嘗試修復(fù)

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-restartpolicy.yaml 
pod/pod-restartpolicy created
[root@master ~]# //查看pod,不是正常運行狀態(tài);RESTARTS數(shù)值為0(重啟次數(shù)為0),不需要像前面一樣,要等很久才能看見非正常狀態(tài)
[root@master ~]# kubectl get -f pod-restartpolicy.yaml 
NAME                READY   STATUS      RESTARTS   AGE
pod-restartpolicy   0/1     Completed   0          31s//查看pod詳細信息,容器啟動錯誤后,沒有重啟,而是直接Killing容器
[root@master ~]# kubectl describe -f pod-restartpolicy.yaml
(省略)
Events:Type     Reason     Age                    From               Message----     ------     ----                   ----               -------Normal   Scheduled  5m52s                  default-scheduler  Successfully assigned lcwanf/pod-restartpolicy to node1Normal   Pulled     5m53s                  kubelet            Container image "lcwanf/apache:v0.1" already present on machineNormal   Created    5m53s                  kubelet            Created container httpdNormal   Started    5m53s                  kubelet            Started container httpdWarning  Unhealthy  5m23s (x3 over 5m43s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404Normal   Killing    5m23s                  kubelet            Stopping container httpd
[root@master ~]# //等待一段時間,重啟次數(shù)依然為0
[root@master ~]# kubectl get -f pod-restartpolicy.yaml 
NAME                READY   STATUS      RESTARTS   AGE
pod-restartpolicy   0/1     Completed   0          9m42s
[root@master ~]# 


四、Pod調(diào)度

在默認情況下,一個Pod在哪個Node節(jié)點上運行,是由Scheduler組件采用相應(yīng)的算法計算出來的,這個過程是不受人工控制的。但是在實際使用中,這并不滿足的需求,因為很多情況下,我們想控制某些Pod到達某些節(jié)點上,那么應(yīng)該怎么做呢?這就要求了解kubernetes對Pod的調(diào)度規(guī)則,kubernetes提供了四大類調(diào)度方式:

  • 自動調(diào)度:運行在哪個節(jié)點上完全由Scheduler經(jīng)過一系列的算法計算得出
  • 定向調(diào)度:NodeName、NodeSelector
  • 親和性調(diào)度:NodeAffinity、PodAffinity、PodAntiAffinity
  • 污點(容忍)調(diào)度:Taints、Toleration
定向調(diào)度

定向調(diào)度,指的是利用在pod上聲明nodeName或者nodeSelector,以此將Pod調(diào)度到期望的node節(jié)點上。注意,這里的調(diào)度是強制的,這就意味著即使要調(diào)度的目標(biāo)Node不存在,也會向上面進行調(diào)度,只不過pod運行失敗而已。

NodeName

NodeName用于強制約束將Pod調(diào)度到指定的Name的Node節(jié)點上。這種方式,其實是直接跳過Scheduler的調(diào)度邏輯,直接將Pod調(diào)度到指定名稱的節(jié)點。示例如下:

創(chuàng)建一個pod-nodename.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-nodename.yaml
[root@master ~]# cat pod-nodename.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodenamenamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1nodeName: node2               //指定調(diào)度到node2節(jié)點上
[root@master ~]# 

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-nodename.yaml 
pod/pod-nodename created
[root@master ~]# //查看pod
--確實調(diào)度在node2上面
[root@master ~]# kubectl get -f pod-nodename.yaml -o wide
NAME           READY   STATUS    RESTARTS   AGE    IP           NODE    NOMINATED NODE   READINESS GATES
pod-nodename   1/1     Running   0          4m4s   10.244.2.2   node2   <none>           <none>
[root@master ~]# //刪除該pod,修改指定調(diào)度到node3上面去(node3不存在)
[root@master ~]# kubectl delete -f pod-nodename.yaml 
pod "pod-nodename" deleted
[root@master ~]# [root@master ~]# vim pod-nodename.yaml 
[root@master ~]# cat pod-nodename.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodenamenamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1nodeName: node3				//修改指定調(diào)度到node3上
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-nodename.yaml 
pod/pod-nodename created
[root@master ~]#//查看pod
--由于指定的node3這個節(jié)點不存在,所以pod既不能成功創(chuàng)建出來,也不會被調(diào)度到其他節(jié)點,只會是Pending狀態(tài)
[root@master ~]# kubectl get -f pod-nodename.yaml -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
pod-nodename   0/1     Pending   0          17s   <none>   node3   <none>           <none>
[root@master ~]# 
NodeSelector

NodeSelector用于將pod調(diào)度到添加了指定標(biāo)簽的node節(jié)點上。它是通過kubernetes的label-selector機制實現(xiàn)的,也就是說,在pod創(chuàng)建之前,會由scheduler使用MatchNodeSelector調(diào)度策略進行l(wèi)abel匹配,找出目標(biāo)node,然后將pod調(diào)度到目標(biāo)節(jié)點,該匹配規(guī)則是強制約束。示例如下:

分別為node節(jié)點添加標(biāo)簽

//為node1打標(biāo)簽
[root@master ~]# kubectl label nodes node1 nodeenv=pro
node/node1 labeled
[root@master ~]# //為node2打標(biāo)簽
[root@master ~]# kubectl label nodes node2 nodeenv=test
node/node2 labeled
[root@master ~]# 

創(chuàng)建一個pod-nodeselector.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-nodeselector.yaml
[root@master ~]# cat pod-nodeselector.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodeselectornamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1nodeSelector: nodeenv: pro 			//指定調(diào)度到具有nodeenv=pro標(biāo)簽的節(jié)點上
[root@master ~]# 

前面已經(jīng)為node1節(jié)點打上了nodeenv=pro的標(biāo)簽,node2節(jié)點打上了nodeenv=test的標(biāo)簽
資源文件里面寫的是指定調(diào)度到具有nodeenv=pro標(biāo)簽的節(jié)點上,所以此pod會調(diào)度到node1上

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-nodeselector.yaml 
pod/pod-nodeselector created
[root@master ~]# //查看pod
--確實調(diào)度到node1上了
[root@master ~]# kubectl get -f pod-nodeselector.yaml -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-nodeselector   1/1     Running   0          19s   10.244.1.44   node1   <none>           <none>
[root@master ~]# //刪除該pod,修改nodeSelector的值為nodeenv: xxx (標(biāo)簽xxx不存在)
[root@master ~]# kubectl delete -f pod-nodeselector.yaml 
pod "pod-nodeselector" deleted
[root@master ~]# [root@master ~]# vim pod-nodeselector.yaml 
[root@master ~]# cat pod-nodeselector.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodeselectornamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1nodeSelector: nodeenv: xxx
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-nodeselector.yaml 
pod/pod-nodeselector created
[root@master ~]#//查看pod
--由于標(biāo)簽 nodeenv: xxx不存在,所以無法正確調(diào)度pod。處于Pending狀態(tài)
[root@master ~]# kubectl get -f pod-nodeselector.yaml -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod-nodeselector   0/1     Pending   0          18s   <none>   <none>   <none>           <none>
[root@master ~]# 

親和性調(diào)度

上面兩種定向調(diào)度的方式,使用起來非常方便,但是也有一定的問題,那就是如果沒有滿足條件的Node,那么Pod將不會被運行,即使在集群中還有可用Node列表也不行,這就限制了它的使用場景。

基于上面的問題,kubernetes還提供了一種親和性調(diào)度(Affinity)。它在NodeSelector的基礎(chǔ)之上的進行了擴展,可以通過配置的形式,實現(xiàn)優(yōu)先選擇滿足條件的Node進行調(diào)度,如果沒有,也可以調(diào)度到不滿足條件的節(jié)點上,使調(diào)度更加靈活。

Affinity主要分為三類:

  • nodeAffinity(node親和性): 以node為目標(biāo),解決pod可以調(diào)度到哪些node的問題
  • podAffinity(pod親和性) : 以pod為目標(biāo),解決pod可以和哪些已存在的pod部署在同一個拓撲域中的問題
  • podAntiAffinity(pod反親和性) : 以pod為目標(biāo),解決pod不能和哪些已存在pod部署在同一個拓撲域中的問題

關(guān)于親和性(反親和性)使用場景的說明:

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

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


NodeAffinity

首先來看一下NodeAffinity的可配置項:

pod.spec.affinity.nodeAffinityrequiredDuringSchedulingIgnoredDuringExecution  Node節(jié)點必須滿足指定的所有規(guī)則才可以,相當(dāng)于硬限制nodeSelectorTerms  節(jié)點選擇列表matchFields   按節(jié)點字段列出的節(jié)點選擇器要求列表matchExpressions   按節(jié)點標(biāo)簽列出的節(jié)點選擇器要求列表(推薦)key    鍵values 值operator 關(guān)系符 支持Exists, DoesNotExist, In, NotIn, Gt, LtpreferredDuringSchedulingIgnoredDuringExecution 優(yōu)先調(diào)度到滿足指定的規(guī)則的Node,相當(dāng)于軟限制 (傾向)preference   一個節(jié)點選擇器項,與相應(yīng)的權(quán)重相關(guān)聯(lián)matchFields   按節(jié)點字段列出的節(jié)點選擇器要求列表matchExpressions   按節(jié)點標(biāo)簽列出的節(jié)點選擇器要求列表(推薦)key    鍵values 值operator 關(guān)系符 支持In, NotIn, Exists, DoesNotExist, Gt, Ltweight 傾向權(quán)重,在范圍1-100。
關(guān)系符的使用說明:- matchExpressions:- key: nodeenv              # 匹配存在標(biāo)簽的key為nodeenv的節(jié)點operator: Exists- key: nodeenv              # 匹配標(biāo)簽的key為nodeenv,且value是"xxx"或"yyy"的節(jié)點operator: Invalues: ["xxx","yyy"]- key: nodeenv              # 匹配標(biāo)簽的key為nodeenv,且value大于"xxx"的節(jié)點operator: Gtvalues: "xxx"

示例requiredDuringSchedulingIgnoredDuringExecution (硬限制)

創(chuàng)建一個pod-nodeaffinity-required.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-nodeaffinity-required.yaml
[root@master ~]# cat pod-nodeaffinity-required.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodeaffinity-requirednamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1affinity:  #親和性設(shè)置nodeAffinity: #設(shè)置node親和性requiredDuringSchedulingIgnoredDuringExecution: # 硬限制nodeSelectorTerms:- matchExpressions: # 匹配env的值在["xxx","yyy"]中的標(biāo)簽- key: nodeenvoperator: Invalues: ["xxx","yyy"]
[root@master ~]# 

前面已經(jīng)為node1節(jié)點打上了nodeenv=pro的標(biāo)簽,node2節(jié)點打上了nodeenv=test的標(biāo)簽

資源文件里面定義了硬限制:選擇nodeenv=xxx,或者nodeenv=yyy;但是這兩個標(biāo)簽都是不存在的
所以此pod無法正常調(diào)度并運行

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-nodeaffinity-required.yaml 
pod/pod-nodeaffinity-required created
[root@master ~]# //查看pod
--由于定義選擇的標(biāo)簽都是不存在的,并且是硬限制,所以pod是Pending狀態(tài)
[root@master ~]# kubectl get -f pod-nodeaffinity-required.yaml -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod-nodeaffinity-required   0/1     Pending   0          38s   <none>   <none>   <none>           <none>
[root@master ~]# //刪除pod,修改其中一個標(biāo)簽為存在的標(biāo)簽:test。[root@master ~]# kubectl delete -f pod-nodeaffinity-required.yaml 
pod "pod-nodeaffinity-required" deleted
[root@master ~]# //創(chuàng)建pod
[root@master ~]# vim pod-nodeaffinity-required.yaml 
[root@master ~]# cat pod-nodeaffinity-required.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodeaffinity-requirednamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1affinity:  nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms:- matchExpressions: - key: nodeenvoperator: Invalues: ["test","yyy"]			//修改一個標(biāo)簽為存在的標(biāo)簽:test
[root@master ~]# //創(chuàng)建pod
[root@master ~]# kubectl apply -f pod-nodeaffinity-required.yaml 
pod/pod-nodeaffinity-required created
[root@master ~]# //查看pod
--由于標(biāo)簽nodeenv:test是可以選擇到的,所以pod被調(diào)度到對應(yīng)的node2節(jié)點上了,pod正常運行
[root@master ~]# kubectl get -f pod-nodeaffinity-required.yaml -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
pod-nodeaffinity-required   1/1     Running   0          17s   10.244.2.3   node2   <none>           <none>
[root@master ~]# 

示例preferredDuringSchedulingIgnoredDuringExecution (軟限制)

創(chuàng)建一個pod-nodeaffinity-preferred.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-nodeaffinity-preferred.yaml
[root@master ~]# cat pod-nodeaffinity-preferred.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-nodeaffinity-preferrednamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1affinity:  #親和性設(shè)置nodeAffinity: #設(shè)置node親和性preferredDuringSchedulingIgnoredDuringExecution: # 軟限制- weight: 1preference:matchExpressions: # 匹配env的值在["xxx","yyy"]中的標(biāo)簽(當(dāng)前環(huán)境沒有)- key: nodeenvoperator: Invalues: ["xxx","yyy"]
[root@master ~]# 

前面已經(jīng)為node1節(jié)點打上了nodeenv=pro的標(biāo)簽,node2節(jié)點打上了nodeenv=test的標(biāo)簽

資源文件里面定義了軟限制:選擇nodeenv=xxx,或者nodeenv=yyy;雖然這兩個標(biāo)簽都是不存在的,但是由于定義的軟限制,所以這個pod會被調(diào)度其它適合運行的節(jié)點

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-nodeaffinity-preferred.yaml 
pod/pod-nodeaffinity-preferred created
[root@master ~]# //查看pod,在node2上運行成功
[root@master ~]# 
[root@master ~]# kubectl get -f pod-nodeaffinity-preferred.yaml -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
pod-nodeaffinity-preferred   1/1     Running   0          63s   10.244.2.4   node2   <none>           <none>
[root@master ~]# 
NodeAffinity規(guī)則設(shè)置的注意事項:1 如果同時定義了nodeSelector和nodeAffinity,那么必須兩個條件都得到滿足,Pod才能運行在指定的Node上2 如果nodeAffinity指定了多個nodeSelectorTerms,那么只需要其中一個能夠匹配成功即可3 如果一個nodeSelectorTerms中有多個matchExpressions ,則一個節(jié)點必須滿足所有的才能匹配成功4 如果一個pod所在的Node在Pod運行期間其標(biāo)簽發(fā)生了改變,不再符合該Pod的節(jié)點親和性需求,則系統(tǒng)將忽略此變化
PodAffinity

PodAffinity主要實現(xiàn)以運行的Pod為參照,實現(xiàn)讓新創(chuàng)建的Pod跟參照pod在一個區(qū)域的功能。

首先來看一下PodAffinity的可配置項:

pod.spec.affinity.podAffinityrequiredDuringSchedulingIgnoredDuringExecution  硬限制namespaces       指定參照pod的namespacetopologyKey      指定調(diào)度作用域labelSelector    標(biāo)簽選擇器matchExpressions  按節(jié)點標(biāo)簽列出的節(jié)點選擇器要求列表(推薦)key    鍵values 值operator 關(guān)系符 支持In, NotIn, Exists, DoesNotExist.matchLabels    指多個matchExpressions映射的內(nèi)容preferredDuringSchedulingIgnoredDuringExecution 軟限制podAffinityTerm  選項namespaces      topologyKeylabelSelectormatchExpressions  key    鍵values 值operatormatchLabels weight 傾向權(quán)重,在范圍1-100
topologyKey用于指定調(diào)度時作用域,例如:如果指定為kubernetes.io/hostname,那就是以Node節(jié)點為區(qū)分范圍如果指定為beta.kubernetes.io/os,則以Node節(jié)點的操作系統(tǒng)類型來區(qū)分

示例requiredDuringSchedulingIgnoredDuringExecution (硬限制)

先創(chuàng)建一個用于參照的pod

//編寫資源文件,創(chuàng)建pod
[root@master ~]# vim pod-podaffinity-target.yaml
[root@master ~]# cat pod-podaffinity-target.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-podaffinity-targetnamespace: lcwanflabels:podenv: pro 				# 設(shè)置標(biāo)簽
spec:containers:- name: httpdimage: lcwanf/apache:v0.1nodeName: node1 				# 將目標(biāo)pod名確指定到node1上
[root@master ~]# [root@master ~]# kubectl apply -f pod-podaffinity-target.yaml 
pod/pod-podaffinity-target created
[root@master ~]# [root@master ~]# kubectl get -f pod-podaffinity-target.yaml -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-target   1/1     Running   0          14s   10.244.1.45   node1   <none>           <none>
[root@master ~]# 

創(chuàng)建一個pod-podaffinity-required.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-podaffinity-required.yaml
[root@master ~]# cat pod-podaffinity-required.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-podaffinity-requirednamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1affinity:  									# 親和性設(shè)置podAffinity: 								# 設(shè)置pod親和性requiredDuringSchedulingIgnoredDuringExecution: 	# 硬限制- labelSelector:matchExpressions: 				# 匹配env的值在["xxx","yyy"]中的標(biāo)簽- key: podenvoperator: Invalues: ["xxx","yyy"]topologyKey: kubernetes.io/hostname
[root@master ~]# 

前面已經(jīng)為node1節(jié)點打上了nodeenv=pro的標(biāo)簽,node2節(jié)點打上了nodeenv=test的標(biāo)簽

資源文件里定義了新Pod必須要與擁有標(biāo)簽nodeenv=xxx或者nodeenv=yyy的pod在同一Node上

可是現(xiàn)在沒有這樣的pod,所以不會運行成功

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-podaffinity-required.yaml 
pod/pod-podaffinity-required created
[root@master ~]# //查看pod
--容器無法正常運行,為Pending狀態(tài)
[root@master ~]# kubectl get -f pod-podaffinity-required.yaml -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod-podaffinity-required   0/1     Pending   0          23s   <none>   <none>   <none>           <none>
[root@master ~]# //刪除pod,修改 values: ["xxx","yyy"]里面的xxx為pro
# 意思是:新Pod必須要與擁有標(biāo)簽nodeenv=xxx或者nodeenv=yyy的pod在同一Node上
[root@master ~]# kubectl delete -f pod-podaffinity-required.yaml 
pod "pod-podaffinity-required" deleted
[root@master ~]# [root@master ~]# vim pod-podaffinity-required.yaml 
[root@master ~]# cat pod-podaffinity-required.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-podaffinity-requirednamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1affinity:  podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector:matchExpressions: - key: podenvoperator: Invalues: ["pro","yyy"]			//把xxx修改為protopologyKey: kubernetes.io/hostname
[root@master ~]# //創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-podaffinity-required.yaml 
pod/pod-podaffinity-required created
[root@master ~]# //查看pod,運行成功。新pod和參照的pod都在node1節(jié)點上
[root@master ~]# kubectl get -f pod-podaffinity-required.yaml -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-required   1/1     Running   0          12s   10.244.1.46   node1   <none>           <none>
[root@master ~]# 

示例preferredDuringSchedulingIgnoredDuringExecution (軟限制)

在此不做演示,只簡單口述:

PodAffinity的軟限制,是當(dāng)定義一個新pod需要和一個參考pod在同一節(jié)點,但是這個條件無法滿足。就把這個新pod調(diào)度給一個合適的node節(jié)點。和NodeAffinity里面的軟限制示例一樣的


PodAntiAffinity

PodAntiAffinity主要實現(xiàn)以運行的Pod為參照,讓新創(chuàng)建的Pod跟參照pod不在一個區(qū)域中的功能。

它的配置方式和選項跟PodAffinty是一樣的。示例如下:

繼續(xù)使用上一個示例里面的參考pod

[root@master ~]# kubectl get -f pod-podaffinity-target.yaml -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-target   1/1     Running   0          86m   10.244.1.45   node1   <none>           <none>
[root@master ~]# 

創(chuàng)建一個pod-podantiaffinity-required.yaml文件,內(nèi)容如下:

//編寫資源文件
[root@master ~]# vim pod-podantiaffinity-required.yaml
[root@master ~]# cat pod-podantiaffinity-required.yaml 
apiVersion: v1
kind: Pod
metadata:name: pod-podantiaffinity-requirednamespace: lcwanf
spec:containers:- name: httpdimage: lcwanf/apache:v0.1affinity:  #親和性設(shè)置podAntiAffinity: #設(shè)置pod親和性requiredDuringSchedulingIgnoredDuringExecution: # 硬限制- labelSelector:matchExpressions: # 匹配podenv的值在["pro"]中的標(biāo)簽- key: podenvoperator: Invalues: ["pro"]topologyKey: kubernetes.io/hostname
[root@master ~]# 

上面配置表達的意思是:新Pod必須要與擁有標(biāo)簽nodeenv=pro的pod不在同一Node上。

創(chuàng)建資源并查看

//創(chuàng)建資源
[root@master ~]# kubectl apply -f pod-podantiaffinity-required.yaml 
pod/pod-podantiaffinity-required created
[root@master ~]# //查看pod
# 發(fā)現(xiàn)調(diào)度到了node2上
[root@master ~]# kubectl get -f pod-podantiaffinity-required.yaml -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
pod-podantiaffinity-required   1/1     Running   0          67s   10.244.2.5   node2   <none>           <none>
[root@master ~]#


五、污點和容忍

污點(Taints)

前面的調(diào)度方式都是站在Pod的角度上,通過在Pod上添加屬性,來確定Pod是否要調(diào)度到指定的Node上,其實我們也可以站在Node的角度上,通過在Node上添加污點屬性,來決定是否允許Pod調(diào)度過來。

Node被設(shè)置上污點之后就和Pod之間存在了一種相斥的關(guān)系,進而拒絕Pod調(diào)度進來,甚至可以將已經(jīng)存在的Pod驅(qū)逐出去。

污點的格式為:key=value:effect, key和value是污點的標(biāo)簽,effect描述污點的作用,支持如下三個選項:

  • PreferNoSchedule:kubernetes將盡量避免把Pod調(diào)度到具有該污點的Node上,除非沒有其他節(jié)點可調(diào)度
  • NoSchedule:kubernetes將不會把Pod調(diào)度到具有該污點的Node上,但不會影響當(dāng)前Node上已存在的Pod
  • NoExecute:kubernetes將不會把Pod調(diào)度到具有該污點的Node上,同時也會將Node上已存在的Pod驅(qū)離

在這里插入圖片描述

使用kubectl設(shè)置和去除污點的命令示例如下:

# 設(shè)置污點
kubectl taint nodes node1 key=value:effect# 去除污點
kubectl taint nodes node1 key:effect-# 去除所有污點
kubectl taint nodes node1 key-

接下來,演示下污點的效果:

  1. 準(zhǔn)備節(jié)點node1(為了演示效果更加明顯,暫時停止node2節(jié)點)
  2. 為node1節(jié)點設(shè)置一個污點: tag=wanf:PreferNoSchedule;然后創(chuàng)建pod1( pod1 可以 )
  3. 修改為node1節(jié)點設(shè)置一個污點: tag=wanf:NoSchedule;然后創(chuàng)建pod2( pod1 正常 pod2 失敗 )
  4. 修改為node1節(jié)點設(shè)置一個污點: tag=wanf:NoExecute;然后創(chuàng)建pod3 ( 3個pod都失敗 )
# 為node1設(shè)置污點(PreferNoSchedule)
[root@master ~]# kubectl taint nodes node1 tag=wanf:PreferNoSchedule# 創(chuàng)建pod1
[root@master ~]# kubectl run taint1 --image=nginx:1.17.1 -n dev
[root@master ~]# kubectl get pods -n dev -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP           NODE   
taint1-7665f7fd85-574h4   1/1     Running   0          2m24s   10.244.1.59   node1    # 為node1設(shè)置污點(取消PreferNoSchedule,設(shè)置NoSchedule)
[root@master ~]# kubectl taint nodes node1 tag:PreferNoSchedule-
[root@master ~]# kubectl taint nodes node1 tag=wanf:NoSchedule# 創(chuàng)建pod2
[root@master ~]# kubectl run taint2 --image=nginx:1.17.1 -n dev
[root@master ~]# kubectl get pods taint2 -n dev -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE
taint1-7665f7fd85-574h4   1/1     Running   0          2m24s   10.244.1.59   node1 
taint2-544694789-6zmlf    0/1     Pending   0          21s     <none>        <none>   # 為node1設(shè)置污點(取消NoSchedule,設(shè)置NoExecute)
[root@master ~]# kubectl taint nodes node1 tag:NoSchedule-
[root@master ~]# kubectl taint nodes node1 tag=wanf:NoExecute# 創(chuàng)建pod3
[root@master ~]# kubectl run taint3 --image=nginx:1.17.1 -n dev
[root@master ~]# kubectl get pods -n dev -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED 
taint1-7665f7fd85-htkmp   0/1     Pending   0          35s   <none>   <none>   <none>    
taint2-544694789-bn7wb    0/1     Pending   0          35s   <none>   <none>   <none>     
taint3-6d78dbd749-tktkq   0/1     Pending   0          6s    <none>   <none>   <none>     
小提示:使用kubeadm搭建的集群,默認就會給master節(jié)點添加一個污點標(biāo)記,所以pod就不會調(diào)度到master節(jié)點上.
容忍(Toleration)

上面介紹了污點的作用,我們可以在node上添加污點用于拒絕pod調(diào)度上來,但是如果就是想將一個pod調(diào)度到一個有污點的node上去,這時候應(yīng)該怎么做呢?這就要使用到容忍。

在這里插入圖片描述

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

下面先通過一個案例看下效果:

  1. 上一小節(jié),已經(jīng)在node1節(jié)點上打上了NoExecute的污點,此時pod是調(diào)度不上去的
  2. 本小節(jié),可以通過給pod添加容忍,然后將其調(diào)度上去

創(chuàng)建pod-toleration.yaml,內(nèi)容如下

apiVersion: v1
kind: Pod
metadata:name: pod-tolerationnamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1tolerations:      # 添加容忍- key: "tag"        # 要容忍的污點的keyoperator: "Equal" # 操作符value: "wanf"    # 容忍的污點的valueeffect: "NoExecute"   # 添加容忍的規(guī)則,這里必須和標(biāo)記的污點規(guī)則相同
# 添加容忍之前的pod
[root@master ~]# kubectl get pods -n dev -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED 
pod-toleration   0/1     Pending   0          3s    <none>   <none>   <none>           # 添加容忍之后的pod
[root@master ~]# kubectl get pods -n dev -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED
pod-toleration   1/1     Running   0          3s    10.244.1.62   node1   <none>        

下面看一下容忍的詳細配置:

[root@master ~]# kubectl explain pod.spec.tolerations
......
FIELDS:key       # 對應(yīng)著要容忍的污點的鍵,空意味著匹配所有的鍵value     # 對應(yīng)著要容忍的污點的值operator  # key-value的運算符,支持Equal和Exists(默認)effect    # 對應(yīng)污點的effect,空意味著匹配所有影響tolerationSeconds   # 容忍時間, 當(dāng)effect為NoExecute時生效,表示pod在Node上的停留時間
http://www.risenshineclean.com/news/64859.html

相關(guān)文章:

  • 紹興網(wǎng)站設(shè)計騰訊會議價格
  • 上海做公司網(wǎng)站的公司企業(yè)培訓(xùn)內(nèi)容包括哪些內(nèi)容
  • wordpress回收站+恢復(fù)公司網(wǎng)站排名
  • 曲阜做網(wǎng)站的公司360優(yōu)化大師app下載
  • 建網(wǎng)站代碼百度搜索風(fēng)云榜排名
  • 怎么做網(wǎng)站教程+用的工具短視頻代運營合作方案
  • 資源下載站 wordpress軟文營銷ppt
  • 做效果圖有哪些網(wǎng)站線上營銷推廣方法
  • 中山手機網(wǎng)站設(shè)計品牌傳播推廣方案
  • java能做網(wǎng)站開發(fā)么線上平臺推廣方式
  • 昆山網(wǎng)站制作 微博google官方版下載
  • 深圳龍華是低風(fēng)險區(qū)嗎草根seo視頻大全
  • 織夢網(wǎng)站如何做seo西安網(wǎng)站建設(shè)公司排行榜
  • 什么網(wǎng)站可以做推廣的電腦培訓(xùn)班多少費用
  • 德宏網(wǎng)站建設(shè)公司活動營銷案例100例
  • 杭州建網(wǎng)站google移動服務(wù)應(yīng)用優(yōu)化
  • 微信公眾號運營方案seo技術(shù)培訓(xùn)教程
  • 網(wǎng)站開發(fā)順序網(wǎng)絡(luò)營銷服務(wù)公司
  • 建設(shè)網(wǎng)站實訓(xùn)app推廣方法
  • 58同城成都網(wǎng)站建設(shè)搜狗收錄提交
  • bootstrap手機網(wǎng)站模板寧波seo教程推廣平臺
  • 成都那家做網(wǎng)站好?競價推廣教程
  • 做數(shù)據(jù)收集網(wǎng)站百度競價登錄入口
  • 附近那里有做網(wǎng)站的企業(yè)網(wǎng)站設(shè)計的基本內(nèi)容包括哪些
  • 網(wǎng)站默認中文字體怎么自己制作網(wǎng)頁
  • wordpress底部footerseo搜索引擎優(yōu)化工資
  • 上海期貨配資網(wǎng)站開發(fā)沈陽seo優(yōu)化排名公司
  • 北京網(wǎng)站建設(shè)備案代理北京搜索引擎優(yōu)化管理專員
  • wordpress 戀月seo優(yōu)化關(guān)鍵詞
  • 溫州電力建設(shè)有限公司網(wǎng)站網(wǎng)站seo排名公司