Prometheus监控k8s(10)-PrometheusOperator-更优雅的Prometheus部署
安装部署PrometheusOperator
https://www.qikqiak.com/k8s-book/docs/58.Prometheus%20Operator.html
https://blog.csdn.net/ygqygq2/article/details/83655552
1 前言
prometheus用自定义的方式来对 Kubernetes 集群进行监控,但是还是有一些缺陷,比如 Prometheus、AlertManager 这些组件服务本身的高可用,当然也完全可以用自定义的方式来实现这些需求,Promethues 在代码上就已经对 Kubernetes 有了原生的支持,可以通过服务发现的形式来自动监控集群,因此我们可以使用另外一种更加高级的方式来部署 Prometheus:Operator 框架。
Operator
Operator
是由CoreOS公司开发的,用来扩展 Kubernetes API,特定的应用程序控制器,它用来创建、配置和管理复杂的有状态应用,如数据库、缓存和监控系统。Operator
基于 Kubernetes 的资源和控制器概念之上构建,但同时又包含了应用程序特定的一些专业知识,比如创建一个数据库的Operator
,则必须对创建的数据库的各种运维方式非常了解,创建Operator
的关键是CRD
(自定义资源)的设计。
CRD
是对 Kubernetes API 的扩展,Kubernetes 中的每个资源都是一个 API 对象的集合,例如我们在YAML文件里定义的那些spec
都是对 Kubernetes 中的资源对象的定义,所有的自定义资源可以跟 Kubernetes 中内建的资源一样使用 kubectl 操作。
Operator
是将运维人员对软件操作的知识给代码化,同时利用 Kubernetes 强大的抽象来管理大规模的软件应用。目前CoreOS
官方提供了几种Operator
的实现,其中就包括我们今天的主角:Prometheus Operator
,Operator
的核心实现就是基于 Kubernetes 的以下两个概念:
- 资源:对象的状态定义
- 控制器:观测、分析和行动,以调节资源的分布
2 Prometheus-Operator简介
安装完毕后,Prometheus Operator提供了以下功能:
l 创建/毁坏: 在Kubernetes namespace中更容易启动一个Prometheus实例,一个特定的应用程序或团队更容易使用Operator。
l 简单配置: 配置Prometheus的基础东西,比如在Kubernetes的本地资源versions, persistence, retention policies, 和replicas。
l Target Services通过标签: 基于常见的Kubernetes label查询,自动生成监控target 配置;不需要学习普罗米修斯特定的配置语言。
Prometheus-Operator的架构图:
上图是Prometheus-Operator
官方提供的架构图,其中Operator
是最核心的部分,作为一个控制器,他会去创建Prometheus
、ServiceMonitor
、AlertManager
以及PrometheusRule
4个CRD
资源对象,然后会一直监控并维持这4个资源对象的状态。
其中创建的prometheus
这种资源对象就是作为Prometheus Server
存在,而ServiceMonitor
就是exporter
的各种抽象,exporter
前面我们已经学习了,是用来提供专门提供metrics
数据接口的工具,Prometheus
就是通过ServiceMonitor
提供的metrics
数据接口去 pull 数据的,当然alertmanager
这种资源对象就是对应的AlertManager
的抽象,而PrometheusRule
是用来被Prometheus
实例使用的报警规则文件。
这样我们要在集群中监控什么数据,就变成了直接去操作 Kubernetes 集群的资源对象了,是不是方便很多了。上图中的 Service 和 ServiceMonitor 都是 Kubernetes 的资源,一个 ServiceMonitor 可以通过 labelSelector 的方式去匹配一类 Service,Prometheus 也可以通过 labelSelector 去匹配多个ServiceMonitor。
总的来说:
l Operator: Operator 资源会根据自定义资源(Custom Resource Definition / CRDs)来部署和管理 Prometheus Server,同时监控这些自定义资源事件的变化来做相应的处理,是整个系统的控制中心。
l Prometheus: Prometheus 资源是声明性地描述 Prometheus 部署的期望状态。
l Prometheus Server: Operator 根据自定义资源 Prometheus 类型中定义的内容而部署的 Prometheus Server 集群,这些自定义资源可以看作是用来管理 Prometheus Server 集群的 StatefulSets 资源。
l ServiceMonitor: ServiceMonitor 也是一个自定义资源,它描述了一组被 Prometheus 监控的 targets 列表。该资源通过 Labels 来选取对应的 Service Endpoint,让 Prometheus Server 通过选取的 Service 来获取 Metrics 信息。
l Service: Service 资源主要用来对应 Kubernetes 集群中的 Metrics Server Pod,来提供给 ServiceMonitor 选取让 Prometheus Server 来获取信息。简单的说就是 Prometheus 监控的对象,例如 Node Exporter Service、Mysql Exporter Service 等等。
l Alertmanager: Alertmanager 也是一个自定义资源类型,由 Operator 根据资源描述内容来部署 Alertmanager 集群。
3 安装配置
3.1 清理环境
之前自定义安装的环境清除一下,会有很多干扰,例如node-exporter都占用9100端口
3.2 下载源码
直接通过 Prometheus-Operator 的源码来进行安装,当然也可以用 Helm 来进行一键安装,我们采用源码安装可以去了解更多的实现细节。首先将源码 Clone 下来:
最新的版本官方将资源https://github.com/coreos/prometheus-operator/tree/master/contrib/kube-prometheus迁移到了独立的 git 仓库中:https://github.com/coreos/kube-prometheus.git
[root@k8s-master operator]# git clone https://github.com/coreos/kube-prometheus.git 正克隆到 'kube-prometheus'... remote: Enumerating objects: 40, done. remote: Counting objects: 100% (40/40), done. remote: Compressing objects: 100% (28/28), done. remote: Total 6581 (delta 14), reused 19 (delta 8), pack-reused 6541 接收对象中: 100% (6581/6581), 4.01 MiB | 208.00 KiB/s, done. 处理 delta 中: 100% (3921/3921), done. [root@k8s-master operator]# ls kube-prometheus [root@k8s-master operator]# cd kube-prometheus/ [root@k8s-master kube-prometheus]# ls build.sh example.jsonnet go.sum jsonnetfile.lock.json manifests sync-to-internal-registry.jsonnet code-of-conduct.md examples hack kustomization.yaml NOTICE tests DCO experimental jsonnet LICENSE OWNERS test.sh docs go.mod jsonnetfile.json Makefile README.md
3.3 修改metrics配置文件,配置监控kubelet
[root@k8s-master manifests]# pwd /root/prometheus/operator/kube-prometheus/manifests [root@k8s-master manifests]# ls 00namespace-namespace.yaml node-exporter-clusterRole.yaml 0prometheus-operator-0alertmanagerCustomResourceDefinition.yaml node-exporter-daemonset.yaml 0prometheus-operator-0podmonitorCustomResourceDefinition.yaml node-exporter- [root@k8s-master manifests]# cat prometheus-serviceMonitorKubelet.yaml apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: k8s-app: kubelet name: kubelet namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 30s port: http-metrics scheme: http tlsConfig: insecureSkipVerify: true - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token honorLabels: true interval: 30s metricRelabelings: - action: drop regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s) sourceLabels: - __name__ path: /metrics/cadvisor port: http-metrics scheme: http tlsConfig: insecureSkipVerify: true jobLabel: k8s-app namespaceSelector: matchNames: - kube-system selector: matchLabels: k8s-app: kubelet
修改 kubelet 打开只读端口
prometheus 需要访问 kubelet 的 10255 端口获取 metrics。但是默认情况下 10255 端口是不开放的,会导致 prometheus 上有 unhealthy。打开只读端口需要编辑所有节点的vi /var/lib/kubelet/config.yaml (我这里有图形界面可以用gedit命令)文件,加入以下内容
port: 10250 readOnlyPort: 10255 #增加此行
重启 kubelet 服务
systemctl restart kubelet.service
3.4 部署
修改完成后,直接在该文件夹下面执行创建资源命令即可:
kubectl apply -f .
3.5 部署验证
部署完成后,会创建一个名为monitoring的 namespace,所以资源对象对将部署在改命名空间下面,此外 Operator 会自动创建5个 CRD 资源对象:
[root@k8s-master manifests]# kubectl get crd |grep coreos alertmanagers.monitoring.coreos.com 2019-09-26T02:22:11Z podmonitors.monitoring.coreos.com 2019-09-26T02:22:11Z prometheuses.monitoring.coreos.com 2019-09-26T02:22:12Z prometheusrules.monitoring.coreos.com 2019-09-26T02:22:12Z servicemonitors.monitoring.coreos.com 2019-09-26T02:22:12Z [root@k8s-master manifests]#
可以在 monitoring 命名空间下面查看所有的 Pod,其中 alertmanager 和 prometheus 是用 StatefulSet 控制器管理的,其中还有一个比较核心的 prometheus-operator 的 Pod,用来控制其他资源对象和监听对象变化的:
[root@k8s-master manifests]# kubectl get pods -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 0 2m49s alertmanager-main-1 2/2 Running 0 2m49s alertmanager-main-2 2/2 Running 0 2m49s grafana-57bfdd47f8-89jmq 1/1 Running 0 14m kube-state-metrics-ff5cb7949-8tbqj 3/3 Running 0 14m node-exporter-6pqr7 2/2 Running 0 14m node-exporter-sktbx 2/2 Running 0 14m node-exporter-v8hcc 2/2 Running 0 14m prometheus-adapter-668748ddbd-zqllq 1/1 Running 0 14m prometheus-k8s-0 3/3 Running 1 2m47s prometheus-k8s-1 3/3 Running 1 2m47s prometheus-operator-55b978b89-6wtlf 1/1 Running 0 14m [root@k8s-master manifests]#
查看创建的 Service:
[root@k8s-master manifests]# kubectl get svc -n monitoring NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE alertmanager-main ClusterIP 10.97.193.245 <none> 9093/TCP 14m alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 3m14s grafana ClusterIP 10.100.31.73 <none> 3000/TCP 14m kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 14m node-exporter ClusterIP None <none> 9100/TCP 14m prometheus-adapter ClusterIP 10.97.88.175 <none> 443/TCP 14m prometheus-k8s ClusterIP 10.97.199.239 <none> 9090/TCP 14m prometheus-operated ClusterIP None <none> 9090/TCP 3m13s prometheus-operator ClusterIP None <none> 8080/TCP 14m [root@k8s-master manifests]#
3.6 配置grafana和prometheus外网访问
针对 grafana 和 prometheus 都创建了一个类型为 ClusterIP 的 Service,当然如果我们想要在外网访问这两个服务的话可以通过创建对应的 Ingress 对象或者使用 NodePort 类型的 Service,我们这里为了简单,直接使用 NodePort 类型的服务即可,编辑 grafana 和 prometheus-k8s 这两个 Service,将服务类型更改为 NodePort:
[root@k8s-master manifests]# kubectl edit svc grafana -n monitoring service/grafana edited [root@k8s-master manifests]# kubectl edit svc prometheus-k8s -n monitoring service/prometheus-k8s edited [root@k8s-master manifests]# kubectl get svc -n monitoring| grep -E "grafana|prometheus-k8s" grafana NodePort 10.100.31.73 <none> 3000:32339/TCP 35m prometheus-k8s NodePort 10.97.199.239 <none> 9090:31466/TCP 35m [root@k8s-master manifests]#
3.7 外网访问
grafana
prometheus
3.8 监控k8s二进制组件
3大组件,kubelet上面自动配置了
可以看到大部分的配置都是正常的,只有两三个没有管理到对应的监控目标,比如 kube-controller-manager 和 kube-scheduler 这两个系统组件,这就和 ServiceMonitor 的定义有关系了
[root@k8s-master manifests]# cat prometheus-serviceMonitorKubeScheduler.yaml apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: k8s-app: kube-scheduler name: kube-scheduler namespace: monitoring spec: endpoints: - interval: 30s # 每30s获取一次信息 port: http-metrics # 对应service的端口名 jobLabel: k8s-app namespaceSelector: # 表示去匹配某一命名空间中的service,如果想从所有的namespace中匹配用any: true matchNames: - kube-system selector: # 匹配的 Service 的labels,如果使用mathLabels,则下面的所有标签都匹配时才会匹配该service,如果使用matchExpressions,则至少匹配一个标签的service都会被选择 matchLabels: k8s-app: kube-scheduler [root@k8s-master manifests]# cat prometheus-serviceMonitorKubeControllerManager.yaml apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: k8s-app: kube-controller-manager name: kube-controller-manager namespace: monitoring spec: endpoints: - interval: 30s metricRelabelings: - action: drop regex: etcd_(debugging|disk|request|server).* sourceLabels: - __name__ port: http-metrics jobLabel: k8s-app namespaceSelector: matchNames: - kube-system selector: matchLabels: k8s-app: kube-controller-manager
上面是一个典型的 ServiceMonitor 资源文件的声明方式,上面我们通过selector.matchLabels在 kube-system 这个命名空间下面匹配具有k8s-app=kube-scheduler这样的 Service,但是我们系统中根本就没有对应的 Service,所以我们需要手动创建一个 Service:
prometheus-kube-controller-manager-service.yaml
prometheus-kube-scheduler-service.yaml
[root@k8s-master manifests]# cat prometheus-kube-controller-manager-service.yaml apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-controller-manager labels: k8s-app: kube-controller-manager spec: selector: component: kube-controller-manager ports: - name: http-metrics port: 10252 targetPort: 10252 protocol: TCP
[root@k8s-master manifests]# cat prometheus-kube-scheduler-service.yaml apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-scheduler labels: k8s-app: kube-scheduler spec: selector: component: kube-scheduler ports: - name: http-metrics port: 10251 targetPort: 10251 protocol: TCP
#10251是kube-scheduler
组件 metrics 数据所在的端口,10252是kube-controller-manager
组件的监控数据所在端口。
上面 labels 和 selector 部分,labels 区域的配置必须和我们上面的 ServiceMonitor 对象中的 selector 保持一致,selector
下面配置的是component=kube-scheduler
,为什么会是这个 label 标签呢,我们可以去 describe 下 kube-scheduelr 这个 Pod
[root@k8s-master manifests]# kubectl describe pod kube-scheduler-k8s-master -n kube-system Name: kube-scheduler-k8s-master Namespace: kube-system Priority: 2000000000 Priority Class Name: system-cluster-critical Node: k8s-master/10.6.76.25 Start Time: Thu, 29 Aug 2019 09:21:01 +0800 Labels: component=kube-scheduler tier=control-plane ...
[root@k8s-master manifests]# kubectl describe pod kube-controller-manager-k8s-master -n kube-system Name: kube-controller-manager-k8s-master Namespace: kube-system Priority: 2000000000 Priority Class Name: system-cluster-critical Node: k8s-master/10.6.76.25 Start Time: Thu, 29 Aug 2019 09:21:01 +0800 Labels: component=kube-controller-manager tier=control-plane
我们可以看到这个 Pod 具有component=kube-scheduler
和tier=control-plane
这两个标签,而前面这个标签具有更唯一的特性,所以使用前面这个标签较好,这样上面创建的 Service 就可以和我们的 Pod 进行关联了,直接创建即可:
kubectl create -f prometheus-kube-scheduler-service.yaml kubectl create -f prometheus-kube-controller-manager-service.yaml [root@k8s-master manifests]# kubectl get svc -n kube-system | grep -E "contr|sche" kube-controller-manager ClusterIP 10.105.206.57 <none> 10252/TCP 86s kube-scheduler ClusterIP 10.108.11.188 <none> 10251/TCP 21m [root@k8s-master manifests]#
有文章说需要修改kube-scheduler和kube- controller-manager绑定地址,我没有遇到
如果需要修改
$ ls /etc/kubernetes/manifests/ etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yam
将 kube-scheduler.yaml 文件中-command
的--address
地址更改成0.0.0.0
:
containers: - command: - kube-scheduler - --leader-elect=true - --kubeconfig=/etc/kubernetes/scheduler.conf - --address=0.0.0.0
4 grafana-dashboart展示
上面的监控数据配置完成后,现在我们可以去查看下 grafana 下面的 dashboard,同样使用上面的 NodePort 访问即可,第一次登录使用 admin:admin 登录即可,进入首页后,可以发现已经和我们的 Prometheus 数据源关联上了,正常来说可以看到一些监控图表了:
自动配置很多模板
5 配置alertmanger展示
编辑alertmanager-main Service,将服务类型更改为 NodePort:
[root@k8s-master manifests]# kubectl get svc -n monitoring| grep alertmanager-main NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE alertmanager-main ClusterIP 10.97.193.245 <none> 9093/TCP 4h28m [root@k8s-master manifests]# kubectl edit svc alertmanager-main -n monitoring service/alertmanager-main edited [root@k8s-master manifests]# kubectl get svc -n monitoring | grep alertmanager-main alertmanager-main NodePort 10.97.193.245 <none> 9093:31067/TCP 4h30m [root@k8s-master manifests]#