Prometheus k8s

kube-prometheus

notion image

云原生监控挑战

Prometheus 是用 Go 语言编写,从一开始就是开源的,到 2016 年 Prometheus 成为继 Kubernetes 之后,成为 CNCF 的第二个成员。近几年Prometheus的火热,和云原生日趋流行是密不可分的,并且现在已成为云原生生态中监控的事实标准。
传统的监控霸主Zabbix在面对云原生监控时,主要面临如下几个挑战:
  1. 监控对象数量增大:传统监控以单体应用为粒度,结合计算、存储、网络等基础设施监控进行运维保障。但在容器化微服务架构下,监控粒度细致到容器POD或微服务API级别,使得监控对象的数量相比单体应用呈指数级增长。
  1. 监控指标海量:
      • 资源对象类型多,如:Container、Pod、Service、Deployment、ReplicaSet、Endpoint、Ingress、PV、PVC等等;
      • 一个云原生集群可能有几万甚至几十万Pod;
      • 一个云原生集群可能有几千上万级别的Service、Endpoint、Deployment、Ingress等;
      • 海量的监控指标对数据写入、查询性能要求较高,以及存储空间占用优化等,才能承载海量的监控资源
  1. 对象动态变更较为频繁,资源对象的扩缩容、资源对象生命周期大大缩短,甚至有些对象朝生夕死等等,这就会带来两个问题:
      • 采集目标不能使用传统的静态配置方式,而是要基于服务发现机制能及时的感知到变化,并进行快速调整;
      • 资源对象扩缩容等导致的资源对象生命周期大大缩短是很容易导致指标数量的快速膨胀,久而久之会影响整个监控系统性能;
Zabbix出现得比较早,当时容器还没有诞生,自然对容器的支持比较差,而Prometheus的TSDB时序数据存储机制、丰富的服务发现机制等,基本就是为云原生量身定做的,Prometheus开始成为容器监控方面的标配,并且在未来可见的时间内会被广泛应用。

云原生监控方案

kubernetes云原生集群非常复杂,概况总结下我们主要关注的无外乎下面五大块指标:
  1. 容器基础资源指标:组件运行的外部环境相关性能指标,传统场景下组件运行的外部环境是主机,而云原生环境下组件的外部环境是容器,主机我们需要关注CPU、内存、存储、磁盘IO、网络IO等相关指标,同理容器基础资源指标也存在类似相关指标,如:Container的CPU使用率、内存使用率、存储空间、磁盘读写IO和网络IO等。
  1. k8s资源对象指标:容器是最底层的运行时组件,k8s作为强大的调度协调这些容器的平台,抽象定义出了很多资源对象,如Pod、Service、Deployment、ReplicaSet、DaemonSet、Ingress、StatefulSet、ConfigMap、ServiceAccount等等,资源对象指标就是对这些k8s定义的元数据信息进行监控。
  1. k8s服务组件指标:k8s作为一个复杂的集群,自身存在很多组件,如master节点上运行着:api-server组件、etcd组件、kube-scheduler组件、kube-controller-manager组件、coredns组件等,node节点上有kubelet组件、kube-proxy组件等,作为云原生集群的运维人员,肯定要关注这些核心组件的运行状况,避免某些组件性能瓶颈、异常奔溃导致整个云原生集群性能低下甚至不可用。
  1. k8s集群Node指标:云原生集群的各种组件、业务容器等最终都是运行在Node节点上,因此,Node节点的性能、异常情况等对整个云原生集群的影响也是非常大的,所以,我们也需要特别关注Node节点性能指标。
  1. 云原生上层业务指标:上面说的主要是云原生集群底层相关基础指标,云原生作为平台上面自然部署很多业务组件,比如PaaS中间件、业务应用服务等,这些组件运行在云原生上层本身也存在相关指标监控。

环境准备

为了监控上述云原生指标,首先,我们需要准备PrometheusGrafana环境。

Prometheus部署

1、为了方便管理,我们将监控相关的所有资源对象都安装在 monitoring 这个 namespace 下面,没有的话可以提前创建:
2、为了能够方便的管理配置文件,我们这里将 prometheus.yml 配置文件用 ConfigMap 的形式进行管理:
我们这里暂时只配置了对 prometheus 本身的监控,直接创建该资源对象:
配置文件创建完成了,以后如果我们有新的资源需要被监控,我们只需要将上面的 ConfigMap 对象更新即可。
3、现在我们来创建 prometheus 的 Pod 资源:

持久化

另外为了 prometheus 的性能和数据持久化我们这里是直接将通过一个 LocalPV 来进行数据持久化的,**注意一定不能使用 nfs 来持久化数据(TSDB时序库不支持nfs存储,会存在丢失数据风险)**,通过 --storage.tsdb.path=/prometheus 指定数据目录,创建如下所示的一个 PVC 资源对象,注意是一个 LocalPV,和 k8s-02 节点具有亲和性:
这里的volumeBindingMode: WaitForFirstConsumer意思就是延迟绑定,当有符合PVC要求的PV不立即绑定。因为POD关联PVC,而绑定之后,POD被调度到其他节点,显然其他节点很有可能没有那个PV所以POD就挂起了,另外就算该节点有合适的PV,而POD被设置成不能运行在该节点,这时候就没法了,延迟绑定的好处是,POD的调度要参考卷的分布。当开始调度POD的时候看看它要求的LPV在哪里,然后就调度到该节点,然后进行PVC的绑定,最后在挂载到POD中,这样就保证了POD所在的节点就一定是LPV所在的节点。所以让PVC延迟绑定,就是等到使用这个PVC的POD出现在调度器上之后(真正被调度之前),然后根据综合评估再来绑定这个PVC。

RBAC权限

由于 prometheus 可以访问 Kubernetes 的一些资源对象,所以需要配置 rbac 相关认证,这里我们使用了一个名为 prometheus 的 serviceAccount 对象:
由于我们要获取的资源信息,在每一个 namespace 下面都有可能存在,所以我们这里使用的是 ClusterRole 的资源对象,值得一提的是我们这里的权限规则声明中有一个 nonResourceURLs 的属性,是用来对非资源型 metrics 进行操作的权限声明,这个在以前我们很少遇到过,然后直接创建上面的资源对象即可:
现在我们就可以添加 promethues 的资源对象了:

文件权限

创建 Pod 后,我们可以看到并没有成功运行,出现了 open /prometheus/queries.active: permission denied 这样的错误信息,这是因为我们的 prometheus 的镜像中是使用的 nobody 这个用户,然后现在我们通过 LocalPV 挂载到宿主机上面的目录的 ownership 却是 root
所以当然会出现操作权限问题了,这个时候我们就可以通过 securityContext 来为 Pod 设置下 volumes 的权限,通过设置 runAsUser=0 指定运行的用户为 root:
也可以通过设置一个 initContainer 来修改数据目录权限:
这个时候我们重新更新下 prometheus:
Pod 创建成功后,为了能够在外部访问到 prometheus 的 Web UI 服务,我们还需要创建一个 Service 对象:
为了方便测试,我们这里创建一个 NodePort 类型的服务,当然我们可以创建一个 Ingress对象,通过域名来进行访问:
现在我们就可以通过 http://任意节点IP:32478 访问 prometheus 的 webui 服务了:
notion image
这个抓取job是用于抓取 prometheus 本身的一些监控数据了,比如我们这里就选择 process_resident_memory_bytes 这个指标,然后点击 Execute,就可以看到类似于下面的图表数据了:
notion image

Grafana部署

Prometheus 采集了 Kubernetes 集群中的一些监控数据指标,我们也尝试使用 promQL 语句查询出了一些数据,并且在 Prometheus 的 Dashboard 中进行了展示,但是明显可以感觉到 Prometheus 的图表功能相对较弱,所以一般情况下我们还是会使用 Grafana 来进行展示,所以我们可以将 Grafana 安装到集群中来。
1、创建编排文件:
两个比较重要的环境变量GF_SECURITY_ADMIN_USER 和 GF_SECURITY_ADMIN_PASSWORD,用来配置 grafana 的管理员用户和密码的,由于 grafana 将 dashboard、插件这些数据保存在 /var/lib/grafana 这个目录下面的,所以我们这里如果需要做数据持久化的话,就需要针对这个目录进行 volume 挂载声明。
2、创建并验证Pod启动正常:
3、访问 grafana:http://192.168.31.160:32052
notion image
4、添加Prometheus数据源:
notion image

容器基础资源指标

说到容器监控我们自然会想到 cAdvisor,之前分享过如何部署cAdvisor组件监控Docker容器,cAdvisor(Container Advisor) 是 Google 开源的一个容器监控工具,可用于对容器资源的使用情况和性能进行监控。它以守护进程方式运行,用于收集、聚合、处理和导出正在运行容器的有关信息。具体来说,该组件对每个容器都会记录其资源隔离参数、历史资源使用情况、完整历史资源使用情况的直方图和网络统计信息。
cAdvisor 是用于监控容器引擎的,由于其监控的实用性,Kubernetes 已经默认将其内置到 kubelet 组件中,所以我们无需再单独部署 cAdvisor 组件,直接使用 kubelet 组件提供的指标采集地址即可。
cAdvisor 的数据路径为 /api/v1/nodes/<node>/proxy/metrics,但是我们不推荐使用这种方式,因为这种方式是通过 api-server 去代理访问的,对于大规模的集群会对 api-server造成很大的压力,所以我们可以直接通过访问 kubelet 的 /metrics/cadvisor 这个端点来获取 cAdvisor 的数据。

cAdvisor接入

我们这里使用 node 的服务发现模式,因为每一个节点下面都有 kubelet,自然都有 cAdvisor 采集到的数据指标,配置如下:
cadvisor监控接入成功如下图:
notion image

k8s节点node指标

节点性能关键指标

1、主机基本信息
2、CPU使用率:
3、CPU负载:
4、内存使用率:
5、磁盘指标:
6、磁盘IO:
7、网络IO:

节点监控部署

物理节点性能监控一般是通过node_exporter来获取,要监控云原生集群节点同样我们这里使用 node_exporter,由于每个节点都需要获取到监控指标数据,所以我们可以通过 DaemonSet 控制器来部署该服务,这样每一个节点都会自动运行一个 node-exporter 的 Pod,如果我们从集群中删除或者添加节点后,也会进行自动扩展。
1、创建 DaemonSet 控制器的编排文件node-exporter-daemonset.yaml:
由于我们要获取到的数据是主机的监控指标数据,而我们的 node-exporter 是运行在容器中的,所以我们在 Pod 中需要配置一些 Pod 的安全策略,这里我们就添加了 hostPID: truehostIPC: truehostNetwork: true 3 个策略,用来使用主机的 PID namespaceIPC namespace 以及Network namespace,这些 namespace 就是用于容器隔离的关键技术。
另外使用hostPath存储卷技术将主机的 /dev/proc/sys这些目录挂载到容器中,这些因为我们采集的很多节点数据都是通过这些文件夹下面的文件来获取到的,比如我们在使用 top 命令可以查看当前 cpu 使用情况,数据就来源于文件 /proc/stat,使用 free 命令可以查看当前内存使用情况,其数据来源是来自 /proc/meminfo 文件。
2、通过DaemonSet控制器创建Pod:
3、查看Pod是否运行正常:
部署完成后,我们可以看到在 3 个节点上都运行了一个 node-exporter的Pod,且状态Running,可以通过PodIP:9100方式访问获取节点指标:
由于我们指定了 hostNetwork=true,所以PodIP实际上就是节点IP,指定的container port: 9100也会在每个节点上就会绑定一个端口 9100:
[root@k8s-01 ~]# netstat -antp|grep 9100
tcp        0      0 192.168.31.160:9100     0.0.0.0:*               LISTEN      39239/node_exporter
4、Prometheus接入配置:
成功接入后,在prometheus target页面可以看到采集正常:
notion image
5、导入8919 dashboardKubernetes云原生集群节点性能监控指标就展示到模板上,如下图:
notion image
Loading...
目录
文章列表
王小扬博客
产品
Think
Git
软件开发
计算机网络
CI
DB
设计
缓存
Docker
Node
操作系统
Java
大前端
Nestjs
其他
PHP