原文链接:https://segmentfault.com/a/1190000040150566
为什么prometheus是为云原生监控而生的?
-
想必你不止一次的地听说了prometheus是为云原生监控而生的,那你有没有想过这句话意味着什么呢?
-
我们知道在云原生中使用容器和k8s环境作为基础运行环境
-
一体化架构被拆分成众多分散的微服务,而微服务的变更和扩缩容是特别频繁的,也就导致采集的目标信息变化频繁。这就给时序监控系统提出了两个要求:
-
需要采集运行在跨多个宿主机上的海量pod容器
-
同时要及时感知到他们的变化
-
同时要构建完整的k8s监控生态,能有
-
其实说白了就是在云原生环境中监控变得更难了,更复杂了。所以需要一个在设计之初就适合云原生监控场景的系统,而prometheus就是这么设计的。
Prometheus到底做了哪些改进,能配得上k8s ?
k8s中应该关注哪些指标?在下面的表格中简单列举了下我们在k8s需要关注的四大块指标:
适配1. sdk+指标自暴露+pull模型:构建k8s监控的整个生态
-
在上面的列举的表格中我们看到在k8s需要关注的四大块指标
-
其实我们可以简单地把k8s的使用者分为两种角色:k8s集群管理员和普通用户。每种角色关注的指标不相同
自己采集岂不累死了?
-
既然需求这么多,如果只是由监控系统自己采集,第一很累,第二构建不出这么完整的生态
奥妙
-
prometheus是pull模型采集的,各个被监控的源只需要将自身指标暴露在本地http端口中,prometheus就可以访问接口来采集指标
-
prometheus在k8s中也是这样的,组件需要暴露自身指标,如我们在容器基础资源指标中提到的kubelet 内置cadvisor指标就是暴露在10250端口下的/metrics/cadvisor下。
-
prometheus通过 k8s服务发现这些指标源完成采集
适配2. k8s服务发现
举例
-
一、endpoint级别的服务发现 :举例 在采集apiserver、kube-controller-manager等
kubernetes_sd_configs:
role: endpoints
-
二、node级别的服务发现 :举例 在采集cadvisor和kubelet自身指标时
kubernetes_sd_configs:
- role: node
-
三、node级别的服务发现 :举例 在采集pod自打点指标时
kubernetes_sd_configs:
- role: pod
follow_redirects: true
解读:watch即时更新
-
通过watch即时发现资源变化,就满足了我们一开始提出的云原生情况下监控的挑战之一,要及时感知到采集源的变化。
-
同时在k8s大二层环境中,prometheus可以访问到发现出来的的 endpoint 、node、pod
适配3. 采集鉴权:token & 证书
k8s中很多接口都要鉴权,甚至还需要tls双向认证
-
同时我们知道在k8s中很多接口都是带有访问鉴权的,比如我们直接访问k8s node上的kubelet的/metrics/cadvisor接口会返回未授权。如下面所示
[root@Kubernetes-node01 logs]# curl -k https://localhost:10250/metrics/cadvisor
Unauthorized
-
prometheus在采集cadvisor指标时同样面临鉴权问题
解决方法
-
聪明的prometheus开发人员通过在采集中支持配置中相关token和证书来解决这个问题,如下面的配置代表有一个token文件,同时还有一个证书文件。
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
-
我们在使用k8s时知道,k8s通过 service account,clusterrolebinding来解决token、证书挂载问题
-
prometheus也是利用了这一点,在创建prometheus容器是相关的service account,clusterrolebinding配置的示例如下:
apiVersion: rbac.authorization.k8s.io/v1 # api的version
kind: ClusterRole # 类型
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources: # 资源
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus # 自定义名字
namespace: kube-system # 命名空间
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef: # 选择需要绑定的Role
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects: # 对象
- kind: ServiceAccount
name: prometheus
namespace: kube-system
-
我们在创建相关prometheus 的statsfulset时需要在prometheus yaml中需要配置对应的serviceAccountName
serviceAccountName: prometheus
-
配置好之后Kubernetes会将对应的token和证书文件挂载到pod中。
-
我们exec进入prometheus的pod中就可以查看到相关文件在
/var/run/secrets/kubernetes.io/serviceaccount/
,如下图所示:
/ # ls /var/run/secrets/kubernetes.io/serviceaccount/ -l
total 0
lrwxrwxrwx 1 root root 13 Jan 7 20:54 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Jan 7 20:54 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Jan 7 20:54 token -> ..data/token
/ # df -h |grep service
tmpfs 7.8G 12.0K 7.8G 0% /var/run/secrets/kubernetes.io/serviceaccount
/ #
-
在采集etcd时需要配置相关证书的secret
kubectl create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key --from-file=/etc/kubernetes/pki/etcd/ca.crt -n kube-system
适配4. 强大的relabel能力 做标签截取、变换、静态分片
prometheus relabel说明
-
文档地址 https://prometheus.io/docs/pr...
应用1:labelmap 在采集cadvisor指标时 对服务发现标签key名字截取
-
在采集cadvisor时可以看到服务发现源给添加了很多
__meta_kubernetes_node_label_
开头的标签
-
但是这些标签名字太长了,需要精简。我们使用如下的relabel配置
relabel_configs:
- separator: ;
regex: __meta_kubernetes_node_label_(.+)
replacement: $1
action: labelmap
-
以这个标签为例,
__meta_kubernetes_node_label_kubernetes_io_os="linux"
,上面的配置代表匹配_meta_kubernetes_node_label_开头的key,只保留后面的部分,所以在最终的标签看到的就是beta_kubernetes_io_os="linux"
。 -
labelmap代表匹配到的标签赋值给目标标签
应用2:replace 在采集pod自定义指标 对标签进行赋值
-
我们在使用pod自定义指标时在pod yaml 的spec.template.metadata.annotations中需要定义三个以
prometheus.io
开头的配置,分布代表是否需要prometheus采集、metrics暴露的端口、metrics的http path信息,详细配置如下:spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9102'
prometheus.io/path: 'metrics' -
在采集pod自定义指标时采用如下
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
separator: ;
regex: "true"
replacement: $1
action: keep
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
separator: ;
regex: (.+)
target_label: __metrics_path__
replacement: $1
action: replace
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
separator: ;
regex: ([^:]+)(?::\d+)?;(\d+)
target_label: __address__
replacement: $1:$2
action: replace -
意思是将
__meta_kubernetes_pod_annotation_prometheus_io_path
赋值给__metrics_path__
-
意思是将相关
__meta_kubernetes_pod_annotation_prometheus_io_port
赋值给__address__
后面的端口
应用2:keep 做过滤,在采集服务组件endpoint时
-
endpoint资源是暴露一个服务的ip地址和port的列表
-
代表采用k8s服务发现 endpoint,endpoint会非常多,所以需要过滤apiserver的
kubernetes_sd_configs:
- role: endpoints
-
过滤手段为 标签 __meta_kubernetes_namespace匹配default并且 __meta_kubernetes_service_name 匹配kubernetes 并且 __meta_kubernetes_endpoint_port_name 匹配https,咋样呢 :
keep
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
separator: ;
regex: default;kubernetes;https
replacement: $1
action: keep
-
k8s 会在default namespace中创建apiserver的 service
$ kubectl get svc -A |grep 443
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d -
最后获取到的endpoint转换为采集路径为:
https://masterip:6443/metrics
Prometheus为k8s监控做的适配工作:
长按扫描
系统学习Prometheus监控系统
- END -
推荐阅读 K8s运维架构师实战集训营【多个企业项目】 Prometheus+Granafa构建高大上的MySQL监控平台 12年资深运维老司机的成长感悟 快速入门 Ansible 自动化运维工具 | 16张图 运维的工作边界,这次真的搞明白了! 最强整理!常用正则表达式速查手册 60道常见的 Kubernetes 面试题总结 不管你是开发还是运维,微服务这些你得知道! 从零开始搭建创业公司DevOps技术栈 2021年的DevOps趋势预测 搭建一套完整的企业级 K8s 集群(v1.20,kubeadm方式) 点亮,服务器三年不宕机
文章评论