虚拟化容器,大数据,DBA,中间件,监控。

Kubernetes HPA pod扩容缩容基于Metrics Server

19 05月
作者:admin|分类:容器虚拟化

第三种 Metrics,是 Kubernetes 相关的监控数据。这部分数据,一般叫作 Kubernetes 核心监控数据(core metrics)。这其中包括了 Pod、Node、容器、Service 等主要 Kubernetes 核心概念的 Metrics。

其中,容器相关的 Metrics 主要来自于 kubelet 内置的 cAdvisor 服务。在 kubelet 启动后,cAdvisor 服务也随之启动,而它能够提供的信息,可以细化到每一个容器的 CPU 、文件系统、内存、网络等资源的使用情况。

需要注意的是,这里提到的 Kubernetes 核心监控数据,其实使用的是 Kubernetes 的一个非常重要的扩展能力,叫作 Metrics Server。

Metrics Server 在 Kubernetes 社区的定位,其实是用来取代 Heapster 这个项目的。在 Kubernetes 项目发展的初期,Heapster 是用户获取 Kubernetes 监控数据(比如 Pod 和 Node 的资源使用情况) 的主要渠道。而后面提出来的 Metrics Server,则把这些信息,通过标准的 Kubernetes API 暴露了出来。这样,Metrics 信息就跟 Heapster 完成了解耦,允许 Heapster 项目慢慢退出舞台。

而有了 Metrics Server 之后,用户就可以通过标准的 Kubernetes API 来访问到这些监控数据了。比如,下面这个 URL:

http://127.0.0.1:8001/apis/metrics.k8s.io/v1beta1/namespaces/<namespace-name>/pods/<pod-name>

当你访问这个 Metrics API 时,它就会为你返回一个 Pod 的监控数据,而这些数据,其实是从 kubelet 的 Summary API (即 <kubelet_ip>:<kubelet_port>/stats/summary)采集而来的。Summary API 返回的信息,既包括了 cAdVisor 的监控数据,也包括了 kubelet 本身汇总的信息。

需要指出的是, Metrics Server 并不是 kube-apiserver 的一部分,而是通过 Aggregator 这种插件机制,在独立部署的情况下同 kube-apiserver 一起统一对外服务的。

这里,Aggregator APIServer 的工作原理,可以用如下所示的一幅示意图来表示清楚: 

可以看到,当 Kubernetes 的 API Server 开启了 Aggregator 模式之后,你再访问 apis/metrics.k8s.io/v1beta1 的时候,实际上访问到的是一个叫作 kube-aggregator 的代理。而 kube-apiserver,正是这个代理的一个后端,而 Metrics Server,则是另一个后端。

 而且,在这个机制下,你还可以添加更多的后端给这个 kube-aggregator。所以 kube-aggregator 其实就是一个根据 URL 选择具体的 API 后端的代理服务器。通过这种方式,我们就可以很方便地扩展 Kubernetes 的 API 了。

而 Aggregator 模式的开启也非常简单:

  • 如果你是使用 kubeadm 或者官方的 kube-up.sh 脚本部署 Kubernetes 集群的话,Aggregator 模式就是默认开启的
  • 如果是手动 DIY 搭建的话,你就需要在 kube-apiserver 的启动参数里加上如下所示的配置: 
--requestheader-client-ca-file=<path to aggregator CA cert>
--requestheader-allowed-names=front-proxy-client
--requestheader-extra-headers-prefix=X-Remote-Extra
---requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--proxy-client-cert-file=<path to aggregator proxy cert>
--proxy-client-key-file=<path to aggregator proxy key>

 而这些配置的作用,主要就是为 Aggregator 这一层设置对应的 Key 和 Cert 文件。而这些文件的生成,就需要你自己手动完成了,具体流程请参考这篇官方文档。

Aggregator 功能开启之后,你只需要将 Metrics Server 的 YAML 文件部署起来,如下所示:

$ git clone https://github.com/kubernetes-incubator/metrics-server
$ cd metrics-server
$ kubectl create -f deploy/1.8+/

接下来,你就会看到 metrics.k8s.io 这个 API 出现在了你的 Kubernetes API 列表当中。

以上来自极客时间张磊的k8s里面相关内容

 

Pod自动扩容/缩容:HPA介绍


Horizontal Pod Autoscaler(HPA,Pod水平自动伸缩): 根据资源利用率或者自定义指标自动调整Deployment的Pod副本数量,提供应用并发。HPA不适于无法缩放的对象,例如DaemonSet。

 

Pod自动扩容/缩容:HPA基本工作原理


Kubernetes 中的 Metrics Server 持续采集所有 Pod 副本的指标数据。HPA 控制器通过 Metrics Server 的 API(聚合 API)获取这些数据,基于用户定义的扩缩容规则进行计算,得到目标 Pod 副本数量。当目标 Pod 副本数量与当前副本数量不同时,HPA 控制器就向 Pod 的Deployment控制器发起scale 操作,调整 Pod 的副本数量,完成扩缩容操作。

聚合层就像nginx一样代理多个应用,并且可以根据在浏览器输入的uri转发到后端的不同应用,聚合层就是代理的作用,有了代理就可以让第三方应用注册到该api上面,访问这个api就可以访问这个代理

HPA控制器会获取指标,这个指标从pod这里获取的,然后hpa对比这个指标和阈值,如果与阈值相同就去扩容

HPA-->apiserver-->获取指标-->pod

可以看到聚合层就扩展了api

 

Pod自动扩容/缩容:使用HPA前提条件


 使用HPA,确保满足以下条件:

启用Kubernetes API聚合层
相应的API已注册:
对于资源指标(例如CPU、内存),将使用metrics.k8s.io API,一般由metrics-server提供。
对于自定义指标(例如QPS),将使用custom.metrics.k8s.io API,由相关适配器(Adapter)服务提供。
已知适配器列表:https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api
 
Kubernetes API聚合层: 在 Kubernetes 1.7 版本引入了聚合层,允许第三方应用程序通过将自己注册到kube-apiserver上,仍然通过 API Server 的 HTTP URL 对新的 API 进行访问和操作。为了实现这个机制,Kubernetes 在 kube-apiserver 服务中引入了一个 API 聚合层(API Aggregation Layer),用于将扩展 API 的访问请求转发到用户服务的功能。

部署metrics-server会注册到聚合层,访问该地址的时候就会转发到metrics-server上面,metrics-server根据该指标做扩容的条件

根据不同的url访问不同的api帮你转发到后面不同的服务,只要你的服务可以注册到该聚合层就行

注册的接口名字也不一样

  • 访问metrics.k8s.io API  资源接口会代理到metrics-server
  • 访问 custom.metrics.k8s.io API 会代理到适配器上面

 

 

启用聚合层


如果你使用kubeadm部署的,默认已开启。这一部分就是:
 
 - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
- --requestheader-username-headers=X-Remote-User
你使用二进制方式部署的话,需要在kube-APIServer中添加启动参数,增加以下配置:
[root@k8s-master ~]# vim /opt/kubernetes/cfg/kube-apiserver.conf 
...
--requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \
--proxy-client-cert-file=/opt/kubernetes/ssl/server.pem \
--proxy-client-key-file=/opt/kubernetes/ssl/server-key.pem \
--requestheader-allowed-names=kubernetes \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--enable-aggregator-routing=true \
...

这个启用了就可以去做hpa了,所以这是前提条件

 

基于资源的指标,需要部署server-metrics组件


Metrics Server: 是一个数据聚合器,从kubelet收集资源指标,并通过Metrics API在Kubernetes apiserver暴露,以供HPA使用。(只做数据的收集,不做处理和存储)
项目地址:https://github.com/kubernetes-sigs/metrics-server
Kubelet里面集成了cadvisor,cadvisor收集了容器资源的利用率,然后通过kubelet暴露出来

这个就是让自己注册到apiserver里面的资源

apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100

指定访问kubelet地址的类型,以逗号分隔,越靠前越以这种方式访问kubelet,最先使用的是使用内部IP去访问的

 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname

[root@k8s-master ~]# kubectl get node -o wide
NAME         STATUS   ROLES    AGE   VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
k8s-master   Ready    master   94d   v1.19.0   192.168.179.102   <none>        CentOS Linux 7 (Core)   3.10.0-1160.2.2.el7.x86_64   docker://19.3.13

优先使用这个ip去访问kubelet,因为上面列出的就是kubelet的信息 192.168.179.102

部署metrics-server

# wget https://github.com/kubernetes-sigs/metricsserver/releases/download/v0.3.7/components.yaml
# vi components.yaml
...
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --kubelet-insecure-tls
image: lizhenliang/metrics-server:v0.4.1
...



[root@k8s-master ~]# kubectl apply -f metrics-server.yaml 
[root@k8s-master ~]# kubectl get pod -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
metrics-server-b66888848-gdnrq             1/1     Running   0          74s

查看聚合层API注册的状态

[root@k8s-master ~]# kubectl get apiservice
NAME                                   SERVICE                      AVAILABLE   AGE
v1beta1.metrics.k8s.io                 kube-system/metrics-server   True        <invalid>

False (MissingEndpoints) 这个状态是没有关联到后端的pod,这就相对于代理的配置,如果关联到Pod这里时true的状态

测试api原始接口的地址,可以看到返回了json的字符串就说明正常工作的,可以看到节点cpu使用率

[root@k8s-master ~]# kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes
{"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/nodes"},"items":[{"metadata":{"name":"k8s-master","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/k8s-master","creationTimestamp":"2021-02-18T07:20:44Z"},"timestamp":"2021-02-18T07:19:43Z","window":"30s","usage":{"cpu":"300304738n","memory":"942972Ki"}},{"metadata":{"name":"k8s-node1","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/k8s-node1","creationTimestamp":"2021-02-18T07:20:44Z"},"timestamp":"2021-02-18T07:19:50Z","window":"30s","usage":{"cpu":"234243064n","memory":"646960Ki"}},{"metadata":{"name":"k8s-node2","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/k8s-node2","creationTimestamp":"2021-02-18T07:20:44Z"},"timestamp":"2021-02-18T07:19:52Z","window":"30s","usage":{"cpu":"313624781n","memory":"612420Ki"}}]}

获取所有pod资源的消耗了

[root@k8s-master ~]# kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods
{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/pods"},"items":[{"metadata":{"name":"nginx-6799fc88d8-drb2s","namespace":"default","selfLink":"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/nginx-6799fc88d8-drb2s","creationTimestamp":"2021-02-18T07:25:03Z"},"timestamp":"2021-02-18T07:24:46Z","window":"30s","containers":[{"name":"nginx","usage":{"cpu":"0","memory":"1892Ki"}}]},{"metadata":{"name":"calico-kube-controllers-5c6f6b67db-q5qb6","namespace":"ku

上面说明直接请求uri是没有问题的 

也可以使用kubectl top访问Metrics API:
[root@k8s-master ~]# kubectl top node
NAME         CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
k8s-master   415m         41%    929Mi           72%       
k8s-node1    269m         26%    632Mi           52%       
k8s-node2    366m         36%    601Mi           46%   

[root@k8s-master ~]# kubectl top node
Error from server (ServiceUnavailable): the server is currently unable to handle the request (get nodes.metrics.k8s.io)    


[root@k8s-master ~]# kubectl top pod
NAME                     CPU(cores)   MEMORY(bytes)   
nginx-6799fc88d8-drb2s   0m           1Mi 

[root@k8s-master ~]# kubectl top pod
Error from server (ServiceUnavailable): the server is currently unable to handle the request (get pods.metrics.k8s.io)

Kubectl top ->apiserver->metrics server-> kubelet(cadvisor)->pod

现在就可以根据指标做弹性伸缩了

 
 

Pod自动扩容/缩容:基于资源指标


1、部署应用

这里要配置resource,因为HPA的阈值的比对参考resource里面定义的 

[root@k8s-master ~]# kubectl apply -f deployment.yaml 
deployment.apps/web created
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: 
          requests: 
            cpu: 0.5

[root@k8s-master ~]# kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
web-67bbbf48fc-9gpqh   1/1     Running   0          21s
[root@k8s-master ~]# kubectl expose deployment web --port=80 --target-port=80 --dry-run=client -o yaml > service.yaml


[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP   95d
web          ClusterIP   10.107.190.232   <none>        80/TCP    2s
[root@k8s-master ~]# curl 10.107.190.232:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
2、创建HPA

现在创建hap,这里只支持cpu指标

[root@k8s-master ~]# kubectl autoscale deployment web --min=2 --max=10 --cpu-percent=30
horizontalpodautoscaler.autoscaling/web autoscaled
[root@k8s-master ~]# kubectl get hpa
NAME   REFERENCE        TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
web    Deployment/web   0%/30%    2         10        2          5m3s
3、压测
yum install httpd-tools
ab -n 200000 -c 1000 http:/10.107.190.232/index.html # 总20w请求,并发1000
4、观察扩容状态
[root@k8s-master ~]# kubectl get hpa
NAME   REFERENCE        TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
web    Deployment/web   42%/30%   2         10        2          2m28s
[root@k8s-master ~]# kubectl get hpa
NAME   REFERENCE        TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
web    Deployment/web   42%/30%   2         10        3          2m50s
[root@k8s-master ~]# kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
web-67bbbf48fc-9gpqh   1/1     Running   0          25m
web-67bbbf48fc-cpfrz   1/1      Runing   0          2m1s
web-67bbbf48fc-zfth7   1/1      Running   0          14m

可以看到扩容了副本数

 

Pod自动扩容/缩容:冷却周期


在弹性伸缩中,冷却周期是不能逃避的一个话题, 由于评估的度量标准是动态特性,副本的数量可能会不断波动,造成丢失流量,所以不应该在任意时间扩容和缩容

不断的扩容缩容会造成流量的丢失,因为在不断的增加pod和删除pod

如果负载下去了,也不是马上帮你缩放到原来的个数,这个是有一个等待周期的

在 HPA 中,为缓解该问题,默认有一定控制:

  • --horizontal-pod-autoscaler-downscale-delay :当前操作完成后等待多次时间才能执行缩容操作,默认5分钟
  • --horizontal-pod-autoscaler-upscale-delay :当前操作完成后等待多长时间才能执行扩容操作,默认3分钟

这两个参数是在controlmanager当中配置的:

如果冷却时间太长的情况下,可能应对的负载不是很及时,给你增加pod扩容操作就不会很及时,设置太短,副本数就会出现抖动

 

浏览578 评论0
返回
目录
返回
首页
Kubernetes HPA 使用详解 ETCD 集群的备份和恢复