kubernetes/Kubernetes-Pod控制器详解.md
2025-05-17 14:25:24 +08:00

1178 lines
49 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h2><center>Kubernetes Pod控制器详解</center></h2>
------
## 一Pod 控制器详解
Pod是Kubernetes的最小管理单元在kubernetes中按照Pod的创建方式可以将其分为两类
- 自主式podKubernetes直接创建出来的Pod这种Pod删除后就没有了也不会重建
- 控制器创建的Podkubernetes通过控制器创建的pod这种pod删除了之后还会自动重建
**什么是Pod控制器**
Pod控制器是管理pod的中间层使用Pod控制器之后只需要告诉Pod控制器想要多少个什么样的Pod都可以了它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障它会基于指定策略重新编排Pod。
在Kubernetes中有很多类型的pod控制器每种都有自己的适合的场景常见的有下面这些
- ReplicationController比较原始的pod控制器已经被废弃有ReplicaSet替代
- ReplicaSet保证副本数量一直维持在期望值并支持pod数量扩缩容镜像版本升级
- Deployment通过控制ReplicaSet来控制Pod并支持滚动升级、回退版本
- Horizontal Pod Autoscaler可以根据集群负载自动水平调整Pod的数量实现削峰填谷
- DaemonSet在集群中的指定Node上运行且进运行一个副本一般用于守护进程类的任务
- Job它创建出来的pod只要完成任务就立即退出不需要重启或重建用于执行一次性任务
- Cronjob它创建的Pod负责周期性任务控制不需要持续后台运行
- StatefulSet管理由状态应用
## 二ReplicaSetRS
ReplicaSet的主要作用是保证一定数量的pod正常运行它会持续监听这些pod的运行状态一旦Pod发生故障就会重启或重建。同时它还支持对pod数量的扩缩容和镜像版本的升降级。
![](accents\images-202505070013.png)
ReplicaSet的资源清单文件
```yaml
apiVersion: apps/v1 # 版本号
kind: ReplicaSet # 类型
metadata: # 元数据
name: # rs 名称
namespace: # 所属命名空间
labels: # 标签
controller: rs
spec: # 详细描述
replicas: 3 # 副本数量
selector: # 选择器通过它指定该控制器管理哪些pod
matchLabels: # Labels 匹配规则
app: nginx-pod
matchExpressions: # Expressions 匹配规则
- {key: app, operator: In, values: [nginx-pod]}
template: # 模板当副本数量不足时会根据下面的模板创建pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
```
在这里面需要新了解的配置项就是spec下面几个选项
- replicas指定副本数量其实就是当前的rs创建出来的pod数量默认为1
- selector选择器它的作用是建立pod控制器和pod之间的关联关系采用的Label Selector机制在pod模板上定义label在控制器上定义选择器就可以表名当前的控制器能管理哪些pod了
- template模板就是当前控制器创建pod所使用的模板里面其实就是pod的定义
**创建ReplicaSet**
创建pc-replicaset.yaml文件内容如下
```yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: pc-replicaset
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
```
```bash
# 创建rs
[root@master ~]# kubectl create -f pc-replicaset.yaml
replicaset.apps/pc-replicaset created
# 查看rs
# DESIRED:期望副本数量
# CURRENT:当前副本数量
# READY:已经准备好提供服务的副本数量
[root@master ~]# kubectl get rs pc-replicaset -n dev -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
pc-replicaset 3 3 3 34s nginx nginx:1.17.1 app=nginx-pod
# 查看当前控制器创建出来的pod
# 这里发现控制器创建出来的pod的名称是在控制器名称后面拼接了-xxxxx随机码
[root@master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pc-replicaset-76w7p 1/1 Running 0 55s
pc-replicaset-l4nn9 1/1 Running 0 55s
pc-replicaset-mjmzr 1/1 Running 0 55s
```
**扩缩容**
```bash
# 编辑rs的副本数量修改spec:replicas: 6即可
[root@master ~]# kubectl edit rs pc-replicaset -n dev
replicaset.apps/pc-replicaset edited
# 查看pod
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-replicaset-76w7p 1/1 Running 0 3m43s
pc-replicaset-9l42n 1/1 Running 0 59s
pc-replicaset-l4nn9 1/1 Running 0 3m43s
pc-replicaset-mjmzr 1/1 Running 0 3m43s
pc-replicaset-ncf8x 1/1 Running 0 59s
pc-replicaset-pv6q2 1/1 Running 0 59s
# 当然也可以直接使用命令实现
# 使用scale命令实现扩缩容 后面--replicas=n直接指定目标数量即可
[root@master ~]# kubectl scale rs pc-replicaset --replicas=2 -n dev
replicaset.apps/pc-replicaset scaled
# 命令运行完毕立即查看发现已经有4个开始准备退出了
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-replicaset-76w7p 1/1 Running 0 3m43s
pc-replicaset-9l42n 0/1 Running 0 59s
pc-replicaset-l4nn9 1/1 Running 0 3m43s
pc-replicaset-mjmzr 0/1 Running 0 3m43s
pc-replicaset-ncf8x 0/1 Running 0 59s
pc-replicaset-pv6q2 0/1 Running 0 59s
#稍等片刻就只剩下2个了
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-replicaset-76w7p 1/1 Running 0 4m42s
pc-replicaset-l4nn9 1/1 Running 0 4m42s
```
**镜像升级**
```bash
# 编辑rs的容器镜像 - image: nginx:1.17.2
[root@master ~]# kubectl edit rs pc-replicaset -n dev
replicaset.apps/pc-replicaset edited
# 再次查看,发现镜像版本已经变更了
[root@master ~]# kubectl get rs -n dev -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
pc-replicaset 2 2 2 7m24s nginx nginx:1.17.2 app=nginx-pod
# 同样的道理,也可以使用命令完成这个工作
# kubectl set image rs rs名称 容器=镜像版本 -n namespace
[root@master ~]# kubectl set image rs pc-replicaset nginx=nginx:1.17.1 -n dev
replicaset.apps/pc-replicaset image updated
# 再次查看,发现镜像版本已经变更了
[root@master ~]# kubectl get rs -n dev -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
pc-replicaset 2 2 2 8m19s nginx nginx:1.17.1 app=nginx-pod
```
**删除ReplicaSet**
```bash
# 使用kubectl delete命令会删除此RS以及它管理的Pod
# 在kubernetes删除RS前会将RS的replicasclear调整为0等待所有的Pod被删除后在执行RS对象的删除
[root@master ~]# kubectl delete rs pc-replicaset -n dev
replicaset.apps "pc-replicaset" deleted
[root@master ~]# kubectl get pod -n dev -o wide
No resources found in dev namespace.
# 如果希望仅仅删除RS对象保留Pod可以使用kubectl delete命令时添加--cascade=false选项不推荐
[root@master ~]# kubectl delete rs pc-replicaset -n dev --cascade=false
warning: --cascade=false is deprecated (boolean value) and can be replaced with --cascade=orphan.
replicaset.apps "pc-replicaset" deleted
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-replicaset-fcr9f 1/1 Running 0 49s
pc-replicaset-vs6sk 1/1 Running 0 49s
# 也可以使用yaml直接删除(推荐)
[root@master ~]# kubectl delete -f pc-replicaset.yaml
replicaset.apps "pc-replicaset" deleted
```
## 三DeploymentDeploy
为了更好的解决服务编排的问题kubernetes在v1.2版本开始引入了Deployment控制器。值得一提的是这种控制器并不直接管理pod而是通过管理ReplicaSet来间接管理PodDeployment管理ReplicaSetReplicaSet管理Pod。所以Deployment比ReplicaSet功能更加强大。
![](accents\images-202505070014.png)
Deployment主要功能有下面几个
- 支持ReplicaSet的所有功能
- 支持发布的停止、继续
- 支持滚动升级和回滚版本
Deployment的资源清单文件
```yaml
apiVersion: apps/v1 # 版本号
kind: Deployment # 类型
metadata: # 元数据
name: # rs 名称
namespace: # 所属命名空间
labels: # 标签
controller: deploy
spec: # 详情描述
replicas: 3 # 副本数量
revisionHistoryLimit: 3 # 保留历史版本
paused: false # 暂停部署默认是false
progressDeadlineSeconds: 600 # 部署超时时间s默认是600
strategy: # 策略
type: RollingUpdate # 滚动更新策略
rollingUpdate: # 滚动更新
max违规词汇: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
selector: # 选择器通过它指定该控制器管理哪些pod
matchLabels: # Labels匹配规则
app: nginx-pod
matchExpressions: # Expressions匹配规则
- {key: app, operator: In, values: [nginx-pod]}
template: # 模板当副本数量不足时会根据下面的模板创建pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
```
### 1. 创建deployment
创建pc-deployment.yaml内容如下
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pc-deployment
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
```
```bash
# 创建deployment
[root@master ~]# kubectl create -f pc-deployment.yaml --record=true
deployment.apps/pc-deployment created
# 查看deployment
# UP-TO-DATE 最新版本的pod的数量
# AVAILABLE 当前可用的pod的数量
[root@master ~]# kubectl get deploy pc-deployment -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
pc-deployment 3/3 3 3 6m28s
# 查看rs
# 发现rs的名称是在原来deployment的名字后面添加了一个10位数的随机串
[root@master ~]# kubectl get rs -n dev
NAME DESIRED CURRENT READY AGE
pc-deployment-6f7f65b46d 3 3 3 20m
# 查看pod
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-deployment-6f7f65b46d-dgdjn 1/1 Running 0 20m
pc-deployment-6f7f65b46d-pd99k 1/1 Running 0 20m
pc-deployment-6f7f65b46d-wxmrc 1/1 Running 0 20m
```
### 2. 扩缩容
```bash
# 变更副本数量为5个
[root@master ~]# kubectl scale deploy pc-deployment --replicas=5 -n dev
deployment.apps/pc-deployment scaled
# 查看deployment
[root@master ~]# kubectl get deploy pc-deployment -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
pc-deployment 5/5 5 5 22m
# 查看pod
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-deployment-6f7f65b46d-2qpqc 1/1 Running 0 28s
pc-deployment-6f7f65b46d-dgdjn 1/1 Running 0 22m
pc-deployment-6f7f65b46d-pd99k 1/1 Running 0 22m
pc-deployment-6f7f65b46d-sbtlc 1/1 Running 0 28s
pc-deployment-6f7f65b46d-wxmrc 1/1 Running 0 22m
# 编辑deployment的副本数量修改spec:replicas: 4即可
[root@master ~]# kubectl edit deploy pc-deployment -n dev
deployment.apps/pc-deployment edited
# 查看pod
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-deployment-6f7f65b46d-fvnd7 1/1 Running 0 56s
pc-deployment-6f7f65b46d-s2jjn 1/1 Running 0 56s
pc-deployment-6f7f65b46d-wbfq4 1/1 Running 0 56s
```
**镜像更新**
deployment支持两种更新策略重建更新和滚动更新可以通过strategy制定策略类型支持两种属性
```
strategy指定新的Pod替换旧的Pod的策略 支持两个属性:
type指定策略类型支持两种策略
Recreate在创建出新的Pod之前会先杀掉所有已存在的Pod
RollingUpdate滚动更新就是杀死一部分就启动一部分在更新过程中存在两个版本Pod
rollingUpdate当type为RollingUpdate时生效用于为RollingUpdate设置参数支持两个属性
maxUnavailable用来指定在升级过程中不可用Pod的最大数量默认为25%。
max违规词汇 用来指定在升级过程中可以超过期望的Pod的最大数量默认为25%。
```
重建更新
1. 编辑pc-deployment.yaml在spec节点下添加更新策略
```yaml
spec:
strategy: # 策略
type: Recreate # 重建更新
```
2. 创建deploy进行验证
```bash
[root@master ~]# kubectl set image deployment pc-deployment nginx=nginx:1.17.2 -n dev
deployment.apps/pc-deployment image updated
[root@master ~]# kubectl get pods -n dev -w
pc-deployment-6f7f65b46d-fvnd7 1/1 Running 0 2m43s
pc-deployment-6f7f65b46d-s2jjn 1/1 Running 0 2m43s
pc-deployment-6f7f65b46d-wbfq4 1/1 Running 0 2m43s
pc-deployment-86f4996797-6fg4b 0/1 ContainerCreating 0 14s
pc-deployment-86f4996797-6fg4b 1/1 Running 0 34s
pc-deployment-6f7f65b46d-fvnd7 1/1 Terminating 0 3m3s
pc-deployment-86f4996797-fmhs6 0/1 Pending 0 0s
pc-deployment-86f4996797-fmhs6 0/1 Pending 0 0s
pc-deployment-86f4996797-fmhs6 0/1 ContainerCreating 0 0s
pc-deployment-6f7f65b46d-fvnd7 0/1 Terminating 0 3m3s
pc-deployment-6f7f65b46d-fvnd7 0/1 Terminating 0 3m3s
pc-deployment-6f7f65b46d-fvnd7 0/1 Terminating 0 3m3s
pc-deployment-86f4996797-fmhs6 1/1 Running 0 35s
pc-deployment-6f7f65b46d-s2jjn 1/1 Terminating 0 3m38s
pc-deployment-86f4996797-cl76r 0/1 Pending 0 0s
pc-deployment-86f4996797-cl76r 0/1 Pending 0 0s
pc-deployment-86f4996797-cl76r 0/1 ContainerCreating 0 0s
pc-deployment-6f7f65b46d-s2jjn 0/1 Terminating 0 3m39s
pc-deployment-6f7f65b46d-s2jjn 0/1 Terminating 0 3m39s
pc-deployment-6f7f65b46d-s2jjn 0/1 Terminating 0 3m39s
pc-deployment-86f4996797-cl76r 1/1 Running 0 1s
pc-deployment-6f7f65b46d-wbfq4 1/1 Terminating 0 3m39s
pc-deployment-6f7f65b46d-wbfq4 0/1 Terminating 0 3m40s
pc-deployment-6f7f65b46d-wbfq4 0/1 Terminating 0 3m40s
pc-deployment-6f7f65b46d-wbfq4 0/1 Terminating 0 3m40s
pc-deployment-86f4996797-6fg4b 1/1 Running 0 3m43s
pc-deployment-86f4996797-cl76r 1/1 Running 0 2m34s
pc-deployment-86f4996797-fmhs6 1/1 Running 0 3m9s
```
滚动更新
1. 编辑pc-deployment.yaml在spec节点下添加更新策略
```yaml
spec:
strategy:
type: RollingUpdate
rollingUpdate:
max违规词汇: 25%
maxUnavailable: 25%
```
2. 创建deploy进行验证
```bash
# 变更镜像
[root@master ~]# kubectl set image deployment pc-deployment nginx=nginx:1.17.3 -n dev
deployment.apps/pc-deployment image updated
# 观察升级过程
[root@master ~]# kubectl get pods -n dev -w
[root@master ~]# kubectl get pods -n dev -w
NAME READY STATUS RESTARTS AGE
pc-deployment-79f7d88458-grjvx 0/1 ContainerCreating 0 25s
pc-deployment-86f4996797-6fg4b 1/1 Running 0 6m45s
pc-deployment-86f4996797-cl76r 1/1 Running 0 5m36s
pc-deployment-86f4996797-fmhs6 1/1 Running 0 6m11s
pc-deployment-79f7d88458-grjvx 1/1 Running 0 32s
pc-deployment-86f4996797-6fg4b 1/1 Terminating 0 6m52s
pc-deployment-79f7d88458-xn4lc 0/1 Pending 0 0s
pc-deployment-79f7d88458-xn4lc 0/1 Pending 0 0s
pc-deployment-79f7d88458-xn4lc 0/1 ContainerCreating 0 0s
pc-deployment-86f4996797-6fg4b 0/1 Terminating 0 6m53s
pc-deployment-86f4996797-6fg4b 0/1 Terminating 0 6m53s
pc-deployment-86f4996797-6fg4b 0/1 Terminating 0 6m53s
pc-deployment-79f7d88458-xn4lc 1/1 Running 0 30s
pc-deployment-86f4996797-cl76r 1/1 Terminating 0 6m14s
pc-deployment-79f7d88458-qhbcs 0/1 Pending 0 0s
pc-deployment-79f7d88458-qhbcs 0/1 Pending 0 0s
pc-deployment-79f7d88458-qhbcs 0/1 ContainerCreating 0 0s
pc-deployment-79f7d88458-qhbcs 1/1 Running 0 0s
pc-deployment-86f4996797-fmhs6 1/1 Terminating 0 6m49s
pc-deployment-86f4996797-cl76r 0/1 Terminating 0 6m14s
pc-deployment-86f4996797-cl76r 0/1 Terminating 0 6m14s
pc-deployment-86f4996797-cl76r 0/1 Terminating 0 6m14s
pc-deployment-86f4996797-fmhs6 0/1 Terminating 0 6m50s
pc-deployment-86f4996797-fmhs6 0/1 Terminating 0 6m50s
pc-deployment-86f4996797-fmhs6 0/1 Terminating 0 6m50s
pc-deployment-79f7d88458-grjvx 1/1 Running 0 108s
pc-deployment-79f7d88458-qhbcs 1/1 Running 0 45s
pc-deployment-79f7d88458-xn4lc 1/1 Running 0 76s
# 至此新版本的pod创建完毕旧版本的pod销毁完毕
# 中间过程是滚动进行的,也就是边销毁边创建
```
滚动更新的过程
![](accents\images-202505070015.png)
镜像更新中rs的变化
```bash
# 查看rs,发现原来的rs的依旧存在只是pod数量变为了0而后又新产生了一个rspod数量为3
# 其实这就是deployment能够进行版本回退的奥妙所在后面会详细解释
[root@master ~]# kubectl get rs -n dev
NAME DESIRED CURRENT READY AGE
pc-deployment-6f7f65b46d 0 0 0 11m
pc-deployment-79f7d88458 3 3 3 3m2s
pc-deployment-86f4996797 0 0 0 9m22s
```
### 3. 版本回退
deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能下面具体来看
kubectl rollout版本升级相关功能支持下面的选项
- status显示当前升级状态
- history显示升级历史记录
- pause暂停版本升级过程
- resume继续已经暂停的版本升级过程
- restart重启版本升级过程
- undo回滚到上一级版本可以使用-to-revision回滚到指定版本
```bash
# 查看当前升级版本的状态
[root@master ~]# kubectl rollout status deploy pc-deployment -n dev
deployment "pc-deployment" successfully rolled out
# 查看升级历史记录
[root@master ~]# kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment
REVISION CHANGE-CAUSE
1 kubectl create --filename=pc-deployment.yaml --record=true
2 kubectl create --filename=pc-deployment.yaml --record=true
3 kubectl create --filename=pc-deployment.yaml --record=true
# 可以发现有三次版本记录,说明完成过两次升级
# 版本回滚
# 这里直接使用--to-revision=1回滚到了1版本 如果省略这个选项就是回退到上个版本就是2版本
[root@master ~]# kubectl rollout undo deployment pc-deployment --to-revision=1 -n dev
deployment.apps/pc-deployment rolled back
# 查看发现通过nginx镜像版本可以发现到了第一版
[root@master ~]# kubectl get deploy -n dev -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
pc-deployment 3/3 3 3 15m nginx nginx:1.17.1 app=nginx-pod
# 查看rs发现第一个rs中有3个pod运行后面两个版本的rs中pod为运行
# 其实deployment之所以可是实现版本的回滚就是通过记录下历史rs来实现的
# 一旦想回滚到哪个版本只需要将当前版本pod数量降为0然后将回滚版本的pod提升为目标数量就可以了
[root@master ~]# kubectl get rs -n dev
NAME DESIRED CURRENT READY AGE
pc-deployment-6f7f65b46d 3 3 3 15m
pc-deployment-79f7d88458 0 0 0 6m39s
pc-deployment-86f4996797 0 0 0 12m
```
### 4. 金丝雀发布
Deployment控制器支持控制更新过程中的控制如“暂停pause”或“继续resume”更新操作。
比如有一批新的Pod资源创建完成后立即暂停更新过程此时仅存在一部分新版本的应用主体部分还是旧的版本。然后在筛选一小部分的用户请求路由到新版本的Pod应用继续观察能否稳定的按照期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新否则立即回滚更新操作。这就是所谓的金丝雀发布。
```bash
# 更新deployment的版本并配置暂停deployment
[root@master ~]# kubectl set image deploy pc-deployment nginx=nginx:1.17.4 -n dev && kubectl rollout pause deployment pc-deployment -n dev
deployment.apps/pc-deployment image updated
deployment.apps/pc-deployment paused
# 观察更新状态
[root@master ~]# kubectl rollout status deploy pc-deployment -n dev
Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
# 监控更新的过程可以看到已经新增了一个资源但是并未按照预期的状态去删除一个旧的资源就是因为使用了pause暂停命令
[root@master ~]# kubectl get rs -n dev -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
pc-deployment-6f7f65b46d 3 3 3 18m nginx nginx:1.17.1 app=nginx-pod,pod-template-hash=6f7f65b46d
pc-deployment-79f7d88458 0 0 0 10m nginx nginx:1.17.3 app=nginx-pod,pod-template-hash=79f7d88458
pc-deployment-86f4996797 0 0 0 16m nginx nginx:1.17.2 app=nginx-pod,pod-template-hash=86f4996797
pc-deployment-cf7c57879 1 1 1 2m nginx nginx:1.17.4 app=nginx-pod,pod-template-hash=cf7c57879
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-deployment-6f7f65b46d-crrpw 1/1 Running 0 4m23s
pc-deployment-6f7f65b46d-m97cs 1/1 Running 0 4m24s
pc-deployment-6f7f65b46d-tk926 1/1 Running 0 4m25s
pc-deployment-cf7c57879-zvksb 1/1 Running 0 2m25s
# 确保更新的pod没问题了继续更新
[root@master ~]# kubectl rollout resume deploy pc-deployment -n dev
deployment.apps/pc-deployment resumed
# 查看最后的更新情况
[root@master ~]# kubectl get rs -n dev -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
pc-deployment-6f7f65b46d 0 0 0 20m nginx nginx:1.17.1 app=nginx-pod,pod-template-hash=6f7f65b46d
pc-deployment-79f7d88458 0 0 0 11m nginx nginx:1.17.3 app=nginx-pod,pod-template-hash=79f7d88458
pc-deployment-86f4996797 0 0 0 17m nginx nginx:1.17.2 app=nginx-pod,pod-template-hash=86f4996797
pc-deployment-cf7c57879 3 3 3 3m22s nginx nginx:1.17.4 app=nginx-pod,pod-template-hash=cf7c57879
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-deployment-cf7c57879-blbmd 1/1 Running 0 2m5s
pc-deployment-cf7c57879-th25q 1/1 Running 0 92s
pc-deployment-cf7c57879-zvksb 1/1 Running 0 4m50s
```
删除Deployment
```bash
# 删除deployment其下的rs和pod也将被删除
[root@master ~]# kubectl delete -f pc-deployment.yaml
deployment.apps "pc-deployment" deleted
```
## 四Horizontal Pod AutoscalerHPA
在前面的课程中我们已经可以实现通过手工执行kubectl scale命令实现Pod扩容或缩容但是这显然不符合Kubernetes的定位目标-自动化、智能化。Kubernetes期望可以实现通过监测Pod的使用情况实现pod数量的自动调整于是就产生了Horizontal Pod AutoscalerHPA这种控制器。
HPA可以获取每个Pod利用率然后和HPA中定义的指标进行对比同时计算出需要伸缩的具体值最后实现Pod的数量的调整。其实HPA与之前的Deployment一样也属于一种Kubernetes资源对象它通过追踪分析RC控制的所有目标Pod的负载变化情况来确定是否需要针对性地调整目标Pod的副本数这是HPA的实现原理。
![](accents\images-202505080016.png)
### 1. 安装metrics-server
metrics-server可以用来收集集群中的资源使用情况
```bash
# 下载配置文件
[root@master ~]# wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 修改配置文件
[root@master ~]# vim components.yaml
113 ---
114 apiVersion: apps/v1
115 kind: Deployment
116 metadata:
117 labels:
118 k8s-app: metrics-server
119 name: metrics-server
120 namespace: kube-system
121 spec:
122 selector:
123 matchLabels:
124 k8s-app: metrics-server
125 strategy:
126 rollingUpdate:
127 maxUnavailable: 0
128 template:
129 metadata:
130 labels:
131 k8s-app: metrics-server
132 spec:
133 containers:
134 - args:
135 - --cert-dir=/tmp
136 - --secure-port=10250
137 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
138 - --kubelet-use-node-status-port
139 - --metric-resolution=15s
140 - --kubelet-insecure-tls
141 #image: registry.k8s.io/metrics-server/metrics-server:v0.7.2
142 image: registry.aliyuncs.com/google_containers/metrics-server:v0.7.2
```
```bash
# 安装metrics-server
[root@master ~]# kubectl apply -f components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
# 查看pod运行情况
[root@master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-64897985d-hzb7c 1/1 Running 2 (5h16m ago) 23d
coredns-64897985d-l2nvk 1/1 Running 2 (5h16m ago) 23d
etcd-master 1/1 Running 2 (5h16m ago) 23d
kube-apiserver-master 1/1 Running 2 (5h16m ago) 23d
kube-controller-manager-master 1/1 Running 2 (5h16m ago) 23d
kube-proxy-fxv98 1/1 Running 2 (5h16m ago) 23d
kube-proxy-mtn5n 1/1 Running 2 (5h16m ago) 23d
kube-proxy-x82nf 1/1 Running 2 (5h16m ago) 23d
kube-scheduler-master 1/1 Running 2 (5h16m ago) 23d
metrics-server-5cfb85d86f-9l9nb 1/1 Running 0 32s
# 使用kubectl top node 查看资源使用情况
[root@master ~]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 111m 2% 841Mi 44%
node1 29m 0% 310Mi 16%
node2 34m 0% 340Mi 18%
[root@master ~]# kubectl top pod -n kube-system
NAME CPU(cores) MEMORY(bytes)
coredns-64897985d-hzb7c 2m 16Mi
coredns-64897985d-l2nvk 2m 18Mi
etcd-master 13m 52Mi
kube-apiserver-master 34m 292Mi
kube-controller-manager-master 19m 51Mi
kube-proxy-fxv98 1m 19Mi
kube-proxy-mtn5n 1m 17Mi
kube-proxy-x82nf 1m 17Mi
kube-scheduler-master 3m 21Mi
metrics-server-5cfb85d86f-9l9nb 3m 19Mi
```
### 2. 准备deployment和service
创建pc-hpa-pod.yaml文件内容如下
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: dev
spec:
strategy:
type: RollingUpdate
replicas: 1
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
resources:
limits:
cpu: "1"
requests:
cpu: "100m"
```
```bash
# 创建deployment
[root@master ~]# kubectl create -f pc-hpa-pod.yaml
deployment.apps/nginx created
# 创建service
[root@master ~]# kubectl expose deployment nginx --type=NodePort --port=80 -n dev
service/nginx exposed
# 查看
[root@master ~]# kubectl get deployment,pod,svc -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 0/1 1 0 21s
NAME READY STATUS RESTARTS AGE
pod/nginx-f87cbb8b5-47h5d 0/1 ContainerCreating 0 21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx NodePort 10.106.16.79 <none> 80:31522/TCP 6s
```
### 3. 部署HPA
创建pc-hpa.yaml文件内容如下
```yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: pc-hpa
namespace: dev
spec:
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 3
scaleTargetRef:
apiVersion: /v1
kind: Deployment
name: nginx
```
```bash
# 创建hpa
[root@master ~]# kubectl create -f pc-hpa.yaml
horizontalpodautoscaler.autoscaling/pc-hpa created
# 查看hpa
[root@master ~]# kubectl get hpa -n dev
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
pc-hpa Deployment/nginx <unknown>/3% 1 10 0 10s
```
### 4. 测试
使用压测工具对service地址192.168.159.132:31830进行压测然后通过控制台查看hpa和pod的变化
hpa变化
```bash
[root@master ~]# kubectl get hpa -n dev -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
pc-hpa Deployment/nginx 0%/3% 1 10 1 4m11s
pc-hpa Deployment/nginx 0%/3% 1 10 1 5m19s
pc-hpa Deployment/nginx 22%/3% 1 10 1 6m50s
pc-hpa Deployment/nginx 22%/3% 1 10 4 7m5s
pc-hpa Deployment/nginx 22%/3% 1 10 8 7m21s
pc-hpa Deployment/nginx 6%/3% 1 10 8 7m51s
pc-hpa Deployment/nginx 0%/3% 1 10 8 9m6s
pc-hpa Deployment/nginx 0%/3% 1 10 8 13m
pc-hpa Deployment/nginx 0%/3% 1 10 1 14m
```
deployment变化
```bash
[root@master ~]# kubectl get deployment -n dev -w
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 5m48s
nginx 1/4 1 1 13m
nginx 1/4 1 1 13m
nginx 1/4 1 1 13m
nginx 1/4 4 1 13m
nginx 1/8 4 1 14m
nginx 1/8 4 1 14m
nginx 1/8 4 1 14m
nginx 1/8 8 1 14m
nginx 2/8 8 2 14m
nginx 3/8 8 3 14m
nginx 4/8 8 4 14m
nginx 5/8 8 5 14m
nginx 6/8 8 6 14m
nginx 7/8 8 7 14m
nginx 8/8 8 8 15m
nginx 8/1 8 8 20m
nginx 8/1 8 8 20m
nginx 1/1 1 1 20m
```
pod变化
```bash
[root@master ~]# kubectl get pod -n dev -w
NAME READY STATUS RESTARTS AGE
nginx-7df9756ccc-bh8dr 1/1 Running 0 11m
nginx-7df9756ccc-cpgrv 0/1 Pending 0 0s
nginx-7df9756ccc-8zhwk 0/1 Pending 0 0s
nginx-7df9756ccc-rr9bn 0/1 Pending 0 0s
nginx-7df9756ccc-cpgrv 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-8zhwk 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-rr9bn 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-m9gsj 0/1 Pending 0 0s
nginx-7df9756ccc-g56qb 0/1 Pending 0 0s
nginx-7df9756ccc-sl9c6 0/1 Pending 0 0s
nginx-7df9756ccc-fgst7 0/1 Pending 0 0s
nginx-7df9756ccc-g56qb 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-m9gsj 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-sl9c6 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-fgst7 0/1 ContainerCreating 0 0s
nginx-7df9756ccc-8zhwk 1/1 Running 0 19s
nginx-7df9756ccc-rr9bn 1/1 Running 0 30s
nginx-7df9756ccc-m9gsj 1/1 Running 0 21s
nginx-7df9756ccc-cpgrv 1/1 Running 0 47s
nginx-7df9756ccc-sl9c6 1/1 Running 0 33s
nginx-7df9756ccc-g56qb 1/1 Running 0 48s
nginx-7df9756ccc-fgst7 1/1 Running 0 66s
nginx-7df9756ccc-fgst7 1/1 Terminating 0 6m50s
nginx-7df9756ccc-8zhwk 1/1 Terminating 0 7m5s
nginx-7df9756ccc-cpgrv 1/1 Terminating 0 7m5s
nginx-7df9756ccc-g56qb 1/1 Terminating 0 6m50s
nginx-7df9756ccc-rr9bn 1/1 Terminating 0 7m5s
nginx-7df9756ccc-m9gsj 1/1 Terminating 0 6m50s
nginx-7df9756ccc-sl9c6 1/1 Terminating 0 6m50s
```
## 五DaemonSetDS
DaemonSet类型的控制器可以保证在集群中的每一台或指定节点上都运行一个副本。一般适用于日志收集、节点监控等场景。也就是说如果一个Pod提供的功能是节点级别的每个节点都需要且只需要一个那么这类Pod就适合使用DaemonSet类型的控制器创建。
![](accents\images-202505080017.png)
DaemonSet控制器的特点
- 每当向集群中添加一个节点时指定的Pod副本也将添加到该节点上
- 当节点从集群中移除时Pod也就被垃圾回收了
下面先来看下DaemonSet的资源清单文件
```yaml
apiVersion: apps/v1 # 版本号
kind: DaemonSet # 类型
metadata: # 元数据
name: # rs名称
namespace: # 所属命名空间
labels: #标签
controller: daemonset
spec: # 详情描述
revisionHistoryLimit: 3 # 保留历史版本
updateStrategy: # 更新策略
type: RollingUpdate # 滚动更新策略
rollingUpdate: # 滚动更新
maxUnavailable: 1 # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
selector: # 选择器通过它指定该控制器管理哪些pod
matchLabels: # Labels匹配规则
app: nginx-pod
matchExpressions: # Expressions匹配规则
- {key: app, operator: In, values: [nginx-pod]}
template: # 模板当副本数量不足时会根据下面的模板创建pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- containerPort: 80
```
创建pc-daemonset.yaml内容如下
```yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: pc-daemonset
namespace: dev
spec:
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.17.1
```
```bash
# 创建daemonset
[root@master ~]# kubectl create -f pc-daemonset.yaml
daemonset.apps/pc-daemonset created
# 查看daemonset
[root@master ~]# kubectl get ds -n dev -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
pc-daemonset 2 2 1 2 1 <none> 27s nginx nginx:1.17.1 app=nginx-pod
# 查看pod,发现在每个Node上都运行一个pod
[root@master ~]# kubectl get pods -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-f87cbb8b5-47h5d 1/1 Running 0 12m 10.244.1.2 node1 <none> <none>
pc-daemonset-w6rdx 1/1 Running 0 50s 10.244.2.4 node2 <none> <none>
pc-daemonset-z6twz 1/1 Running 0 50s 10.244.1.3 node1 <none> <none>
# 删除daemonset
[root@master ~]# kubectl delete -f pc-daemonset.yaml
daemonset.apps "pc-daemonset" deleted
```
## 六Job
Job主要用于负责“批量处理一次要处理指定数量任务短暂的一次性每个任务进运行一次就结束”任务。Job特点如下
- 当Job创建的pod执行成功结束时Job将记录成功结束的pod数量
- 当成功结束的pod达到指定的数量时Job将完成执行
![](accents\images-202505080018.png)
Job的资源清单文件
```yaml
apiVersion: batch/v1 # 版本号
kind: Job # 类型
metadata: # 元数据
name: # rs名称
namespace: # 所属命名空间
labels: #标签
controller: job
spec: # 详情描述
completions: 1 # 指定job需要成功运行Pods的次数。默认值: 1
parallelism: 1 # 指定job在任一时刻应该并发运行Pods的数量。默认值: 1
activeDeadlineSeconds: 30 # 指定job可运行的时间期限超过时间还未结束系统将会尝试进行终止。
backoffLimit: 6 # 指定job失败后进行重试的次数。默认是6
manualSelector: true # 是否可以使用selector选择器选择pod默认是false
selector: # 选择器通过它指定该控制器管理哪些pod
matchLabels: # Labels匹配规则
app: counter-pod
matchExpressions: # Expressions匹配规则
- {key: app, operator: In, values: [counter-pod]}
template: # 模板当副本数量不足时会根据下面的模板创建pod副本
metadata:
labels:
app: counter-pod
spec:
restartPolicy: Never # 重启策略只能设置为Never或者OnFailure
containers:
- name: counter
image: busybox:1.30
command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 2;done"]
```
关于重启策略设置的说明:
- 如果指定为OnFailure则job会在pod出现故障时重启容器而不是创建podfailed次数不变
- 如果指定为Never则job会在pod出现故障时创建新的pod并且故障pod不会消失也不会重启failed次数加1
- 如果指定为Always的话就意味着一直重启意味着job任务会重复去执行了当然不对所以不能设置为Always
创建pc-job.yaml内容如下
```yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pc-job
namespace: dev
spec:
manualSelector: true
selector:
matchLabels:
app: counter-pod
template:
metadata:
labels:
app: counter-pod
spec:
restartPolicy: Never
containers:
- name: counter
image: busybox:1.30
command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 3;done"]
```
```bash
# 创建job
[root@master ~]# kubectl create -f pc-job.yaml
job.batch/pc-job created
# 查看job
[root@master ~]# kubectl get job -n dev -o wide -w
NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR
pc-job 0/1 13s 13s counter busybox:1.30 app=counter-pod
pc-job 0/1 52s 52s counter busybox:1.30 app=counter-pod
pc-job 1/1 52s 52s counter busybox:1.30 app=counter-pod
# 通过观察pod状态可以看到pod在运行完毕任务后就会变成Completed状态
[root@master ~]# kubectl get pods -n dev -w
NAME READY STATUS RESTARTS AGE
pc-job-8rpm6 0/1 Completed 0 81s
# 接下来调整下pod运行的总数量和并行数量 即在spec下设置下面两个选项
# completions: 6 # 指定job需要成功运行Pods的次数为6
# parallelism: 3 # 指定job并发运行Pods的数量为3
# 然后重新运行job观察效果此时会发现job会每次运行3个pod总共执行了6个pod
[root@master ~]# kubectl get pods -n dev -w
NAME READY STATUS RESTARTS AGE
pc-job-4bjb5 1/1 Running 0 5s
pc-job-65xtn 1/1 Running 0 5s
pc-job-gld44 0/1 ContainerCreating 0 5s
pc-job-gld44 1/1 Running 0 25s
pc-job-4bjb5 0/1 Completed 0 28s
pc-job-ps7zz 0/1 Pending 0 0s
pc-job-65xtn 0/1 Completed 0 28s
pc-job-ps7zz 0/1 Pending 0 0s
pc-job-4bjb5 0/1 Completed 0 28s
pc-job-ps7zz 0/1 ContainerCreating 0 0s
pc-job-ddxs5 0/1 Pending 0 0s
pc-job-ddxs5 0/1 Pending 0 0s
pc-job-65xtn 0/1 Completed 0 28s
pc-job-ddxs5 0/1 ContainerCreating 0 0s
pc-job-ps7zz 1/1 Running 0 1s
pc-job-ddxs5 1/1 Running 0 1s
pc-job-gld44 0/1 Completed 0 52s
pc-job-5xjz9 0/1 Pending 0 0s
pc-job-5xjz9 0/1 Pending 0 0s
pc-job-gld44 0/1 Completed 0 52s
pc-job-5xjz9 0/1 ContainerCreating 0 0s
pc-job-5xjz9 1/1 Running 0 1s
pc-job-ps7zz 0/1 Completed 0 29s
pc-job-ddxs5 0/1 Completed 0 29s
pc-job-ps7zz 0/1 Completed 0 29s
pc-job-ddxs5 0/1 Completed 0 29s
pc-job-5xjz9 0/1 Completed 0 28s
pc-job-5xjz9 0/1 Completed 0 28s
# 删除job
[root@master ~]# kubectl delete -f pc-job.yaml
job.batch "pc-job" deleted
```
## 七CronJobCJ
CronJob控制器以Job控制器资源为其管控对象并借助它管理pod资源对象Job控制器定义的作业任务在其控制器资源创建之后便会立即执行但CronJob可以以类似于Linux操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。也就是说CronJob可以在特定的时间点反复的去运行Job任务。
![](accents\images-202505080019.png)
CronJob的资源清单文件
```yaml
apiVersion: batch/v1beta1 # 版本号
kind: CronJob # 类型
metadata: # 元数据
name: # rs名称
namespace: # 所属命名空间
labels: #标签
controller: cronjob
spec: # 详情描述
schedule: # cron格式的作业调度运行时间点,用于控制任务在什么时间执行
concurrencyPolicy: # 并发执行策略,用于定义前一次作业运行尚未完成时是否以及如何运行后一次的作业
failedJobHistoryLimit: # 为失败的任务执行保留的历史记录数默认为1
successfulJobHistoryLimit: # 为成功的任务执行保留的历史记录数默认为3
startingDeadlineSeconds: # 启动作业错误的超时时长
jobTemplate: # job控制器模板用于为cronjob控制器生成job对象;下面其实就是job的定义
metadata:
spec:
completions: 1
parallelism: 1
activeDeadlineSeconds: 30
backoffLimit: 6
manualSelector: true
selector:
matchLabels:
app: counter-pod
matchExpressions: 规则
- {key: app, operator: In, values: [counter-pod]}
template:
metadata:
labels:
app: counter-pod
spec:
restartPolicy: Never
containers:
- name: counter
image: busybox:1.30
command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 20;done"]
```
```
需要重点解释的几个选项:
schedule: cron表达式用于指定任务的执行时间
*/1 * * * *
<分钟> <小时> <日> <月份> <星期>
分钟 值从 0 到 59.
小时 值从 0 到 23.
日 值从 1 到 31.
月 值从 1 到 12.
星期 值从 0 到 6, 0 代表星期日
多个时间可以用逗号隔开; 范围可以用连字符给出;*可以作为通配符; /表示每...
concurrencyPolicy:
Allow: 允许Jobs并发运行(默认)
Forbid: 禁止并发运行,如果上一次运行尚未完成,则跳过下一次运行
Replace: 替换,取消当前正在运行的作业并用新作业替换它
```
创建pc-cronjob.yaml内容如下
```yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: pc-cronjob
namespace: dev
labels:
controller: cronjob
spec:
schedule: "*/1 * * * *"
jobTemplate:
metadata:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: counter
image: busybox:1.30
command: ["bin/sh","-c","for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 3;done"]
```
```bash
# 创建cronjob
[root@master ~]# kubectl create -f pc-cronjob.yaml
cronjob.batch/pc-cronjob created
# 查看cronjob
[root@master ~]# kubectl get cronjobs -n dev
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
pc-cronjob */1 * * * * False 0 <none> 18s
# 查看job
[root@master ~]# kubectl get jobs -n dev
NAME COMPLETIONS DURATION AGE
pc-cronjob-29111669 1/1 28s 38s
# 查看pod
[root@master ~]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-cronjob-29111669-k5gdw 0/1 Completed 0 57s
# 删除cronjob
[root@master ~]# kubectl delete -f pc-cronjob.yaml
cronjob.batch "pc-cronjob" deleted
```