Pod


          user containerN
          user imageN
          
           ......
           
           user contaner1
           user image1
           
               Pause
   gcr.io/google_containers/pause-amd64

 

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

  • 用戶程序所在的容器,數量可多可少
  • Pause容器,這是每個Pod都會有一個根容器,它的作用有兩個 : 1.可以以它為依據,評估整個Pod的健康狀態。2.可以在根容器上設置IP地址,其他容器共享此IP,實現pod內部的網絡通信
這里是Pod的內部通信,Pod之間的通信采用虛擬二層網絡技術來實現,當前環境使用的是flanne

Pod的定義

以下是Pod的資源清單,也就是yml配置

apiVersion: v1  #必選,版本號
kind: Pod  #必選,資源類型,例如Pod,service,deployment
metadata:   #必選,元數據
  name: string #必選,Pod名稱
  namespace: string  #Pod所在的名稱空間,默認為“default”
  labels:  #自定義標簽
    - name: string
spec: #必選,Pod中容器的詳細定義
  containers: #必選,Pod中容器列表
  - name: string #必選,容器名稱
    image: #必選,容器鏡像名稱
    imagePillPolicy: [Always|Never|IfNotPresent] #獲取鏡像策略
    command: [string] #啟動容器的命令參數列表,如不指定,使用打包時使用的啟動命令
    args: [string] #容器啟動的參數列表
    workingDir: string  #容器的工作目錄
    volumeMounts: #掛載到容器內部的存儲卷配置
    - name: string #引用pod定義的共享存儲卷民初,需要使用volumes[]部分定義的卷名
      mountPath: string #存儲卷在容器mount的絕對路徑
      readOnly: boolean #是否為只讀模式
    ports: #需要暴露的端口庫號列表
    - name: string  #端口的名稱
      containerPort: int #容器需要監聽的端口號
      hostPort: int #容器所在主機需要監聽的端口號,默認於Container相同
      protocol: string #端口協議默認TCP
    env: # 容器運行前設置環境變量列表
    - name: staring # 環境變量名稱
      value: 環境變量值
    resources: #資源現在和請求的設置
      limits: #資源限制的設置
        cpu: string #cpu限制,單位為core數,將用於docker run --cpu-share參數
        memory: string # 內存限制,單位Mib/Gib,將用於docker run --memory參數
      requests: #資源請求的設置
        cpu: string #cpu請求,容器啟動的初始可用數量
        memory: string #內存請求,容器啟動的初始可用量
    lifecycle: #生命周期鈎子
        postStart: #容器啟動后立即執行此鈎子,如果執行失敗,會根據重啟策略進行重啟
        preStop: #容器終止前執行此鈎子,無論結果如何,容器都會終止
    livenessProbe: #對Pod內各個容器健康檢查的設置,當探測無響應幾次后將自動重啟該容器
      exec: #對Pod容器內檢查方式設置為exec方式
        command: [string] #exec方式需要自定的命令或腳本
      httpGet: #對Pod內容器檢查方式設置我Httpget,需要制定path,port
        path: string
        port: int
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket: #對Pod容器健康檢查方式這種問tcpSocket方式
          port: number
        initialDelaySecondes: 0 #容器啟動完成后首次探測的時間,單位為秒
        timeoutSeconds: 0 #對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒
        periodSeconds: 0 #對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次
        successThreshold:0
        failuerThreshold:0
        securityContext:
          privileged: false
restarPolicy: [Always|Never|OnFailure] #Pod的重啟策略
nodeName: <string> #設置NodeName表示將該Pod調度到指定名稱的node節點上
nodeSeletor: obeject #設置NodeSeletor表示將該Pod調度到包含這個label的node上
imagePullSecrets:#Pull鏡像時使用的Secret名稱,以Key:secretkey格式指定
- name: string
hostNetwork: false  #是否使用主機網絡模式,默認false
voulmes: #在該Pod上定義共享存儲卷列表
- name: string #共享存儲卷名稱(volumes類型有很多種)
  emptyDir: {} #類型為emtDir的存儲卷,與Pod同生命周期的一個臨時目錄。為空值
  hostPath: string #類型為HostPath的存儲卷,表示掛載Pod所在的宿主機的目錄
    path: string  #pod所在的宿主機的目錄,將被用於同期種mount的目錄
  secret: #類型為secret的存儲卷,掛載集群與定義的secret對象到容器內部
    secretname: string
    itmes:
    - key: string
      path: string
 configMap: #類型為configMap的存儲卷,掛載預定義的configMap對象到容器
   name:string
   items:
   - key: string
     path: string

 可以使用以下命令查詢每種資源的配置方式

# kubectl explain 資源類型
# kubectl explain 資源類型.屬性

 

Pod配置

創建一個pod-base.yml文件,內容如下

apiVersion: v1
kind: Pod
metadata:
  name: pod-base
  namespace: dev
  labels:
    version: test
spec: 
  containers:
  - name: nginx
    image: nginx:1.17.2
  - name: busybox
    image: busybox:1.30

 

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

  • nginx: 用1.17.2版本的nginx鏡像創建
  • busybox: 用1.30版本的busybox鏡像創建
#創建Pod
kubectl apply -f pod-bose.yml

#查看Pod狀態
 kubectl  get pod -n dev
NAME                     READY   STATUS             RESTARTS   AGE
nginx-64777cd554-7p7xt   1/1     Running            2          31h
nginx-64777cd554-cqbjd   1/1     Running            1          25h
nginx-64777cd554-tv5g2   1/1     Running            2          31h
pod-base                 1/2     CrashLoopBackOff   5          5m9s


#可以通過describe查看內部的詳情
#此時已經運行了一個基本的pod,雖然出現了一些問題
[root@master ~]# kubectl  describe  pod  pod-base -n dev
............
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  4m34s                  default-scheduler  Successfully assigned dev/pod-base to node1
  Normal   Pulling    4m31s                  kubelet, node1     Pulling image "nginx:1.17.2"
  Normal   Pulled     3m42s                  kubelet, node1     Successfully pulled image "nginx:1.17.2"
  Normal   Created    3m41s                  kubelet, node1     Created container nginx
  Normal   Started    3m40s                  kubelet, node1     Started container nginx
  Normal   Pulling    3m40s                  kubelet, node1     Pulling image "busybox:1.30"
  Normal   Pulled     3m22s                  kubelet, node1     Successfully pulled image "busybox:1.30"
  Normal   Created    2m39s (x4 over 3m22s)  kubelet, node1     Created container busybox
  Normal   Pulled     2m39s (x3 over 3m20s)  kubelet, node1     Container image "busybox:1.30" already present on machine
  Normal   Started    2m38s (x4 over 3m22s)  kubelet, node1     Started container busybox
  Warning  BackOff    2m8s (x8 over 3m19s)   kubelet, node1     Back-off restarting failed container

 

鏡像拉取

創建pod-imagePullPolicy.yml文件,內容如下

apiVersion: v1
kind: Pod
metadata:
  name: pod-imagepullpolicy
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.3
    imagePullPolicy: Always
  - name: busybox
    image: busybox:1.30

 

imagePullPolicy,用於設置鏡像拉取策略,kubernetes中支持配置的三種拉取策略

  • Always:總是從遠程倉庫拉取鏡像
  • IfNotPresent: 本地有鏡像則使用本地,沒有則遠程拉取
  • Never: 只能使用本地鏡像,從不去遠程拉取

默認值說明:

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

如果鏡像tag為latest,默認策略時always

#創建Pod
kubectl apply -f pod-imagePullPolicy.yml

# 查看pod
kubectl get pod -n dev

# 查看詳細信息
kubectl get pod pod-imagepullpolicy -n dev 

 

啟動命令

上面的容器案例中,有一個問題沒有解決,就是busybox運行一直沒有成功,因為busybox並不是一個程序,而是一個類似工具類的集合,kubernetes集群啟動管理后,它會自動關閉,解決辦法就是讓其一直運行,就需要使用到command配置,

vim pod-command.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-command
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    imagePullPolicy: IfNotPresent
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3;done"]
    
    
# 創建pod
kubectl apply -f pod-command.yml

#查看狀態,可以看到兩個Pod都正常運行了
[root@master ~]# kubectl  get pod  pod-command -n dev
NAME          READY   STATUS    RESTARTS   AGE
pod-command   2/2     Running   0          85s

#進入pod中的busybox容器,查看文件內容
kubectl exec pod-command -n dev --it -c  busybox /bin/sh

說明:

通過上面方向command已經可用完成啟動命令和傳遞參數的功能,為什么這里還要通過args選項,用於傳遞參數?

這其實和docker有點關系,kubernetes中的comand,arges兩項其實是實現覆蓋DockerfileHon中的ENTRYPOINT的功能。

  • 如果command和args均沒有寫,那么就用Dockerfile的配置。
  • 如果command寫了,arges沒有寫,那么Dockerfile默認的配置會被忽略,執行輸入的command
  • 如果command沒寫,但args寫了,那么Dockerfile中配置的ENTRYPOINT的命令會被執行,使用當前args的參數
  • 如果command和args都寫了,那么Dockerfile的配置被忽略,執行command並追加上args參數

 

環境變量

vim pod-env.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-env
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    imagePullPolicy: IfNotPresent
  - name: busybox
    image: busybox:1.30
    command: ["/bin/sh","-c","touch /tmp/hello.txt;while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3;done"]
    env:
    - name: "username"
      value: "admin"
    - name: "password"
      value: "123456"

 env,環境變量,用於Pod中容器設置環境變量

# 創建Pod
kubectl create -f pod-env.yml

#進入容器查看環境變量
[root@master ~]# kubectl exec pod-env -n dev -it -c busybox /bin/sh
/ # echo $username
admin
/ # echo $password
123456

 不推薦使用這種方式,推薦這些配置在單獨存儲的配置文件中

端口設置

vim pod-ports.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-ports
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    imagePullPolicy: IfNotPresent
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP


#啟動pod
kubectl create -f  pod-ports.yml

# 查看
kubectl get pod pod-ports -n dev

 

資源配額

容器中的程序要運行坑,而程序的運行肯定要占用一定的資源,如果不對某一個容器限定資源,可能會在某一瞬間吃掉大量的資源,導致其他容器無法運行。針對這種情況,kuberneters提供了對內存和cpu資源進行配額的機制,這個機制主要是在resources選項實現,其有兩個子選線。

  • limits: 用於限制運行時容器的最大占用資源,當容器超過limits時會被終止,並進行重啟
  • requests:用於設置容器需要的最小資源,如果環境資源不夠,容器將無法啟動

可用通過以上兩個選項色澤資源的上下限

vim pod-resources.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-resuorces
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        cpu: "1"
        memory: "1Gi"
      requests:
        cpu: "0.2"
        memory: "10Mi"


# 運行pod
 kubectl  create -f pod-resources.yml
 
# 查看pod
kubectl  get pod pod-resuorces  -n dev

 

Pod生命周期

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

  • Pod創建過程

  • 運行初始化容器過程

  • 運行主容器過程

    容器啟動后鈎子,容器終止前鈎子

    容器的存活性探測,就緒性探測

  • pod終止過程

在整個生命周期種Pod會出現5種狀態(相位),分別如下;

  • 掛起(Pending):apiserver已經創建了Pod資源對象,但它尚未被調度完成或者仍處於鏡像下載狀態

  • 運行中(running):pod已經被調到至某節點,並且所有容器都已經被kubelet創建完成

  • 成功(Succeded): pod中的所有容器都已經成功並且不會被重啟

  • 失敗(Failed): 所有容器都已經終止,但至少有一個容器終止失敗,即容器返回非0值的退出狀態

  • 未知(Unkown): apiserver無法正常獲取到pod對象的狀態信息,通常由網絡通信失敗導致

初始化容器

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

1.初始化容器必選運行完成至結束,若某一個初始化容器運行失敗,那么kubernetes需要重啟直到完成為止。

2.初始化容器必選按照定義的順序執行,當且僅當前一個成功之后,后面一個才能運行

初始化容器由很多的應用場景,下面列出的是最常見的幾個;

  • 提供主容器鏡像中不具被的工具程序或自定義代碼

  • 初始化容器要選育應用容器串行啟動並運行完成,因此可用於延后應用容器的啟動直至其依賴的條件得到滿足

示例:

假設要以主容器來運行nginx,但是需要在運行nginx之前先要能夠連接上MySQL和redis所在的服務器,為了簡化測試,事先規定號MySQL(192.168.248.4)和redis(192.168.248.24)服務器的地址。

創建pod-initcontainer.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-initcontainer
  namespace: dev
spec:
  containers:
  - name: main-container
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
  initContainers:
  - name: test-mysql
    image: busybox:1.30
    command: ['sh','-c','until ping 192.168.248.4 -c 1;do echo waiting for mysql ... ;sleep 2;done']
  - name: test-redis
    image: busybox:1.30
    command: ['sh','-c','until ping 192.168.248.24 -c 1;do echo waiting for redis ... ;sleep 2;done'] 
    
# 啟動pod
kubectl create -f pod-initcontainer.yml 

#查看狀態
[root@master ~]# kubectl  get pod pod-initcontainer -n dev
NAME                READY   STATUS     RESTARTS   AGE
pod-initcontainer   0/1     Init:0/2   0          18s

#動態查看狀態
[root@master ~]# kubectl  get pod pod-initcontainer -n dev -w
NAME                READY   STATUS     RESTARTS   AGE
pod-initcontainer   0/1     Init:0/2   0          52s


#新開一個窗口,為當前服務器增加兩個IP
ifconfig  ens33:1 192.168.248.4 netmask 255.255.255.0 up
ifconfig  ens33:1 192.168.248.24 netmask 255.255.255.0 up

[root@master ~]# kubectl  get pod pod-initcontainer -n dev -w
NAME                READY   STATUS     RESTARTS   AGE
pod-initcontainer   0/1     Init:0/2   0          52s
pod-initcontainer   0/1     Init:1/2   0          2m37s
pod-initcontainer   0/1     Init:1/2   0          2m38s
pod-initcontainer   0/1     PodInitializing   0          2m51s
pod-initcontainer   1/1     Running           0          2m52s

 

鈎子函數

鈎子函數能夠感知自身生命周期中的事件,並在相應的時候到來之運行用戶指定的程序代碼。

kubeernetes在主容器啟動之后和停止之前提供了兩個鈎子函數:

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

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

Exec命令: 在容器內執行一次命令

......
    lifecycle:
      postStart:
        exec:
          command:
          - cat
          - /tmp/healthy
......

 TCPSocket: 在放棄容器嘗試訪問指定的socket

.....
    lifecycle:
      postStart:
        tcpoSocket:
          port: 8080
.....

 HTTPGet:在當前容器中向某個url發起http請求

.....
    lifecycle:
      postStart:
        httpGet:
          path: / #url地址
          post: 80 #端口號
          host: 192.168.248.11 #主機地址
          scheme: HTTP #支持協議,http或者https
......  

 下面以exec方式為例,演示鈎子函數的使用,創建pod-hook-exec.yml文件

apiVersion: v1
kind: Pod
metadata:
  name: pod-hook-exec
  namespace: dev
spec:
  containers:
  - name: main-container
    image: nginx:1.17.2
    ports:
    - name: nginx-pod
      containerPort: 80
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh","-c","echo postStart... > /usr/share/nginx/html/index.html"]
      preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]



# 創建pod
kubectl create -f pod-hook-exec.yml

# 查看pod
[root@master ~]# kubectl  get pod pod-hook-exec -n dev -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-hook-exec   1/1     Running   0          57s   10.244.1.43   node1   <none>           <none>

# 訪問測試
[root@master ~]# curl 10.244.1.43
postStart...

 

容器探測

容器探測用於檢測容器中的應用示例是否正常工作,是保證業務可用性的一種傳統機制。如果經過探測,示例的狀態不符合預期,那塊kubernetes就會把該問題實例"摘除",不承擔業務流量。kubernetes提供了兩種探針來實現容器探測,分別是:

  • liveness probes:存活性探針,用於檢測應用實例當前是否處於正常運行狀態,如果不是,ks會重啟容器

  • rediness probes: 就緒性探針,用於檢測應用實例當前是否可用接受到請求,如果不能,k8s不會轉發流量

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

Exec命令:在容器內執行一次命令,如果命令執行的退出嗎為0,則程序認為正常,否則不正常

  livenessProbe: 
      exec:
        command:
        - cat 
        - /tmp/healthy

 TCPSocket:將會嘗試訪問一個用戶容器的端口,如果能建立連接,則認為正常,否則不正常

 livenessProbe:
      tcpSocket:
        port: 8080

 HTTPGet:調用web應用url,如果返回在200-399,則認為程序正常,否則不正常

 lifecycle:
      postStart:
        httpGet:
          path: / #url地址
          post: 80 #端口號
          host: 192.168.248.11 #主機地址
          scheme: HTTP #支持協議,http或者https

 

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

創建文件pod-liveness.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/cat","/tmp/hello.txt"]

#創建pod
[root@master ~]# kubectl create -f pod-liveness.yml 
pod/pod-liveness created

#查看pod詳情
[root@master ~]# kubectl describe pod pod-liveness -n dev
....................
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  <unknown>          default-scheduler  Successfully assigned dev/pod-liveness to node2
  Normal   Pulled     28s (x2 over 50s)  kubelet, node2     Container image "nginx:1.17.2" already present on machine
  Normal   Created    28s (x2 over 50s)  kubelet, node2     Created container nginx
  Normal   Started    28s (x2 over 50s)  kubelet, node2     Started container nginx
  Normal   Killing    28s                kubelet, node2     Container nginx failed liveness probe, will be restarted
  Warning  Unhealthy  8s (x5 over 48s)   kubelet, node2     Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  <unknown>          default-scheduler  Successfully assigned dev/pod-liveness to node2
  Normal   Pulled     28s (x2 over 50s)  kubelet, node2     Container image "nginx:1.17.2" already present on machine
  Normal   Created    28s (x2 over 50s)  kubelet, node2     Created container nginx
  Normal   Started    28s (x2 over 50s)  kubelet, node2     Started container nginx
  Normal   Killing    28s                kubelet, node2     Container nginx failed liveness probe, will be restarted
  Warning  Unhealthy  8s (x5 over 48s)   kubelet, node2     Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory

#因為沒有hello.txt文件,存活性探針會一直重啟這個Pod
[root@master ~]# kubectl get  pod pod-liveness -n dev
NAME           READY   STATUS    RESTARTS   AGE
pod-liveness   1/1     Running   4          2m21s


#正確示例
[root@master ~]# kubectl delete -f pod-liveness.yml 
pod "pod-liveness" deleted

[root@master ~]# vim pod-liveness.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/ls","/tmp"]

# 創建pod
[root@master ~]# kubectl create -f pod-liveness.yml 
pod/pod-liveness created

#創建成功並沒有重啟
[root@master ~]# kubectl get  pod pod-liveness -n dev
NAME           READY   STATUS    RESTARTS   AGE
pod-liveness   1/1     Running   0          11s

 

TCPSocket

創建pod-liveness-tcpsocket.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-tcpsocket
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      tcpSocket:
        port: 8080   #嘗試訪問8080端口


# 創建Pod
[root@master ~]# kubectl create  -f pod-liveness-tcpsocket.yml 
pod/pod-tcpsocket created

#查看信息
[root@master ~]# kubectl describe pod pod-tcpsocket -n dev
...........
Events:
  Type     Reason     Age        From               Message
  ----     ------     ----       ----               -------
  Normal   Scheduled  <unknown>  default-scheduler  Successfully assigned dev/pod-tcpsocket to node1
  Normal   Pulled     15s        kubelet, node1     Container image "nginx:1.17.2" already present on machine
  Normal   Created    15s        kubelet, node1     Created container nginx
  Normal   Started    15s        kubelet, node1     Started container nginx
  Warning  Unhealthy  9s         kubelet, node1     Liveness probe failed: dial tcp 10.244.1.46:8080: connect: connection refused

 

HTTPGet

創建文件pod-liveness-httpget.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-httpget
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.1
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80
        path: /


# 創建pod
[root@master ~]# kubectl  create -f  pod-liveness-httpget.yml 
pod/pod-httpget created

#查看pod詳情
[root@master ~]# kubectl describe  pod pod-httpget -n dev
.............
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned dev/pod-httpget to node2
  Normal  Pulled     29s        kubelet, node2     Container image "nginx:1.17.1" already present on machine
  Normal  Created    29s        kubelet, node2     Created container nginx
  Normal  Started    29s        kubelet, node2     Started container nginx
[root@master ~]# vim pod-liveness-httpget.yml

 

重啟策略

一旦容器探測出現了問題,kubernetes就會對容器所在的Pod進行重啟,其實這是由pod重啟策略決定的,pod的重啟策略有3種,分別是:

  • Always: 容器失效時,自動重啟該容器,這也是默認從值

  • OnFailure: 容器終止運行且退出碼不為0時重啟

  • Never: 不論狀態為何,都不重啟該容器

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

創建pod-restarpolicy.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-restartpolicy
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80
        path: /hello
  restartPolicy: Never
  
# 創建Pod
[root@master ~]# kubectl  create -f pod-restartpolicy.yml 
pod/pod-restartpolicy created

# 查看Pod詳情發現nginx容器重啟失敗
[root@master ~]# kubectl  describe pod pod-restartpolicy -n dev
.......
Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  <unknown>             default-scheduler  Successfully assigned dev/pod-restartpolicy to node1
  Normal   Pulled     2m20s                 kubelet, node1     Container image "nginx:1.17.2" already present on machine
  Normal   Created    2m20s                 kubelet, node1     Created container nginx
  Normal   Started    2m19s                 kubelet, node1     Started container nginx
  Warning  Unhealthy  114s (x3 over 2m14s)  kubelet, node1     Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    114s                  kubelet, node1     Stopping container nginx

# 由於策略定義的是Never所以容器不會重啟
[root@master ~]# kubectl  get pod pod-restartpolicy -n dev
NAME                READY   STATUS      RESTARTS   AGE
pod-restartpolicy   0/1     Completed   0          3m41

 

Pod調度

在默認情況下,一個Pod在那個Node節點上與性能,是由Scheduler組件采用相應的算法計算出來的,這個過程是不受人工控制的,但是在實際使用中,這並不能滿足需求,因為在很多情況下,我們想控制某些Pod到達某些節點上,應該怎么做呢?這就需要了解Kubernetes對Pod的調度規則,kubernetes提供了四大類的調度。

  • 自動調度: 運行在那個節點上完全由Scheduler經過一系列是算法得出

  • 定性調度: NodeName,NodeSelector

  • 親和性調度: NodeAffinity,PodAffinity,PodAntiAffinity

  • 污點(容忍)調度: Taints,Toleration

定向調度

定向調度,指的是利用在Pod上聲明的NodeName或者NodeSelector,以此將Pod調度到期望的node節點上。注意,這里的調 是強制的,這就意味着即使要調度的目標Node不存在,也會向上面進行調度,只不過是Pod運行失敗而已。

NodeName

NodeName用於強制約束將Pod調度到指定的node上,着種方式直接跳過了Scheduler的調度邏輯,直接寫入PodList列表中

測試一些,創建一個pod-nodename.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodename
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  nodeName: node1

# 創建pod
[root@master ~]# kubectl  create -f pod-nodename.yml 
pod/pod-nodename created

# 查看pod調度到Node屬性,確實調度到了node1節點上
[root@master ~]# kubectl  get pod pod-nodename -n dev -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-nodename   1/1     Running   0          69s   10.244.1.56   node1   <none>           <none>

 

NodeSeletor

NodeSeletor用於將Pod調度到添加了指定標簽的node節點上,它通過kubernetes的label-selector機制實現,也就是說,在Pod創建之前,會有scheduler使MatchNodeSelector調度策略進行label匹配,找出目標node,然后將Pod調度到目標節點,該匹配規則是強制約束。

示例:

# 首先分別給node節點加上標簽
[root@master ~]# kubectl label nodes node1 nodeenv=pro
node/node1 labeled
[root@master ~]# kubectl label nodes node2 nodeenv=dev
node/node2 labeled

# 創建一個pod-nodeselector.yml文件,並使用它創建pod
vim pod-nodeselector.yml
apiVersion: v1
kind: Pod
metadata:
 name: pod-nodeselector
 namespace: dev
spec:
 containers:
 - name: nginx
   image: nginx:1.17.2
 nodeSelector:
   nodeenv: dev
   
#創建Pod
[root@master ~]# kubectl  create -f pod-nodeselector.yml 
pod/pod-nodeselector created

#查看pod調度到NODE屬性,確實調度到了node2節點上
[root@master ~]# kubectl  get pod pod-nodeselector -n dev -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-nodeselector   1/1     Running   0          22s   10.244.2.74   node2   <none>           <none>

# 刪除Pod,修改nodeSelector的值為一個不存在的標簽
[root@master ~]# kubectl delete -f pod-nodeselector.yml 
pod "pod-nodeselector" deleted

[root@master ~]# vim pod-nodeselector.yml 
[root@master ~]# kubectl  create -f pod-nodeselector.yml 
pod/pod-nodeselector created

# 再次查看發現Pod我i發正常運行,Node的值問none
[root@master ~]# kubectl  get pod pod-nodeselector -n dev -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod-nodeselector   0/1     Pending   0          56s   <none>   <none>   <none>           <none>

# 查看詳情發現node selector匹配失敗的提示
[root@master ~]# kubectl  describe  pod pod-nodeselector -n dev
....................
Events:
 Type     Reason            Age        From               Message
 ----     ------            ----       ----               -------
 Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
 Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

 

親和性調度

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

基於上面的問題,kubeneter還提供了一種親和性調度(Affinity)。它在NodeSelector的基礎上進行了擴展,可以通過匹配的形式,實現優先選擇滿足條件的Node進行調度,如果沒有,也可以調度到不滿足的節點上,使調度更加靈活。

Affinity主要分為三類:

  • nodeAffinity(node親和性):以node為目標,解決pod可以調度到那些node的問題

  • podAffinity(pod親和性): 以pod為目標,解決Pod可以和那些已存在的Pod部署在同一個拓撲域中的問題

  • podAntiAffinity(pod反親和性): 以pod為目標,解決pod不能和那些已存在pod部署在同一個拓撲域中的問題

關於親和性(反親和性)使用場景說明:

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

反親和性:當應用采用多副本部署使,有必要采用反親和性讓各個應用實例打散分布在各個node上,這樣可以提高服務的高可用性。

 

NodeAffinity

首先來看一下NodeAffinity的可配置文件

od.spec.affinity.nodeAffinity
  requiredDuringSchedulingIgnoredDuringExecution 必須滿足指定的規則才可以調度,相當於應限制
    nodeSelectorTerms  節點選擇列表
      matchFields  按節點字段列出的節點選擇器要求列表
      matchExpressions 按節點標簽列出的節點選擇器要求列表(推薦)
        key 
        values
        operator 關系符 支持Exists,DoesNotExist,In,NotIn,Gt,Lt
  preferredDuringSchedulingIgnoredDuringExecution 優先調度到滿足指定的規則Node,相等於軟限制(傾向)
    preference 一個節點選擇器,於相應的權重相關聯
      matchFields 按節點字段列出的節點選擇器要求列表
      matchExpressions 按節點標簽列出的節點選擇器要求列表(推薦)
        key
        values
        operator 關系符 支持In,NotIn,Exists,DoesNotExist,Gt,Lt
    weight 傾向權重,在范圍1-100
    
關系符使用說明
- matchExpressions:
  - key: nodeenv  # 匹配存在標簽的key為nodeenv的節點
    operator: Exists 
  - key: nodeenv   # 匹配標簽的key為nodeenv,且value是"xxx"或"yyy"的節點
    operator: In
    values: ["xxx","yyy"]
  - key: nodeenv  #匹配標簽的key為nodeenv,且value大於"xxx"的節點
    operator: Gt
    values: "xxx"

 

演示一下requireDuringSchedulingIgnoredDuringExecution

創建pod-nodeaffinity-required.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeaffinity-required
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: nodeenv
            operator: In
            values: ["xxx","yyy"]
            
# 創建pod
[root@master ~]# kubectl  create -f  pod-nodeaffinity-required.yml 
pod/pod-nodeaffinity-required created

# 查看pod狀態發現運行失敗
[root@master ~]# kubectl  get pod pod-nodeaffinity-required -n dev
NAME                        READY   STATUS    RESTARTS   AGE
pod-nodeaffinity-required   0/1     Pending   0          3m19s

# 查看pod發現調度失敗,提示node選擇失敗
[root@master ~]# kubectl  describe  pod pod-nodeaffinity-required -n dev
.................
Events:
  Type     Reason            Age        From               Message
  ----     ------            ----       ----               -------
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
  Warning  FailedScheduling  <unknown>  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
  
 # 接下來停止pod
 [root@master ~]# kubectl  delete -f pod-nodeaffinity-required.yml 
pod "pod-nodeaffinity-required" deleted

# 修改文件,將values: ["xxx","yyy" ]------->["dev","yyy"]后在次啟動
[root@master ~]# kubectl create -f pod-nodeaffinity-required.yml 
pod/pod-nodeaffinity-required created

#此時查看,發現已經調度成功,已經將pod調度到了node1上
[root@master ~]# kubectl  get pod pod-nodeaffinity-required -n dev -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-nodeaffinity-required   1/1     Running   0          42s   10.244.1.73   node1   <none>           <none>
 

 

下面在演示preferredDuringSchedulingIgnoredDuringExecution

創建pod-nodeaffinity-preferred

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeaffinity-preferred
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: nodeenv
            operator: In
            values: ["xxx","yyy"]
            
# 創建pod
[root@master ~]# kubectl  create -f pod-nodeaffinity-prefereed.yml 
pod/pod-nodeaffinity-preferred created

# 查看pod狀態(運行成功)
[root@master ~]# kubectl  get pod pod-nodeaffinity-preferred -n dev -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-nodeaffinity-preferred   1/1     Running   0          44s   10.244.2.83   node2   <none>           <none>

NodeAffinity規則設置的注意事項:
 1.如果同時定義了nodeSelector和nodeAffinity,那么必須兩個條件都得到滿足,Pod才能運行在指定的node上
 2.如果nodeAffinity指定了多個nodeSelectorTerms,那么只需要其中一個能夠匹配成功即可
 3.如果一個nodeSelectorTerms中有多個matchExperssions,則一個節點必須滿足所有的才能匹配成功
 4.如果一個pod所在的Node在Pod運行期間其標簽發生了改變,不再符合該Pod的節點親和性需求,則系統將忽略此變化

 

podAffinity配置

PodAffinty主要實現以運行的Pod為參照,實現讓新創建的Pod跟參照pod在一個區域的功能。

PodAffinity的可配置項:

pod.spec.affinity.podAffinity
  requiredDuringSchedulingIgnoredDuringExecution: 硬限制
    namespaces 指定參照pod的namespace
    topologKet 指定調度作用域
    labelSelector 標簽選擇器
      matcheExpressions 按節點標簽列出的節點選擇器要求列表(推薦)
        key
        values
        operator 關系符
    matchLabels 值多個matchExperssions映射的內容
    
  preferredDuringSchedulingIgnoredDuringExecution: 軟限制
    podAffinityTerm 選項
      namespace
      topologyKey
      labelSelector
        matchExpressions
          key
          values
          operator
        matchLabels
    weight: 權重傾向,1-100

topologyKey用於指定調度時作用域,例如:
  如果指定為kubernetes.io/hostname,那么就是以Node節點為區分范圍
  如果指定為beta.kubernetes.io/os,則是以Node節點的操作系統類型來區分范圍

 

下面演示一下requiredDuringSchedulingIgnoredDuringExecution

創建一個pod-podaffinity-target.yml文件

apiVersion: v1
kind: Pod
metadata:
  name: pod_podaffinity-target
  namespace: dev
  labels:
    version: v1
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  nodeName: node1

# 創建pod
[root@master ~]# kubectl  create -f pod-podaffinity-target.yml 
pod/pod-podaffinity-target created

# 查看pod狀態
[root@master ~]# kubectl  get pod pod-podaffinity-target -n dev -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-target   1/1     Running   0          39s   10.244.1.83   node1   <none>           <none>


# 創建pod-podaffinity-required.yml
apiVersion: v1
kind: Pod
metadata:
  name: pod-podaffinity-required
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: version
            operator: In
            values: ["v1","yyy"]
        topologyKey: kubernetes.io/hostname
上面配置表達的意思: 新的Pod必須要與擁有標簽version=v1或者version=yyy的pod在一個node上

# 創建Pod
[root@master ~]# kubectl create -f pod-podaffinity-required.yml 
pod/pod-podaffinity-required created

# 查看pod
[root@master ~]# kubectl  get  pod pod-podaffinity-required -n dev -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-required   1/1     Running   0          89s   10.244.1.84   node1   <none>           <none>

 

PodAntiAffinity

PodAntiAffinity主要實現以運行的Pod為參照,讓新創建的Pod跟參照的pod不在同一個區域中的功能,其配置方式和PodAffinity是一樣的。

繼續使用上一個例子中目標pod

創建pod-podantiaffinity-required.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-podantiaffinity-required
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: version
            operator: In
            values: ["v1","yyy"]
        topologyKey: kubernetes.io/hostname

#創建pod
[root@master ~]# kubectl  create -f pod-podantiaffinity-required.yml 
pod/pod-podantiaffinity-required created

# 查看pod信息,可以看到調度到了node2上
[root@master ~]# kubectl  get pod pod-podantiaffinity-required -n dev -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-podantiaffinity-required   1/1     Running   0          47s   10.244.2.93   node2   <none>           <none>

 

污點和容忍

污點(Taints)

前面的調度方式都是站在Pod的角度上,通過在Pod上添加屬性,來確定Pod是否調度到指定的Node上,可以通過在Node上添加污點,來決定是否允許Pod調度。

Node被設置上污點一會就和Pod之間存在一種相斥的關系,從而拒絕Pod的調度,甚至可以將Pod驅逐出去

污點格式為: key=value:effect, key和value是污點的標簽,effect描敘污點的作用,支持如下3個選項:

  • PreferNoSchedule: kubernetes將盡量避免把Pod調度都具有該污點的Node上,除非沒有其他可調度的節點
  • NoSchedlue: kubernetes將不會把Pod調度到具有該污點的Node上,但不會影響當前Node上存在的Pod
  • NoExecute: kubernetes將不會把Pod調度到具有該污點的Node上,同是將Node上已存在的Pod驅逐

使用kubectl設置和去除污點的命令如下:

#設置污點
kubectl taint nodes node1 key=values:effect

#去除污點
kubectl taint nodes node1 key:effect-

#去除所有污點
kubectl taint nodes node1 key-

 

下面演示污點效果:

  1. 准備節點node1(為了演示效果,暫時停止node2)
  2. 為node1節點設置一個污點: tag=test:PreferNoSchedule,然后創建pod1
  3. 修改為node1節點設置一個污點: tag=test:NoSchedule,然后創建pod2
  4. 修改為node1節點設置一個污點: tag=test:NoExectue,然后創建pod2
[root@master ~]# kubectl cordon node2

#為node1設置污點PreferNoSchedule
[root@master ~]# kubectl  taint nodes node1 tag=test:PreferNoSchedule
node/node1 tainted

# 創建pod1
[root@master ~]# kubectl  run tainit1 --image=nginx:1.17.2 -n dev
[root@master ~]# kubectl  get pods -n dev -o wide
tainit1-68d6b64b66-6bx5k       1/1     Running            0          2m7s    10.244.1.85   node1    <none>           <none>


#將node1污點修改為NoSchedule
[root@master ~]# kubectl  taint nodes node1 tag=test:PreferNoSchedule-
node/node1 untainted
[root@master ~]# kubectl  taint nodes node1 tag=test:NoSchedule
node/node1 tainted

#創建pod2
[root@master ~]# kubectl  run tainit2 --image=nginx:1.17.2 -n dev
[root@master ~]# kubectl  get pods -n dev -o wide
tainit2-7f6d6975b-2bc9k        0/1     Pending            0          5s      <none>        <none>   <none>           <none>


#將node1污點修改為NoExecute
[root@master ~]# kubectl  taint nodes node1 tag-
node/node1 untainted

#創建pod3
[root@master ~]# kubectl  run tainit3 --image=nginx:1.17.2 -n dev
[root@master ~]# kubectl  get pods -n dev -o wide
tainit1-68d6b64b66-9ps7p       0/1     Pending            0          62s     <none>        <none>   <none>           <none>
tainit2-7f6d6975b-drvk4        0/1     Pending            0          62s     <none>        <none>   <none>           <none>
tainit3-6f647d4d94-lj5bn       0/1     Pending            0          36s     <none>        <none>   <none>           <none>

 

容忍(Toleration) 上面介紹了污點的作用,我們可以在Node上添加污點用於拒絕pod調度上了,但是如果就是想將一個pod調度到一個有污點的Node上去,這個時候就可以使用容忍

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

上面已經在node1上打上了NoExecute的污點,此時pod是調度不上去的,可以通過個pod添加容忍,然后將其調度上去

創建pod-toleration.yml

apiVersion: v1
kind: Pod
metadata:
  name: pod-tolertion
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2
  tolerations: # 添加容忍
  - key: "tag"  # 要容忍的污點的key
    operator: "Equal"  # 操作符
    value: "test"  # 容忍的污點的value
    effect: "NoExecute"  # 容忍規則,必須和標記污點相同


# 創建pod
[root@master ~]# kubectl create -f pod-toleration.yml 
pod/pod-tolertion created
[root@master ~]# kubectl  get pods  pod-tolertion -n dev -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pod-tolertion   1/1     Running   0          19s   10.244.1.93   node1   <none>           <none>

 

Pod控制器詳解

在Kubernetes中,按照Pod的創建方式可以將其分為兩類:

  • 自主式pod: kubernetes直接創建出來的pod,這種pod刪除后就沒有了,也不會重建
  • 控制器創建的pod: 通過控制器創建的Pod,這種pod刪除了之后還會重建

Pod控制器式管理pod的中間層,使用了pod控制器后,我們只需要告訴pod創建,想要多少個什么樣的pod就可以了,他就會創建滿足條件的pod並確保每一個pod處於用戶期望的狀態,如果pod在運行種出現故障,控制器會基於指定策略重啟或者重建pod。

在kubernetes種,有很多類型的pod控制器,每種都有自己的合適場景,常見的有下面幾種:

  • ReplicationController: 比較原始的pod控制器,已經被廢棄,由ReplicaSet替代

  • ReplicaSet: 保證指定數量的pod運行,並支持pod數量變更,鏡像版本變更

  • Deployment: 通過控制ReplicaSet來控制pod,並支持滾動升級,版本回退

  • Horizontal Pod Autoscaler: 可以根據集群負載自動調整pod的數量,實現削峰填谷

  • DaemonSet:在集群中的指定Node上都運行一個副本,一般用於手好進程類的任務

  • Job: 它創建出來的pod只要完成任務后立即退出,用於執行一次性任務

  • Cronjob: 它創建的pod會周期性的執行,用於執行周期性任務

  • StatefulSet: 管理有狀態的應用

ReplicaSet

ReplicaSet的主要作用式保證一定數量的Pod能夠正常運行,它會持續監聽這些pod的運行狀態,一旦pod發生故障,就會重啟或重建。同時它還支持對pod數量的擴容和版本鏡像的升級。

ReplicaSet的資源清單文件:

apiVersion: apps/V1 #版本號
kind: ReplicaSet  #類型
metadata: #元數據
  name:  #rs名稱
  namespace: #所屬名稱空間
  labels: #標簽
    controller: rs
spec: #詳情描述
  replicas: 3 #副本數量
  selector: #選擇器,通過它自動該控制器管理那些pod
    matchLabels:  #label匹配規則
      app: nginx-pod
    matchExpressions: # Expressions匹配規則
      - {key: app,operator: IN, values: [nginx-pod]}
  template: #模板,當副本數量不足時,會根據下面的模板創建pod
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2
        ports:
        - containerPort: 80

 

在這里需要新了解的配置項就是spec下面幾個選項:

  • replicas: 指定副本數量,其實就是當前rs創建出來的pod數量,默認為1
  • selector: 選擇器,它的作用是建立pod控制器和pod之間的關聯關系,采用了Label Selector機制,在pod模板上定義label,在控制器上定義選擇器,就可以表明當前控制器能管理那些pod了
  • template: 模板,就是當前控制器創建pod所使用的模板

創建ReplicaSet

創建pc-replicaset.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: pc-replicaset
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2


# 創建rs
[root@master ~]# kubectl create -f pc-replicaset.yml 
replicaset.apps/pc-replicaset created

# 查看ReplicaSet信息 
[root@master ~]# kubectl get rs pc-replicaset -n dev -o wide
NAME            DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES         SELECTOR
pc-replicaset   3         3         3       9m22s   nginx        nginx:1.17.2   app=nginx-pod

 擴容縮容

# 編輯rs副本數量,修改spec:replicas:數量即可
[root@master ~]# kubectl  edit rs pc-replicaset -n dev
replicaset.apps/pc-replicaset edited

#查看pod
][root@master ~]# kubectl  get pod -n dev -o wide
NAME                  READY   STATUS              RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pc-replicaset-4s6rz   0/1     ContainerCreating   0          28s   <none>        node2   <none>           <none>
pc-replicaset-5cdzq   1/1     Running             0          62m   10.244.1.98   node1   <none>           <none>
pc-replicaset-s2wlt   0/1     ContainerCreating   0          28s   <none>        node2   <none>           <none>
pc-replicaset-xt7cf   1/1     Running             0          65m   10.244.1.95   node1   <none>           <none>
pc-replicaset-zhf2z   1/1     Running             0          65m   10.244.1.96   node1   <none>           <none>


#也可以使用命令直接實現,使用scale命令實現擴縮容,后面--replicas=n直接指定目標數量即可
[root@master ~]# kubectl  scale rs pc-replicaset --replicas=2 -n dev
replicaset.apps/pc-replicaset scaled

#命令運行完畢,查看pod,發現有3個退出
[root@master ~]# kubectl  get pod -n dev -o wide
NAME                  READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
pc-replicaset-xt7cf   1/1     Running   0          68m   10.244.1.95   node1   <none>           <none>
pc-replicaset-zhf2z   1/1     Running   0          68m   10.244.1.96   node1   <none>           <none>

 鏡像升級

#編輯rs的 容器鏡像 - image: nginx:1.17.3
[root@master ~]# kubectl  edit rs pc-replicaset -n dev
replicaset.apps/pc-replicaset edite

#再次查看,發現鏡像版本已經變更
[root@master ~]# kubectl  get rs -n dev -o wide
NAME            DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
pc-replicaset   2         2         2       72m   nginx        nginx:1.17.3   app=nginx-pod

#也可以使用命令完成,kubectl set image rs  rs名稱 容器=鏡像版本 -n namespace
[root@master ~]# kubectl  set image rs pc-replicaset  nginx=nginx=1.17.1 -n dev
replicaset.apps/pc-replicaset image updated

#再次查看,可以看到鏡像版本已經更新
[root@master ~]# kubectl  get rs -n dev -o wide
NAME            DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES         SELECTOR
pc-replicaset   2         2         2       74m   nginx        nginx=1.17.1   app=nginx-pod

 刪除ReplicaSet

#使用kubectl delete命令會三次此RS以及它管理的pod
#在kubernetes刪除RS前,會將RS的replicasclear調整為0,等待所有的Pod刪除后,在執行RS對象刪除
[root@master ~]# kubectl  delete rs pc-replicaset -n dev
replicaset.apps "pc-replicaset" deleted


#如果希望僅僅刪除RS對象(保留pod),可以使用kubectl delete命令是添加--cascade=false選項(不推薦)
[root@master ~]# kubectl  delete rs pc-replicaset -n dev --cascade=false
replicaset.apps "pc-replicaset" deleted
[root@master ~]# kubectl  get pod -n dev
NAME                  READY   STATUS              RESTARTS   AGE
pc-replicaset-9556m   0/1     ContainerCreating   0          57s
pc-replicaset-qvznw   1/1     Running             0          57s

#也可以使用哦那個yml直接刪除
[root@master ~]# kubectl  delete -f pc-replicaset.yml

 

Deployment(Deploy)

為了更好的解決服務編排的問題,kubernetes在v1.2版本開始,引入Deployment控制器。值得一提的是,這種控制器並不直接管理pod,而是通過ReplicaSet來間接管理Pod,即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更加強大。

Deployment主要功能有下面幾個:

  • 支持ReplicaSet的所用功能
  • 支持發布的停止,繼續
  • 支持版本滾動升級和版本回退

Deploymenr的資源清單文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: #rs名稱
  namespace: #所屬的名稱空間
spec:
  replicas: 3 #副本數量
  revisionHistoryLimit: 3 #保留歷史版本,默認10
  paused: false  #暫停部署,默認false
  progressDeadlineSeconds: 600 #部署超時時間,默認600s
  strategy: #策略
    type: RollingUpdate #滾動更新策略
    rolliingUpdate: #滾動更新
      maxSurge: 30% #最大額外可以存在的副本數,可以為百分比可以為整數
      maxUnavailable: 30% #最大不可以狀態的pod,可以為百分比可以為整數
  selector: # 選擇器,通過它指定該控制器管理那些pod
    matchLabels:  #Label匹配規則
      app: nginx-pod
    matchExpressions: # Expressions匹配規則
      - {key:app, operator: IN , values:[nginx-pod]}
    template: #模板
      metadata:
        labels:
          app: nginx-pod
      spec:
        containers:
        - name: nginx
          image: nginx:1.17.2
          ports:
            containerPorts: 80

 

創建Deployment

創建文件pc-deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.2
        
# 創建deployment
# --record=true 記錄每次的版本變化
[root@master ~]# kubectl create -f  pc-deployment.yml --record=true
deployment.apps/pc-deployment created

#查看deployment,UP-TO-DATE最新版本的pod的數量,AVAILABLE 當前可用pod的數量
[root@master ~]# kubectl  get deploy -n dev -o wide
NAME            READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
pc-deployment   1/3     3            1           40s   nginx        nginx:1.17.2   app=nginx-pod

#查看rs,發現rs的名稱是在原來deployment的名字后面添加了一個隨機10位數的隨機串
[root@master ~]# kubectl  get rs -n dev 
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-675d469f8b   3         3         1       3m37

#查看pod
[root@master ~]# kubectl  get pod -n dev 
NAME                             READY   STATUS    RESTARTS   AGE
pc-deployment-675d469f8b-2jqkd   1/1     Running   1          9m55s
pc-deployment-675d469f8b-n8vmx   1/1     Running   1          9m55s
pc-deployment-675d469f8b-stswc   1/1     Running   0          9m55s

 擴縮容

#變更副本數量為5個
[root@master ~]# kubectl  scale deploy pc-deployment -n dev --replicas=5
deployment.apps/pc-deployment scaled

#查看deployment
[root@master ~]# kubectl get deploy -n dev
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
pc-deployment   5/5     5            5           11m

#查看pod
[root@master ~]# kubectl  get pod -n dev
NAME                             READY   STATUS    RESTARTS   AGE
pc-deployment-675d469f8b-2jqkd   1/1     Running   1          12m
pc-deployment-675d469f8b-fqfld   1/1     Running   0          48s
pc-deployment-675d469f8b-khwr2   1/1     Running   0          48s
pc-deployment-675d469f8b-n8vmx   1/1     Running   1          12m
pc-deployment-675d469f8b-stswc   1/1     Running   0          12m

# 編譯deployment的副本數量,修改spec:replicas: 3
[root@master ~]# kubectl  edit deploy pc-deployment -n dev
deployment.apps/pc-deployment edited

# 查看pod
[root@master ~]# kubectl  get pod -n dev
NAME                             READY   STATUS    RESTARTS   AGE
pc-deployment-675d469f8b-2jqkd   1/1     Running   1          13m
pc-deployment-675d469f8b-fqfld   1/1     Running   0          2m33s
pc-deployment-675d469f8b-stswc   1/1     Running   0          13m

 

鏡像更新

Deployment支持兩種鏡像更新的策略: 重建鏡像和滾動跟新(默認),可用通過strategy選項進行配置

strategy: 指定新的Pod替換舊的Pod的策略,支持兩個屬性
  type: 指定策略類型,支持兩種策略
    Recreate: 在創建出新的Pod之前會先殺掉所有已存在的pod
    RollingUpdate: 滾動跟新,就是殺死部分,就啟動一部分,在更新的過程中存在兩個版本的Pod
  rollingUpdate: 當type為RollingUpdate是生效,用於為RollingUpdate設置參數,支持兩個屬性:
    maxUnavailabe: 用來指定在升級過程中不可以pod的最大數量,默認25%
    maxSurge: 用來指定在升級過程中可用超過期望的Pod的最大數量,默認25%

 重建更新:

#1.編輯pc-deployment.yml,在spec節點下添加更新策略
spec:
  strategy:
    type: Recrate
# 應用策略
[root@master ~]# kubectl apply -f pc-deployment.yml

# 2.創建deploy進行驗證
#變更鏡像
[root@master ~]# kubectl  set image deployment pc-deployment nginx=nginx:1.17.4 -n dev
deployment.apps/pc-deployment image updated
root@master ~]# kubectl  get pod -n dev -w
NAME                             READY   STATUS    RESTARTS   AGE
pc-deployment-675d469f8b-2jqkd   1/1     Running   1          94m
pc-deployment-675d469f8b-fqfld   1/1     Running   0          82m
pc-deployment-675d469f8b-stswc   1/1     Running   0          94m
pc-deployment-675d469f8b-stswc   1/1     Terminating   0          94m
pc-deployment-675d469f8b-2jqkd   1/1     Terminating   1          94m
pc-deployment-675d469f8b-fqfld   1/1     Terminating   0          83m
pc-deployment-675d469f8b-2jqkd   0/1     Terminating   1          94m
pc-deployment-675d469f8b-stswc   0/1     Terminating   0          94m
pc-deployment-675d469f8b-fqfld   0/1     Terminating   0          83m
pc-deployment-675d469f8b-2jqkd   0/1     Terminating   1          94m
pc-deployment-675d469f8b-2jqkd   0/1     Terminating   1          94m
pc-deployment-675d469f8b-fqfld   0/1     Terminating   0          83m
pc-deployment-675d469f8b-fqfld   0/1     Terminating   0          83m
pc-deployment-675d469f8b-stswc   0/1     Terminating   0          94m
pc-deployment-675d469f8b-stswc   0/1     Terminating   0          94m
pc-deployment-6c9f56fcfb-wrdtj   0/1     Pending       0          0s
pc-deployment-6c9f56fcfb-zpmv7   0/1     Pending       0          0s
pc-deployment-6c9f56fcfb-v2vl6   0/1     Pending       0          0s
pc-deployment-6c9f56fcfb-wrdtj   0/1     Pending       0          0s
pc-deployment-6c9f56fcfb-zpmv7   0/1     Pending       0          0s
pc-deployment-6c9f56fcfb-v2vl6   0/1     Pending       0          0s
pc-deployment-6c9f56fcfb-zpmv7   0/1     ContainerCreating   0          0s
pc-deployment-6c9f56fcfb-wrdtj   0/1     ContainerCreating   0          0s
pc-deployment-6c9f56fcfb-v2vl6   0/1     ContainerCreating   0          0s
pc-deployment-6c9f56fcfb-zpmv7   1/1     Running             0          16s
pc-deployment-6c9f56fcfb-v2vl6   1/1     Running             0          32s
pc-deployment-6c9f56fcfb-wrdtj   1/1     Running             0          47s

 滾動更新

1.編輯pc-deployment.yml,在spec節點下添加跟新策略
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 25%
      maxSurge: 25%

#應用
[root@master ~]# kubectl apply -f pc-deployment.yml 
deployment.apps/pc-deployment configured

#變更鏡像
[root@master ~]# kubectl  set image deployment pc-deployment nginx=nginx:1.17.1 -n dev
deployment.apps/pc-deployment image updated
[root@master ~]# kubectl  get pod -n dev -w
NAME                             READY   STATUS    RESTARTS   AGE
pc-deployment-6c9f56fcfb-v2vl6   1/1     Running   0          3m1s
pc-deployment-6c9f56fcfb-wrdtj   1/1     Running   0          3m1s
pc-deployment-6c9f56fcfb-zpmv7   1/1     Running   0          3m1s
pc-deployment-675d469f8b-gsvgm   0/1     Pending   0          0s
pc-deployment-675d469f8b-gsvgm   0/1     Pending   0          0s
pc-deployment-675d469f8b-gsvgm   0/1     ContainerCreating   0          0s
pc-deployment-675d469f8b-gsvgm   1/1     Running             0          3s
pc-deployment-6c9f56fcfb-wrdtj   1/1     Terminating         0          6m5s
pc-deployment-675d469f8b-vtgbs   0/1     Pending             0          0s
pc-deployment-675d469f8b-vtgbs   0/1     Pending             0          0s
pc-deployment-675d469f8b-vtgbs   0/1     ContainerCreating   0          0s
pc-deployment-6c9f56fcfb-wrdtj   0/1     Terminating         0          6m6s
pc-deployment-6c9f56fcfb-wrdtj   0/1     Terminating         0          6m7s
pc-deployment-675d469f8b-vtgbs   1/1     Running             0          2s
pc-deployment-6c9f56fcfb-v2vl6   1/1     Terminating         0          6m7s
pc-deployment-675d469f8b-4l4zz   0/1     Pending             0          0s
pc-deployment-675d469f8b-4l4zz   0/1     Pending             0          0s
pc-deployment-675d469f8b-4l4zz   0/1     ContainerCreating   0          0s
pc-deployment-6c9f56fcfb-v2vl6   0/1     Terminating         0          6m8s
pc-deployment-675d469f8b-4l4zz   1/1     Running             0          2s
pc-deployment-6c9f56fcfb-zpmv7   1/1     Terminating         0          6m9s
pc-deployment-6c9f56fcfb-wrdtj   0/1     Terminating         0          6m10s
pc-deployment-6c9f56fcfb-wrdtj   0/1     Terminating         0          6m10s
pc-deployment-6c9f56fcfb-zpmv7   0/1     Terminating         0          6m10s
pc-deployment-6c9f56fcfb-zpmv7   0/1     Terminating         0          6m11s
pc-deployment-6c9f56fcfb-zpmv7   0/1     Terminating         0          6m11s
pc-deployment-6c9f56fcfb-v2vl6   0/1     Terminating         0          6m20s
pc-deployment-6c9f56fcfb-v2vl6   0/1     Terminating         0          6m20s
pc-deployment-5d89bdfbf9-xt428   0/1     Pending             0          0s
pc-deployment-5d89bdfbf9-xt428   0/1     Pending             0          0s
pc-deployment-5d89bdfbf9-xt428   0/1     ContainerCreating   0          0s
pc-deployment-5d89bdfbf9-xt428   1/1     Running             0          2s
pc-deployment-675d469f8b-4l4zz   1/1     Terminating         0          42s
pc-deployment-5d89bdfbf9-cjpp2   0/1     Pending             0          0s
pc-deployment-5d89bdfbf9-cjpp2   0/1     Pending             0          0s
pc-deployment-5d89bdfbf9-cjpp2   0/1     ContainerCreating   0          0s
pc-deployment-675d469f8b-4l4zz   0/1     Terminating         0          43s
pc-deployment-5d89bdfbf9-cjpp2   1/1     Running             0          1s
pc-deployment-675d469f8b-vtgbs   1/1     Terminating         0          45s

 鏡像更新中rs的變化:

#查看rs,發現原來的rs依舊存在,只是pod變為了0,然后新產生一個rs,pod數量為3
[root@master ~]# kubectl  get rs -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-5d89bdfbf9   3         3         3       2m
pc-deployment-675d469f8b   0         0         0       103m
pc-deployment-6c9f56fcfb   0         0         0       8m47s

 

版本回退

deployment支持版本升級過程中暫停,繼續功能以及版本回退等諸多功能。

kubectl rollout: 版本升級相關功能,支持下面的選項:

  • status 顯示當前升級狀態
  • history 顯示升級歷史記錄
  • pause 暫停版本升級過程
  • resume 繼續以及暫停的版本升級過程
  • restart 重啟版本升級過程
  • undo 回滾到上一個版本(可用使用--to-revision回滾到指定版本)
# 查看當前升級的版本狀態
[root@master ~]# kubectl  rollout status deployment pc-deployment -n dev
deployment "pc-deployment" successfully rolled out

# [root@master ~]# kubectl  rollout history  deployment pc-deployment -n dev
deployment.apps/pc-deployment 
REVISION  CHANGE-CAUSE
2         kubectl create --filename=pc-deployment.yml --record=true
3         kubectl create --filename=pc-deployment.yml --record=true
4         kubectl create --filename=pc-deployment.yml --record=true

# 版本回滾
# 這里直接使用--to-revision=2回滾到2版本,如果省略這個選項就是回退到上一個版本
[root@master ~]# kubectl  rollout undo  deployment pc-deployment --to-revision=2 -n dev
deployment.apps/pc-deployment rolled back

#查看發現,通過nginx進行版本可用發現到了1.17.4版本
[root@master ~]# kubectl  get rs -n dev -o wide
NAME                       DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
pc-deployment-5d89bdfbf9   0         0         0       16m    nginx        nginx:1.17.1   app=nginx-pod,pod-template-hash=5d89bdfbf9
pc-deployment-675d469f8b   0         0         0       117m   nginx        nginx:1.17.2   app=nginx-pod,pod-template-hash=675d469f8b
pc-deployment-6c9f56fcfb   3         3         3       23m    nginx        nginx:1.17.4   app=nginx-pod,pod-template-hash=6c9f56fcfb

 

金絲雀發布 deployment支持更新過程中的控制,如“暫停(pause)”或“繼續(resume)”更新操作

比如有一批新的pod資源創建完成后立即暫停更新過程,此時,僅存在一部分新版本應用,主體部分還是舊版本。然后,在篩選一小部分的用戶請求路由到新版本的pod應用,繼續概觀察能否穩定的按期望的方式運行,確定沒問題后在舉行完成余下的pod資源滾動更新,否則立即回滾更新操作。

# 更新deployment的版本,並配置暫停deployment
[root@master ~]# kubectl  set image deploy pc-deployment nginx=nginx:1.17.3 -n dev && kubectl rollout pause deployment pc-deployment -n dev
deployment.apps/pc-deployment image updated
deployment.apps/pc-deployment paused

#觀察更新狀態
[root@master ~]# kubectl rollout status  deploy pc-deployment -n dev
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...

# 監控更新過程,可用看到已經新增了一個資源,但是並未按照預期的狀態刪除一個舊的資源,就是因為使用了pause暫停命令
[root@master ~]# kubectl  get rs -n dev -o wide
NAME                       DESIRED   CURRENT   READY   AGE    CONTAINERS   IMAGES         SELECTOR
pc-deployment-5d89bdfbf9   0         0         0       25m    nginx        nginx:1.17.1   app=nginx-pod,pod-template-hash=5d89bdfbf9
pc-deployment-675d469f8b   0         0         0       126m   nginx        nginx:1.17.2   app=nginx-pod,pod-template-hash=675d469f8b
pc-deployment-6c9f56fcfb   3         3         3       31m    nginx        nginx:1.17.4   app=nginx-pod,pod-template-hash=6c9f56fcfb
pc-deployment-6dfdf96cc5   1         1         0       119s   nginx        ngnix:1.17.3   app=nginx-pod,pod-template-hash=6dfdf96cc5


# 繼續更新
[root@master ~]# kubectl rollout resume  deployment pc-deployment -n dev
deployment.apps/pc-deployment resumed

#查看deploy
[root@master ~]# kubectl  get rs  -n dev
NAME                       DESIRED   CURRENT   READY   AGE
pc-deployment-5d89bdfbf9   0         0         0       35m
pc-deployment-675d469f8b   0         0         0       136m
pc-deployment-6c9f56fcfb   0         0         0       41m
pc-deployment-6dfdf96cc5   0         0         0       11m
pc-deployment-7865c58bdf   3         3         3       63s

 

Horizonta Pod Autoscaler(HPA)

可用通過手工執行kubectl scale命令實現Pod擴容,但是這顯然不符合kubernetes的定位目標--自動化、智能化。Kubernetes期望可用通過監測Pod的使用情況,實現pod數量的自動調整,於是就產生了HPA這種控制器。

HPA可以獲取每個pod利用率,然后和PHPA中定義的指標進行對比,同時計算出需要伸縮的具體值,最后實現pod的數量的調整。其實HPA與之前的Deployment一樣,也屬於一種Kubernetes資源對象,它通過追蹤分析目標pod的負載變化情況,來確定是否需要針對性的調整目標Pod的數量

1.安裝metrice-server

metrucs-server可以用來收集集群中的資源使用情況

#安裝git
[root@master ~]# yum -y install git
#獲取metrics-server,注意使用版本
[root@master ~]# git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server
#修改deployment,注意修改的是鏡像和初始化參數
[root@master ~]# cd metrics-server/deploy/1.8+/
[root@master 1.8+]# vim metrics-server-deployment.yaml
[root@master 1.8+]# vim metrics-server-deployment.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
    spec:
      hostNetwork: true
      serviceAccountName: metrics-server
      volumes:
      # mount in tmp so we can safely use from-scratch images and/or read-only containers
      - name: tmp-dir
        emptyDir: {}
      containers:
      - name: metrics-server
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 
        imagePullPolicy: Always
        args:
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp
#查看pod運行狀態
[root@master 1.8+]# kubectl  get pod -n kube-system
metrics-server-6b976979db-2hqm6   1/1     Running                 0          2m21s

#使用kubectl top node 查看資源使用狀態
[root@master 1.8+]# kubectl  top node
NAME     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master   111m         5%     970Mi           56%       
node1    28m          1%     388Mi           44%       
node2    34m          1%     426Mi           48% 
[root@master 1.8+]# kubectl  top pod  -n kube-system
NAME                              CPU(cores)   MEMORY(bytes)   
coredns-6955765f44-sch82          4m           15Mi            
coredns-6955765f44-thfs7          4m           15Mi            
etcd-master                       15m          86Mi            
kube-apiserver-master             33m          294Mi           
kube-controller-manager-master    15m          63Mi  
..........................
#至此,metrics-server安裝完成

2.准備deployment和service

# 創建deployment
vim nginx.yml
apiVersion: apps/v1 # 版本號
kind: Deployment # 類型
metadata: # 元數據
  name: nginx # deployment的名稱
  namespace: dev # 命名類型
spec: # 詳細描述
  selector: # 選擇器,通過它指定該控制器可以管理哪些Pod
    matchLabels: # Labels匹配規則
      app: nginx-pod
  template: # 模塊 當副本數據不足的時候,會根據下面的模板創建Pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
        - name: nginx # 容器名稱
          image: nginx:1.17.1 # 容器需要的鏡像地址
          ports:
            - containerPort: 80 # 容器所監聽的端口
          resources: # 資源限制
            requests:
              cpu: "100m" # 100m表示100millicpu,即0.1個CPU

#創建Deployment
[root@master 1.8+]# kubectl create -f nginx.yml 
deployment.apps/nginx created

#查看Deployment和Pod
[root@master 1.8+]# kubectl get pod,deploy -n dev
NAME                        READY   STATUS    RESTARTS   AGE
pod/nginx-7b766dbb7-8qrdv   1/1     Running   0          31s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           31s

#創建Service
[root@master 1.8+]# kubectl expose deployment nginx --name=nginx --type=NodePort --port=80 --target-port=80 -n dev
service/nginx exposed

#查看Service
[root@master 1.8+]# kubectl get svc -n dev
NAME    TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.105.180.5   <none>        80:31628/TCP   35s

3.部署HPA

創建pc-hpa.yaml文件

apiVersion: autoscaling/v1 # 版本號
kind: HorizontalPodAutoscaler # 類型
metadata: # 元數據
  name: pc-hpa # deployment的名稱
  namespace: dev # 命名類型
spec:
  minReplicas: 1 # 最小Pod數量
  maxReplicas: 10 # 最大Pod數量
  targetCPUUtilizationPercentage: 3 # CPU使用率指標
  scaleTargetRef:  # 指定要控制的Nginx的信息
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
    
#創建hpa
[root@master 1.8+]# kubectl create -f pc-hpa.yaml
horizontalpodautoscaler.autoscaling/pc-hpa created

#查看hpa
[root@master 1.8+]# kubectl get hpa -n dev
NAME     REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx   0%/3%     1         10        1          42s

4.測試

● 使用壓測工具如Jmeter對service的地址http://192.168.248.11:31628進行壓測,然后通過控制台查看hpa和pod的變化

hpa的變化
[root@master ~]# kubectl  get hpa -n dev -w
NAME     REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
pc-hpa   Deployment/nginx   0%/3%     1         10        1          3m28s
pc-hpa   Deployment/nginx   0%/3%     1         10        1          5m18s
pc-hpa   Deployment/nginx   1%/3%     1         10        1          9m6s
pc-hpa   Deployment/nginx   0%/3%     1         10        1          10m
pc-hpa   Deployment/nginx   1%/3%     1         10        1          12m
pc-hpa   Deployment/nginx   0%/3%     1         10        1          13m
pc-hpa   Deployment/nginx   0%/3%     1         10        1          18m
pc-hpa   Deployment/nginx   20%/3%    1         10        1          20m
pc-hpa   Deployment/nginx   20%/3%    1         10        4          21m
pc-hpa   Deployment/nginx   20%/3%    1         10        7          21m
pc-hpa   Deployment/nginx   4%/3%     1         10        7          21m
pc-hpa   Deployment/nginx   1%/3%     1         10        7          23m

 

DaemonSet(DS)

DaemonSet類型的控制器可以保證集群中的每一台(或指定)節點上都運行一個副本,一般適用於日志收集、節點監控等場景。也就是說,如果一個Pod提供的功能是節點級別的(每個節點都需要且只需要一個),那么這類Pod就適合使用DaemonSet類型的控制器創建。

DaemonSet控制器的特點:

  • 每向集群中添加一個節點的時候,指定的Pod副本也將添加到該節點上。
  • 當節點從集群中移除的時候,Pod也會被垃圾回收。

DaemonSet的資源清單:

apiVersion: apps/v1 # 版本號
kind: DaemonSet # 類型
metadata: # 元數據
  name: # 名稱
  namespace: #命名空間
  labels: #標簽
    controller: daemonset
spec: # 詳情描述
  revisionHistoryLimit: 3 # 保留歷史版本
  updateStrategy: # 更新策略
    type: RollingUpdate # 滾動更新策略
    rollingUpdate: # 滾動更新
      maxUnavailable: 1 # 最大不可用狀態的Pod的最大值,可用為百分比,也可以為整數
  selector: # 選擇器,通過它指定該控制器管理那些Pod
    matchLabels: # Labels匹配規則
      app: nginx-pod
    matchExpressions: # Expressions匹配規則
      - key: app
        operator: In
        values:
          - nginx-pod
  template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板
     metadata:
       labels:
         app: nginx-pod
     spec:
       containers:
         - name: nginx
           image: nginx:1.17.1
           ports:
             - containerPort: 80

 

創建DaemonSet

創建pc-daemonset.yml文件

apiVersion: apps/v1 # 版本號
kind: DaemonSet # 類型
metadata: # 元數據
  name: pc-damonset # 名稱
  namespace: dev #命名空間
spec: # 詳情描述
  selector: # 選擇器,通過它指定該控制器管理那些Pod
    matchLabels: # Labels匹配規則
      app: nginx-pod
  template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板
     metadata:
       labels:
         app: nginx-pod
     spec:
       containers:
         - name: nginx
           image: nginx:1.17.1
           ports:
             - containerPort: 80

#創建DaemonSet
[root@master ~]# kubectl create -f pc-daemonset.yml
daemonset.apps/pc-damonset created


#查看DaemonSet
[root@master ~]# kubectl get ds -n dev -o wide
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE   CONTAINERS   IMAGES         SELECTOR
pc-damonset   2         2         2       2            2           <none>          25s   nginx        nginx:1.17.1   app=nginx-pod


#刪除DaemonSet
[root@master ~]# kubectl delete ds pc-damonset -n dev
daemonset.apps "pc-damonset" deleted

 

job

Job主要用於負責批量處理短暫的一次性任務。

Job的特點:

  • 當Job創建的Pod執行成功結束時,Job將記錄成功結束的Pod數量。
  • 當成功結束的Pod達到指定的數量時,Job將完成執行

job資源清單

apiVersion: batch/v1 # 版本號
kind: Job # 類型
metadata: # 元數據
  name:  # 名稱
  namespace:  #命名空間
  labels: # 標簽
    controller: job
spec: # 詳情描述
  completions: 1 # 指定Job需要成功運行Pod的總次數,默認為1
  parallelism: 1 # 指定Job在任一時刻應該並發運行Pod的數量,默認為1
  activeDeadlineSeconds: 30 # 指定Job可以運行的時間期限,超過時間還沒結束,系統將會嘗試進行終止
  backoffLimit: 6 # 指定Job失敗后進行重試的次數,默認為6
  manualSelector: true # 是否可以使用selector選擇器選擇Pod,默認為false
  selector: # 選擇器,通過它指定該控制器管理那些Pod
    matchLabels: # Labels匹配規則
      app: counter-pod
    matchExpressions: # Expressions匹配規則
      - key: app
        operator: In
        values:
          - counter-pod
  template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板
     metadata:
       labels:
         app: counter-pod
     spec:
       restartPolicy: Never # 重啟策略只能設置為Never或OnFailure
       containers:
         - name: counter
           image: busybox:1.30
           command: ["/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 20;done"]
           
關於模板中的重啟策略的說明:
# 如果設置為OnFailure,則Job會在Pod出現故障的時候重啟容器,而不是創建Pod,failed次數不變。
# 如果設置為Never,則Job會在Pod出現故障的時候創建新的Pod,並且故障Pod不會消失,也不會重啟,failed次數+1。
#如果指定為Always的話,就意味着一直重啟,意味着Pod任務會重復執行,這和Job的定義沖突,所以不能設置為Always。

 創建pc-job.yml文件

apiVersion: batch/v1 # 版本號
kind: Job # 類型
metadata: # 元數據
  name: pc-job # 名稱
  namespace: dev #命名空間
spec: # 詳情描述
  manualSelector: true # 是否可以使用selector選擇器選擇Pod,默認為false
  selector: # 選擇器,通過它指定該控制器管理那些Pod
    matchLabels: # Labels匹配規則
      app: counter-pod
  template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板
    metadata:
      labels:
        app: counter-pod
    spec:
      restartPolicy: Never # 重啟策略只能設置為Never或OnFailure
      containers:
        - name: counter
          image: busybox:1.30
          command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 3;done" ]
          
# 創建job
[root@master ~]# kubectl  create -f pc-job.yml 
job.batch/pc-job created

# 查看job
[root@master ~]# kubectl  get job -n dev -o wide -w
NAME     COMPLETIONS   DURATION   AGE   CONTAINERS   IMAGES         SELECTOR
pc-job   0/1           2s         2s    counter      busybox:1.30   app=counter-pod
pc-job   1/1           28s        28s   counter      busybox:1.30   app=counter-pod

#查看pod
[root@master ~]# kubectl  get pod -n dev -w
NAME           READY   STATUS    RESTARTS   AGE
pc-job-5s9ck   0/1     Pending   0          0s
pc-job-5s9ck   0/1     Pending   0          0s
pc-job-5s9ck   0/1     ContainerCreating   0          0s
pc-job-5s9ck   1/1     Running             0          1s
pc-job-5s9ck   0/1     Completed           0          28s

#刪除job
[root@master ~]# kubectl  delete  -f pc-job.yml 
job.batch "pc-job" deleted

 

CronJob(CJ)

CronJob控制器以Job控制器為其管控對象,並借助它管理Pod資源對象,Job控制器定義的作業任務在其控制器資源創建之后便會立即執行,但CronJob可以以類似Linux操作系統的周期性任務作業計划的方式控制器運行時間點及重復運行的方式,換言之,CronJob可以在特定的時間點反復去執行Job任務

CronJob的資源清單

apiVersion: batch/v1beta1 # 版本號
kind: CronJob # 類型
metadata: # 元數據
  name:  # 名稱
  namespace:  #命名空間
  labels:
    controller: cronjob
spec: # 詳情描述
  schedule: # cron格式的作業調度運行時間點,用於控制任務任務時間執行
  concurrencyPolicy: # 並發執行策略
  failedJobsHistoryLimit: # 為失敗的任務執行保留的歷史記錄數,默認為1
  successfulJobsHistoryLimit: # 為成功的任務執行保留的歷史記錄數,默認為3
  jobTemplate: # job控制器模板,用於為cronjob控制器生成job對象,下面其實就是job的定義
    metadata: {}
    spec:
      completions: 1 # 指定Job需要成功運行Pod的總次數,默認為1
      parallelism: 1 # 指定Job在任一時刻應該並發運行Pod的數量,默認為1
      activeDeadlineSeconds: 30 # 指定Job可以運行的時間期限,超過時間還沒結束,系統將會嘗試進行終止
      backoffLimit: 6 # 指定Job失敗后進行重試的次數,默認為6
      template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板
        spec:
          restartPolicy: Never # 重啟策略只能設置為Never或OnFailure
          containers:
            - name: counter
              image: busybox:1.30
              command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 20;done" ]
schedule:cron表達式,用於指定任務的執行時間。
● */1  *  *  *  *:表示分鍾  小時  日  月份  星期。
● 分鍾的值從0到59。
● 小時的值從0到23。
● 日的值從1到31。
● 月的值從1到12。
● 星期的值從0到6,0表示星期日。
● 多個時間可以用逗號隔開,范圍可以用連字符給出:* 可以作為通配符,/表示每...
concurrencyPolicy:並發執行策略
● Allow:運行Job並發運行(默認)。
● Forbid:禁止並發運行,如果上一次運行尚未完成,則跳過下一次運行。
● Replace:替換,取消當前正在運行的作業並使用新作業替換它。

 創建pc-cronjob.yml文件

apiVersion: batch/v1beta1 # 版本號
kind: CronJob # 類型
metadata: # 元數據
  name: pc-cronjob # 名稱
  namespace: dev  #命名空間
spec: # 詳情描述
  schedule: "*/1 * * * * " # cron格式的作業調度運行時間點,用於控制任務任務時間執行
  jobTemplate: # job控制器模板,用於為cronjob控制器生成job對象,下面其實就是job的定義
    metadata: {}
    spec:
      template: # 模板,當副本數量不足時,會根據下面的模板創建Pod模板
        spec:
          restartPolicy: Never # 重啟策略只能設置為Never或OnFailure
          containers:
            - name: counter
              image: busybox:1.30
              command: [ "/bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1;do echo $i;sleep 2;done" ]
            
#創建CronJob
[root@master ~]# kubectl create -f pc-cronjob.yml
cronjob.batch/pc-cronjob created

#查看cronjob
[root@master ~]# kubectl get cronjob -n dev -w
NAME         SCHEDULE       SUSPEND   ACTIVE   LAST SCHEDULE   AGE
pc-cronjob   */1 * * * *    False     0        <none>          0s
pc-cronjob   */1 * * * *    False     1        8s              23s
pc-cronjob   */1 * * * *    False     0        28s             43s
pc-cronjob   */1 * * * *    False     1        8s              83s
pc-cronjob   */1 * * * *    False     0        28s             103s

#刪除CronJob
[root@master ~]# kubectl  delete -f pc-cronjob.yml 
cronjob.batch "pc-cronjob" deleted

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM