Pod控制器详解
本章主要介绍Pod控制器的详细使用
1. Pod控制器介绍
在kubernetes中,按照pod的创建方式可以将其分为2类:
- 自主式pod:kubernetes直接创建出来的pod,这种pod删除后就没有了,也不会重建
- 控制器创建的pod:通过控制器创建的pod,这种pod删除后还会自动重建
什么是Pod控制器?
Pod控制器是管理pod的中间层,使用了pod控制器之后,我们只需要告诉pod控制器,需要多少个pod就可以了。他会创建出满足条件的pod,并确保每个pod处于用户期望的状态。如果pod在运行中出现故障,控制器就会基于指定策略重启或重建pod。
在kubernetes中,有很多种类型的pod控制器,每种都有它适合的场景,常见有:
- ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代
- ReplicaSet:保证指定数量pod运行,并支持pod数量变更,镜像版本变更
- Deployment:通过ReplicaSet来控制pod,并支持滚动升级、版本回退
- Horizontal Pod Autoscaler:可以根据集群负载自动调整Pod的数量,实现削峰填谷
- DaemonSet:在集群中的指定Node上都运行一个副本,一般用于守护进程类的任务
- Job:它创建出来的pod只要完成任务就立即退出,用于执行一次性任务
- Cronjob:它创建的pod会周期性的执行,用于执行周期性任务
- StatefulSet:管理有状态应用
2. ReplicaSet
ReplicaSet的主要作用是保证一定数量的pod能够正常运行,它会持续监听这些pod运行状态,一旦pod发生故障,就会重启或重建。同时它还支持对pod数量的扩缩容和版本镜像的升降级。
ReplicaSet 如下图所示:
常规配置:
apiVersion: apps/v1 kind: ReplicaSet metadata: name: namespace: labels: controller: rs spec: replicas: 3 #副本数量 selector: #选择器,通过它指定控制器管理哪些 pod matchLabels: app: nginx-pod matchExpressions: - {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定义
部署
示例:
$ cat yamls/pc-replicaset.yaml apiVersion: apps/v1 kind: ReplicaSet metadata: name: pc-replicaset namespace: dev labels: controller: rs spec: replicas: 3 #副本数量 selector: matchLabels: app: nginx-pod matchExpressions: - {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
查看创建的rs:
$ kubectl get rs -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-replicaset 3 3 3 115s nginx nginx:1.17.1 app=nginx-pod,app in (nginx-pod)
扩缩容
有2种方法:
1. 直接编辑
$ kubectl edit rs -n dev
replicaset.apps/pc-replicaset edited
2. kubescale rs 命令
$ kubectl scale rs pc-replicaset --replicas=4 -n dev replicaset.apps/pc-replicaset scaled
镜像版本升降级
同样
1. 直接编辑
$ kubectl edit rs -n dev replicaset.apps/pc-replicaset edited $ kubectl get rs pc-replicaset -n dev -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR pc-replicaset 4 4 4 5m39s nginx nginx:1.17.2 app=nginx-pod,app in (nginx-pod)
2. kubect set image 命令
$ kubectl set image rs pc-replicaset nginx=nginx:1.17.1 -n dev replicaset.apps/pc-replicaset image updated
删除
使用kubectl delete 命令可以删除rs以及它管理的pod。Kubernetes在删除rs前,会将rs的replicascaler调整为0,等待所有pod被删除后,再执行rs对象的删除。
如果希望仅仅删除rs对象(保留pod),可以使用kubectl delete 命令时添加 --cascade=false(不推荐)
当然,删除yaml的形式也是可以的
3. Deployment
为了更好地解决服务编排的问题,kubernetes在V1.2 版本开始,引入了Deployment控制器。这种控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod。即:Deployment管理ReplicaSet,ReplicaSet管理Pod。所以Deployment比ReplicaSet功能更强大。
Deployment主要功能有:
- 支持ReplicaSet的所有功能
- 支持发布的停止、继续
- 支持版本滚动升级和版本回退
Deployment资源主要配置:
apiVersion: apps/v1 kind: Deployment metadata: name: namespace: labels: controller: deploy spec: replicas: 3 revisionHistoryLimit: 3 # 保留历史版本,默认为10 paused: false # 暂停部署,默认是false progressDeadlineSeconds: 600 # 部署超时时间(s),默认是600 strategy: # 策略 type: RollingUpdate # 滚动更新策略 rollingUpdate: # 滚动更新 maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比或整数 maxUnavailable: 30% # 最大不可用状态的Pod的最大值,可以为百分比或整数 selector: matchLabels: app: nginx-pod matchExpressions: - {key: app, operator: In, values: [nginx-pod]} template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80
扩缩容
1. kubectl scale deploy pc-deployment --replicas=5 -n dev
2. kubectl edit deploy pc-deployment -n dev
镜像更新
Deployment支持2种镜像更新策略:重建更新和滚动更新(默认),可以通过strategy选项进行配置。
重建更新就是一次性删除所有老版本pod,然后重建。滚动就是先删一部分,启动一部分,中间状态是新版本与老版本pod均存在,最终只有新版本pod存在。
strategy: # 指定新的pod替换旧pod的策略,支持2个属性 type: # 支持2个属性 Recreate: # 在创建出新的Pod之前会kill掉所有已存在的pod RollingUpdate: # 滚动更新,kill一部分启动一部分,在更新过程中,存在2个版本的pod rollingUpdate: # 当type为RollingUpdate时生效,用于设置它的参数 maxUnavailable: # 用来指定在升级过程中不可用 Pod 的最大数量,默认为25% maxSurge: # 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为 25%
1. 重建更新
测试配置项:
$ cat yamls/pc-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: pc-deployment namespace: dev labels: controller: deploy spec: replicas: 3 strategy: type: Recreate selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80
变更镜像:
$ kubectl set image deployment pc-deployment nginx=nginx:1.17.2 -n dev deployment.apps/pc-deployment image updated $ kubectl get pods -n dev -o wide –w NAME READY STATUS R pc-deployment-7d7dd5499b-5wdlc 1/1 Running 0 pc-deployment-7d7dd5499b-czpzs 1/1 Running 0 pc-deployment-7d7dd5499b-dgvp5 1/1 Running 0 … pc-deployment-7d7dd5499b-5wdlc 1/1 Terminating pc-deployment-7d7dd5499b-dgvp5 1/1 Terminating pc-deployment-7d7dd5499b-czpzs 1/1 Terminating …. pc-deployment-7bbbd589d5-kkdcs 0/1 Pending pc-deployment-7bbbd589d5-kkdcs 0/1 Pending pc-deployment-7bbbd589d5-xtw4l 0/1 Pending … pc-deployment-7bbbd589d5-kkdcs 0/1 ContainerCreating pc-deployment-7bbbd589d5-xtw4l 0/1 ContainerCreating pc-deployment-7bbbd589d5-ztfbw 0/1 ContainerCreating … pc-deployment-7bbbd589d5-xtw4l 1/1 Running pc-deployment-7bbbd589d5-ztfbw 1/1 Running pc-deployment-7bbbd589d5-kkdcs 1/1 Running
从这个部署记录可以看到,recreate 的策略是一次性全部terminate,然后启动新版本pod。
2. 滚动更新
更改配置:
spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25%
变更 image 后打印的输出:
$ kubectl get pods -n dev -o wide -w NAME READY STATUS pc-deployment-866fdcbd54-9xwrb 0/1 Pending pc-deployment-866fdcbd54-9xwrb 0/1 Pending pc-deployment-866fdcbd54-9xwrb 0/1 ContainerCreating pc-deployment-866fdcbd54-9xwrb 1/1 Running pc-deployment-7bbbd589d5-xbnmw 1/1 Terminating pc-deployment-866fdcbd54-wjs8n 0/1 Pending pc-deployment-866fdcbd54-wjs8n 0/1 Pending pc-deployment-866fdcbd54-wjs8n 0/1 ContainerCreating pc-deployment-7bbbd589d5-xbnmw 0/1 Terminating pc-deployment-7bbbd589d5-xbnmw 0/1 Terminating pc-deployment-7bbbd589d5-xbnmw 0/1 Terminating pc-deployment-866fdcbd54-wjs8n 1/1 Running pc-deployment-7bbbd589d5-2cjvp 1/1 Terminating pc-deployment-866fdcbd54-ls9b8 0/1 Pending pc-deployment-866fdcbd54-ls9b8 0/1 Pending pc-deployment-866fdcbd54-ls9b8 0/1 ContainerCreating pc-deployment-7bbbd589d5-2cjvp 0/1 Terminating pc-deployment-866fdcbd54-ls9b8 1/1 Running pc-deployment-7bbbd589d5-f44sx 1/1 Terminating pc-deployment-7bbbd589d5-f44sx 0/1 Terminating pc-deployment-7bbbd589d5-2cjvp 0/1 Terminating pc-deployment-7bbbd589d5-2cjvp 0/1 Terminating pc-deployment-7bbbd589d5-f44sx 0/1 Terminating pc-deployment-7bbbd589d5-f44sx 0/1 Terminating
可以看到在过程中是启动一个停止一个。
滚动更新其实是通过2个ReplicaSet 完成的,新版本pod全在新的rs中启动。旧版本pod在旧rs中陆续关闭。旧版本的ReplicaSet 不会被删掉,这是为版本回退而做的设计。
查看rs数量,可以看到第二次实验有2个rs:
$ kubectl get rs -n dev NAME DESIRED CURRENT READY AGE pc-deployment-7bbbd589d5 0 0 0 32m pc-deployment-7d7dd5499b 0 0 0 32m pc-deployment-866fdcbd54 3 3 3 30m
3. 版本回退
Deployment支持版本升级过程中的暂停、继续功能以及版本回退等功能。
kubectl rollout 是版本升级相关的功能,支持的选项有:
- status:显示当前升级状态
- history:显示升级历史记录
- pause:暂停版本升级过程
- resume:继续已经暂停的版本升级过程
- restart:重启版本升级过程
- undo:回滚到上一版本(可以使用--to-version回滚到指定版本)
#查看deployment 升级的当前状态 $ kubectl rollout status deploy pc-deployment -n dev deployment "pc-deployment" successfully rolled out # 查看版本升级历史 $ kubectl rollout history deploy pc-deployment -n dev deployment.apps/pc-deployment REVISION CHANGE-CAUSE 1 <none> 2 <none> 3 <none> 这里change-cause为<none> 是因为我们在部署 deployment的时候未添加--record的选项 加上 kubectl apply -f yamls/pc-deployment.yaml --record 后再次尝试的结果: $ kubectl rollout history deploy pc-deployment -n dev deployment.apps/pc-deployment REVISION CHANGE-CAUSE 1 kubectl apply --filename=yamls/pc-deployment.yaml --record=true 2 kubectl apply --filename=yamls/pc-deployment.yaml --record=true # 版本回退,若未指定版本号,默认回退到上一版本 $ kubectl rollout undo deploy pc-deployment -n dev deployment.apps/pc-deployment rolled back # 其实这个回退版本另一方面又是一个新版本(版本1 现在变为了版本4): $ kubectl rollout history deploy pc-deployment -n dev deployment.apps/pc-deployment REVISION CHANGE-CAUSE 2 kubectl apply --filename=yamls/pc-deployment.yaml --record=true 3 kubectl apply --filename=yamls/pc-deployment.yaml --record=true
金丝雀发布
Deployment支持更新过程中的控制,如“暂停(pause)”或继续(resume)”更新操作。
比如有一批新的Pod资源创建完成后立即暂停更新过程。此时,仅存在一部分新版本的应用,主体部分还是旧版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望方式运行。确定没问题后再继续完成余下Pod资源滚动更新,否则立即回滚更新操作。这就是金丝雀发布。
# 更新deployment版本,并配置暂停deployment $ 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 # 查看 rs $ kubectl get rs -n dev NAME DESIRED CURRENT READY AGE pc-deployment-56f77b8695 1 1 1 18s pc-deployment-7d7dd5499b 3 3 3 35m 可以看到老版本是仍有3个,新版本仅有1个 # 查看 deployment status $ 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... 后续可以将部分流量先导入到新的rs中进行测试,最终没有任何问题后,可以继续rollout的流程: $ kubectl rollout resume deployment pc-deployment -n dev deployment.apps/pc-deployment resumed $ 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... Waiting for deployment spec update to be observed... Waiting for deployment spec update to be observed... Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "pc-deployment" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "pc-deployment" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "pc-deployment" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "pc-deployment" rollout to finish: 1 old replicas are pending termination... deployment "pc-deployment" successfully rolled out
4. Horizontal Pod Autoscaler(HPA)
前面都是通过kubectl scale进行的手动扩容,在生产中更多的是自动化扩展。通过HPA可以实现此续期。
HPA可以获取每个pod利用率,然后和HPA中定义的指标进行对比,同时计算需要伸缩的具体指,最后实现pod数量调整。
HPA与之前的Deployment一样,也属于一种kubernetes 资源对象,它通过追踪分析目标pod的负载变化情况,来确定是否需要针对性地调整目标pod的副本数。
4.1. 安装metrics-server
metrics-server可以用来收集集群中的资源使用情况。
$ git clone -b v0.3.6 https://github.com/kubernetes-incubator/metrics-server $ cd metrics-server/deploy/1.8+/ # 修改metrics-server-deployment.yaml 文件以下内容 spec: hostNetwork: true serviceAccountName: metrics-server volumes: # mount in tmp so we can safely use from-scratch images and/or read-only containers - name: tmp-dir emptyDir: {} containers: - name: metrics-server image: registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 imagePullPolicy: Always volumeMounts: - name: tmp-dir mountPath: /tmp args: - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP # 部署 kubectl apply -f ./ # 验证 $ kubectl get pods -n kube-system metrics-server-5f55b696bd-xmgkp 1/1 Running 0 2m2s
部署完成后即可查看资源使用情况
# 查看资源使用情况 $ kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% ip-10-0-1-217.cn-north-1.compute.internal 51m 2% 657Mi 19% ip-10-0-2-30.cn-north-1.compute.internal 42m 2% 565Mi 16%
4.2. 准备deployment和service
# 创建deployment $ kubectl get deploy,pod -n dev NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-dep 1/1 1 1 61s NAME READY STATUS RESTARTS AGE pod/nginx-dep-755c49cf64-9hrfn 1/1 Running 0 61s # 准备service $ kubectl expose deploy nginx-dep --type=NodePort --port 80 --target-port=80 -n dev service/nginx-dep exposed
4.3. 部署HPA
$ cat yamls/pc-hpa.yaml apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: pc-hpa namespace: dev spec: minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 3 # 此处用3仅是为了测试 scaleTargetRef: # 指定要扩展的target deployment apiVersion: apps/v1 kind: Deployment name: nginx-dep # 部署后 $ kubectl get hpa -n dev NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE pc-hpa Deployment/nginx-dep <unknown>/3% 1 10 0 11s => 这里 unknown 表示当前的使用情况,仍在计算中,需要等待一会儿出数据 $ kubectl get hpa -n dev NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE pc-hpa Deployment/nginx-dep 0%/3% 1 10 1 21m 如果hpa一直报invalid metrics (1 invalid out of 1), first error is: failed to get cpu utilization: missing request for cpu,说明 deploy中没有配置 CPU requests。需要执行下面的命令: kubectl patch deployment nginx-dep -p='{"spec":{"template":{"spec":{"containers":[{"name":"nginx","resources":{"requests":{"cpu":"200m"}}}]}}}}' -n dev
开始压测,并观察hpa与deploy的结果:
$ kubectl get hpa -n dev -o wide -w NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE pc-hpa Deployment/nginx-dep 0%/3% 1 10 1 32m pc-hpa Deployment/nginx-dep 3%/3% 1 10 1 32m pc-hpa Deployment/nginx-dep 9%/3% 1 10 1 33m $ kubectl get deploy -n dev NAME READY UP-TO-DATE AVAILABLE AGE nginx-dep 3/3 3 3 51m # 停掉一段时间后 $ kubectl get deploy -n dev NAME READY UP-TO-DATE AVAILABLE AGE nginx-dep 1/1 1 1 63m
5. DaemonSet
DaemonSet类型的控制器可以保证集群中每一台(或指定)节点上都运行一个副本,一般适合于日志收集、节点监控等常见。也就是说,如果一个pod提供的功能是节点级别的(每个节点都需要且仅需要一个),那么这类Pod就适合使用DaemonSet类型的控制器创建。
DaemonSet控制器的特点:
- 每当向集群中添加一个节点时,指定的pod副本也会添加到该节点上
- 每当节点从集群中移除时,pod也就被垃圾回收了
6. Job
Job主要用于负责批量处理(一次处理多个任务)、短暂的、一次性任务。有以下2个特点:
- 当job创建的pod执行成功结束时,job将记录成功结束后的pod数量
- 当成功结束的pod达到指定的数量时,job将完成执行
主要属性有:
spec: completions: 1 # 指定job需要成功运行Pods的数量。默认为1 parallelism: 1 # 指定job在任一时刻应该并发运行Pods的数量 activeDeadlineSeconds: 30 # job可运行的时间期限,若是超时仍未结束,则系统会尝试终止 backoffLimit: 6 # job失败后重试次数,默认为6 manualSelector: true # 是否使用selector选择器选择pod,默认false selector: matchLabels: app: counter-pod matchExpressions: - {key: app, operator: In, values: [counter-pod]}
7. CronJob(CJ)
Cronjob控制器以Job控制器资源为其管控对象,并借助它管理pod资源对象,Job控制器定义的作业任务在其控制器资源创建之后便立即执行。但CronJob可以以类似于Linux操作系统的方式实现周期性地在某时间点运行。
主要属性有:
spec: schedule: # cron格式的作业调度运行时间点,控制任务什么时间执行 concurrencyPolicy: # 并发执行策略,定义前一次作业未完成时是否运行后一次 failedJobHistoryLimit: # 为失败的任务执行那个保留的历史记录数,默认为1 successfulJobHistoryLimit: # 为成功的任务执行保留的历史记录数,默认为3 startingDeadlineSeconds: # 启动作业错误的超时时长 jobTemplate: # job控制器模板,用于为cronjob控制器生成job对象 metadata: spec: completions: 1 parallelism: 1 activeDeadlineSeconds: 30 ... template: metadata: labels: app: counter-pod spec: restartPolicy: Never containers: - name: counter ...