一、扩缩容
手动扩容
k8s使用过kubectl scale
命令进行扩容
假设原本的pod有3个,这个时候由于业务的增长,我们可以将pod增加到5个
kubectl scale rc blog --replicas=5
这里的blog是rc的名称
当--replicas的值设置为比原来的pod数,k8s会杀掉一些pod,下面3个变成1个
kubectl scale rc blog --replicas=1
自动扩容(HPA)
用于实现基于CPU使用率进行自动Pod扩缩容的功能。HPA控制器基于Master的kube-controller-manager服务启动参数--horizontal-pod-autoscaler-sync-period
定义的探测周期(默认值为 15s),周期性地监测目标Pod的资源性能指标,并与HPA资源对象中的扩缩容条件进行对比,在满足条件时对Pod副本数量进行调整.
HPA的原理
k8s通过某个个Metrics Server持续采集集群中pod副本的性能指标,然后HPA通过Metrics Server提供的api获取这些数据,跟用户定于性能指标规则对比,计算出所需的pod数量,当计算出的数量跟当前集群中的pod数量不同,HPA就调用RC控制器进行扩缩容。
扩缩容算法
最终pod的数量=ceil[当前的pod数量*(当前性能指标数/期望性能性能指标数)]
ceil向上取整
比如:当前的cpu使用率是60%,但是我期望的是30%,并且当前已经存在2个pod了
2*(60% / 30%)= 4,所以应该扩容2个pod变成4个
比如:当前的cpu使用200m,但是我期望的是100m,并且当前已经存在2个pod了
2*(200m / 100m)= 4,所以应该扩容2个pod变成4个
容忍度
容忍度通过kube-controller-manager服务的启动参数--horizontal- pod-autoscaler-tolerance
进行设置,默认值为0.1(即10%),表示基于上 述算法得到的结果在[-10%-+10%]区间内,即[0.9-1.1],控制器都不会进
行扩缩容操作。
由于有可能业务不稳定,突然有服务压力但过几分钟就结束了,kubernetes 增加了弹性增加节点和减少节点的延迟时间(kube-controller-manager启动参数)。
--horizontal-pod-autoscaler-downscale-delay
: 弹性减少节点延迟时间,默认5分钟
--horizontal-pod-autoscaler-upscale-delay
: 弹性增加节点延迟时间,默认3分钟
k8s针对扩容做了一个最大限制,每次扩容的pod数量不会大于当前副本数量的2倍。
HorizontalPodAutoscaler
k8s提供HorizontalPodAutoscaler资源对象,让我们可以使用它进行配置扩缩容的规则。
HorizontalPodAutoscaler有两个版本,autoscaling/v1 只支持CPU使用率的指标数,autoscaling/v2则用于支持基于任意指标的自动扩缩容配置,包括基于资源使用率(Resource)、Pod指标(Pods)、其他指标(Object)等。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec: scaleTargetRef:
apiVersion: apps/v1beta1
kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
averageUtilization:50 设置cpu的平均使用率为50
平均值所有Pod副本当前指标值的总和除以Pod 副本数量得到的平均值
metrics的type可以设置为Resource、Pods、Object3种
Resource可以设置CPU和内存。对于CPU使用率,在target参数中设置averageUtilization定义目标平均CPU使用率。对于内存资源,在target参数中设置AverageValue定义目标平均内存使用值
metrics:
- type: Pods
pods:
metric
name: packets-per-second
target:
type: AverageValue
averageValue: 1k
平均每秒的数据量达到1000进行扩容
类型为Pods的指标数据来源于Pod对象本身,其target指标类型只能使用AverageValue
metrics:
- type: Object
object:
metric
name: requests-per-second
describedObject:
apiVersion: extensions/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 2k
设置指标的名称为requests-per-second,其值来源于 Ingress“main-route”,将目标值(value)设置为2000,即在Ingress的每 秒请求数量达到2000个时触发扩缩容
类型为Object的指标数据来源于其他资源对象或任意自定义指标, 其target指标类型可以使用Value或AverageValue(根据Pod副本数计算平 均值)进行设置
HPA 最佳实践
1)为容器配置 CPU Requests
2)HPA 目标设置恰当,如设置 70% 给容器和应用预留 30% 的余量
3)保持 Pods 和 Nodes 健康(避免 Pod 频繁重建)
4)保证用户请求的负载均衡
5)使用 kubectl top node 和 kubectl top pod 查看资源使用情况
二、滚动升级
当集群中的某个服务需要升级时,我们需要停止目前与该服务相关的所有Pod,然后下载新版本镜像并创建新的Pod。如果集群规模比较大,服务不能对外提供服务,则这个工作变成了一个挑战,而且先全部停止然后逐步升级的方式会导致较长时间的服务不可用。Kubernetes提供了滚动升级功能来解决上述问题。
kubectl set image完成滚动升级
Pod镜像需要被更新为Nginx:1.9.1, 我们可以通过kubectl set image命令为Deployment设置新的镜像名称
$ image (-f filename | type name) CONTAINER_NAME_1=CONTAINER_IMAGE_1 ... CONTAINER_NAME_N=CONTAINER_IMAGE_N
资源对象 pod (po)、replicationcontroller (rc)、deployment (deploy)、daemonset (ds)、job、replicaset (rs)
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment为资源对象类型
nginx-deployment 为资源对象名
nginx=nginx:1.9.1 容器名为nginx 更新镜像为nginx:1.9.1
一旦镜像名(或Pod定义)发生了修改,则将触发系统完成 Deployment所有运行Pod的滚动升级操作。
可以使用kubectl rollout status
命令查看Deployment的更新过程
spec.strategy.rollingUpdate.maxUnavailable:用于指定更新过程中,不可用的pod的数量
可以是整数如3,也可以是百分比30%(从Kubernetes 1.6开始, maxUnavailable的默认值从1改为25%)
比如设置为30%,滚动更新开始时立即将副本数缩小到所需副本总数的70%,等新的pod准备后,在进一步缩容。
spec.strategy.rollingUpdate.maxSurge:用于指定更新过程中,新旧pod数量总和的上限
可以是整数如3,也可以是百分比30%(向上取整)(从Kubernetes 1.6开始, maxUnavailable的默认值从1改为25%)举例来说,当maxSurge的值被设置为30%时,新的ReplicaSet可以在滚动更新开始时立即进行副本数扩容,只需要保证新旧ReplicaSet 的Pod副本数之和不超过期望副本数的130%即可
kubectl rolling-update命令进行滚动升级
见篇另一篇博客 k8s初识的滚动升级
三、回滚
在实际发布项目中,一般不会这么顺利,我们会经常遇到发布错了。比如我们要发布镜像为nginx:1.9.1,结果不小心发布成了nginx:1.9.2。这个时候我们需要回滚到上一个版本。
默认情况下,k8s会将有deployment发布历史记录保存在系统中,方便我们回滚。(可以设置保存的记录条数)
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.2
由于nginx:1.9.2不存在,发布过程卡主我们使用Ctrl-C中止
用kubectl rollout status 命令查看Deployment的更新过程
kubectl rollout status deployment/nginx-deployment
kubectl rollout history查看这个Deployment的历史记录
kubectl rollout history deployment/nginx-deployment
查看特定版本的详情信息
kubectl rollout history deployment/nginx-deployment --revision=3
回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment
回滚到特定版本
kubectl rollout undo deployment/nginx-deployment --to-revision=2
在创建Deployment时使用--record参数,就可以在CHANGE- CAUSE列看到每个版本使用的命令了。
kubectl create -f nginx-deployment.yaml --record=true
注意:只有修改spec.template才会创建新的修订版本,如更新镜像,容器标签。其他更新不会触发更新操作如修改pod的数量。这也意味着我们将Deployment回滚到 之前的版本时,只有Deployment的Pod模板部分会被修改。
四、暂停更新和恢复
对于一次复杂的Deployment配置修改,为了避免频繁触发 Deployment的更新操作,可以先暂停Deployment的更新操作,然后进行配置修改,再恢复Deployment,一次性触发完整的更新操作,就可以避 免不必要的Deployment更新操作了。
通过kubectl rollout pause命令暂停Deployment的更新操作:
kubectl rollout pause deployment/nginx-deployment
进行一系列操作,比如修改镜像,(并不会更新)
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
设置容器的资源
kubectl set resources deployment nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
恢复这个Deployment的部署操作:
kubectl rollout resume nginx-deployment
注意:
在恢复暂停的Deployment之前,无法回滚该Deployment