k8s

Metrics Server介绍

Posted by Mathew on 2019-12-20

Metrics Server本身是以deployment方式部署,只需要配置多副本集到不同节点即可满足高可用,了解下Metrics Server背景和工作流程。

一、Metrics Server背景

kubernetesv1.11以后不再支持通过heaspter采集监控数据,支持新的监控数据采集组件metrics-server,比heaspter轻量很多,也不做数据的持久化存储,提供实时的监控数据查询还是很好用的。

   1)metrics-server 通过 kube-apiserver 发现所有节点,然后调用 kubelet APIs(通过 https 接口)获得各节点(Node)和 Pod 的 CPU、Memory 等资源使用情况。从v1.8开始,资源使用情况的监控可以通过Metrics API的形式获取,具体的组件为Metrics-Server,用来替换之前的heapster,从 Kubernetes 1.12 开始,kubernetes 的安装脚本移除了 Heapster,从 1.13 开始完全移除了对 Heapster 的支持,Heapster 不再被维护。
   2)Metrics-Server是集群核心监控数据的聚合器,从Kubernetes1.8开始,它作为一个Deployment对象默认部署在由kube-up.sh脚本创建的集群中;
   3)kubernetes的新监控体系中,metrics-server属于Core metrics(核心指标),提供API-metrics.k8s.io,主要作用为kube-scheduler,HorizontalPodAutoscaler等k8s核心组件,以及kubectl top命令和Dashboard等UI组件提供数据来源。

二、Metrics-Server在k8s监控体系中的位置

k8s最新监控体系
k8s最新的监控体系架构.png

1)Metrics server定时从Kubelet的Summary API(类似/ap1/v1/nodes/nodename/stats/summary)采集指标信息,这些聚合过的数据将存储在内存中,且以metric-api的形式暴露出去;即metrics-server通过调用Kubelet Summary API获取采集核心指标数据,给k8s集群内的kubectl,hpa,scheduler等组件使用;
2)Metrics server复用了api-server的库来实现自己的功能,比如鉴权、版本等,为了实现将数据存放在内存中,去掉了默认的etcd存储,引入了内存存储(即实现Storage interface)。因为存放在内存中,因此监控数据是没有持久化的,可以通过第三方存储来拓展,这个和heapster是一致的;Metrics-server负责采集的核心指标数据,虽然是放在内存中但也是需要缓存的,所以使用emptyDIr存储卷,当然也可以使用持久存储卷;
3)如上图,Metrics server出现后,新的​Kubernetes 监控架构将变成上图的样子:
   (1)核心流程(黑色部分):这是Kubernetes正常工作所需要的核心度量,从Kubelet、cAdvisor等获取度量数据,再由metrics-server提供Dashboard、HPA控制器等使用;
   (2)监控流程(蓝色部分):基于核心度量构建的监控流程,比如Prometheus可以从metrics-server获取核心度量,从其他数据源(如Node_Exporter等)获取非核心度量,再基于它们构建监控告警系统;
   (3)Metric-Server属于kubenetes处于孵化的项目;它有两个组件:
      Metrics API #提供resource定义,即自定义apiserver
      Metrics server #定义背后resource资源定义是否合法

三、Metrics API的概念:

   1)Metrics API相比于之前的监控采集方式(hepaster)是一种新的思路,官方希望核心指标的监控应该是稳定的,版本可控的,且可以直接被用户访问(例如通过使用 kubectl top 命令),或由集群中的控制器使用(如HPA),和其他的Kubernetes APIs一样;

   2)官方废弃heapster项目,就是为了将核心资源监控作为一等公民对待,即像pod、service那样直接通过api-server或者client直接访问,不再是安装一个hepater来汇聚且由heapster单独管理;

   3)假设每个pod和node我们收集10个指标,最新版本k8s官方文档描述中提到支持5000+节点,假设每个节点30个pod,假设采集粒度为1分钟一次,则:10 x 5000 x 30 / 60 = 25000 平均每分钟2万多个采集指标;

   4)因为k8s的api-server将所有的数据持久化到了etcd中,k8s本身不能处理这种频率的采集,而且这种监控数据变化快且都是临时数据,因此需要有一个组件单独处理他们,k8s只存放部分在内存中,于是metric-server的概念诞生了;

   5)其实hepaster已经有暴露了api,但是用户和Kubernetes的其他组件必须通过master proxy的方式才能访问到,且heapster的接口不像api-server一样,有完整的鉴权以及client集成;

   6)有了Metrics Server组件,也采集到了该有的数据,也暴露了api,但因为api要统一,如何将请求到api-server的/apis/metrics请求转发给Metrics-Server呢,解决方案就是:kube-aggregator,在k8s的1.7中已经完成,之前Metrics-Server一直没有面世,就是耽误在了kube-aggregator这一步(目前线上 1.14和1.15版本k8s集群部署了metrics-server组件);
kube-aggregator(聚合api)主要提供:
   (1)Provide an API for registering API servers.
   (2)Summarize discovery information from all the servers.
   (3)Proxy client requests to individual servers.

   7)metrics api的使用:

    (1)Metrics API只可以查询当前的度量数据,并不保存历史数据
    (2)Metrics API URI为/apis/metrics.k8s.io/在k8s.io/metrics维护
    (3)必须部署metrics-server才能使用该 API,metrics-server通过调用Kubelet Summary API获取数据;
例如:
http://127.0.0.1:8080/apis/metrics.k8s.io/v1beta1/nodes
http://127.0.0.1:8080/apis/metrics.k8s.io/v1beta1/nodes/<node-name>
http://127.0.0.1:8080/apis/metrics.k8s.io/v1beta1/namespace/<namespace-name>/pods/<pod-name>

再结合kube-aggregator看下整体数据流转

image.png
 使用kubectl top nodes命令查看node节点cpu、memory资源使用情况时底层会请求apiserver的/apis/metric.k8s.io/v1beta1/ 这个metrics-server提供的metric uri,这个uri时候会被aggregator聚合层proxy到 metrics-server 的endpoint。

   在metrics-server官方部署参考中,metrics-sever以deployment形式部署,作为metrics-server svc的endpoint存在,对外以clusterip提供服务。所以metrics-server服务的高可用,保证集群内metrics-server多副本分散在不同节点部署即可。
如下图:
image.png

四、部署关键点

  1. 开启 API Aggregation

前面已经了解到要想使用metric api的调用会经过聚合层kube-aggregator的proxy所以在部署 metrics-server 之前,需要在 kube-apiserver 中开启 API Aggregation,即增加以下配置:

1
2
3
4
5
6
7
8
--proxy-client-cert-file=/etc/kubernetes/certs/proxy.crt
--proxy-client-key-file=/etc/kubernetes/certs/proxy.key
--requestheader-client-ca-file=/etc/kubernetes/certs/proxy-ca.crt
--requestheader-allowed-names=aggregator
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--enable-aggregator-routing=true
  1. 部署 metrics-server
      Metrics-Server在Kubernetes集群中表现为一个Deployment对象。不过准确地说,它是Deployment,Service,ClusterRole,ClusterRoleBinding,APIService,RoleBinding资源对象的综合体
    部署过程待补充

  2. 验证

  • 检查metrics api是否正常
    image.pngv1beta1.metrics.k8s.iometrics api的请求会转发到kube-system/metrics-server
    image.png
  • 检查metrics-server deployment
1
2
3
4
5
6
注意:这里对应的node节点需要启动kube-proxy否则pod会一直crash

[root@lfrz-platform-kube-master-a001.prod.lfrz.momo.com ~]# kubectl get deploy -n kube-system | grep metric
metrics-server-v0.3.2 1/1 1 1 14h
[root@lfrz-platform-kube-master-a001.prod.lfrz.momo.com ~]# kubectl get pod -n kube-system -o wide | grep metric
metrics-server-v0.3.2-7fd455f458-hq2zw 2/2 Running 2 14h 10.116.2.2 lfrz-platform-kube-node-a009.prod.lfrz.momo.com <none> <none>

   这里会看到pod里面有两个容器,解释下两个容器作用:
    1)metrcis-server:访问node10250端口获取node 和 pod cpu、memory使用情况
    2) pod_nanny:Metrics Server的资源占用量会随着集群中的Pod数量的不断增长而不断上升,因此需要addon-resizer垂直扩缩这个容器。addon-resizer依据集群中节点的数量线性地扩展Metrics Server,以保证其能够有能力提供完整的metrics API服务,具体参考

  • kubectl top验证
    image.png

  • kubectl 访问metric api验证
    image.png

  • node节点需要启动kebe-proxy,kube-proxy会监测svc变化动态更新iptables规则保证clusterip和pod的通信正常
    分析节点iptables

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Generated by iptables-save v1.4.21 on Thu Dec 19 19:51:02 2019
*nat
:PREROUTING ACCEPT [7840:524996]
:INPUT ACCEPT [2229:148644]
:OUTPUT ACCEPT [17370:1205583]
:POSTROUTING ACCEPT [22918:1577143]
:KUBE-MARK-MASQ - [0:0]
:KUBE-NODEPORTS - [0:0]
:KUBE-POSTROUTING - [0:0]
:KUBE-SEP-AJIBZNOXY25CI64Z - [0:0]
:KUBE-SEP-DG7GAPH5E46FMQLD - [0:0]
:KUBE-SEP-QDUJWM4LTCAIM4ZL - [0:0]
:KUBE-SEP-S6NVP3Q37LNJW7RG - [0:0]
:KUBE-SERVICES - [0:0]
:KUBE-SVC-LC5QY66VUV2HJ6WZ - [0:0]
:KUBE-SVC-NPX46M4PTMTKRN6Y - [0:0]
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
-A KUBE-SEP-AJIBZNOXY25CI64Z -s 10.96.102.31/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-AJIBZNOXY25CI64Z -p tcp -m tcp -j DNAT --to-destination 10.96.102.31:6443
-A KUBE-SEP-DG7GAPH5E46FMQLD -s 10.96.101.31/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-DG7GAPH5E46FMQLD -p tcp -m tcp -j DNAT --to-destination 10.96.101.31:6443
-A KUBE-SEP-QDUJWM4LTCAIM4ZL -s 10.116.2.2/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-QDUJWM4LTCAIM4ZL -p tcp -m tcp -j DNAT --to-destination 10.116.2.2:443
-A KUBE-SEP-S6NVP3Q37LNJW7RG -s 10.96.101.161/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-S6NVP3Q37LNJW7RG -p tcp -m tcp -j DNAT --to-destination 10.96.101.161:6443
-A KUBE-SERVICES -d 192.168.97.242/32 -p tcp -m comment --comment "kube-system/metrics-server: cluster IP" -m tcp --dport 443 -j KUBE-SVC-LC5QY66VUV2HJ6WZ
-A KUBE-SERVICES -d 192.168.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
-A KUBE-SVC-LC5QY66VUV2HJ6WZ -j KUBE-SEP-QDUJWM4LTCAIM4ZL
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-S6NVP3Q37LNJW7RG
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-DG7GAPH5E46FMQLD
-A KUBE-SVC-NPX46M4PTMTKRN6Y -j KUBE-SEP-AJIBZNOXY25CI64Z
COMMIT
# Completed on Thu Dec 19 19:51:02 2019
# Generated by iptables-save v1.4.21 on Thu Dec 19 19:51:02 2019
*filter
:INPUT ACCEPT [165166:26489144]
:FORWARD ACCEPT [764355:1257485599]
:OUTPUT ACCEPT [188084:192388172]
:DOCKER-USER - [0:0]
:KUBE-EXTERNAL-SERVICES - [0:0]
:KUBE-FORWARD - [0:0]
:KUBE-SERVICES - [0:0]
-A INPUT -m conntrack --ctstate NEW -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A INPUT -m conntrack --ctstate NEW -m comment --comment "kubernetes externally-visible service portals" -j KUBE-EXTERNAL-SERVICES
-A FORWARD -j DOCKER-USER
-A FORWARD -m comment --comment "kubernetes forwarding rules" -j KUBE-FORWARD
-A FORWARD -m conntrack --ctstate NEW -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m conntrack --ctstate NEW -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A DOCKER-USER -j RETURN
-A KUBE-FORWARD -m conntrack --ctstate INVALID -j DROP
-A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
COMMIT
# Completed on Thu Dec 19 19:51:02 2019

这里面主要是对访问clusterip的数据包打标记做dnat和snat,因为我们网络模式是ospf的bridge,podip可以直通bondip,所以从metric-server pod出向数据包不需要snat,默认直接可以和master地址通信,简化后iptables:

1
2
-A PREROUTING -d 192.168.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j DNAT --to-destination 10.96.101.31:6443
-A PREROUTING -d 192.168.97.242/32 -p tcp -m comment --comment "kube-system/metrics-server: cluster IP" -m tcp --dport 443 -j DNAT --to-destination 10.116.2.2:443

如果metric-server pod ip可固定的话,就不需要启动kube-proxy动态更新iptables。

  • 查看metric-server组成
    image.png
    (1) metrics-server二进制程序
    (2) 启动程序时候会生成访自签名证书用来访问节点summary/stats
    (3) --kubelet-preferred-address-types=InternalIP 指定连接node节点时候使用nodeip连
    这些启动参数在metrics-server yaml里面可以适当修改和适配

思考todo:

  1. 依据官方metrics-sever镜像重构加入ssh等工具包
  2. host网络模式部署metric-server

参考:

Resource Metrics API设计文档
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/resource-metrics-api.md
kube-aggregator 聚合层api设计文档:
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/aggregated-api-servers.md
k8s监控体系设计文档:
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/monitoring_architecture.md
metrics-server设计文档:
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/metrics-server.md
metric-server部署:
https://github.com/kubernetes-sigs/metrics-server#flags