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