自动缩扩容是现代化的容器调度平台带给咱们的最激动人心的一项能力。在上规模的业务系统中咱们无时无刻不面临着这样的难题:用户的流量每每随着时间波动,甚至偶尔出现不可预测的峰值(毛刺流量),每当流量增长时都须要手工的对应用进行扩容,峰值流量消失后又须要将扩容的机器回收,运维起来费时费力。git
幸运的是,k8s这样的容器调度平台正在逐渐帮助咱们解决这样的问题,它带来的AutoScaler功能目前已经支持在多个不一样维度上的弹性缩扩容,能够根据应用的负载状况进行自适应。尽管在一些较为苛刻的场景下,因为容器启动速度等缘由的限制,AutoScaler的效果还不尽人意,但相信在不久的未来,自动缩扩容方案将会彻底成熟,届时咱们将轻松获取具备强大弹性能力的服务集群。github
如今来试着使用一下k8s的Scale相关功能吧算法
咱们可使用kubectl
提供的命令来手动调整某个Deployment
的规模,也就是其包含的Pod数量,这里拿上一节里建立的HelloWorld服务来做为例子,当前的deployment状态以下:缓存
咱们可使用kubectl scale
命令来手动调整deployment的规模,如今尝试把helloworld服务的副本数量扩充到4个:bash
执行命令后,k8s很快就为咱们建立了另外3个helloworld的副本,这时候整个服务就有多个实例在运行了,那么对应Service的负载均衡功能便会生效,能够看到Service的状态里已经侦测到多个EndPoint:架构
当咱们连续调用service时,能够看到每次实际调用的pod都不一样(这里对服务的源码作了一些修改,打印出了hostname):app
同理,咱们也能够用一样的方式把服务缩容,好比把副本集的数量下调到两个:负载均衡
参考好文运维
刚才的例子中,咱们是经过命令行的方式来手动调整服务规模的,显然在面对线上真实流量时是不能这么作的,咱们但愿调度平台可以根据服务的负载来智能地调控规模,进行弹性缩扩容。这时候就轮到k8s中的AutoScaler出场了ssh
到目前为止,k8s一共提供了3个不一样维度的AutoScaler,以下图:
k8s把弹性伸缩分为两类:
对应两种伸缩策略:
水平伸缩
垂直伸缩
其中最为成熟也是最为经常使用的伸缩策略就是HPA(水平Pod伸缩),因此下面以它为例来重点分析,官方文档在此:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
任何弹性系统的缩扩容都无外乎于如下几个步骤:
下面就按照这个顺序来分析HPA的工做方式,这里先给出一个HPA大致的架构图:
根据官方文档的描述,HPA是使用巡检(Control Loop)的机制来采集Pod资源使用状况的,默认采集间隔为15s,能够经过Controller Manager(Master节点上的一个进程)的--horizontal-pod-autoscaler-sync-period
参数来手动控制。
目前HPA默认采集指标的实现是Heapster
,它主要采集CPU的使用率;beta版本也支持自定义的监控指标采集,但尚不稳定,不推荐使用
所以能够简单认为,HPA就是经过CPU的使用率做为监控指标的
采集到CPU指标后,k8s经过下面的公式来判断须要扩容多少个pod
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
复制代码
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
复制代码
运行上面的命令后,能够在dashboard看到HPA已经被建立,策略是以CPU使用率10%为临界值,最少副本集数量为1,最大为5:
使用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
复制代码
写个循环去访问咱们的helloworld服务(为了更快的出效果,我把服务的scale缩减到只有一个副本集,直接压这个pod的ip)
/ # while true; do wget -q -O- http://172.17.0.5:8080; done
复制代码
大概2,3分钟后就能看到结果,此时查看hpa的状态,能够看到已经触发水平扩容,副本集的数量由1个追加到4个:
dashboard上也能看到效果:
关掉压测脚本,静置一下子,再看HPA的状态:
自动缩容到了1个副本集,那么HPA的实践使用到这里就算是结束了
服务代码必然是会常常修改的,当代码发生变更时,就须要从新打包生成镜像,而后进行发布和部署,来看看在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
复制代码
执行该命令后,能够从kubectl和dashboard中看到,新的容器组正在被建立,同时旧的容器组也在被回收:
最终全部的旧版本pod都会被回收,只留下新发布版本的容器组副本集:
来测试一下服务是否更新:
假设咱们的发布到线上的版本出现了致命的问题,须要紧急将服务回退到上一个版本,该怎么作呢?使用kubectl rollout undo
便可,来看看效果:
能够看到执行回滚命令后,新版本的pod开始被回收,同时上一个版本镜像所对应的pod被唤醒(这里速度很是快,我感受k8s在发布完新服务后可能并不会马上销毁历史版本的pod实例,而是会缓存一段时间,这样很是快速的回滚,只要把service的负载均衡指回历史版本的pod就能够了)
回滚完成后再度请求服务,能够发现服务已经变回了上一个版本的内容:
上面这些发布和回滚的特性在k8s中被称为滚动更新,它容许咱们按照必定的比例逐步(能够手工设置百分比)更新pod,从而实现平滑的更新和回滚,也能够借此实现相似蓝绿发布和金丝雀发布的功能。
经过实际操做体验了k8s的缩扩容以及发布机制,虽然遇到了几个坑,但总体上用起来仍是很是丝滑的,到这里k8s的基本功能就探索的差很少了,从下一篇开始将会继续深刻分析k8s的原理,敬请期待!
原文地址 http://marklux.cn/blog/107, 转载请注明出处