k8s控制器資源(三)


Pod

pod在之前說過,pod是kubernetes集群中是最小的調度單元,pod中可以運行多個容器,而node又可以包含多個pod,關系如下圖:

在對pod的用法進行說明之前,有必要先對docker容器進行說明

在使用docker時,可以使用docker run命令創建一個容器,而在kubernetes集群中對長時間運行容器的要求是:

  • 主程序需要一直在前台執行

如果我們創建的docker鏡像的啟動命令是后台執行程序,例如Linux腳本:

nohup ./start.sh &

那么kubelet在創建這個Pod執行完這個命令后,會認為這個Pod執行完畢,從而進行銷毀pod,如果pod定義了ReplicationController,那么銷毀了還會在創建,繼續執行上述的命令然后又銷毀,然后又重建,這樣就會陷入惡性循環,這也是為什么執行的命令要運行在前台的原因,這一點一定要注意

 

Pod生命周期和重啟策略

 

 Pod的重啟策略(RestartPolicy):

  • Always:當容器失敗時,由kubelet自動重啟該容器
  • OnFailure:當容器終止運行且退出代碼不為0的時候,由kubelet自動重啟
  • Never:不論容器運行狀態如何,kubelet永遠都不會重啟該容器

Pod的重啟策略和控制器息息相關,每種控制器對Pod的重啟策略如下:

  • RC和DaemonSet:必須設置為Always,需要保證該容器持續運行
  • Job:OnFailure和Never,確保容器執行完畢后不在重啟
  • kubelet:在Pod失效時自動重啟它,不論將RestartPolicy設置成什么值,也不會對Pod進行健康檢查

 

 

我們簡單介紹完kubernetes的邏輯結構之后我們來看一下k8s控制器資源,k8s控制器資源分很多種,有replication controller,deployment,Horizontal pod autoscaler,statefulSet,daemonSet,job等...,接下來我們來詳細分析一下下面資源的使用場景和區別

replication Controller控制器

replication controller簡稱RC,是kubernetes系統中的核心概念之一,簡單來說,它其實定義了一個期望的場景,即聲明某種pod的副本數量在任意時刻都復合某個預期值,所以RC的定義包含以下部分:

  • pod期待的副本數量
  • 用於篩選目標pod的Label Selector
  • 當pod的副本數量小於期望值時,用於創建新的pod的pod模板(template)

下面是一個完整的RC定義的例子,即確保擁有app=mynginx標簽的這個pod在整個kubernetes集群中始終只有一個副本,紅色字體一定要一直,因為我們的控制器就是根據標簽篩選出來的(因為pod的ip和pod名字都會變化):

[root@master ~]# vim nginx.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
  namespace: default
spec:
  replicas: 1
  selector:
    app: mynginx
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: mycontainer
        image: lizhaoqwe/nginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

在我們定義了一個RC並將其提交到kubernetes集群中后,master上的controller Manager組件就得到了通知,定期巡檢系統中當前存貨的目標pod,並確保目標pod實力數量剛好等於此RC的期望值,如果多余期望值,則停掉一些,如果少於期望值會再創建一些。

以下面3個Node節點的集群為例,說明kubernetes是如何通過RC來實現pod副本數量自動控制的機制,我們創建2個pod運行redis-slave,系統可能會再兩個節點上創建pod,如下圖

 

假設Node2上的pod意外終止,則根據RC定義的replicas數量1,kubernetes將會自動創建並啟動兩個新的pod,以保證在整個集群中始終有兩個redis-slave Pod運行,如下圖所示,系統可能選擇Node3或者Node1來創建新的pod

 

 

 此外,我們還可以通過修改RC的副本數量,來實現Pod的動態擴容和縮容

[root@master ~]# kubectl scale --replicas=3 rc myweb 
replicationcontroller/myweb scaled

結果如下

 

 

 這里需要注意的是,刪除RC並不會影響通過該RC已創建好的pod,為了刪除所有pod,可以設置replicas的值為0,然后更新該RC,另外,kubectl提供了stop和delete命令來一次性刪除RC和RC控制的全部Pod

ReplicaSet

上一階段講過了ReplicationController控制器之后,相信大家對其已經了解了,ReplicaSet控制器其實就是ReplicationController的升級版,官網解釋為下一代的“RC”,ReplicationController和ReplicaSet的唯一區別是ReplicaSet支持基於集合的Label selector,而RC只支持基於等式的Label Selector,這使得ReplicaSet的功能更強,下面等價於之前的RC例子的ReokucaSet的定義

[root@master ~]# vim replicaSet.yaml              
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
  name: myweb
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mynginx
    matchExpressions:
      - {key: app, operator: In, values: [mynginx]}
  template:
    metadata:
      labels:
        app: mynginx
    spec:
      containers:
      - name: mycontainer
        image: lizhaoqwe/nginx:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

 kubectl命令行工具適用於RC的絕大部分命令同樣適用於ReplicaSet,此外,我們當前很少單獨適用ReplicaSet,它主要被Deployment這個更高層的資源對象所使用,從而形成一整套Pod創建,刪除,更新的編排機制,我們在使用Deployment時無需關心它是如何維護和創建ReplicaSet的,這一切都是自動發生的

最后,總結一下RC(ReplicaSet)的一些特性和作用:

  • 在絕大多數情況下,我們通過定義一個RC實現Pod的創建及副本數量的自動控制
  • 在RC里包括完整的Pod定義模板
  • RC通過Label Selector機制實現對Pod副本的自動控制
  • 通過改變RC里的Pod副本數量,可以實現Pod的擴容和縮容
  • 通過改變RC里Pod模板中的鏡像版本,可以實現滾動升級

Deployment

Deployment是kubernetes在1.2版本中引入的新概念,用於更好的解決Pod的編排問題,為此,Deployment在內部使用了ReplicaSet來實現目的,我們可以把Deployment理解為ReplicaSet的一次升級,兩者的相似度超過90%

Deployment的使用場景有以下幾個:

  • 創建一個Deployment對象來生成對應的ReplicaSet並完成Pod副本的創建
  • 檢查Deployment的狀態來看部署動作是否完成(Pod副本數量是否達到了預期的值)
  • 更新Deployment以創建新的Pod(比如鏡像升級)
  • 如果當前Deployment不穩定,可以回滾到一個早先的Deployment版本
  • 暫停Deployment以便於一次性修改多個PodTemplateSpec的配置項,之后在恢復Deployment,進行新的發布
  • 擴展Deployment以應對高負載
  • 查看Deployment的狀態,以此作為發布是否成功的紙幣哦
  • 清理不在需要的舊版本ReplicaSet

除了API生命與Kind類型有區別,Deployment的定義與Replica Set的定義很類似,我們這里還是以上面為例子

apiVersion: extensions/v1beta1          apiVersion: apps/v1
kind: ReplicaSet                        kind: Deployment

執行文件

[root@master ~]# kubectl apply -f deploy.yaml 
deployment.apps/myweb created

查看結果

[root@master ~]# kubectl get deployments
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
myweb   1/1     1            1           5m5s

解釋一下上面的顯示

NAME:你的deployment控制器的名字

READY:已經准備好的Pod個數/所期望的Pod個數

UP-TO-DATE:最新版本的Pod數量,用於在執行滾動升級時,有多少個Pod副本已經成功升級

AVAILABLE:當前集群中可用的Pod數量,也就是集群中存活的Pod數量

StatefulSet

在kubernetes系統中,Pod的管理對象RC,Deployment,DaemonSet和Job都面向無狀態的服務,但現實中有很多服務時有狀態的,比如一些集群服務,例如mysql集群,集群一般都會有這四個特點:

  1. 每個節點都是有固定的身份ID,集群中的成員可以相互發現並通信
  2. 集群的規模是比較固定的,集群規模不能隨意變動
  3. 集群中的每個節點都是有狀態的,通常會持久化數據到永久存儲中
  4. 如果磁盤損壞,則集群里的某個節點無法正常運行,集群功能受損

如果你通過RC或Deployment控制Pod副本數量來實現上述有狀態的集群,就會發現第一點是無法滿足的,因為Pod名稱和ip是隨機產生的,並且各Pod中的共享存儲中的數據不能都動,因此StatefulSet在這種情況下就派上用場了,那么StatefulSet具有以下特性:

  • StatefulSet里的每個Pod都有穩定,唯一的網絡標識,可以用來發現集群內的其它成員,假設,StatefulSet的名稱為fengzi,那么第1個Pod叫fengzi-0,第2個叫fengzi-1,以此類推
  • StatefulSet控制的Pod副本的啟停順序是受控的,操作第N個Pod時,前N-1個Pod已經是運行且准備狀態
  • StatefulSet里的Pod采用穩定的持久化存儲卷,通過PV或PVC來實現,刪除Pod時默認不會刪除與StatefulSet相關的存儲卷(為了保證數據的安全)

StatefulSet除了要與PV卷捆綁使用以存儲Pod的狀態數據,還要與Headless,Service配合使用,每個StatefulSet定義中都要生命它屬於哪個Handless Service,Handless Service與普通Service的關鍵區別在於,它沒有Cluster IP

一、創建pv

[root@master ~]# cat createpv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
  nfs:
    path: /share_v1
    server: 192.168.254.14
  accessModes:
  - ReadWriteMany
  - ReadWriteOnce
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv02
spec:
  nfs:
    path: /share_v2
    server: 192.168.254.14
  accessModes:
  - ReadWriteMany
  - ReadWriteOnce
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv03
spec:
  nfs:
    path: /share_v3
    server: 192.168.254.14
  accessModes:
  - ReadWriteMany
  - ReadWriteOnce
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv04
spec:
  nfs:
    path: /share_v4
    server: 192.168.254.14
  accessModes:
  - ReadWriteMany
  - ReadWriteOnce
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv05
spec:
  nfs:
    path: /share_v5
    server: 192.168.254.11
  accessModes:
  - ReadWriteMany
  - ReadWriteOnce
  capacity:
    storage: 2Gi

二、創建pvc和statfulset控制器管理的pod

[root@master ~]# cat state.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
  labels:
    app: myapp
spec:
  ports:
  - name: http
    port: 80
  clusterIP: None
  selector:
    app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  serviceName: myapp-svc
  replicas: 3
  selector:
    matchLabels:
      app: myapp-pod
  template:
    metadata:
      labels:
        app: myapp-pod
    spec:
      containers:
      - name: myapp
        image: liwang7314/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
        volumeMounts:
        - name: myappdata
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: myappdata
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

三、創建完畢后觀察

[root@master ~]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
myapp-0   1/1     Running   0          8s
myapp-1   1/1     Running   0          5s
myapp-2   1/1     Running   0          3s

 

DemonSet

在每一個node節點上只調度一個Pod,因此無需指定replicas的個數,比如:

  • 在每個node上都運行一個日志采集程序,負責收集node節點本身和node節點之上的各個Pod所產生的日志
  • 在每個node上都運行一個性能監控程序,采集該node的運行性能數據

 

[root@localhost ~]# cat daemon.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-cloud-logging
  namespace: kube-system
  labels:
    k8s-app: fluentd-cloud-logging
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-cloud-logging
  template:
    metadata:
      namespace: kube-system
      labels:
        k8s-app: fluentd-cloud-logging
    spec:
      containers:
      - name: fluentd-cloud-logging
        image: kayrus/fluentd-elasticsearch:1.20
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
        env:
        - name: FLUENTD_ARGS
          value: -q
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          readOnly: false
        - name: containers
          mountPath: /var/lib/docker/containers
          readOnly: false
      volumes:
      - name: containers
        hostPath:
          path: /usr
      - name: varlog
        hostPath:
          path: /usr/sbin

查看pod所在的節點

[root@localhost ~]# kubectl get pods -n kube-system -o wide
NAME                             READY   STATUS        RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
coredns-bccdc95cf-8sqzn          1/1     Running       2          2d7h    10.244.0.6       master   <none>           <none>
coredns-bccdc95cf-vt8nz          1/1     Running       2          2d7h    10.244.0.7       master   <none>           <none>
etcd-master                      1/1     Running       1          2d7h    192.168.254.13   master   <none>           <none>
fluentd-cloud-logging-6xx4l      1/1     Running       0          4h24m   10.244.2.7       node2    <none>           <none>
fluentd-cloud-logging-qrgg6      1/1     Rruning       0          4h24m   10.244.1.7       node1    <none>           <none>
kube-apiserver-master            1/1     Running       1          2d7h    192.168.254.13   master   <none>           <none>
kube-controller-manager-master   1/1     Running       1          2d7h    192.168.254.13   master   <none>           <none>
kube-flannel-ds-amd64-c97wh      1/1     Running       0          2d7h    192.168.254.12   node1    <none>           <none>
kube-flannel-ds-amd64-gl6wg      1/1     Running       1          2d7h    192.168.254.13   master   <none>           <none>
kube-flannel-ds-amd64-npsqf      1/1     Running       0          2d7h    192.168.254.10   node2    <none>           <none>
kube-proxy-gwmx8                 1/1     Running       1          2d7h    192.168.254.13   master   <none>           <none>
kube-proxy-phqk2                 1/1     Running       0          2d7h    192.168.254.12   node1    <none>           <none>
kube-proxy-qtt4b                 1/1     Running       0          2d7h    192.168.254.10   node2    <none>           <none>
kube-scheduler-master            1/1     Running       2          2d7h    192.168.254.13   master   <none>           <none>

 

 


免責聲明!

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



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