前言
为什么 prometheus 是为云原生监控而生的
- 想必你不止一次的地据说了 prometheus 是为云原生监控而生的,那你有没有想过这句话意味着什么呢?
- 咱们晓得在云原生中应用容器和 k8s 环境作为根底运行环境
-
一体化架构被拆分成泛滥扩散的微服务,而微服务的变更和扩缩容是特地频繁的,也就导致采集的指标信息变动频繁。这就给时序监控零碎提出了两个要求:
- 须要采集运行在跨多个宿主机上的海量 pod 容器
- 同时要及时感知到他们的变动
- 同时要构建残缺的 k8s 监控生态,能有
- 其实说白了就是在云原生环境中监控变得更难了,更简单了。所以须要一个在设计之初就适宜云原生监控场景的零碎,而 prometheus 就是这么设计的。
prometheus 到底做了哪些改良,能配得上 k8 ?
k8s 中应该关注哪些指标
我在上面的表格中简略列举了下咱们在 k8s 须要关注的四大块指标:
指标类型 | 采集源 | 利用举例 | 发现类型 | grafana 截图 |
---|---|---|---|---|
容器根底资源指标 | kubelet 内置 cadvisor metrics 接口 | 查看容器 cpu、mem 利用率等 | k8s_sd node 级别间接拜访 node_ip | |
k8s 资源指标 | kube-stats-metrics (简称 ksm) | 具体能够看从容器监控 kube-stats-metrics 看 k8s 泛滥组件 看 pod 状态如 pod waiting 状态的起因 数个数如:查看 node pod 按 namespace 散布状况 |
通过 coredns 拜访域名 | |
k8s 服务组件指标 | 服务组件 metrics 接口 | 查看 apiserver、scheduler、etc、coredns 申请提早等 | k8s_sd endpoint 级别 | |
部署在 pod 中业务埋点指标 | pod 的 metrics 接口 | 根据业务指标场景 | k8s_sd pod 级别,拜访 pod ip 的 metricspath |
适配 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 监控做的适配工作
适配名字 | 阐明 | 举例 |
---|---|---|
各个组件 metrics 自裸露 | 所有组件将本身指标裸露在各自的服务端口上,prometheus 通过 pull 过去拉取指标 | apiserver:6443/metrics |
k8s 服务发现 | 通过 watch 即时发现资源变动 | kubernetes_sd_configs:- role: node |
鉴权 | k8s 的组件接口都是要鉴权的,所以 k8s 的采集器要反对配置鉴权 | 反对配置 token 和 tls 证书 |
标签 relabel 能力 | 过滤服务发现标的 | labelmap 去掉服务发现标签的长前缀 replace 做替换 hashmod 做动态分片 |