1. 程式人生 > 其它 >VC多執行緒併發控制方法

VC多執行緒併發控制方法

k8s的控制器型別

Kubernetes中內建了很多controller(控制器),這些相當於一個狀態機,用來控制Pod的具體狀態和行為

  • Deployment:適合無狀態的服務部署
  • StatefullSet:適合有狀態的服務部署
  • DaemonSet:一次部署,所有的node節點都會部署,例如一些典型的應用場景:
    • 執行叢集儲存 daemon,例如在每個Node上執行 glusterd、ceph
    • 在每個Node上執行日誌收集 daemon,例如 fluentd、 logstash
    • 在每個Node上執行監控 daemon,例如 Prometheus Node Exporter
  • Job:一次性的執行任務
  • Cronjob:週期性的執行任務

Deployment控制器

概述

Deployment物件,顧名思義,是用於部署應用的物件。它使Kubernetes中最常用的一個物件,它為ReplicaSet和Pod的建立提供了一種宣告式的定義方法,從而無需像前兩篇文章中那樣手動建立ReplicaSet和Pod物件(使用Deployment而不直接建立ReplicaSet是因為Deployment物件擁有許多ReplicaSet沒有的特性,例如滾動升級和回滾)。

通過Deployment物件,你可以輕鬆的做到以下事情:

  • 建立ReplicaSet和Pod
  • 滾動升級(不停止舊服務的狀態下升級)和回滾應用(將應用回滾到之前的版本)
  • 平滑地擴容和縮容
  • 暫停和繼續Deployment

建立

[root@master ~]# vim deploy.yml
[root@master ~]# cat deploy.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
   matchLabels:
     app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80


[root@master ~]# kubectl create -f deploy.yml  --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/nginx-deployment created

--record引數可以記錄當前版本的Deployment都執行過哪些命令。

建立完成後立即執行get命令可以檢視這個Deployment:

[root@master ~]# kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           2m14s
[root@master ~]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-74d589986c-kxcvx   1/1     Running   0          2m11s
nginx-deployment-74d589986c-s277p   1/1     Running   0          2m11s
nginx-deployment-74d589986c-zlf8v   1/1     Running   0          2m11s

NAME代表Deployment的名字,DESIRED代表這個Deployment期望的副本數量,CURRENT代表當前已經建立了的副本數量,UP-TO-DATE代表已經更新完成的副本數量,AVAILABLE代表對於當前使用者可用的副本數量,AGE代表當前Deployment已經執行的時長。

等待幾秒鐘,再次執行get命令,可以檢視到變化:

[root@master ~]# kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           3m4s

通過kubectl get rs來檢視系統中ReplicaSet物件,由此可以看出Deployment會自動建立一個ReplicaSet物件。

[root@master ~]# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-74d589986c   3         3         3       4m29s

通過kubectl get pods --show-labels命令來檢視當前系統中的Pod物件,可以成功觀察到nginx-deployment建立的3個Pod。

[root@master ~]# kubectl get pods --show-labels
NAME                                READY   STATUS    RESTARTS   AGE     LABELS
nginx-deployment-74d589986c-kxcvx   1/1     Running   0          3m55s   app=nginx,pod-template-hash=74d589986c
nginx-deployment-74d589986c-s277p   1/1     Running   0          3m55s   app=nginx,pod-template-hash=74d589986c
nginx-deployment-74d589986c-zlf8v   1/1     Running   0          3m55s   app=nginx,pod-template-hash=74d589986c

Deployment的更新

假如我們現在想要讓 nginx pod 使用 nginx:1.9.1 的映象來代替原來的 nginx的映象,執行以下命令:
[root@master ~]# kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment.apps/nginx-deployment image updated

或者我們可以使用 edit 命令來編輯 Deployment,將image從nginx改寫成 nginx:1.9.1。
kubectl edit deployment/nginx-deployment

檢視更新進度:
[root@master ~]# kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out

Deployment更新時會建立一個新的ReplicaSet,然後將新的ReplicaSet中的Pod慢慢擴容到指定的副本數,將舊的ReplicaSet慢慢縮容到0。因此,更新時總能夠確保舊的服務不會停止,這就是滾動更新。

Deployment的回滾

使用rollout history命令檢視Deployment的版本(revision):
[root@master ~]# kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy.yml --record=true
2         kubectl create --filename=deploy.yml --record=true

因為我們建立 Deployment 的時候使用了 —recored 引數可以記錄命令,我們可以很方便的檢視每次 revison 的變化。

檢視單個 revision 的詳細資訊:
[root@master ~]# kubectl rollout history deployment/nginx-deployment --revision=2
deployment.apps/nginx-deployment with revision #2
Pod Template:
  Labels:       app=nginx
        pod-template-hash=658d7f4b4b
  Annotations:  kubernetes.io/change-cause: kubectl create --filename=deploy.yml --record=true
  Containers:
   nginx:
    Image:      nginx:1.9.1
    Port:       80/TCP
    Host Port:  0/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

現在,可以使用rollout undo命令回滾到前一個revision:
[root@master ~]# kubectl rollout undo deployment/nginx-deployment
deployment.apps/nginx-deployment rolled back

[root@master ~]# kubectl describe deployment/nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Fri, 24 Dec 2021 22:24:10 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 3
                        kubernetes.io/change-cause: kubectl create --filename=deploy.yml --record=true
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>

也可以使用–to-revision引數指定某個歷史版本:
[root@master ~]#  kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment.apps/nginx-deployment rolled back

[root@master ~]# kubectl describe deployment/nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Fri, 24 Dec 2021 22:24:10 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 4
                        kubernetes.io/change-cause: kubectl create --filename=deploy.yml --record=true
Selector:               app=nginx
Replicas:               3 desired | 3 updated | 4 total | 3 available | 1 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.9.1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>

Replicaset控制器

Replicaset概述

ReplicaSet是kubernetes中的一種副本控制器,簡稱rs,主要作用是控制由其管理的pod,使pod副本的數量始終維持在預設的個數。它的主要作用就是保證一定數量的Pod能夠在叢集中正常執行,它會持續監聽這些Pod的執行狀態,在Pod發生故障時重啟pod,pod數量減少時重新執行新的 Pod副本。官方推薦不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高階的概念,它會管理ReplicaSet並提供很多其它有用的特性,最重要的是Deployments支援宣告式更新,宣告式更新的好處是不會丟失歷史變更。所以Deployment控制器不直接管理Pod物件,而是由 Deployment 管理ReplicaSet,再由ReplicaSet負責管理Pod物件。

Replicaset工作原理

Replicaset核心作用在於使用者建立指定數量的pod副本,並確保pod副本一直處於滿足使用者期望的數量, 起到多退少補的作用,並且還具有自動擴容縮容等制。 Replicaset控制器主要由三個部分組成:

  • 使用者期望的pod副本數:用來定義由這個控制器管控的pod副本有幾個
  • 標籤選擇器:選定哪些pod是自己管理的,如果通過標籤選擇器選到的- pod副本數量少於我們指定的數量,需要用到下面的元件
  • pod資源模板:如果叢集中現存的pod數量不夠我們定義的副本中期望的數量怎麼辦,需要新建pod,這就需要pod模板,新建的pod是基於模板來建立的。

Replicaset使用

[root@k8s-master1 ~]# cat replicaset.yml 
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: nginx
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy:  IfNotPresent


[root@master ~]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@master ~]# kubectl  get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-7rrp6   1/1     Running   0          9s
frontend-drmcf   1/1     Running   0          9s
frontend-qnlz6   1/1     Running   0          9s
[root@master ~]# kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
frontend   3         3         3       41s

DaemonSet控制器

DaemonSet 簡介

DaemonSet:服務守護程序,它的主要作用是在Kubernetes叢集的所有節點中執行我們部署的守護程序,相當於在叢集節點上分別部署Pod副本,如果有新節點加入叢集,Daemonset會自動的在該節點上執行我們需要部署的Pod副本,相反如果有節點退出叢集,Daemonset也會移除掉部署在舊節點的Pod副本。

DaemonSet的主要特徵

  • 這個 Pod 執行在 Kubernetes 叢集裡的每一個節點(Node)上;
  • 每個節點上只會執行一個這樣的 Pod 例項; = 如果新的節點加入 Kubernetes 集群后,該 Pod 會自動地在新節點上被創建出來;
  • 而當舊節點被刪除後,它上面的 Pod 也相應地會被回收掉。

Daemon Pods的排程特性

預設情況下,Pod被分配到具體哪一臺Node上執行是由Scheduler(負責分配排程Pod到叢集內的Node上,它通過監聽ApiServer,查詢還未分配Node的Pod,然後根據排程策略為這些Pod分配Node)決定的。但是,DaemonSet物件建立的Pod卻擁有一些特殊的特性:

  • Node的unschedulable屬性會被DaemonSet Controller忽略。
  • 即使Scheduler還未啟動,DaemonSet Controller也能夠建立並執行Pod。

DaemonSet常用場景

  • 網路外掛的 Agent 元件,如(Flannel,Calico)需要執行在每一個節點上,用來處理這個節點上的容器網路;
  • 儲存外掛的 Agent 元件,如(Ceph,Glusterfs)需要執行在每一個節點上,用來在這個節點上掛載F遠端儲存目錄;
  • 監控系統的資料收集元件,如(Prometheus Node Exporter,Cadvisor)需要執行在每一個節點上,負責這個節點上的監控資訊蒐集。
  • 日誌系統的資料收集元件,如(Fluent,Logstash)需要執行在每一個節點上,負責這個節點上的日誌資訊蒐集。

建立一個DaemonSet物件

[root@master kubenetres]# vi daemonset.yml
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers



[root@master ~]# kubectl get pod -n kube-system
NAME                                         READY   STATUS    RESTARTS      AGE
coredns-6d8c4cb4d-6n2xc                      1/1     Running   2 (53m ago)   3d1h
coredns-6d8c4cb4d-hjznw                      1/1     Running   2 (53m ago)   3d1h
etcd-master.example.com                      1/1     Running   8 (53m ago)   3d1h
fluentd-elasticsearch-6sgnt                  1/1     Running   0             44s
fluentd-elasticsearch-chfhc                  1/1     Running   0             42s
kube-apiserver-master.example.com            1/1     Running   9 (53m ago)   3d1h
kube-controller-manager-master.example.com   1/1     Running   8 (53m ago)   3d1h
kube-flannel-ds-67kht                        1/1     Running   3 (53m ago)   3d1h
kube-flannel-ds-hr47p                        1/1     Running   2 (53m ago)   3d1h
kube-flannel-ds-k678m                        1/1     Running   2 (53m ago)   3d1h
kube-proxy-44zx6                             1/1     Running   2 (53m ago)   3d1h
kube-proxy-knkbm                             1/1     Running   2 (53m ago)   3d1h
kube-proxy-n875j                             1/1     Running   3 (53m ago)   3d1h
kube-scheduler-master.example.com            1/1     Running   8 (53m ago)   3d1h

Job控制器

Job Controller

Job Controller負責根據Job Spec建立Pod,並持續監控Pod的狀態,直至其成功結束。如果失敗,則根據restartPolicy(只支援OnFailure和Never,不支援Always)決定是否建立新的Pod再次重試任務。

Job負責批量處理短暫的一次性任務 (short lived one-off tasks),即僅執行一次的任務,它保證批處理任務的一個或多個Pod成功結束。

Kubernetes支援以下幾種Job:

  • 非並行Job:通常建立一個Pod直至其成功結束
  • 固定結束次數的Job:設定.spec.completions,建立多個Pod,直到.spec.completions個Pod成功結束
  • 帶有工作佇列的並行Job:設定.spec.Parallelism但不設定.spec.completions,當所有Pod結束並且至少一個成功時,Job就認為是成功

job的使用

[root@master ~]# vi job.yml 
---
apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  template:
    spec:
      containers:
      - name: myjob
        image: busybox
        command: ["echo",  "hello k8s job"]
      restartPolicy: Never


[root@master ~]# kubectl apply -f job.yml 
job.batch/myjob created
[root@master ~]# kubectl get pods
NAME          READY   STATUS      RESTARTS   AGE
myjob-gq27p   0/1     Completed   0          37s

[root@master ~]# kubectl get job
NAME    COMPLETIONS   DURATION   AGE
myjob   1/1           19s        5m11s

[root@master ~]# kubectl logs myjob-gq27p
hello k8s job

CronJob控制器

CronJob可以用來執行基於時間計劃的定時任務,類似於Linux/Unix系統中的 crontable (opens new window)。

CronJob 執行週期性的重複任務時非常有用,例如備份資料、傳送郵件等。CronJob 也可以用來指定將來某個時間點執行單個任務,例如將某項任務定時到系統負載比較低的時候執行。

一個 CronJob 物件就像 crontab (cron table) 檔案中的一行。 它用Cron格式進行編寫, 並週期性地在給定的排程時間執行 Job。

下面的 CronJob 示例清單會在每分鐘打印出當前時間和問候訊息:
[root@master kubenetres]# vi cronjob.yml
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello world
          restartPolicy: OnFailure
建立pod檢視
[root@master ~]# kubectl apply -f cronjob.yml 
Warning: batch/v1beta1 CronJob is deprecated in v1.21+, unavailable in v1.25+; use batch/v1 CronJob
cronjob.batch/hello created

等一分鐘檢視
[root@master ~]# kubectl get pods
NAME                   READY   STATUS      RESTARTS   AGE
hello-27339330-kkfxv   0/1     Completed   0          2s

檢視日誌
[root@master ~]# kubectl logs hello-27339330-kkfxv
Fri Dec 24 19:00 UTC 2021
Hello world