天天看点

Prometheus监控运维实战十五:监控Kubernetes

kuberentes是一款开源容器编排产品,由google开发并发布到社区,并在 2015 年将该项目捐献给了云原生基金会(cloud native computing foundation)。从2014年第一个版本发布以来,kubernetes便迅速获得开源社区的追捧,包括redhat、vmware在内的很多知名企业都加入到开发和推广的阵营。目前,kubernets已经成为发展最快、市场占有率最高的容器编排产品。

promehteus是一款近年来非常火热的容器监控系统,它使用go语言开发,设计思路来源于google的borgmom(一个监控容器平台的系统)。2016年,云原生基金会将其纳入麾下,成为该基金会继kubernetes后,第二大开源项目。因此,prometheus天然具有对容器的适配性,可非常方便的满足容器的监控需求,目前已成为监控kubernetes的主要工具。

本文将介绍如何通过prometheus监控kubernetes集群状态的方案。(对于kubernetes的技术细节本文不做讲解,不熟悉的朋友可先自行查看相关资料。)

Prometheus监控运维实战十五:监控Kubernetes

prometheus通过自动发现的方式获取kubernetes集群的资源信息,因此,需要在监控集群上安装prometheus来实现。本文通过yaml文件的方式部署prometheus。

创建namespace.yml文件,内容如下 

执行该yml文件

查看命名空间,已成功创建。

rbac为kubernetes的授权认证方式,包括 serviceaccount、clusterrole、clusterrolebinding三类yaml文件。该规则用于授权prometheus获取资源信息。

创建prometheus-rbac.yml文件,内容如下:

查看rbac是否创建成功

我们使用configmap来管理prometheus的配置文件,此处先使用默认的配置,用于启动prometheus,后面再根据需要进行修改。

创建prometheus-config.yml文件,内容如下

查看configmap资源是否生成

在完成configmap资源创建后,我们可以开始部署prometheus的实例了。此处,我们使用deployment来部署prometheus,并通过volume挂载的方式,将prometheus的配置文件挂载到pod中。另外,在正式环境中建议通过pvc的方法,将收集的监控数据挂载到外部存储,避免因pod被删除而造成数据丢失。

创建prometheus-deployment.yml文件,内容如下

查看prometheus实例状态

创建prometheus的service,用于集群内外部访问。默认情况下,service只能在集群内访问,如果希望开放给集群外部,可选方案有ingress、nodeport、externalips、loadbalancer等几种,此处使用loadbalancer方式。

创建prometheus-service.yml,内容如下:

查看service状态,service已创建完成,其中cluster-ip用于集群内部访问,external-ip则是给到集群外部访问。

浏览器打开http://$ip:9090,可看到prometheus已部署完成。

Prometheus监控运维实战十五:监控Kubernetes

查看targets目标,当前除了监控prometheus自身实例,还未有其他kubernetes资源。

Prometheus监控运维实战十五:监控Kubernetes

在监控kubernetes集群的过程中,我们需要使用到针对kubernetes的服务发现功能,这个在prometheus的原生功能中已经支持。kubernetes_sd_config配置允许从kubernetes的 rest api 检索抓取目标,并始终与集群状态保持同步,这点非常有用。

以下几种类型的资源可被配置为服务发现的目标,对于集群的监控方案有不少,关键是看如何灵活应用这些角色发现的功能和标签。

该node 角色发现用于发现集群中的节点目标信息,其地址默认为节点kubelet的http访问端口。目标地址默认类型顺序为nodeinternalip,nodeexternalip, nodelegacyhostip,和nodehostname中的第一个现有地址。​

可使用的元数据标签如下:

• __meta_kubernetes_node_name:节点对象的名称。

• __meta_kubernetes_node_label_<labelname>:节点对象所定义的各个label

• __meta_kubernetes_node_labelpresent_<labelname>:节点对象所定义的各个label,value固定为true。

• _meta_kubernetes_node_annotation_<annotationname>:来自节点对象的每个注释

• _meta_kubernetes_node_annotationpresent_<annotationname>:来自节点对象的每个注释,value固定为true。

• _meta_kubernetes_node_address_<address_type>:每个节点地址类型的第一个地址(如果存在)

此外,节点的实例标签将被设置为从api服务检索到的节点名称。

该service角色发现用于发现集群中每个服务目标,并且将该服务开放的端口做为目标端口。该地址将设置为服务的kubernetes dns名称以及相应的服务端口。

​​__meta_kubernetes_namespace​​: 服务对象的名称空间。

​​__meta_kubernetes_service_annotation_<annotationname>​​:服务对象的每个注释。

​​__meta_kubernetes_service_annotationpresent_<annotationname>​​: 服务对象的每个注释,value固定为true。

​​__meta_kubernetes_service_cluster_ip​​:  服务对象的集群ip。 (不适用于"外部名称"类型的服务)

​​__meta_kubernetes_service_external_name​​: 服务的dns名称。(适用于"外部名称"类型的服务)

​​__meta_kubernetes_service_label_<labelname>​​: 服务对象中的每个label。

​​__meta_kubernetes_service_labelpresent_<labelname>​​: 服务对象中的每个label,value固定为true。

​​__meta_kubernetes_service_name​​: 服务对象的名称。

​​__meta_kubernetes_service_port_name​​: 目标服务端口的名称。

​​__meta_kubernetes_service_port_protocol​​: 目标服务端口的协议。

​​__meta_kubernetes_service_type​​: 服务的类型。

该pod角色发现用于发现所有pod并将其容器做为目标访问,对于容器的每个声明的端口,将生成一个目标。如果容器没有指定的端口,则会为每个容器创建无端口目标,以通过标签重写(relabeling)手动添加端口。

​​__meta_kubernetes_namespace​​: pod对象的名称空间。

​​__meta_kubernetes_pod_name​​: pod对象的名称。

​​__meta_kubernetes_pod_ip​​: pod对象的pod ip。

​​__meta_kubernetes_pod_label_<labelname>​​: 来自pod对象的每个标签。

​​__meta_kubernetes_pod_labelpresent_<labelname>​​: 来自pod对象的每个标签,value固定为true。

​​__meta_kubernetes_pod_annotation_<annotationname>​​: 来自pod对象的每个注释。

​​__meta_kubernetes_pod_annotationpresent_<annotationname>​​: 来自pod对象的每个注释,value固定为true。

​​__meta_kubernetes_pod_container_init​​: 如果容器是初始化容器,则value为true。

​​__meta_kubernetes_pod_container_name​​: 目标地址指向的容器的名称。

​​__meta_kubernetes_pod_container_port_name​​: 容器端口的名称。

​​__meta_kubernetes_pod_container_port_number​​: 容器端口号。

​​__meta_kubernetes_pod_container_port_protocol​​: 容器端口的协议。

​​__meta_kubernetes_pod_ready​​: 代表pod状态是否就绪,value为true或false。

​​__meta_kubernetes_pod_phase​​: pod的生命周期,value值为pending,running,succeeded,failed或unknown 。

​​__meta_kubernetes_pod_node_name​​: 将pod调度到的节点的名称。

​​__meta_kubernetes_pod_host_ip​​: pod对象的当前主机ip。

​​__meta_kubernetes_pod_uid​​: pod对象的uid。

​​__meta_kubernetes_pod_controller_kind​​: pod控制器的对象种类。

​​__meta_kubernetes_pod_controller_name​​: pod控制器的名称。​

该endpoints角色发现用于发现服务的endpoints目标,且每个endpoints的port地址会生成一个目标。如果端点由pod支持,则该pod的所有其他容器端口(包括未绑定到endpoints的端口)也将作为目标。

​​__meta_kubernetes_namespace​​: endpoints对象的命名空间

​​__meta_kubernetes_endpoints_name​​: endpoints对象的名称

对于直接从端点列表中发现的所有目标(不包括由底层pod推断出来的目标),将附加以下标签:

​​__meta_kubernetes_endpoint_hostname​​: 端点的主机名

​​__meta_kubernetes_endpoint_node_name​​: 托管endpoints的节点名称  

​​__meta_kubernetes_endpoint_ready​​:  代表endpoint 状态是否就绪,value为true或false。

​​__meta_kubernetes_endpoint_port_name​​: endpoint 端口的名称。

​​__meta_kubernetes_endpoint_port_protocol​​: endpoint 端口的协议。

​​__meta_kubernetes_endpoint_address_target_kind​​: endpo int地址目标的类型,如deployment、daemonset等。  

​​__meta_kubernetes_endpoint_address_target_name​​:  endpoint地址目标的名称。

该ingress角色发现用于发现ingress的每个地址目标。该地址将设置为ingress的spec配置中指定的host。

​​__meta_kubernetes_namespace​​: ingress 对外的命名空间。

​​__meta_kubernetes_ingress_name​​: ingress 对象的名称。

​​__meta_kubernetes_ingress_label_<labelname>​​: ingress 对象的各个标签。

​​__meta_kubernetes_ingress_labelpresent_<labelname>​​: ingress 对象的各个标签,value为true或false。

​​__meta_kubernetes_ingress_annotation_<annotationname>​​: ingress 对象的各个注释。

​​__meta_kubernetes_ingress_annotationpresent_<annotationname>​​: ingress 对象的各个注释,value为true或false。

​​__meta_kubernetes_ingress_class_name​​: ingress的spec配置中的class名称,如果存在的话。

​​__meta_kubernetes_ingress_scheme​​: ingress使用的协议 ,http或https。

​​__meta_kubernetes_ingress_path​​:  ingress的spec配置中指定的路径,默认为 /

创建node_exporter-daemonset.yml文件,内容如下。在spec配置中添加了tolerations,用于污点容忍,保证master节点也会部署。

确认daemonset及pod状态正常

在prometheus-config.yml文件中添下如下任务,并执行生效。

注解:该任务通过node角色发现动态获取节点地址信息,并使用标签重写(relabeling)功能重写targets目标端口为node-expoerter端口,从而实现自动监控集群节点功能。

任务生效后,可看到prometheus已自动获取到节点信息并监控。

Prometheus监控运维实战十五:监控Kubernetes

kubernetes各节点的kubelet除包含自身的监控指标信息以外,还内置了对cadviosr的支持。在前面的容器监控篇章中,我们知道可以通过安装cadviosr来监控节点上的容器状态。而在kuberentes集群中,通过kubelet可实现类似的效果,不需要再额外安装cadviosr。

prometheus-config.yml文件中添下如下任务,并执行生效。

注解:该任务通过node角色发现动态获取节点地址信息。由于直接访问kubelet地址会有证书验证问题,这里使用标签重写(relabeling)功能重写targets目标地址和地址,通过api server提供的代理地址访问kubelet的/metrics/cadvisor。

任务生效后,可看到prometheus已自动生成相关目标信息。

Prometheus监控运维实战十五:监控Kubernetes

kube api server做为整个kubernetes集群管理的入口服务,负责对外暴露kuberentes api,服务的稳定与否影响着集群的可用性。通过对kube api server的监控,我们能够清楚api的请求处理延迟、错误和可用性等参数。

kube api server组件一般独立部署集群外部,运行在master的主机上,为了能够让集群内部的应用能够与api进行交互,kubernetes会在default的命名空间下创建一个kubernetes的service,用于集群内部访问。

该kubernetes服务代理的后端实际地址通过endpoints进行维护,该endpoints代理地址指向了master节点的6443端口,也即是master上运行的kube api server服务端口。

​因此,我们可通过prometheus的endpoints角色发现功能,来实现kube api server的目标发现并监控。

注解:该任务通过endpoints角色发现动态获取endpoints信息,并使用标签重写(relabeling)功能只保留符合正则表达式匹配的endpoints目标。

任务生效后,查看prometheus已自动生成相关目标信息。

Prometheus监控运维实战十五:监控Kubernetes

kubelet组件运行在集群中每个worker节点上,用于处理master下发到本节点的任务,包括管理pod和其中的容器。kubelet会在kube api server上注册节点信息,并定期向集群汇报节点资源使用情况。kubelet的运行状态关乎着该节点的是否可以正常工作,基于该组件的重要性,我们有必要对各个节点的kubelet进行监控。

​注解:该任务通过node角色发现动态获取节点地址信息。由于直接访问kubelet地址会有证书验证问题,这里使用标签重写(relabeling)功能重写targets目标地址和地址,通过api server提供的代理地址访问kubelet的/metrics路径。

Prometheus监控运维实战十五:监控Kubernetes

kubernetes资源对象包括pod、deployment、statefulsets等,我们需要知道相关资源的使用情况和状态,如pod是否正常运行。由于并不是所有资源都支持prometheus的监控, 因此,我们需要使用开源的kube-state-metrics方案来完成获取监控指标。 kube-state-metrics是kubernetes组织下的一个项目,它通过监听kube api收集相关资源和对象的最新信息,并提供接口地址给到prometheus获取指标。

kube-state-metrics对kubernetes有版本要求,如下图。我们环境的kubernetes为1.18,所以需要下载v2.0.0及以上版本。

Prometheus监控运维实战十五:监控Kubernetes

下载项目仓库

​部署安装

​查看服务状态

​任务生效后,查看prometheus已自动生成相关目标信息。

Prometheus监控运维实战十五:监控Kubernetes

继续阅读