https://blog.csdn.net/lijingjingchn/article/details/115248195
手动:
2. 手动调整服务规模
我们可以使用kubectl
提供的命令来手动调整某个Deployment
的规模,也就是其包含的Pod
数量,这里拿上一节里创建的HelloWorld
服务来作为例子,当前的deployment
状态如下:
文章图片
DISIRED
表示配置时声明的期望副本数CURRENT
表示当前正在运行的副本数UP-TO-DATE
表示符合预期状态的副本数(比如某个副本宕机了,这里就不会计算那个副本)AVAILABLE
表示目前可用的副本数
kubectl scale
命令来手动调整deployment
的规模,现在尝试把helloworld
服务的副本数量扩充到4个:文章图片
执行命令后,k8s很快就为我们创建了另外3个helloworld的副本,这时候整个服务就有多个实例在运行了,那么
对应Service的负载均衡功能便会生效
,可以看到Service的状态里已经侦测到多个EndPoint
:文章图片
当我们连续调用service时,可以看到每次实际调用的pod都不同(这里对服务的源码做了一些修改,打印出了hostname):
文章图片
同理,我们也可以用同样的方式把服务缩容,比如把副本集的数量下调到两个:
文章图片
自动缩扩容:极致弹性?
参考好文刚才的例子中,我们是通过命令行的方式来手动调整服务规模的,显然在面对线上真实流量时是不能这么做的,我们希望调度平台能够根据服务的负载来智能地调控规模,进行弹性缩扩容。这时候就轮到k8s中的
AutoScaler
出场了。【K8s扩容】到目前为止,k8s一共提供了3个不同维度的AutoScaler,如下图:
文章图片
k8s把弹性伸缩分为两类:
- 资源维度:保障集群资源池大小满足整体规划,当集群内的资源不足以支撑产出新的pod时,就会触发边界进行扩容
- 应用维度:保障应用的负载处在预期的容量规划内
- 水平伸缩
- 集群维度:自动调整资源池规模(新增/删除Worker节点)
- Pod维度:自动调整Pod的副本集数量
- 垂直伸缩
- 集群维度:不支持
- Pod维度:自动调整应用的资源分配(增大/减少pod的cpu、内存占用)
HPA(水平Pod伸缩)
,所以下面以它为例来重点分析,官方文档在此:kubernetes.io/docs/tasks/…3.1 基本流程
任何弹性系统的缩扩容都无外乎于以下几个步骤:
- 采集监控指标
- 聚合监控指标,判断是否需要执行缩扩容
- 执行缩扩容动作
文章图片
3.2 监控指标
根据官方文档的描述,HPA是使用
巡检(Control Loop)的机制
来采集Pod资源使用情况的,默认采集间隔为15s
,可以通过Controller Manager
(Master节点上的一个进程)的–horizontal-pod-autoscaler-sync-period
参数来手动控制。目前HPA默认采集指标的实现是
Heapster
,它主要采集CPU的使用率;beta版本也支持自定义的监控指标采集,但尚不稳定,不推荐使用。因此可以简单认为,HPA就是通过CPU的使用率作为监控指标的。
3.3 聚合算法
采集到CPU指标后,k8s通过下面的公式来判断需要扩容多少个pod:
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
- 1
ceil
表示向上取整,举个实际例子,假设某个服务运行了4个Pod,当前的CPU使用率为50%,预期的CPU使用率为25%,那么满足预期的实际Pod数量就是4 * (50% / 25%) = 8
个,即需要将Pod容量扩大一倍,增加4个Pod来满足需求。当然上述的指标并不是绝对精确的,首先,k8s会尽可能的让指标往期望值靠近,而不是完全相等,其次HPA设置了一个
容忍度(tolerance)
的概念,允许指标在一定范围内偏离期望值,默认是0.1
,这就意味着如果你设置调度策略为CPU预期使用率 = 50%,实际的调度策略会是小于45%或者大于55%进行缩扩容,HPA会尽力把指标控制在这个范围内(容忍度可以通过–horizontal-pod-autoscaler-tolerance
来调整)。另外有两点需要说明的细节:
- k8s做出决策的间隔,它不会连续地执行扩缩容动作,而是存在一定的
cd
,目前扩容动作的cd为3分钟,缩容则为5分钟。 - k8s针对扩容做了一个最大限制,每次扩容的pod数量不会大于当前副本数量的2倍。
最后我们来尝试实际使用一下HPA,依然是使用
kubectl
命令行的方式来创建:kubectl autoscale deployment helloworld --cpu-percent=10 --min=1 --max=5
- 1
文章图片
使用
kubectl get hpa
也可以看到:文章图片
但是这里出现了异常,
targets
的当前CPU使用率始终显示为unknown
,网上说是因为副本集里没有配置resources
导致的。我们需要在dashboard里找到对应的副本集,然后在spec.containers.resources
里声明requests
和limits
值:文章图片
其中
requests
表示pod所需要分配的资源配额,limits
表示单个pod最大能够获取到的资源配额。配置完之后还是没有出现指标,继续百度,发现没有安装
heapster
支持,那就安装,具体方法可见此文,注意需要把国外gcr的镜像通过阿里云代理一把才能安装(如果你不太会搞,可以用我转好的,见github),influxDB
,grafana
和heapster
三个组件都装好后,记得再装一把heapster rbac
(在kubeconfig/rbac
目录下),最后重启一波minikube
,打开控制台,可以看到节点页面已经有了指标图像:文章图片
kubectl top
命令也能正常返回数值了:文章图片
然而,
kubectl get hpa
显示cpu的当前指标还是unknown
,郁闷,进到deployment
里看一把日志:文章图片
可以看到HPA一直在报无法从
metrics API
获取请求资源的错误,github走一波,找到一个类似的issue,原因是1.9
版本以后的k8s默认的监控指标来源从heapster
变成了metrics-server
(我用的1.0,坑),不过要再安装一套metrics-server实在太麻烦了,可以通过修改kube-controller-manager
的启动参数来禁用这个新特性。minikube ssh
进入到vm内部,然后找到/etc/kubernetes/manifests/kube-controller-manager.yaml
这个文件,在启动参数里加上–horizontal-pod-autoscaler-use-rest-clients=false
,这时候对应的容器组会自动重启更新,再执行kubectl get hpa
,可以看到cpu的指标终于Ok了:文章图片
留下了感动的泪水,终于可以开始压测试水了,赶紧搞个
buzybox
压起来:kubectl run -i --tty load-generator --image=busybox /bin/sh
- 1
helloworld
服务(为了更快的出效果,我把服务的scale缩减到只有一个副本集,直接压这个pod的ip)/ # while true;
do wget -q -O- http://172.17.0.5:8080;
done
- 1
文章图片
dashboard上也能看到效果:
文章图片
关掉压测脚本,静置一会儿,再看HPA的状态:
文章图片
自动缩容到了1个副本集,那么HPA的实践使用到这里就算是结束了。
4. 更新、发布、回滚
服务代码必然是会经常修改的,当代码发生变动时,就需要重新打包生成镜像,然后进行发布和部署,来看看在k8s中是如何对这些步骤进行处理的。
现在我们对代码做了一些改动,加上了hostname的输出,然后打包形成了一个
2.0
版本的新镜像,下面需要把这个新版本的镜像部署到k8s的容器集群上,使用kubectl set image
在deployment
上指定新的镜像:kubectl set image deployments/helloworld helloworld=registry.cn-qingdao.aliyuncs.com/gold-faas/gold-demo-service:2.0
- 1
kubectl
和dashboard
中看到,新的容器组正在被创建,同时旧的容器组也在被回收:文章图片
文章图片
最终所有的旧版本pod都会被回收,只留下新发布版本的容器组副本集:
文章图片
来测试一下服务是否更新:
文章图片
假设我们的发布到线上的版本出现了致命的问题,需要紧急将服务回退到上一个版本,该怎么做呢?使用
kubectl rollout undo
即可,来看看效果:文章图片
可以看到执行回滚命令后,新版本的pod开始被回收,同时上一个版本镜像所对应的pod被唤醒(这里速度非常快,我感觉k8s在发布完新服务后可能并不会立刻销毁历史版本的pod实例,而是会缓存一段时间,这样非常快速的回滚,只要把service的负载均衡指回历史版本的pod就可以了)
文章图片
回滚完成后再度请求服务,可以发现服务已经变回了上一个版本的内容:
文章图片
上面这些发布和回滚的特性在k8s中被称为
滚动更新
,它允许我们按照一定的比例逐步(可以手工设置百分比)更新pod,从而实现平滑
的更新和回滚
,也可以借此实现类似蓝绿发布
和金丝雀发布
的功能。5. 小结
通过实际操作体验了k8s的缩扩容以及发布机制,虽然遇到了几个坑,但整体上用起来还是非常丝滑的,到这里k8s的基本功能就探索的差不多了,从下一篇开始将会继续深入分析k8s的原理,敬请期待!
推荐阅读
- jenkins|一文读懂Jenkins的前世今生,零基础学Jenkins必看教程(Jenkins部署+Jenkins安装+Jenkins持续集成)
- 云原生|【云原生 ? DevOps】一文掌握持续集成工具 Jenkins
- 什么是DevOps?为大家都在用DevOps
- 云原生|【云原生实战】DevOps基础与实战项目
- devops|国内首届DataOps+MLOps meetup回顾
- devops|GitLab+Jenkins+Harbor+Kubernetes构建Devops体系
- 初识DevOps
- DevOps: 每个阶段最常用的工具有哪些()
- DevOps|k8s 驱逐 磁盘空间不足