集群外独立部署Prometheus+Grafana监控K8S全面解析

简介

Prometheus+Grafana作为监控K8S的解决方案,大都是在K8S集群内部部署,这样可以直接调用集群内的cert及各种监控url,但是增加了集群的资源开销。因此在资源有限的情况下,我更倾向于K8S集群外独立部署Prometheus+Grafana。

无论哪种部署方式,都需要通过exporter收集各种维度的监控指标,其维度如下:

维度 工具 监控url(__metrics_path__) 备注
Node性能 node-exporter /api/v1/nodes/node名:9100/proxy/metrics 节点状态
Pod性能 kubelet
cadvisor
/api/v1/nodes/node名:10250/proxy/metrics
/api/v1/nodes/node名:10250/proxy/metrics/cadvisor
容器状态
K8S资源 kube-state-metrics Deploy/ds等

大家可能在此有疑问,为什么kube-state-metrics没有监控url?
其实从上表可以看出,监控url并不完整,因为prometheus的动态发现会基于标签进行自动补全,补全格式为:__scheme__://__address____metrics_path__。其中标签的值都可以通过Prometheus的relabel_config拼接成最终的监控url。

正是基于以上原因,集群外部署Prometheus和集群内部署Prometheus是不一样的,因为集群内的Prometheus有的监控使用的是集群私有ip,而集群外Prometheus使用默认自动拼接的监控url是无法访问的,此时需要自行构造apiserver proxy URLs,可以参考Manually constructing apiserver proxy URLs。通过proxy url集群外Prometheus就可以访问监控url来拉取监控指标了。

上表中Pod性能和Node性能的监控url其实都是自行构造的proxy url,而K8S资源使用默认的监控url,就会发现其endpoint都是K8S集群内部的私有ip,因此所有的状态都是down的。
在这里插入图片描述但如果通过自行改造的proxy url访问,则所有的状态则是up的。
在这里插入图片描述

构造apiserver proxy url

通过Accessing services running on the cluster了解到在k8s集群中nodes、pods、services都有自己的私有IP,但是无法从集群外访问;但K8S提供以下几种方式来访问:

  • 通过public IPs访问service
  • 通过proxy 访问node、pod、service
  • 通过集群内的node或pod间接访问

而通过kubectl cluster-info可以查看kube-system命令空间的proxy url:

# kubectl cluster-info 
Kubernetes master is running at https://192.168.3.217:6443
KubeDNS is running at https://192.168.3.217:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://192.168.3.217:6443/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy

其默认的构造规则为:

# 访问node
https://${other_apiserver_address}/api/v1/nodes/node_name:[port_name]/proxy/metrics
# 访问service
https://${other_apiserver_address}/api/v1/namespaces/service_namespace/services/http:service_name[:port_name]/proxy/metrics
# 访问pod
https://${other_apiserver_address}/api/v1/namespaces/pod_namespace/pods/http:pod_name[:port_name]/proxy/metrics

在了解如何构造proxy url后,我们就可以通过集群外Prometheus的relabel_config自行构造proxy url了。

apiserver授权

要访问K8S apiserver需要先进行授权,而集群内部Prometheus可以使用集群内默认配置进行访问,而集群外访问需要使用token+客户端cert进行认证,因此需要先进行RBAC授权。

由于我们需要访问不同的namespace,因此我们最好分配cluster-admin,以免权限不足。具体步骤如下:

# 0.创建命名空间
  kubectl create ns devops
# 1.创建serviceaccounts
kubectl create sa  prometheus -n devops
# 2.创建prometheus角色并对其绑定cluster-admin
kubectl create clusterrolebinding prometheus --clusterrole cluster-admin --serviceaccount=devops:prometheus

# 注意:prometheus 在devops命名空间中

虽创建了serviceaccount,但访问apiserver并不是直接使用serviceaccount,而是通过token。因此我们需要获取serviceaccount:prometheus对应的token,而此token是经过base64加密过的,必须解密后才能使用。

# 1.查看sa,在默认namespace
# kubectl get sa 
NAME      SECRETS   AGE
default   1         113m
prometheus   1         19m

# 2.查看secret
# kubectl get sa prometheus -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2020-07-28T08:27:55Z"
  name: prometheus
  namespace: default
  resourceVersion: "14403390"
  selfLink: /api/v1/namespaces/default/serviceaccounts/prometheus
  uid: 43a98176-faa1-43f7-ad91-0352ca2dce2c
secrets:
- name: prometheus-token-44jkm

# 3.获取token,从yaml中得到token
# kubectl get secret  prometheus-token-44jkm -o yaml
...省略...
token: ZXlKaGJHY2lPaUpTV...
...省略...

# 4.token解密
# 由于此token是经过base64加密的,我们需要通过base64解密获取token值
# echo "xxxxxxxx" |base64 -d

通过一系列操作获得的token,可以作为bearer_token访问apiserver。

好了,了解以上几点后,接下来我们按以下顺序来介绍:

  1. 使用exporter收集各种K8S监控指标;
  2. Prometheus如何构造exporter的监控url;
  3. Grafana的图形化展示;

监控指标收集

1.node性能

通过node-exporter采集集群node节点的服务器层面的数据,如cpu、内存、磁盘、网络流量等,其监控url为"http://node_ip:9100/metrics"。
node-exporter可以独立部署在node节点服务器上,但Prometheus需要通过static_config静态配置手动添加监控,在集群扩展情况下,还需要再手动安装node-exporter。因此将node-exporter以DaemonSet形式部署,配合Prometheus动态发现更加方便。

# 1.vim node-exporter.yaml
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: node-exporter
  annotations:
    prometheus.io/scrape: 'true'
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
      name: node-exporter
    spec:
      containers:
      - image: quay.io/prometheus/node-exporter:latest
        name: node-exporter
        ports:
        - containerPort: 9100
          hostPort: 9100
          name: node-exporter
      hostNetwork: true
      hostPID: true
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

---
kind: Service
apiVersion: v1
metadata:
  annotations:
    prometheus.io/scrape: 'true'
  labels:
    app: node-exporter
  name: node-exporter
spec:
  type: ClusterIP
  clusterIP: None
  ports:
  - name: node-exporter
    port: 9100
    protocol: TCP
  selector:
    app: node-exporter

# 2.部署
kubectl apply -f node-exporter.yaml

注意:

  1. node-exporter以DaemonSet部署并且设置为hostNetwork,可通过宿主机ip+9100直接访问,因此我认为Service可以不创建,经测试是可以的
  2. node-exporter需要收集集群内所有节点,而master节点默认有NoSchedule污点,即不参与任何调度;因此我们需要单独设置toleration来使master节点也可以部署node-exporter;
  3. 添加prometheus.io/scrape: 'true’用于自动发现;

2.pod性能

cAdvisor 是一个开源的分析容器资源使用率和性能特性的代理工具,集成到 Kubelet中,当Kubelet启动时会同时启动cAdvisor,且一个cAdvisor只监控一个Node节点的信息。cAdvisor 自动查找所有在其所在节点上的容器,自动采集 CPU、内存、文件系统和网络使用的统计信息。cAdvisor 通过它所在节点机的 Root 容器,采集并分析该节点机的全面使用情况。

当然kubelet也会输出一些监控指标数据,因此pod的监控数据有kubelet和cadvisor,监控url分别为
https://NodeIP:10250/metrics和https://NodeIP:10250/metrics/cadvisor。

由于kubelet天然存在,因此直接远程访问即可,无需做其他配置。

3.K8S资源对象

kube-state-metrics是一个简单的服务,它监听Kubernetes API服务器并生成关联对象的指标。 它不关注单个Kubernetes组件的运行状况,而是关注内部各种对象(如deployment、node、pod等)的运行状况。

# 1.下载部署文件

https://github.com/kubernetes/kube-state-metrics/tree/master/examples/standard

# 2.部署

kubectl apply -f service-account.yaml
kubectl apply -f cluster-role.yaml
kubectl apply -f cluster-role-binding.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

4.小结

监控数据的指标采集比较简单,按需部署即可。重点的是Prometheus如何配置k8s自动发现、通过构造apiserver proxy url拉取metrics,因为K8S中的资源都是动态的。

Prometheus

1.部署

Prometheus使用docker部署在K8S集群外。

# 1.创建持久化数据目录并授权
mkdir -p /App/prometheus/etc
# 默认启动的容器用户信息为:uid=65534(nobody) gid=65534(nogroup),如果不改成777 ,容器启动失败
chmod -R 777 /APP/prometheus

# 2.docker启动 
docker run -d -p 9090:9090 -v /App/prometheus/etc/prometheus.yml:/etc/prometheus/prometheus.yml -v /App/prometheus:/prometheus prom/prometheus

在后期我们可能要删除一些metric,此时需要调用API,默认是关闭的,可在容器启动时开启,因此我们使用docker-compose部署更合适:

# 1.编辑docker-compose.yaml
version: '3'
services:
prometheus:
image: prom/prometheus
container_name: prometheus
restart: always
ports:
- "9090:9090"
volumes:
- /App/prometheus/etc/prometheus.yml:/etc/prometheus/prometheus.yml
- /App/prometheus:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.enable-admin-api' # 控制对admin HTTP API的访问,其中包括删除时间序列等功能
- '--web.enable-lifecycle' # 支持热更新,直接执行localhost:9090/-/reload立即生效

# 2.启动
docker-compose up -d

# 3.删除metric
# curl -X POST -g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={job="kubernetes-kube-state"}'
{
    
    "status":"error","errorType":"unavailable","error":"admin APIs disabled"}

2.自动发现

kubernetes_sd_config从Kubernetes的REST API查找并拉取指标,并始终与集群状态保持同步。
可自动发现的几种role

  • node
    自动发现每个集群节点发现一个target,其地址默认为Kubelet的HTTP端口,如"https://192.168.3.217:10250/metrics"

  • service
    自动发现每个服务的每个服务端口的target。

  • pod
    自动发现所有容器及端口

  • endpoints
    自动发现service中的endpoint,如图
    在这里插入图片描述

  • ingrsss
    自动发现ingress中path

本次我们主要用到了node和endpoint,分别对应node级别和endpoint级别,但是默认情况自动生成的url有时是不可用的,这就需要我们通过以下内容学习relabel_configs如何使用了。

3.拉取node监控指标

标签 默认 构造后
__scheme__ https https
__address__ 192.168.3.217:10250 192.168.3.217:6443
__metrics_path__ /metrics /api/v1/nodes/uvmsvr-3-217:9100/proxy/metrics
完整url https://192.168.3.217:10250//metrics https://192.168.3.217:6443/api/v1/nodes/uvmsvr-3-217:9100/proxy/metrics

通过relabel_configs构造如下:

**注意:tls_config和bearer_token_file 必须在job内和kubernetes_sd_configs都存在,否则会导致认证失败。**

scrape_configs:
- job_name: "kube-state-metrics"
  scheme: https
  tls_config:
    insecure_skip_verify: true
  #使用apiserver授权部分解密的token值,以文件形式存储
  bearer_token_file: /prometheus/k8s_token
  # k8s自动发现具体配置
  kubernetes_sd_configs:
  # 使用endpoint级别自动发现
  - role: endpoints
    api_server: "https://192.168.3.217:6443"
    tls_config:
      insecure_skip_verify: true
    bearer_token_file: /prometheus/k8s_token
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_name]
    # 只保留指定匹配正则的标签,不匹配则删除
    action: keep
    regex: '^(kube-state-metrics)$'
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
    # 只保留指定匹配正则的标签,不匹配则删除
    action: keep
    regex: true
  - source_labels: [__address__]
    action: replace
    target_label: instance
  - target_label: __address__
    # 使用replacement值替换__address__默认值
    replacement: 192.168.3.217:6443
  - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_name, __meta_kubernetes_pod_container_port_number]
    # 正则匹配
    regex: ([^;]+);([^;]+);([^;]+)
    # 使用replacement值替换__metrics_path__默认值
    target_label: __metrics_path__
    # 自行构建的apiserver proxy url
    replacement: /api/v1/namespaces/${1}/pods/http:${2}:${3}/proxy/metrics
  - action: labelmap
    regex: __meta_kubernetes_service_label_(.+)
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    # 将标签__meta_kubernetes_namespace修改为kubernetes_namespace
    target_label: kubernetes_namespace
  - source_labels: [__meta_kubernetes_service_name]
    action: replace
    # 将标签__meta_kubernetes_service_name修改为service_name
    target_label: service_name

最终的效果如下:
在这里插入图片描述

4.拉取pod监控指标

kubelet

标签 默认 构造后
__scheme__ https https
__address__ 192.168.3.217:10250 192.168.3.217:6443
__metrics_path__ /metrics /api/v1/nodes/uvmsvr-3-217:10250/proxy/metrics
完整url https://192.168.3.217:10250/metrics https://192.168.3.217:6443/api/v1/nodes/uvmsvr-3-217:10250/proxy/metrics

advisor

标签 默认 构造后
__scheme__ https https
__address__ 192.168.3.217:10250 192.168.3.217:6443
__metrics_path__ /metrics /api/v1/nodes/uvmsvr-3-219:10250/proxy/metrics/cadvisor
完整url https://192.168.3.217:10250/metrics https://192.168.3.217:6443/api/v1/nodes/uvmsvr-3-219:10250/proxy/metrics/cadvisor

通过relabel_configs构造如下:

# kubelet
- job_name: "kube-node-kubelet"
  scheme: https
  tls_config:
    insecure_skip_verify: true
  bearer_token_file: /prometheus/k8s_token
  kubernetes_sd_configs:
  - role: node
    api_server: "https://192.168.3.217:6443"
    tls_config:
      insecure_skip_verify: true
    bearer_token_file: /prometheus/k8s_token
  relabel_configs:
  - target_label: __address__
    # 使用replacement值替换__address__默认值
    replacement: 192.168.3.217:6443
  - source_labels: [__meta_kubernetes_node_name]
    regex: (.+)
    # 使用replacement值替换__metrics_path__默认值
    target_label: __metrics_path__
    replacement: /api/v1/nodes/${1}:10250/proxy/metrics
  - action: labelmap
    regex: __meta_kubernetes_service_label_(.+)
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace
  - source_labels: [__meta_kubernetes_service_name]
    action: replace
    target_label: service_name

# advisor    
- job_name: "kube-node-cadvisor"
  scheme: https
  tls_config:
    insecure_skip_verify: true
  bearer_token_file: /prometheus/k8s_token
  kubernetes_sd_configs:
  - role: node
    api_server: "https://192.168.3.217:6443"
    tls_config:
      insecure_skip_verify: true
    bearer_token_file: /prometheus/k8s_token
  relabel_configs:
  - target_label: __address__
    # 使用replacement值替换__address__默认值
    replacement: 192.168.3.217:6443
  - source_labels: [__meta_kubernetes_node_name]
    regex: (.+)
    # 使用replacement值替换__metrics_path__默认值
    target_label: __metrics_path__
    replacement: /api/v1/nodes/${1}:10250/proxy/metrics/cadvisor
  - action: labelmap
    regex: __meta_kubernetes_service_label_(.+)
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace
  - source_labels: [__meta_kubernetes_service_name]
    action: replace
    target_label: service_name

5.拉取K8S资源监控指标

标签 默认 构造后
__scheme__ https https
__address__ 10.244.2.10:8081 192.168.3.217:6443
__metrics_path__ /metrics /api/v1/namespaces/kube-system/pods/http:kube-state-metrics-6b6b4476bd-4qh7g:8081/proxy/metrics
完整url https://10.244.2.10:8081//metrics https://192.168.3.217:6443/api/v1/namespaces/kube-system/pods/http:kube-state-metrics-6b6b4476bd-4qh7g:8081/proxy/metrics

通过relabel_configs构造如下:

scrape_configs:
- job_name: "kube-state-metrics"
  scheme: https
  tls_config:
    insecure_skip_verify: true
  bearer_token_file: /prometheus/k8s_token
  kubernetes_sd_configs:
  - role: endpoints
    api_server: "https://192.168.3.217:6443"
    tls_config:
      insecure_skip_verify: true
    bearer_token_file: /prometheus/k8s_token
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_name]
    action: keep
    regex: '^(kube-state-metrics)$'
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  - source_labels: [__address__]
    action: replace
    target_label: instance
  - target_label: __address__
    # 使用replacement值替换__address__默认值
    replacement: 192.168.3.217:6443
  - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_name, __meta_kubernetes_pod_container_port_number]
    regex: ([^;]+);([^;]+);([^;]+)
    # 使用replacement值替换__metrics_path__默认值
    target_label: __metrics_path__
    replacement: /api/v1/namespaces/${1}/pods/http:${2}:${3}/proxy/metrics
  - action: labelmap
    regex: __meta_kubernetes_service_label_(.+)
  - source_labels: [__meta_kubernetes_namespace]
    action: replace
    target_label: kubernetes_namespace
  - source_labels: [__meta_kubernetes_service_name]
    action: replace
    target_label: service_name

Grafana

Grafana从prometheus数据源读取监控指标并进行图形化展示,可通过以下几种方式进行展示:

1.grafana dashboard模板

Grafana Dashboard提供了很多模板供我们下载使用,针对以上不同维度的监控指标,我们可以自行选择喜欢的模板直接导入Dashboard id使用。

  1. node性能
    Dashboard id:8919
    在这里插入图片描述Dashboard id:9276
    在这里插入图片描述
  2. pod性能

Dashboard id:8588
在这里插入图片描述

  1. K8S资源
    Dashboard id:3119
    在这里插入图片描述
    Dashboard id:6417
    在这里插入图片描述

注意: 如果Dashboard没有数据,需要具体查看相关指标或标签是否存在,因为有的模板是几年前上传的,没有更新。

2.grafana plugin

通过Dashboard 模板我们需要自行选择并组合,灵活有余但规范不足。而grafana自带专门针对Kubernetes集群监控的插件grafana-kubernetes-app,它包括4个仪表板,集群,节点,Pod /容器和部署。但是这个插件已经3年+没有更新了,有很多的metrics和label没有更新。

在此特推荐KubeGraf,是grafana-kubernetes-app升级版本,该插件可以用来可视化和分析 Kubernetes 集群的性能,通过各种图形直观的展示了 Kubernetes 集群的主要服务的指标和特征,还可以用于检查应用程序的生命周期和错误日志。

  1. 安装
# 1.安装
grafana-cli plugins install devopsprodigy-kubegraf-app
# 2.重启grafana
systemctl restart grafana-server
  1. 配置
    “Add New Cluster” 后,我们就可以进行以下配置
    在这里插入图片描述
  • URL:填写K8S apiserver地址
  • TLS Client Auth:使用tls认证
  • Skip TLS Verify:不会检查服务器凭证的有效性,这会导致HTTPS链接不安全
  • With CA Cert:不开启,将不使用CA Cert
  • CA Cert:和With CA Cert同时使用
    填入解密的内容
# 从/root/.kube/config 获取certificate-authority-data 值并解密
echo "xxxx" |base64 -d
  • Client Cert
    填入解密的内容
# 从/root/.kube/config 获取client-certificate-data 值并解密
echo "xxxx" |base64 -d
  • Client Key
    填入解密的内容
# 从/root/.kube/config 获取client-key-data 值并解密
echo "xxxx" |base64 -d
  1. 展示效果

集群状态

在这里插入图片描述

node状态

在这里插入图片描述

Deployment状态

在这里插入图片描述

DaemonSet 状态

在这里插入图片描述

pod状态

在这里插入图片描述

总结

监控K8S一定要提前规划好Prometheus的位置,熟悉RBAC授权及apiserver proxy url,这样我们在部署过程中能够快速定位问题。

至于Prometheus部署在集群外还是集群内,大家见仁见智,根据自己的实际需求进行部署。建议多个小集群可通过集群外Prometheus统一监控;大集群则避免Prometheus中心化,还是每个集群内部单独部署。

参考文章:

https://cloud.tencent.com/developer/article/1402436
https://cloud.tencent.com/developer/article/1449803
https://blog.rj-bai.com/post/159.html
https://help.aliyun.com/document_detail/123394.html

猜你喜欢

转载自blog.csdn.net/yanggd1987/article/details/108807171