Kuberentes是一款开源的容器编排产品,由Google开发后发布到社区,并在2015年将该项目捐献给了云原生基金会(Cloud Native Computing Foundation)。 从2014年第一个版本发布以来,Kubernetes便迅速获得开源社区的追捧,包括RedHat、VMware在内的很多知名企业都加入到开发和推广的阵营。目前,Kubernets已经成为发展最快、市场占有率最高的容器编排产品。
Prometheus是一款近年来非常火热的容器监控系统,它使用go语言开发,设计思路来源于Google的Borgmom(一个监控容器平台的系统)。 2016年,云原生基金会将其纳入麾下,成为该基金会继Kubernetes后,第二大开源项目。因此,Prometheus天然具有对容器的适配性,可非常方便的满足容器的监控需求,目前已成为监控Kubernetes的主要工具。
本文将介绍如何通过Prometheus监控Kubernetes集群状态的方案,限于篇幅原因会分为上、下两个篇章进行。 (对于Kubernetes的技术细节本文不做讲解,不熟悉的朋友可先自行查阅相关资料。)
一.安装Prometheus
Prometheus支持基于Kubernetes的服务发现,通过<kubernetes_sd_config>
配置允许从 Kubernetes 的API 检索抓取目标,并始终与集群状态保持同步。
我们需要在被监控集群上安装Prometheus,本文将使用YAML文件的方式进行部署。
- 创建命名空间 创建namespace.yml文件,内容如下
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
执行该yml文件
$ kubectl apply -f namespace.yml
namespace/monitoring created
查看命名空间,已成功创建。
$ kubectl get ns monitoring
NAME STATUS AGE
monitoring Active 2m53s
- 创建RBAC规则 RBAC为Kubernetes的授权认证方式,包括 ServiceAccount、ClusterRole、ClusterRoleBinding三类YAML文件。该规则用于授权Prometheus获取资源信息。
创建prometheus-rbac.yml文件,内容如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/proxy", "services", "endpoints", "pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
执行该yml文件
$ kubectl apply -f prometheus-rbac.yml
serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
查看RBAC是否创建成功
$ kubectl get sa prometheus -n monitoring
NAME SECRETS AGE
prometheus 1 77s
$ kubectl get ClusterRole prometheus
NAME CREATED AT
prometheus 2021-10-24T04:30:33Z
$ kubectl get ClusterRoleBinding prometheus -n monitoring
NAME ROLE AGE
prometheus ClusterRole/prometheus 2m20s
- 创建Configmap 我们使用Configmap来管理Prometheus的配置文件,此处先使用默认的配置,用于启动Prometheus,后面再根据需要进行修改。
创建prometheus-config.yml文件,内容如下
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
执行该yml文件
$ kubectl apply -f prometheus-config.yml
configmap/prometheus-config created
查看configmap资源是否生成
$ kubectl get configmap prometheus-config -n monitoring
NAME DATA AGE
prometheus-config 1 84s
- 部署Deployment
在完成Configmap资源创建后,我们可以开始部署Prometheus的实例了。此处,我们使用Deployment来部署Prometheus,并通过Volume挂载的方式,将Prometheus的配置文件挂载到Pod内。另外,在正式环境中建议通过PVC的方式,将收集的监控数据挂载到外部存储,避免因Pod被删除而造成数据丢失。
创建prometheus-deployment.yml文件,内容如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
labels:
app: prometheus
spec:
strategy:
type: Recreate
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- image: prom/prometheus:v2.20.0
name: prometheus
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/config/prometheus.yml"
- "--storage.tsdb.path=/data"
- "--web.enable-lifecycle"
securityContext:
runAsUser: 0
ports:
- containerPort: 9090
protocol: TCP
volumeMounts:
- mountPath: "/etc/prometheus/config/"
name: config
- name: host-time
mountPath: /etc/localtime
serviceAccountName: prometheus
volumes:
- name: config
configMap:
name: prometheus-config
- name: host-time
hostPath:
path: /etc/localtime
执行该yml文件
$ kubectl apply -f prometheus-deployment.yml
deployment.apps/prometheus created
查看Prometheus实例状态
$ kubectl get deploy -n monitoring
NAME READY UP-TO-DATE AVAILABLE AGE
prometheus 1/1 1 1 4m53s
$ kubectl get pod -n monitoring
NAME READY STATUS RESTARTS AGE
prometheus-fcfb4bbd7-4vgl9 1/1 Running 0 69s
- 创建Service 创建Prometheus的Service,用于集群内外部访问。默认情况下,Service只能在集群内访问,如果希望开放给集群外部,可选方案有Ingress、NodePort、ExternalIPs、LoadBalancer等几种。此处使用LoadBalancer方式。
创建prometheus-service.yml,内容如下:
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus
name: prometheus
namespace: monitoring
spec:
ports:
- name: "web"
port: 9090
protocol: TCP
targetPort: 9090
selector:
app: prometheus
type: LoadBalancer
执行该yml文件
$ kubectl apply -f prometheus-service.yml
service/prometheus created
查看Service状态,Service已创建完成,其中Cluster-ip用于集群内部访问,External-ip则是给到集群外部访问。
$ kubectl get service prometheus -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus LoadBalancer 10.220.57.72 10.12.61.202 9090:31183/TCP 56s
浏览器打开http://$ip:9090
,可看到Prometheus已部署完成。
查看Targets目标,当前除了监控Prometheus自身实例,还未有其他Kubernetes资源。
二. 基于Kubernetes的服务发现
在监控Kubernetes集群的过程中,我们需要使用到针对Kubernetes的服务发现功能,这个在Prometheus的原生功能中已经支持。
以下几种类型的资源角色可被配置为服务发现的目标,对于集群的监控即是通过有效利用这些角色及标签来实现。
- node角色
该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:每个节点地址类型的第一个地址(如果存在)
此外,节点的instance标签将被设置为从API服务检索到的节点名称。
- service角色 该角色发现用于检索集群中每个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角色发现用于发现所有Pod并将其容器做为目标访问,对于容器的每个声明的端口,将生成一个目标。如果容器没有指定的端口,则会为每个容器创建无端口目标。
该角色可获取到的元数据标签如下:
- __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目标,且每个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: endpoint地址目标的类型,如deployment、DaemonSet等。
- __meta_kubernetes_endpoint_address_target_name: endpoint地址目标的名称。
- ingress角色 该ingress角色发现用于发现ingress的每个地址目标。该地址将设置为ingress的spec配置中指定的host。
可使用的元数据标签如下:
结语:
本篇我们主要介绍了Prometheus实例在 Kubernetes 中的部署方式,以及监控集群所需要的服务发现功能。 下篇我们将讲解如何通过这些功能,来实现对 Kubernetes 集群的监控。