MENU

kubernetes自动扩容与缩容:autoscale

2019 年 05 月 20 日 • 应用服务器

emmmm,其实我一直都有听说kubernetes有弹性伸缩的功能,看来有必要了解一下了,然后最近就在琢磨这个东西,因为之前集群宕机,恢复之后总会抛出一切特别奇葩的问题,像是什么coredns无法启动,抛权限的错误,而且怎么查都找不到解决办法,我都要放弃了,可能是我太菜了吧,最后一怒之下重装系统集群重建,系统还是centos7.6,但Kubernetes的版本从之前的1.12.6升级到现在最新的稳定版本,也就是1.13.6,具体搭建的方法还是按着我之前的文档去搭建的,这次比较熟悉操作,不到一小时就搞定了,刚刚顺便又把master节点安装了kubelet&kube-proxy加入到集群中,所以现在的情况是这样,部署了coredns启动了两个副本,剩下的暂时没必要。

[root@master-1 ~]# kubectl -n kube-system get cs,pod,node

大概就是这样,下面进入正题,体验一下autoscale功能,还有了解一下他的原理是啥子。

Horizontal Pod Autoscaler

官方介绍,简单的说就是就是通过监控pod的CPU利用率或是一些别的指标,自动调整pod的数量,但是有些类型是不支持的,譬如DaemonSet,控制器会定期调整pod数量,判断的根据就是你指定的指标,超了你的指标就会自动扩容pod数量,使用率低了就会自动回收pod,刚刚提到了指标,需要用到一个插件去收集指标,譬如收集CPU利用率或是内存利用率,当前k8s版本需要使用metrics-server来收集指标,代替了heapsterGitHub地址,先部署一下metrics-server吧。

部署 metrics-server

地址我上面贴了,在服务器上我直接用git clone下载下来了。

[root@master-1 ~]# git clone https://github.com/kubernetes-incubator/metrics-server.git
[root@master-1 ~]# cd metrics-server/deploy/1.8+/
[root@master-1 ~/metrics-server/deploy/1.8+]# ls
aggregated-metrics-reader.yaml  auth-delegator.yaml  auth-reader.yaml  metrics-apiservice.yaml  metrics-server-deployment.yaml  metrics-server-service.yaml  resource-reader.yaml

部署需要用到的就是这些文件,但是不能直接部署,需要改点东西,首先是apiserver启动文件,加入如下内容,重启apiserver

[root@master-1 ~]# vim /usr/local/kubernetes/cfg/kube-apiserver
--requestheader-client-ca-file=/usr/local/kubernetes/ssl/ca.pem \
--requestheader-allowed-names=aggregator \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--proxy-client-cert-file=/usr/local/kubernetes/ssl/kube-proxy.pem \
--proxy-client-key-file=/usr/local/kubernetes/ssl/kube-proxy-key.pem"
[root@master-1 ~]# systemctl daemon-reload
[root@master-1 ~]# systemctl restart kube-apiserver

证书位置自行修改吧,下面改一下metrics-server-deployment.yaml,我用的是1.8+目录内的部署文件,也就是最新的,需要改一下镜像地址,默认的下不了撒,还要修改默认的启动命令,具体如下。

      containers:
      - name: metrics-server
        image: swr.cn-north-1.myhuaweicloud.com/rj-bai/metrics-server-amd64:v0.3.3
        imagePullPolicy: IfNotPresent
        command:
        - /metrics-server
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
        volumeMounts:

这样就阔以了撒,创建吧,顺便禁止master节点运行pod

[root@master-1 ~/metrics-server/deploy/1.8+]# kubectl taint nodes master-{1..2} node-role.kubernetes.io/master=true:NoSchedule
[root@master-1 ~/metrics-server/deploy/1.8+]# kubectl create -f .
[root@master-1 ~/metrics-server/deploy/1.8+]# kubectl -n kube-system get pod
[root@master-1 ~/metrics-server/deploy/1.8+]# kubectl -n kube-system logs metrics-server-97dbf6fc9-pwp7d 

没问题,pod正常启动了,然后看一下podnode的资源利用率。

[root@master-1 ~]# kubectl top node 
Error from server (Forbidden): nodes.metrics.k8s.io is forbidden: User "system:kube-proxy" cannot list resource "nodes" in API group "metrics.k8s.io" at the cluster scope

然后就抛错了,看上去是kube-proxy用户莫得权限,emmmm,授一下权吧。

[root@master-1 ~]# kubectl create clusterrolebinding cluster-kube-proxy --clusterrole=cluster-admin --user=system:kube-proxy
[root@master-1 ~]# kubectl top node 
[root@master-1 ~]# kubectl top pod -n kube-system 

收集数据正常,可以进行下一步操作了。

自动伸缩实例

还是基于官方文档,镜像我做好了,直接运行就完了,首先创建一个特别吃CPUpod,然后启动N个client去访问他,等所有podCPU平均使用率到我预定的值,就开始扩容pod了,下面试试,先启动server端,直接用命令启动了。

创建server端

[root@master-1 ~]# kubectl run php-apache --image=swr.cn-north-1.myhuaweicloud.com/rj-bai/hpa:php --requests=cpu=500m --expose --port=80
[root@master-1 ~]# kubectl get pod,services

注意deployment的名字不要改撒,我在client脚本里是写死的,而且做了资源限制,500m cpu,也就是0.5核,暴露80端口出来,已经创建好了,下面创建一下Horizontal Pod Autoscaler

创建HPA

[root@master-1 ~]# kubectl autoscale deployment php-apache --cpu-percent=60 --min=1 --max=20
horizontalpodautoscaler.autoscaling/php-apache autoscaled
[root@master-1 ~]# kubectl get hpa -w

主要看的是这里,如果一直是unknown就说明你的metrics有问题,刚刚那条命令的意思是所有POD 的 CPU平均使用率超了百分之六十(最近一分钟的平均值)就要进行扩展了,最大扩展到20个,最小保留一个,现在就是CPU使用率是0,因为木有人去访问他,现在启动client吧。

创建client&测试

[root@master-1 ~]# kubectl run client --image=swr.cn-north-1.myhuaweicloud.com/rj-bai/hpa:client 
[root@master-1 ~]# kubectl get pod -w
NAME                          READY   STATUS              RESTARTS   AGE
client-5d7768fc5d-4tt4l       0/1     ContainerCreating   0          6s

暂时就先创建一个,一会有必要的话再扩展,正在创建,创建完成之后动态看一下hpa&pod的状态,等他稳定下来之后我贴张图,先下去抽根烟。

回来了,总共启动了三个,然后我新开一个窗口,将client扩展一下,扩展到5

[root@master-1 ~]# kubectl scale deployment --replicas=5 client 
deployment.extensions/client scaled

再等一会稳定下来后截图

稳定下来了,从三个自动扩展到了14个,如图。

这样看自动扩展是没问题了,再看一下自动收缩,现在将client调整到两个,

[root@master-1 ~]# kubectl scale deployment --replicas=2 client 
deployment.extensions/client scaled

稳定下来后贴图。

稳定下来了撒,看图,从14pod自动缩到了现在的7个。

这样看有点耗时间,自动扩展的冷却延时时间为五分钟,如需调整请修改kube-controller-manager配置文件添加如下内容。

--horizontal-pod-autoscaler-downscale-stabilization=3m0s \

最后看一眼hpa&pod

大概就是这种效果,莫得问题,一个最简单的实例,需要使用这个功能的时候必须要指定指标,否则无效,用白话总结一下,刚刚我创建的那个hpa可以保证所有podCPU使用率不超过60,如果平均超了百分之六十,我就要进行扩展了,最高存在20pod,等啥子时候使用率低了,最低保留一个pod,就是这样,正常生产的话资源限制不会这么低,目前就是为了看效果,下面再看看之前健康检查遇到的坑。

健康检查的坑

再一个就是健康检查的问题,目前公司线上用的还是swarm,就在上个月出了一个问题,有一个小系统,用了6个服务器,其中五个跑基础服务,一个配置比较好的服务器跑业务项目,这时候的服务器配置还算可以,不用担心资源不够的问题,直到有一点有人找我说现在服务器能不能降一下配,现在也没什么太大的量,啥时候用量大了再加,但是我表示不能再降了,项目很多的,有的还启动了多个副本,可能会出现资源不够用的风险,但是人家坚持要降,那就没办法了,我就降了,然后改了一个项目的内存限制,副本数还是之前的那些,资源更紧张了,感觉在某一天绝对要教训我们一下。

果然几天后,开发的大哥找我说现在项目莫名其妙的在一直重启,是不是服务器被黑了,我一听项目一直在重启,我大概知道了发生什么了,到家之后没看别的,先看了一眼系统日志,发现了这些,我截了一段。

物理内存爆了,而且没用启用swap,使用swap物理内存不够之后系统就卡死,运气好的话还能动,最严重的时候需要在阿里云的后台重启服务器,而且重启也要好长时间,之前确实是经历过几次,所以一直就没启用swap

既然物理内存不够了内核就开始杀进程了,从占用最高的开始,一直杀到尾,上面只是贴了一个,这里先甩一波锅,特么的这套系统没zabbix,就六台云服务器且资源紧张,阿里云账户绑定的手机号也不知道是谁的,如果有告警发出来也就是发到了那个绑定的手机号上,所以我没及时发现问题。大概就这样。

开发的大哥说项目无限重启,重新部署也不行,我:

不用看了,问题就出在了容器健康检查这里,因为所有项目容器都内核被杀了,而且我用的还是swarm,这个不用多说了吧,swarm会帮你重新拉起那些被杀掉的容器,我看了一下一共是8个服务,崩掉的只是业务服务器,跑基础服务的服务器没有问题,所以最少有8个项目容器在同时启动,所以CPU直接炸了,而且最要命的是这八个项目都在同一台服务器上,在健康检查的时间范围内根本无法正常启动,CPU百分之四百没下来过,最终的办法就是通过scale将后台相关的项目副本数调整了0,腾出了一部分资源,优先启动了接口和对外提供服务的项目,削减了一些服务的副本数,折腾了几分钟算是恢复了。

最后再来聊聊健康检查的逻辑,之前提过k8s的健康检查逻辑,其实swarm健康检查逻辑k8slivenessProbe&readinessProbe两种类型的逻辑一致,但是检查方法这里swarm只能执行命令,健康检查失败之后重启容器,如果容器没有健康检查成功就不会接收请求,而且健康检查生产环境不得不加,否则问题会特别大,swarm的延时更新就是扯淡的,照样丢请求。

在启动了健康检查之后在滚动更新的时候也会特别慢,在更新某一个容器的时候要等到健康检查成功之后才会去更新下一个,k8s支持按pod总数量的百分比去更新,这个就比较舒服了,swarm就不行了,默认1,如果副本太多就需要在更新的时候指定同时更新的个数了。

总之这东西就是把双刃剑,配置好了无损更新服务,配置不好可能会导致服务瘫痪,像是上文服务器崩了全部瘫痪,健康检查无法成功,如果没有健康检查可能时间会久一点,项目都能正常启动,我目前所有项目的都是检查三次,一分钟一次,三分钟之内正常来说项目已经起来了,如果说三分钟之内还是没有正常启动就可能有问题了,所以判定更新失败直接回滚,最后推荐一个swarm的图形化工具吧,用着也是蛮方便的,官方,部署文件如下,官网扒过来的。

[root@docker-manager ~]# cat portainer.yml 
version: '3.7'
services:
  server:
    image: portainer/portainer:latest
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    ports:
      - "9000:9000"
    volumes:
      - portainer_data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - portainer
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
  agent:
    image: portainer/agent:latest
    environment:
      AGENT_CLUSTER_ADDR: tasks.agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    ports:
      - target: 9001
        published: 9001
        protocol: tcp
        mode: host
    networks:
      - portainer
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

networks:
  portainer:
    driver: overlay
    attachable: true

volumes:
  portainer_data:
[root@docker-manager ~]# docker stack deploy -c portainer.yml portainer

然后打开你的IP:9000就可以访问到了,创建用户名密码之后登陆。

一些很实用的功能,远程连接容器看日志管理服务,功能还是蛮多的,自行探索吧,距离生产使用k8s还有一段路要走,暂时就这样吧,溜了。

返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码