
目录
在Kubernetes中,Pod是最小的管理单元,是一组紧密关联的容器组合。
但是,单独的Pod并不能保障总是可用,比如我们创建一个nginx的Pod,因为某些原因,该Pod被意外删除,我们希望其能够自动新建一个同属性的Pod。很遗憾,单纯的Pod并不能满足需求。
为此,Kubernetes实现了一系列控制器来管理Pod,使Pod的期望状态和实际状态保持一致
工作负载控制器(Workload Controllers)是K8s的一个抽象概念,用于更高级层次对象,部署和管理Pod。常用工作负载控制器:
• Deployment :无状态应用部署
• StatefulSet :有状态应用部署
• DaemonSet :确保所有Node运行同一个Pod
• Job :一次性任务
• Cronjob :定时任务
控制器的作用:
• 管理Pod对象
• 使用标签与Pod关联
• 控制器实现了Pod的运维,例如滚动更新、伸缩、副本管理、维护Pod状态等。
Deployment的功能:
• 管理Pod和ReplicaSet
• 具有上线部署、副本设定、滚动升级、回滚等功能
• 提供声明式更新,例如只更新一个新的Image 应用场景:网站、API、微服务

deployment部署一个应用,副本数为3
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: web
- namespace: default
- spec:
- replicas: 3 # 副本数量
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx # Pod副本的标签
- spec:
- containers:
- - name: web
- image: nginx:1.15
pod 副本为3 , 成功调度到 node1和node2两个节点上

服务暴露出来,查询对用的服务端口
kubectl expose deployment web --port=80 --target-port=80 --type=NodePort

三个节点的任意 IP加上 31812端口 都可以访问

业务应用基本都是通过Deployment的方式部署在Kubernetes中的,应用的更新和回滚是常态的工作,特别是在互联网企业,快速迭代抓住用户的一个重要途径。
但是,并不是每一次的迭代都是100%正常的,如果异常,如何快速恢复也是要考虑的事情。为适应这种场景,Deployment提供滚动更新和快速回滚的能力。
Deployment默认的更新方式就是滚动更新,可以通过strategy.type来指定更新方式。
- ## 部署应用
- kubectl apply -f deployment.yaml
-
- ## 暴露应用服务的端口
- kubectl expose deployment web --port=80 --target-port=80 --type=NodePort
• kubectl apply -f xxx.yaml
• kubectl set image deployment/web nginx=nginx:1.16
• kubectl edit deployment/web

滚动升级:K8s对Pod升级的默认策略,通过使用新版本Pod逐步更新旧版本Pod,实现零停机发布,用户无感知。
查看三个pod 服务 对应的 IP和端口
- [root@k8s-master1 ~]# kubectl get ep
- NAME ENDPOINTS AGE
- kubernetes 192.168.2.117:6443,192.168.2.119:6443 7d2h
- pod-check
6h - web 10.244.159.134:80,10.244.224.10:80,10.244.36.74:80 32m
nginx:1.15 镜像升级到 nginx:1.16
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: web
- namespace: default
- spec:
- replicas: 3
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - name: web
- image: nginx:1.16
replicas 一个一个升级创建一个新的删除旧的,具体的策略可以,自行配置


导出 web deployment, 查看完整的 Deployment 配置
- kubectl get deployment web -o yaml > deploy.yaml
-
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- annotations:
- deployment.kubernetes.io/revision: "7"
- kubectl.kubernetes.io/last-applied-configuration: |
- {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"kubernetes.io/change-cause":"web.v1-nginx-1.17"},"name":"web","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.17","name":"web"}]}}}}
- kubernetes.io/change-cause: web.v1-nginx-1.17
- creationTimestamp: "2022-11-12T09:11:15Z"
- generation: 8
- managedFields:
- - apiVersion: apps/v1
- fieldsType: FieldsV1
- fieldsV1:
- f:metadata:
- f:annotations:
- .: {}
- f:kubectl.kubernetes.io/last-applied-configuration: {}
- f:spec:
- f:progressDeadlineSeconds: {}
- f:replicas: {}
- f:revisionHistoryLimit: {}
- f:selector:
- f:matchLabels:
- .: {}
- f:app: {}
- f:strategy:
- f:rollingUpdate:
- .: {}
- f:maxSurge: {}
- f:maxUnavailable: {}
- f:type: {}
- f:template:
- f:metadata:
- f:labels:
- .: {}
- f:app: {}
- f:spec:
- f:containers:
- k:{"name":"web"}:
- .: {}
- f:imagePullPolicy: {}
- f:name: {}
- f:resources: {}
- f:terminationMessagePath: {}
- f:terminationMessagePolicy: {}
- f:dnsPolicy: {}
- f:restartPolicy: {}
- f:schedulerName: {}
- f:securityContext: {}
- f:terminationGracePeriodSeconds: {}
- manager: kubectl-client-side-apply
- operation: Update
- time: "2022-11-12T10:33:02Z"
- - apiVersion: apps/v1
- fieldsType: FieldsV1
- fieldsV1:
- f:metadata:
- f:annotations:
- f:kubernetes.io/change-cause: {}
- f:spec:
- f:template:
- f:spec:
- f:containers:
- k:{"name":"web"}:
- f:image: {}
- manager: kubectl
- operation: Update
- time: "2022-11-12T10:33:12Z"
- - apiVersion: apps/v1
- fieldsType: FieldsV1
- fieldsV1:
- f:metadata:
- f:annotations:
- f:deployment.kubernetes.io/revision: {}
- f:status:
- f:availableReplicas: {}
- f:conditions:
- .: {}
- k:{"type":"Available"}:
- .: {}
- f:lastTransitionTime: {}
- f:lastUpdateTime: {}
- f:message: {}
- f:reason: {}
- f:status: {}
- f:type: {}
- k:{"type":"Progressing"}:
- .: {}
- f:lastTransitionTime: {}
- f:lastUpdateTime: {}
- f:message: {}
- f:reason: {}
- f:status: {}
- f:type: {}
- f:observedGeneration: {}
- f:readyReplicas: {}
- f:replicas: {}
- f:updatedReplicas: {}
- manager: kube-controller-manager
- operation: Update
- time: "2022-11-12T10:33:21Z"
- name: web
- namespace: default
- resourceVersion: "1262530"
- selfLink: /apis/apps/v1/namespaces/default/deployments/web
- uid: 7b334d04-b47e-4023-bb3f-8043fd1474e2
- spec:
- progressDeadlineSeconds: 600
- replicas: 3
- revisionHistoryLimit: 10
- selector:
- matchLabels:
- app: nginx
- strategy:
- rollingUpdate:
- maxSurge: 25% ###
- maxUnavailable: 25% ###
- type: RollingUpdate ###
- template:
- metadata:
- creationTimestamp: null
- labels:
- app: nginx
- spec:
- containers:
- - image: nginx:1.17
- imagePullPolicy: IfNotPresent
- name: web
- resources: {}
- terminationMessagePath: /dev/termination-log
- terminationMessagePolicy: File
- dnsPolicy: ClusterFirst
- restartPolicy: Always
- schedulerName: default-scheduler
- securityContext: {}
- terminationGracePeriodSeconds: 30
- status:
- availableReplicas: 3 ###
- conditions:
- - lastTransitionTime: "2022-11-12T09:23:15Z"
- lastUpdateTime: "2022-11-12T09:23:15Z"
- message: Deployment has minimum availability.
- reason: MinimumReplicasAvailable
- status: "True"
- type: Available
- - lastTransitionTime: "2022-11-12T09:11:15Z"
- lastUpdateTime: "2022-11-12T10:33:21Z"
- message: ReplicaSet "web-76f5f6d7f5" has successfully progressed.
- reason: NewReplicaSetAvailable
- status: "True"
- type: Progressing
- observedGeneration: 8
- readyReplicas: 3
- replicas: 3
- updatedReplicas: 3
当然,这时候应在Pod中加上health check检查应用的健康状态,而不是简单的依赖容器的running状态。配置相应的健康检查可以确保服务的可靠性和延续性。
发布失败恢复正常版本
- # 查看历史发布版本
- kubectl rollout history deployment/web
- # 回滚上一个版本
- kubectl rollout undo deployment/web
- # 回滚历史指定版本
- kubectl rollout undo deployment/web --to-revision=2
ngnix 版本可自由改动 ,尝试 升级和回滚
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: web
- namespace: default
- annotations: # 记录回滚参数
- kubernetes.io/change-cause: "web.v1-nginx-1.17" #记录到revision中的内容,记录版本号
- spec:
- replicas: 3
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - name: web
- image: nginx:1.17
注:回滚是重新部署某一次部署时的状态,即当时版本所有配置
查看正在运行的服务版本,镜像是 nginx: 1.17

回滚到上个版本,镜像是 nginx: 1.16

ReplicaSet控制器用途:
• Pod副本数量管理,不断对比当前Pod数量与期望Pod数量
• Deployment每次发布都会创建一个RS作为记录,用于实现回滚
- # 查看RS记录
- kubectl get rs
- # 版本对应RS记录
- kubectl rollout history deployment web
-
- # 命令直接修改副本个数,或者 修改yaml重新应用下
- kubectl scale deployment web --replicas 5 deployment.apps/web scaled
-
- ## 也可以直接修改 ep 文件
- kubectl edit ep web -o yaml
新增两个 pod

DaemonSet保证在每个Node上都运行一个Pod,如果新增一个Node,这个Pod也会运行在新增的Node上,如果删除这个DadmonSet,就会清除它所创建的Pod。常用来部署一些集群日志收集,监控等全局应用。
DaemonSet也是支持更新和回滚的,具体操作和Deployment类似。
常见的场景如下:
1、运行存储集群daemon,比如ceph,glusterd等;
2、运行一个日志收集daemon,比如logstash,fluentd等;
3、运行监控daemon,比如Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond等;

部署一个日志采集程序,因为使用 kubeadm 安装 所以 master 节点打了污点,下面filebeat 配置污点容忍,使其在 master 节点 也可以调度成功。
- apiVersion: apps/v1
- kind: DaemonSet
- metadata:
- name: filebeat
- namespace: kube-system
- spec:
- selector:
- matchLabels:
- name: filebeat
- template:
- metadata:
- labels:
- name: filebeat
- spec:
- tolerations:
- - effect: NoSchedule
- operator: Exists
- containers:
- - name: log
- image: elastic/filebeat:7.3.2
三个 节点成功部署 filebeat

计算圆周率
- 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
应用场景:离线数据处理,视频解码等业务
- 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 kangll
- restartPolicy: OnFailure

需要注意的是,由于cron的特殊性,有时候会存在由于上一个定时任务还没有执行完成,新的定时任务又开始了的情况,我们可以通过定义spec.concurrencyPolicy字段来定义规则,比如:
上面介绍的是日常工作中常用的控制器,其中Deployment和DaemonSet的使用频率最高,熟练掌握这些控制器,并且学会在什么时候选择什么样的控制器,合理使用使工作效率最高。