一、簡介
控制器(Controller)是集群上管理和運行容器的對象。Pod就是通過Controller實現應用的運維,如伸縮、滾動升級等,其中Pod與Controller之間通過標簽(Label)以及標簽選擇器(Selector)建立關聯。
控制器(Controller)對象有不同的類型,比較常用的有:
- Deployment 使用它可以進行應用的部署、應用的升級回滾、彈性伸縮等。
- StatefulSet 管理有狀態應用,用來管理某 Pod集合的部署和擴縮, 並為這些 Pod 提供持久存儲和持久標識符。
- DaemonSet 確保全部(或者某些)節點上運行一個 Pod 的副本。
- Job 一次性任務
- CronJob 創建基於時隔重復調度的 Jobs
二、Deployment
(一)應用部署
Deployment常用的場景就是應用的部署、升級、回滾、伸縮等。
1、部署准備
在之前的操作中直接通過命令行的方式進行應用的部署:
[root@k8smaster ~]# kubectl create development web --image=nginx
但是這樣不利於重用,所以可以采用yaml文件的方式:
# 導出yaml文件 [root@k8smaster ~]# kubectl create deployment web --image=nginx --dry-run -o yaml > web.yam
可以看到yaml文件中的內容:
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: web name: web spec: replicas: 1 selector: matchLabels: app: web strategy: {} template: metadata: creationTimestamp: null labels: app: web spec: containers: - image: nginx name: nginx resources: {} status: {}
可以看到Deployment控制器中的selector中與Pod中的labels進行匹配,它們之間就是基於此進行關聯。
2、yaml部署
[root@k8smaster ~]# kubectl apply -f web.yaml deployment.apps/web created
目前該應用只能集群內部訪問,需要暴露端口到外部,這樣外部才能訪問。
3、應用發布(對外暴露端口)
# 導出yaml文件 [root@k8smaster ~]# kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=webOut -o yaml > webOut.yaml
apiVersion: v1 kind: Service metadata: creationTimestamp: "2021-06-18T18:11:36Z" labels: app: web managedFields: - apiVersion: v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:labels: .: {} f:app: {} f:spec: f:externalTrafficPolicy: {} f:ports: .: {} k:{"port":80,"protocol":"TCP"}: .: {} f:port: {} f:protocol: {} f:targetPort: {} f:selector: .: {} f:app: {} f:sessionAffinity: {} f:type: {} manager: kubectl operation: Update time: "2021-06-18T18:11:36Z" name: web1 namespace: default resourceVersion: "393318" selfLink: /api/v1/namespaces/default/services/web1 uid: 9cbe6be0-d147-43a4-812f-32ae6722fdf3 spec: clusterIP: 10.97.65.66 externalTrafficPolicy: Cluster ports: - nodePort: 31681 port: 80 protocol: TCP targetPort: 80 selector: app: web sessionAffinity: None type: NodePort status: loadBalancer: {}
進行部署:
[root@k8smaster ~]# kubectl apply -f web1.yaml # 查看 [root@k8smaster ~]# kubectl get pods,svc NAME READY STATUS RESTARTS AGE pod/web-5dcb957ccc-j2pg4 1/1 Running 0 15m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 61d service/web1 NodePort 10.97.65.66 <none> 80:31681/TCP 3m51s
(二)應用升級、回滾
1、應用升級
# 升級 [root@k8smaster ~]# kubectl set image deployment web nginx=nginx:1.15 deployment.apps/web image updated # 查看升級狀態 [root@k8smaster ~]# kubectl rollout status deployment web deployment "web" successfully rolled out
2、應用回滾
# 查看回滾版本 [root@k8smaster ~]# kubectl rollout history deployment web deployment.apps/web REVISION CHANGE-CAUSE 1 <none> 2 <none> # 回滾到上一個版本 [root@k8smaster ~]# kubectl rollout undo deployment web deployment.apps/web rolled back # 回滾到指定版本 [root@k8smaster ~]# kubectl rollout undo deployment web --to-revision=2
(三)彈性伸縮
# 伸縮前查看 [root@k8smaster ~]# kubectl get pods,svc NAME READY STATUS RESTARTS AGE pod/web-5dcb957ccc-66txn 1/1 Running 0 3m5s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 61d service/web1 NodePort 10.97.65.66 <none> 80:31681/TCP 40m # 進行伸縮 [root@k8smaster ~]# kubectl scale deployment web --replicas=3 deployment.apps/web scaled # 伸縮后查看 [root@k8smaster ~]# kubectl get pods,svc NAME READY STATUS RESTARTS AGE pod/web-5dcb957ccc-66txn 1/1 Running 0 3m41s pod/web-5dcb957ccc-jx4kl 0/1 ContainerCreating 0 2s pod/web-5dcb957ccc-zvmcm 0/1 ContainerCreating 0 2s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 61d service/web1 NodePort 10.97.65.66 <none> 80:31681/TCP 41m
三、StatefulSet
StatefulSet 用來管理某 Pod 集合的部署和擴縮, 並為這些 Pod 提供持久存儲和持久標識符。所以相對於Deployment而言它是有狀態的,需要考慮下面的情況:
- 保持每個Pod獨立、啟動順序、唯一性
- 唯一的網絡標識、持久存儲
創建StatefulSet:
apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx-statefulset namespace: default spec: serviceName: nginx replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
它創建了一個 Headless Service nginx用來發布 StatefulSet web中的 Pod 的 IP 地址,表現形式就是clusterIP為None。執行上面的yaml文件:
[root@k8smaster ~]# kubectl apply -f statefulset.yaml service/nginx created
上面創建兩個Pod的副本,但是它是按照{0,N-1}的順序來創建Pod的,也就是Pod是有順序的。
其次查看創建的兩個Pod:
[root@k8smaster ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-statefulset-0 1/1 Running 0 15m nginx-statefulset-1 1/1 Running 0 14m
每個都是有唯一的名稱,最后看一下網絡標識,每個 Pod 都擁有一個基於其順序索引的穩定的主機名。使用kubectl exec在每個 Pod 中執行hostname。
[root@k8smaster ~]# for i in 0 1; do kubectl exec "nginx-statefulset-$i" -- sh -c 'hostname'; done nginx-statefulset-0 nginx-statefulset-1
四、DaemonSet
DaemonSet 確保全部(或者某些)節點上運行一個 Pod 的副本。 當有節點加入集群時, 也會為他們新增一個 Pod 。 當有節點從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod
DaemonSet 的一些應用場景:
- 在每個節點上運行集群守護進程
- 在每個節點上運行日志收集守護進程
- 在每個節點上運行監控守護進程
創建 一個日志收集工具的DaemonSet:
apiVersion: apps/v1 kind: DaemonSet metadata: name: ds-test labels: app: filebeat spec: selector: matchLabels: app: filebeat template: metadata: labels: app: filebeat spec: containers: - name: logs image: nginx ports: - containerPort: 80 volumeMounts: - name: varlog mountPath: /tmp/log volumes: - name: varlog hostPath: path: /var/log
執行該yaml文件:
[root@k8smaster ~]# kubectl apply -f ds.yaml daemonset.apps/ds-test created
可以看到在各個node節點上已經部署了Pod:
[root@k8smaster ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES ds-test-6qdwg 1/1 Running 0 84s 10.244.1.23 k8snode1 <none> <none> ds-test-m79px 1/1 Running 0 84s 10.244.2.20 k8snode2 <none> <none>
進入到某個Pod中進行查看:
[root@k8smaster ~]# kubectl exec -it ds-test-6qdwg bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead. root@ds-test-6qdwg:/# ls /tmp/log/ anaconda btmp-20210617 dmesg maillog pods secure-20210617 tuned audit containers dmesg.old maillog-20210617 ppp spooler vmware-vmsvc.log boot.log cron firewalld messages rhsm spooler-20210617 wtmp btmp cron-20210617 lastlog messages-20210617 secure tallylog yum.log
五、Job
Job 會創建一個或者多個 Pods,並將繼續重試 Pods 的執行,直到指定數量的 Pods 成功終止。 隨着 Pods 成功結束,Job 跟蹤記錄成功完成的 Pods 個數。 當數量達到指定的成功個數閾值時,任務(即 Job)結束。 刪除 Job 的操作會清除所創建的全部 Pods。 掛起 Job 的操作會刪除 Job 的所有活躍 Pod,直到 Job 被再次恢復執行。
下面是一個 Job 配置示例。它負責計算 π 到小數點后 2000 位,並將結果打印出來。
apiVersion: batch/v1 kind: Job metadata: name: pi spec: template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never backoffLimit: 4
執行:
[root@k8smaster ~]# kubectl apply -f job.yaml job.batch/pi created
查看Pod狀態:
# 因為是一次性任務,所以執行后即結束 [root@k8smaster ~]# kubectl get pods NAME READY STATUS RESTARTS AGE pi-vbmwk 0/1 Completed 0 4m26s
查看結果:
[root@k8smaster ~]# kubectl logs pi-vbmwk 3.14159265358979323846264338327950...
六、CronJob
CronJobs 對於創建周期性的、反復重復的任務很有用,例如執行數據備份或者發送郵件。 CronJobs 也可以用來計划在指定時間來執行的獨立任務,例如計划當集群看起來很空閑時 執行某個 Job。如下實例:
apiVersion: batch/v1beta1 kind: CronJob metadata: name: hello spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: hello image: busybox args: - /bin/sh - -c - date; echo Hello from the Kubernetes cluster restartPolicy: OnFailure
執行:
[root@k8smaster ~]# kubectl apply -f cronjob.yaml cronjob.batch/hello created
可以看到周期性的調用:
[root@k8smaster ~]# kubectl get pods NAME READY STATUS RESTARTS AGE hello-1624090140-w8xcn 0/1 Completed 0 2m57s hello-1624090200-m2lng 0/1 ContainerCreating 0 2m21s hello-1624090260-bwhjj 0/1 ContainerCreating 0 80s hello-1624090320-bcd7b 0/1 ContainerCreating 0 20s
查看某個Pod里面的內容:
[root@k8smaster ~]# kubectl logs hello-1624090140-w8xcn Sat Jun 19 08:11:44 UTC 2021 Hello from the Kubernetes cluster
