categraf 监控k8s
采集器categraf集成了prometheus的agent mode模式,prometheus所支持服务发现模式,例如docker_swarm_ad_configs,docker_sd_config, dns_sd_configs, http_sd_configs都可以和categraf无缝对接。
prometheus自动发现之kubernetes_sd_configs
1. 为什么要使用服务发现
通常我们的Kubernetes 集群中会有很多的 Service 和 Pod等资源,这些资源可以随着需求规模的变化而变化,而这些pod的ip,名称也并非一成不变的。那么当k8s资源创建或更新时,如果一个一个的去更改或创建对应的监控Job,那操作将会非常的繁琐。而prometheus的自动发现功能,便轻松的解决了上述问题。
2. 什么是服务发现
对于上述问题,Prometheus这一类基于Pull模式的监控系统,很显然也无法继续使用的static_configs的方式静态的定义监控目标。而Prometheus的解决方案就是引入一个中间的代理人(服务注册中心),这个代理人掌握着当前所有监控目标的访问信息,Prometheus只需要向这个代理人询问有哪些监控目标即可,Prometheus查询到需要监控的Target列表,然后轮训这些Target获取监控数据,这种模式被称为服务发现。
Prometheus支持多种服务发现机制:文件、DNS、Consul、Kubernetes、OpenStack、EC2等。本文以Kubernetes服务发现机制为例,详细探究。
在Kubernetes下,Prometheus 通过与 Kubernetes API 集成主要支持5种服务发现模式:Node、Service、Pod、Endpoints、Ingress。不同的服务发现模式适用于不同的场景,例如:node适用于与主机相关的监控资源,如节点中运行的Kubernetes 组件状态、节点上运行的容器状态等;service 和 ingress 适用于通过黑盒监控的场景,如对服务的可用性以及服务质量的监控;endpoints 和 pod 均可用于获取 Pod 实例的监控数据,如监控用户或者管理员部署的支持 Prometheus 的应用。
配置文件编写流程
prometheus自动发现的核心之处在于relabel_configs的相关配置,首先是通过source_labels配置以__meta_开头的这些元数据标签,声明要匹配的资源,然后通过regex匹配规则找到相关的资源对象,最后再对采集过来的指标做二次处理,比如保留、过来、替换等操作
global: # 间隔时间 scrape_interval: 30s # 超时时间 scrape_timeout: 10s # 另一个独立的规则周期,对告警规则做定期计算 evaluation_interval: 30s # 外部系统标签用于区分prometheus服务实例 external_labels: prometheus: monitoring/k8s prometheus_replica: prometheus-k8s-1 scrape_configs: # 定义job名称,一个能够被抓取监控数据的endpoint叫做Instance,有着同样目的的Instance集合叫做Job。 - job_name: "prometheus" # Honor_labels 控制 Prometheus 如何处理已存在于抓取数据中的标签与 Prometheus 将在服务器端附加的标签(“作业”和“实例”标签、手动配置的目标标签以及由服务发现实现生成的标签)之间的冲突。 # 如果honor_labels 设置为“true”,标签冲突通过从抓取的数据中保留标签值并忽略冲突的服务器端标签来解决。 # 如果 Honor_labels 设置为“false”,则通过将抓取数据中的冲突标签重命名为“exported_<original-label>”来解决标签冲突( # 将 Honor_labels 设置为“true”对于联邦和抓取 Pushgateway 等用例很有用,其中应保留目标中指定的所有标签。 honor_labels: true # Honor_timestamps是否采用抓取数据中存在的时间戳默认为true。设置为“true”,则将使用目标公开的指标的时间戳。设置为“false”,则目标公开的指标的时间戳将被忽略。 honor_timestamps: true # 抓取目标的频率 scrape_interval: 30s # 抓取请求超时的时间 scrape_timeout: 10s # 配置抓取请求的 TLS 设置。(https协议时需要填写证书等相关配置) #tls_config: # [ <tls_config> ] # bearer_token_file # 使用配置的承载令牌在每个scrape请求上设置`Authorization`标头。 它`bearer_token_file`和是互斥的。 #[ bearer_token: <secret> ] # 使用配置的承载令牌在每个scrape请求上设置`Authorization`标头。 它`bearer_token`和是互斥的。 # [ bearer_token_file: /path/to/bearer/token/file ] # 从目标获取指标的资源路径,默认为/metrics metrics_path: /metrics # 配置请求使用的协议方案,默认为http scheme: http # 基于kubernetes的API server实现自动发现 kubernetes_sd_configs: # 角色为 endpoints,通过service来发现后端endpoints,每一个service都有对应的endpoints,如果满足采集条件,那么在service、POD中定义的labels也会被采集进去 - role: endpoints # 标签匹配处理相关配置 relabel_configs: # 以prometheus服务为例,他的service标签为app=prometheus。因此source_labels选择__meta_kubernetes_service_label_app,他会列出k8s所有服务对象的标签,其他常用的元数据标签如下 # 节点node # __meta_kubernetes_node_name: 节点对象的名称 # __meta_kubernetes_node_label_<labelname>: 节点对象的每个标签 # __meta_kubernetes_node_address_<address_type>: 如果存在,每一个节点对象类型的第一个地址 # 服务service # __meta_kubernetes_namespace: 服务对象的命名空间 # __meta_kubernetes_service_cluster_ip: 服务的群集IP地址。(不适用于ExternalName类型的服务) # __meta_kubernetes_service_external_name: 服务的DNS名称。(适用于ExternalName类型的服务) # __meta_kubernetes_service_label_<labelname>: 服务对象的标签。 # __meta_kubernetes_service_name: 服务对象的名称 # __meta_kubernetes_service_port_name: 目标服务端口的名称 # __meta_kubernetes_service_port_protocol: 目标服务端口的协议 # __meta_kubernetes_service_type: 服务的类型 # pod # __meta_kubernetes_namespace: pod对象的命名空间 # __meta_kubernetes_pod_name: pod对象的名称 # __meta_kubernetes_pod_ip: pod对象的IP地址 # __meta_kubernetes_pod_label_<labelname>: pod对象的标签 # __meta_kubernetes_pod_container_name: 目标地址的容器名称 # __meta_kubernetes_pod_container_port_name: 容器端口名称 # __meta_kubernetes_pod_ready: 设置pod ready状态为true或者false # __meta_kubernetes_pod_phase: 在生命周期中设置 Pending, Running, Succeeded, Failed 或 Unknown # __meta_kubernetes_pod_node_name: pod调度的node名称 # __meta_kubernetes_pod_host_ip: 节点对象的主机IP # __meta_kubernetes_pod_uid: pod对象的UID。 # __meta_kubernetes_pod_controller_kind: pod控制器的kind对象. # __meta_kubernetes_pod_controller_name: pod控制器的名称. # 端点endpoints # __meta_kubernetes_namespace: 端点对象的命名空间 # __meta_kubernetes_endpoints_name: 端点对象的名称 # __meta_kubernetes_endpoint_hostname: 端点的Hostname # __meta_kubernetes_endpoint_node_name: 端点所在节点的名称。 # __meta_kubernetes_endpoint_ready: endpoint ready状态设置为true或者false。 # __meta_kubernetes_endpoint_port_name: 端点的端口名称 # __meta_kubernetes_endpoint_port_protocol: 端点的端口协议 # __meta_kubernetes_endpoint_address_target_kind: 端点地址目标的kind。 # __meta_kubernetes_endpoint_address_target_name: 端点地址目标的名称。 # ingress # __meta_kubernetes_namespace: ingress对象的命名空间 # __meta_kubernetes_ingress_name: ingress对象的名称 # __meta_kubernetes_ingress_label_<labelname>: ingress对象的每个label。 # __meta_kubernetes_ingress_scheme: 协议方案,如果设置了TLS配置,则为https。默认为http。 # __meta_kubernetes_ingress_path: ingree spec的路径。默认为/。 - source_labels: [__meta_kubernetes_service_label_app] # 通过正式表达式匹配,条件为service的label标签app=prometheus的资源 regex: prometheus # 执行动作 # keep:仅收集匹配到regex的源标签,而会丢弃没有匹配到的所有标签,用于选择 # replace:默认行为,不配置action的话就采用这种行为,它会根据regex来去匹配source_labels标签上的值,并将并将匹配到的值写入target_label中 # labelmap:它会根据regex去匹配标签名称,并将匹配到的内容作为新标签的名称,其值作为新标签的值 # drop:丢弃匹配到regex的源标签,而会收集没有匹配到的所有标签,用于排除 # labeldrop:使用regex匹配标签,符合regex规则的标签将从target实例中移除,其实也就是不收集不保存 # labelkeep:使用regex匹配标签,仅收集符合regex规则的标签,不符合的不收集 action: keep # 添加服务对象的名称空间信息,并替换标签名为namespace - source_labels: [__meta_kubernetes_namespace] action: replace target_label: namespace # 添加对象的名称信息,并替换为name - source_labels: [__meta_kubernetes_service_name] action: replace target_label: name # 添加pod对象的名称信息,并替换为pod - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: pod
kubernetes node 容器负载监控, 抓取方案一
容器层面主要关注cpu和内存使用情况,pod层面主要关注网络IO情况 ,因为多个容器共享pod的network namespace,pod内多个容器的网络数据相同 容器的监控数据可以直接通过docker引擎的接口读取到, 也可以直接读取cadvisor接口,kubelet里内置了cadvisor, cadvisor 不管是docker还是 containerd 都能采集到,推荐 通过kubernetes_sd_configs做服务发现,查找所有的node,通过kubernetes apiserver的proxy接口,抓取各个node(即 kubelet)的/metrics/cadvisor接口 的prometheus协议的数据 这个抓取只需要部署一个实例, 调用apiserver 的接口即可维护较为简单,采集频率可以调大,30s或者60s 所有的拉取请求都走apiserver,如果规模很大的集群,apiserver 压力很大。
kubernetes node 容器负载监控, 抓取方案二
直接调用kubelet的接口 /metrics/cadvisor, 不走apiserver 这个proxy,避免对apiserver的请求压力 采用daemonset 的方式部署 但是,缺少了对__meta_kubernetes_node_label_(.+)的 labelamp, 即:通过这种方式采集的数据,我们无法得到node上的label 数据,node上的label 数据最核心的就是标识了node的ip 我们通过环境变量为抓取器注入nodeip, 比如用categraf的话,就会自动把本机IP作为标签带上去,设置config.toml的 hostname=“$IP”.
kubernetes node 容器负载监控, 关键指标
cpu使用率
分子是每秒内容器用了多少cpu时间,分母是每秒内被限制使用多少cpu 时间 sum(irate(container_cpu_usage_seconds_total[3m])) by (pod,namespace,container,ident,image) / sum(container_spec_cpu_quota/container_spec_cpu_period) by (pod,namespace,container,ident,image)
container_cpu_usage_seconds_total 使用cpu总量,所以加了irate,单位时间内cpu的使用量
container_spec_cpu_quota 每秒内限制容器cpu quota时间,需要和单位换算一下(period),相当于在这个period里,设置的quota 大小
内存使用率
container_spec_memory_limit_bytes ! 0 是因为有些容器没有配置 limit 的内存大小 container_memory_usage_bytes / container_spec_memory_limit_bytes and container_spec_memory_limit_bytes != 0
cpu 被限制的时间比例
increase(container_cpu_cfs_throttled_periods_total[1m]) / increase(container_cpu_cfs_periods_total[1m]) * 100
pod是cpu密集型的应用,对延迟要求比较敏感,要关注 cpu被限制的时间比例, 如果值比较高,说明应用老是用cpu,但是操作系统总是给限制,
相当于cpu不够用,所以要把cpu的算力分配的更多一些
pod网络出入向流量
irate(container_network_transmit_bytes_total[1m])
irate(container_network_receive_bytes_total[1m])
pod磁盘IO读写流量
irate(container_fs_reads_bytes_total[1m])
irate(container_fs_writes_bytes_total[1m])
kubenetes node - kubelet监控
kubelet_running_pods: 运行的pod数量,gauge类型 kubelet_running_containers: 运行的容器的数量,gauge类型, container_state标签来区分容器状态 volume_manager_total_volumes: volume的数量,gauge类型,state标签用于区分是actual还是desired kubelet_runtime_operations_total: 通过kubelet执行的各类操作的数量,counter类型。 kubelet_runtime_operations_errors_total: 通过kubelet 执行的操作失败次数。 kubelet_pod_start_duration_seconds: histogram类型, 描述pod 从pending状态进入running状态花费的时间 go_goroutines: kubelet的goroutine的数量 kubelet_pleg_relist_duration_seconds: histogram类型,pleg是pod lifecycle event generator 如果这个时间花费太大, 会对kubernetes中的pod状态造成影响。 kubelet_pleg_relist_interval_seconds: histogram类型,relist的频率间隔
kubelet 在/metrics/cadvisor 暴露的是cadvisor 的监控数据(prometheus协议), 在/stats/summary/暴露的容器的概要监控数据
(普通json协议),在/metrics暴露的自身的监控数据
categraf 的仓库中, inputs/kubernetes/kubelet-metrics-dash.json 是kubelet 的大盘文件
kubernetes node - kube-proxy 监控
up 关注kube-proxy的存活性 rest_client_request_duration_seconds: 针对kube-apiserver的请求延迟指标 rest_client_requests_total: 针对apiserver的请求量的指标 kubeproxy_sync_proxy_rules_duration_seconds 同步网路规则的延迟指标
kube-proxy 在/metrics 暴露监控数据,可以直接拉取
categraf的仓库中 inputs/kubernetes/kube-proxy-dash.json 就是kube-proxy的大盘文件
kubernetes master apiserver监控
apiserver_request_total : 请求量的指标, 可以统计每秒请求数,成功率
apiserver_request_duration_secondes 请求延迟统计
process_cpu_seconds_total 进程使用cpu的时间
process_resident_memory_bytes 进程的内存使用量
apiserver通过/metrics 接口暴露监控数据,直接拉取即可
apiserver部署在容器里则通过服务发现的方式采集, 如果部署在宿主机上,可以直接通过写死抓取地址的方式
apiserver 会缓存很多数据到内存中,进程占用的内存,要关注内存使用率
categraf 大盘 k8s/apiserver-dash.json
kubernetes master controller-manager 监控
rest_client_request_duration_seconds: 请求apiserver的耗时分布
workqueue_adds_total : 各个controller已处理的任务总数
workqueue_depth:各个controller的队列深度,表示一个controller中的任务数量,值越大表示越繁忙
process_cpu_secondes_total: 进程使用cpu的时间总量,rate之后的就是cpu使用率
controller-manager 通过/metrics接口暴露监控数据,直接拉取,
categraf 大盘 k8s/cm-dash.json
kubernetes master scheduler 监控
rest_client_request_duration_seconds: 请求apiserver耗时分布
scheduler_framework_extension_point_duration_seconds: 调度框架的扩展点延迟分布
scheduler_pending_pods: 调度pending的pod数量,按照queue type分别统计
scheduler_scheduler_attempts_total: 按照调度结果统计的调度重试次数。
scheduler 通过/metrics 接口博暴露监控数据,直接拉取
categraf 大盘 k8s/scheduler-dash.json
kubentes ETCD 监控
etcd_server_has_leader etcd是否有leader
etcd_server_leader_changes_seen_total: 偶尔切换问题不大,频繁切换需要关注
etcd_server_proposals_failed_total 提案失败次数
etcd_disk_backend_commit_duration_seconds
etcd_disk_wal_fsync_duration_seconds
etcd强依赖硬盘 做数据持久化,一定要用io性能高的磁盘。
etcd 直接暴露/metrics 接口,直接抓取
categraf 大盘 k8s/etcd-dash.json
参考:
flashcats
https://blog.csdn.net/qq_33816243/article/details/126863790