k8s (五) --- Kubernetes Pod控制器詳舉例詳解

一、Pod控制器

Pod 的分類

自主式 Pod:Pod 退出後不會被創建
控制器管理的 Pod:在控制器的生命週期裏,始終要維持 Pod 的副本數目

控制器類型

  • Replication Controller和ReplicaSet
  • Deployment
  • DaemonSet
  • StatefulSet
  • Job
  • CronJob
  • HPA全稱Horizontal Pod Autoscaler

Replication Controller和ReplicaSet

ReplicaSet (RS)是下一代的 Replication Controller(RC),官方推薦使用ReplicaSet。

ReplicaSet 和 Replication Controller 的唯一區別是選擇器的支持,ReplicaSet 支持新的基於集合的選擇器需求。

ReplicaSet 確保任何時間都有指定數量的 Pod 副本在運行。

雖然 ReplicaSets 可以獨立使用,但今天它主要被Deployments 用作協調 Pod 創建、刪除和更新的機制。

Deployment

Deployment 爲 Pod 和 ReplicaSet 提供了一個申明式的定義方法。
典型的應用場景:

  • 用來創建Pod和ReplicaSet
  • 滾動更新和回滾
  • 擴容和縮容
  • 暫停與恢復

DaemonSet

DaemonSet 確保全部(或者某些)節點上運行一個 Pod 的副本。當有節點加入集羣時, 也會爲他們新增一個 Pod 。當有節點從集羣移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。

DaemonSet 的典型用法:

  • 在每個節點上運行集羣存儲 DaemonSet,例如 glusterd、ceph。
  • 在每個節點上運行日誌收集 DaemonSet,例如 fluentd、logstash。
  • 在每個節點上運行監控 DaemonSet,例如 Prometheus Node Exporter、zabbix agent等

一個簡單的用法是在所有的節點上都啓動一個 DaemonSet,將被作爲每種類型的 daemon 使用。

一個稍微複雜的用法是單獨對每種 daemon 類型使用多個 DaemonSet,但具有不同的標誌, 並且對不同硬件類型具有不同的內存、CPU 要求。

StatefulSet

StatefulSet 是用來管理有狀態應用的工作負載 API 對象。實例之間有不對等關係,以及實例對外部數據有依賴關係的應用,稱爲“有狀態應用

StatefulSet 用來管理 Deployment 和擴展一組 Pod,並且能爲這些 Pod 提供序號和唯一性保證。

StatefulSets 對於需要滿足以下一個或多個需求的應用程序很有價值:

  • 穩定的、唯一的網絡標識符。
  • 穩定的、持久的存儲。
  • 有序的、優雅的部署和縮放。
  • 有序的、自動的滾動更新。

Job

執行批處理任務,僅執行一次任務,保證任務的一個或多個Pod成功結束。

CronJob

Cron Job 創建基於時間調度的 Jobs。

一個 CronJob 對象就像 crontab (cron table) 文件中的一行,它用 Cron 格式進行編寫,並週期性地在給定的調度時間執行 Job。

HPA

根據資源利用率自動調整service中Pod數量,實現Pod水平自動縮放。

二、Pod控制器使用示例

ReplicaSet舉例

編輯以下yaml文件:

[root@server1 ~]# vim rs.yaml 
[root@server1 ~]# cat rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: replicaset-example
spec:
  replicas: 2			#啓動pod的副本數
  selector:				#定義選擇器爲標籤選擇器。
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx				#定義容器的標籤
    spec:						#定義容器
      containers:
      - name: nginx
        image: nginx

以上使用的控制器的RS,RS控制器通過pod的標籤(matchLabels)來控制pod的數量,使用apply命令可以實現創建,更新pod,而create命令創建後若需要更新只能刪除之後再創建,因此建議使用apply:

[root@server1 ~]# kubectl apply -f rs.yaml 
replicaset.apps/replicaset-example created
[root@server1 ~]# kubectl apply -f rs.yaml 
replicaset.apps/replicaset-example unchanged

查看狀態:

[root@server1 ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
replicaset-example-p6sv6   1/1     Running   0          34s
replicaset-example-s5jps   1/1     Running   0          34s
[root@server1 ~]# kubectl get rs			#獲取rs的信息
NAME                 DESIRED   CURRENT   READY   AGE
replicaset-example   2         2         2       36s
[root@server1 ~]# kubectl get pod -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
replicaset-example-p6sv6   1/1     Running   0          38s   10.244.1.14   server2   <none>           <none>
replicaset-example-s5jps   1/1     Running   0          38s   10.244.2.21   server3   <none>           <none>

可以看出一且正常,接下來進行pod的拉伸與壓縮:

拉伸:

[root@server1 ~]# vim rs.yaml 
[root@server1 ~]# cat rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: replicaset-example
spec:
  replicas: 4		#拉伸爲4個
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

[root@server1 ~]# kubectl apply -f rs.yaml 
replicaset.apps/replicaset-example configured

查看pod數:

[root@server1 ~]# kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
replicaset-example-p6sv6   1/1     Running   0          97s
replicaset-example-s5jps   1/1     Running   0          97s
replicaset-example-wzclz   1/1     Running   0          21s
replicaset-example-zk4mb   1/1     Running   0          21s

已經被拉伸成了4個。

縮減:

[root@server1 ~]# vim rs.yaml 
[root@server1 ~]# cat rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
    name: replicaset-example
spec:
  replicas: 2			#縮減爲2個
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

[root@server1 ~]# kubectl apply -f rs.yaml 
replicaset.apps/replicaset-example configured
[root@server1 ~]# kubectl get pod
NAME                       READY   STATUS        RESTARTS   AGE
replicaset-example-p6sv6   1/1     Running       0          2m6s
replicaset-example-s5jps   1/1     Running       0          2m6s

可以看出刪除的是剛剛創建的那兩個pod。

接下來更改一個pod 的標籤:

[root@server1 ~]# kubectl label pod replicaset-example-s5jps app=myapp --overwrite 		#將標籤強制更改爲myapp
pod/replicaset-example-s5jps labeled
[root@server1 ~]# kubectl get pod --show-labels
NAME                       READY   STATUS    RESTARTS   AGE     LABELS
replicaset-example-p6sv6   1/1     Running   0          3m56s   app=nginx
replicaset-example-s5jps   1/1     Running   0          3m56s   app=myapp
replicaset-example-w98nk   1/1     Running   0          26s     app=nginx

可以看出現在有3個pod,兩個標籤爲nginx一個爲myapp,RS控制器的工作原理就是維持標籤爲nginx的pod個數有2個,因此當我們更改一個pod的標籤後,RS又會給我們創建一個標籤爲nginx的pod,而當我們將標籤爲myapp的pod刪除後RS控制器不會有操作:

[root@server1 ~]# kubectl delete pod replicaset-example-s5jps
pod "replicaset-example-s5jps" deleted
[root@server1 ~]# kubectl get pod --show-labels
NAME                       READY   STATUS    RESTARTS   AGE    LABELS
replicaset-example-p6sv6   1/1     Running   0          5m8s   app=nginx
replicaset-example-w98nk   1/1     Running   0          98s    app=nginx

此時我們再更改:

[root@server1 ~]# kubectl label pod replicaset-example-p6sv6 app=myapp --overwrite 		#首先保證3個pod
pod/replicaset-example-p6sv6 labeled
[root@server1 ~]# kubectl get pod --show-labels
NAME                       READY   STATUS    RESTARTS   AGE     LABELS
replicaset-example-p6sv6   1/1     Running   0          6m4s    app=myapp
replicaset-example-w98nk   1/1     Running   0          2m34s   app=nginx
replicaset-example-x2lq9   1/1     Running   0          26s     app=nginx


[root@server1 ~]# kubectl label pod replicaset-example-p6sv6 app=nginx --overwrite
pod/replicaset-example-p6sv6 labeled
[root@server1 ~]# kubectl get pod --show-labels
NAME                       READY   STATUS        RESTARTS   AGE     LABELS
replicaset-example-p6sv6   1/1     Running       0          6m23s   app=nginx
replicaset-example-w98nk   1/1     Running       0          2m53s   app=nginx
replicaset-example-x2lq9   0/1     Terminating   0          45s     app=nginx
[root@server1 ~]# kubectl get pod --show-labels
NAME                       READY   STATUS    RESTARTS   AGE     LABELS
replicaset-example-p6sv6   1/1     Running   0          6m25s   app=nginx
replicaset-example-w98nk   1/1     Running   0          2m55s   app=nginx

以上實驗可以看出,當集羣裏有3個標籤是nginx的pod的時候,RS控制器又會幫我們將最後創建的pod刪除。

實驗後刪除:

[root@server1 ~]# kubectl delete -f rs.yaml 
replicaset.apps "replicaset-example" deleted

Deployment控制器示例

編輯yaml文件:

[root@server1 ~]# vim deployment.yaml 
[root@server1 ~]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80

創建pod:

[root@server1 ~]# kubectl apply -f deployment.yaml 
deployment.apps/deployment-nginx created
[root@server1 ~]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-56d786cd98-kx5pw   1/1     Running   0          23s
deployment-nginx-56d786cd98-qgcjl   1/1     Running   0          23s

[root@server1 ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
deployment-nginx-56d786cd98   2         2         2       28s
[root@server1 ~]# kubectl get deployments.apps 		#查看deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
deployment-nginx   2/2     2            2           32s

以上運行結果可以看出deployments底層也是由RS實現的,接下來進行拉伸:

[root@server1 ~]# vim deployment.yaml 
[root@server1 ~]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  labels:
    app: nginx
spec:
  replicas: 4			#拉伸爲4個
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80

[root@server1 ~]# kubectl apply -f deployment.yaml 
deployment.apps/deployment-nginx configured
[root@server1 ~]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-56d786cd98-942dh   1/1     Running   0          26s
deployment-nginx-56d786cd98-kx5pw   1/1     Running   0          108s
deployment-nginx-56d786cd98-qgcjl   1/1     Running   0          108s
deployment-nginx-56d786cd98-zb8s8   1/1     Running   0          26s

可以看出已經拉伸爲4個。接下來進行滾動更新:

[root@server1 ~]# vim deployment.yaml 
[root@server1 ~]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  labels:
    app: nginx
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v2		#更新到v2
        ports:
        - containerPort: 80

[root@server1 ~]# kubectl apply -f deployment.yaml 
deployment.apps/deployment-nginx configured
[root@server1 ~]# kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
deployment-nginx-868855d887-2zh45   1/1     Running   0          2m39s   10.244.2.26   server3   <none>           <none>
deployment-nginx-868855d887-87m22   1/1     Running   0          2m34s   10.244.1.20   server2   <none>           <none>
deployment-nginx-868855d887-hb6mv   1/1     Running   0          2m39s   10.244.1.19   server2   <none>           <none>
deployment-nginx-868855d887-v8ndt   1/1     Running   0          2m33s   10.244.2.27   server3   <none>           <none>
[root@server1 ~]# curl 10.244.2.26
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

可以看出版本已經更新到了v2,我們查看rs可以看出更新過程:

[root@server1 ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
deployment-nginx-56d786cd98   0         0         0       4m41s
deployment-nginx-868855d887   4         4         4       2m27s

可以看出更新時控制器新建一個rs,然後再新建4個pod,原來的rs依然存在,爲了方便我們進行回滾:

[root@server1 ~]# vim deployment.yaml 
[root@server1 ~]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
  labels:
    app: nginx
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80

[root@server1 ~]# kubectl apply -f deployment.yaml 
deployment.apps/deployment-nginx configured
[root@server1 ~]# kubectl get pod
NAME                                READY   STATUS              RESTARTS   AGE
deployment-nginx-56d786cd98-78m7z   0/1     ContainerCreating   0          4s
deployment-nginx-56d786cd98-8hnns   1/1     Running             0          9s
deployment-nginx-56d786cd98-lcvzw   1/1     Running             0          9s
deployment-nginx-56d786cd98-xkjhq   0/1     ContainerCreating   0          3s
deployment-nginx-868855d887-2zh45   1/1     Running             0          3m22s
deployment-nginx-868855d887-hb6mv   1/1     Terminating         0          3m22s
deployment-nginx-868855d887-v8ndt   1/1     Terminating         0          3m16s

[root@server1 ~]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-56d786cd98-78m7z   1/1     Running   0          26s
deployment-nginx-56d786cd98-8hnns   1/1     Running   0          31s
deployment-nginx-56d786cd98-lcvzw   1/1     Running   0          31s
deployment-nginx-56d786cd98-xkjhq   1/1     Running   0          25s

可以看出原來v1版本的rs被重新啓用,再原來的rs下面新建4個pod。當然我門也可以使用kubectl delete rs --all命令刪除不用的rs(注意:正在使用的rs不會刪除):

[root@server1 ~]# kubectl delete rs --all
replicaset.apps "deployment-nginx-56d786cd98" deleted
replicaset.apps "deployment-nginx-868855d887" deleted
[root@server1 ~]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
deployment-nginx-56d786cd98-6r589   1/1     Running   0          21s
deployment-nginx-56d786cd98-hvz24   1/1     Running   0          21s
deployment-nginx-56d786cd98-k62lj   1/1     Running   0          21s
deployment-nginx-56d786cd98-ss97z   1/1     Running   0          21s
[root@server1 ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
deployment-nginx-56d786cd98   4         4         4       24s		#正在使用的RS不會刪除

實驗後刪除:

[root@server1 ~]# kubectl delete -f deployment.yaml 
deployment.apps "deployment-nginx" deleted

DaemonSet舉例

DaemonSet控制器保證每個節點上都運行一個pod:

[root@server1 ~]# vim daemonset.yaml 
[root@server1 ~]# cat daemonset.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-example
  labels:
    app: zabbix-agent
spec:
  selector:
    matchLabels:
      name: zabbix-agent
  template:
    metadata:
      labels:
        name: zabbix-agent
    spec:
      containers:
      - name: zabbix-agent
        image: zabbix/zabbix-agent

創建pod:

[root@server1 ~]# kubectl apply -f daemonset.yaml 
daemonset.apps/daemonset-example created
[root@server1 ~]# kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
daemonset-example-ctbgh   1/1     Running   0          6m5s
daemonset-example-mdqzk   1/1     Running   0          6m5s

[root@server1 ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
daemonset-example-ctbgh   1/1     Running   0          7m16s   10.244.2.32   server3   <none>           <none>
daemonset-example-mdqzk   1/1     Running   0          7m16s   10.244.1.25   server2   <none>           <none>

可以看出我們的每個節點(server3和server2)上都運行了一個pod,當我們刪除一個pod時:

[root@server1 ~]# kubectl delete pod daemonset-example-ctbgh
pod "daemonset-example-ctbgh" deleted
[root@server1 ~]# kubectl get pod -o wide
NAME                      READY   STATUS              RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
daemonset-example-998ck   0/1     ContainerCreating   0          8s      <none>        server3   <none>           <none>
daemonset-example-mdqzk   1/1     Running             0          8m22s   10.244.1.25   server2   <none>           <none>
[root@server1 ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
daemonset-example-998ck   1/1     Running   0          24s     10.244.2.33   server3   <none>           <none>
daemonset-example-mdqzk   1/1     Running   0          8m38s   10.244.1.25   server2   <none>           <none>

可以看出刪除後DaemonSet控制器又會幫我們創建pod,以保證每個節點運行一個pod。

實驗後刪除:

[root@server1 ~]# kubectl delete -f daemonset.yaml 
daemonset.apps "daemonset-example" deleted

Job控制器舉例

Job控制器只運行一次

[root@server1 ~]# vim job.yaml 
[root@server1 ~]# cat job.yaml 
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl				#利用perl計算圓周率
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4			#容器啓動失敗重啓4次之後不再重啓。

創建pod:

[root@server1 ~]# kubectl apply -f job.yaml 
job.batch/pi created
[root@server1 ~]# kubectl get pod
NAME       READY   STATUS              RESTARTS   AGE
pi-ktn6p   0/1     ContainerCreating   0          40s
[root@server1 ~]# kubectl get pod
NAME       READY   STATUS      RESTARTS   AGE
pi-ktn6p   0/1     Completed   0          2m12s

由於Job只運行一次,因此運行完後狀態爲Completed,我們可以查看日誌獲取結果:
在這裏插入圖片描述
可以看出計算成功。

實驗後刪除:

[root@server1 ~]# kubectl delete -f job.yaml 
job.batch "pi" deleted

CronJob控制器舉例

CronJob控制器用於定時執行任務:

[root@server1 ~]# vim cronjob.yaml 
[root@server1 ~]# cat cronjob.yaml 
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cronjob-example
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cronjob
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from k8s cluster			#輸出信息
          restartPolicy: OnFailure

其中schedule字段與crontab裏面的寫法相同,"* * * * *"表示每分鐘執行任務。
創建pod:

[root@server1 ~]# kubectl apply -f cronjob.yaml 
cronjob.batch/cronjob-example created
root@server1 ~]# kubectl get pod
NAME                               READY   STATUS              RESTARTS   AGE
cronjob-example-1587387120-ngt6n   0/1     ContainerCreating   0          16s
[root@server1 ~]# kubectl get pod		#等待一分鐘
NAME                               READY   STATUS              RESTARTS   AGE
cronjob-example-1587387120-ngt6n   0/1     Completed           0          60s
cronjob-example-1587387180-hbwzb   0/1     ContainerCreating   0          9s

可以看出每分鐘運行一個pod,查看日誌獲取輸出信息:

[root@server1 ~]# kubectl logs cronjob-example-1587387120-ngt6n
Mon Apr 20 12:52:30 UTC 2020
Hello from k8s cluster
[root@server1 ~]# kubectl logs cronjob-example-1587387180-hbwzb
Mon Apr 20 12:53:35 UTC 2020
Hello from k8s cluster

可以看出輸出也是每分鐘輸出一次,也可以使用以下命令查看cronjob的信息:

[root@server1 ~]# kubectl get cronjobs
NAME              SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob-example   * * * * *   False     1        16s             3m10s

[root@server1 ~]# kubectl get job -w		#查看job信息並且持續輸出
NAME                         COMPLETIONS   DURATION   AGE
cronjob-example-1587387120   1/1           20s        2m23s
cronjob-example-1587387180   1/1           35s        92s
cronjob-example-1587387240   1/1           20s        32s

實驗後刪除

[root@server1 ~]# kubectl delete -f cronjob.yaml 
cronjob.batch "cronjob-example" deleted

還有兩個控制器StatefulSet和HPA我們在接下來的博客中再進行舉例。

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