目录
1、在kubernetes部署Prometheus
1.1、使用ConfigMaps管理应用配置
1.2、使用Deployment部署Prometheus
2、Kubernetes下的服务发现
2.1、Kubernetes的访问授权
2.2、服务发现
2.3、使用Prometheus监控Kubernetes集群
1、在kubernetes部署Prometheus
1.1、使用ConfigMaps管理应用配置
当使用 Deployment 管理和部署应用程序时,用户可以方便了对应用进行扩容或者缩容,从而产生多个 Pod 实例。为了能够统一管理这些Pod 的配置信息,在 Kubernetes 中可以使用 ConfigMaps 资源定义和管理这些配置,并且通过环境变量或者文件系统挂载的方式让容器使用这些配置。
这里将使用 ConfigMaps 管理 Prometheus 的配置文件,创建 prometheus-config.yml 文件,并写入以下内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
使用 kubectl 命令行工具,在命名空间 default 创建 ConfigMap 资源:
kubectl create -f prometheus-config.yml
1.2、使用Deployment部署Prometheus
apiVersion: v1
kind: "Service"
metadata:
name: prometheus
labels:
name: prometheus
spec:
ports:
- name: prometheus
protocol: TCP
port: 9090
targetPort: 9090
selector:
app: prometheus
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: prometheus
name: prometheus
spec:
replicas: 1
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus:v2.2.1
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/prometheus.yml"
ports:
- containerPort: 9090
protocol: TCP
volumeMounts:
- mountPath: "/etc/prometheus"
name: prometheus-config
volumes:
- name: prometheus-config
configMap:
name: prometheus
该文件中分别定义了 Service 和 Deployment , Service 类型为 NodePort ,这样我们可以通过虚拟机 IP 和端口访问到Prometheus 实例。为了能够让 Prometheus 实例使用 ConfigMap 中管理的配置文件,这里通过 volumes 声明了一个磁盘卷。并且通过volumeMounts 将该磁盘卷挂载到 Prometheus 实例的 /etc/prometheus 目录下。
创建资源
kubectl create -f prometheus-deployment.yml
IP 地址和端口 32584 访问到 Prometheus 的服务。
2、Kubernetes下的服务发现
2.1、Kubernetes的访问授权
Prometheus 它能够与通过与“ 中间代理人 “ 的交互,从而动态的获取需要监控的目标实例。而在 Kubernetes 下 Prometheus就是需要与Kubernetes 的 API 进行交互,从而能够动态的发 Kubernetes 中部署的所有可监控的目标资源。
为了能够让 Prometheus 能够访问收到认证保护的 Kubernetes API ,我们首先需要做的是,对 Prometheus 进行访 问授权。在Kubernetes 中主要使用基于角色的访问控制模型 (Role-Based Access Control) ,用于管理Kubernetes下资源访问权限。
里创建 prometheus-rbac-setup.yml 文件,并写入以下内容:
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:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: default
---
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: default
kubectl apply -f prometheus-rbac-setup.yml
修改prometheus-deployment.yml文件,并添加 serviceAccountName 和 serviceAccount 定义:
spec:
replicas: 1
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
serviceAccount: prometheus
通过 kubectl apply 对 Deployment 进行变更升级:
kubectl apply -f prometheus-deployment.yml
指定 ServiceAccount 创建的 Pod 实例中,会自动将用于访问 Kubernetes API 的 CA 证书以及当前账户对应的访问令牌文件挂载到Pod 实例的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录下,可以通过以下命令进行查看:
kubectl exec -it prometheus-69f9ddb588-czn2c ls /var/run/secrets/kubernetes.io/serviceaccount/
2.2、服务发现
在 Kubernetes 下, Promethues 通过与 Kubernetes API 集成目前主要支持 5 种服务发现模式,分别是: Node 、 Service、 Pod 、 Endpoints 、 Ingress 。
- job_name: 'kubernetes-nodes'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
通过指定 kubernetes_sd_config 的模式为 node , Prometheus 会自动从 Kubernetes 中发现到所有的 node 节点并作为当前Job 监控的 Target 实例。如下所示,这里需要指定用于访问 Kubernetes API 的 ca 以及 token 文件路径。
对于 Ingress , Service , Endpoints, Pod 的使用方式也是类似的,下面给出了一个完整 Prometheus 配置的示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'kubernetes-nodes'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
- job_name: 'kubernetes-service'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: service
- job_name: 'kubernetes-endpoints'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: endpoints
- job_name: 'kubernetes-ingress'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: ingress
- job_name: 'kubernetes-pods'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: pod
更新 Prometheus 配置文件,并重建 Prometheus 实例:
kubectl apply -f prometheus-config.yml
kubectl get pods
kubectl delete pods prometheus-69f9ddb588-rbrs2
kubectl get pods
Prometheus 使用新的配置文件重建之后,打开 Prometheus UI ,通过 Service Discovery 页面可以查看到当前Prometheus通过 Kubernetes 发现的所有资源对象了:
同时 Prometheus 会自动将该资源的所有信息,并通过标签的形式体现在 Target 对象上。
如下所示,是 Promthues 获取到的Node 节点的标签信息:
1. __address__="192.168.99.100:10250"
2. __meta_kubernetes_node_address_Hostname="minikube"
3. __meta_kubernetes_node_address_InternalIP="192.168.99.100"
4. __meta_kubernetes_node_annotation_alpha_kubernetes_io_provided_node_ip="192.168.99.100"
5. __meta_kubernetes_node_annotation_node_alpha_kubernetes_io_ttl="0"
6.__meta_kubernetes_node_annotation_volumes_kubernetes_io_controller_managed_attach_detach="true"
7. __meta_kubernetes_node_label_beta_kubernetes_io_arch="amd64"
8. __meta_kubernetes_node_label_beta_kubernetes_io_os="linux"
9. __meta_kubernetes_node_label_kubernetes_io_hostname="minikube"
10. __meta_kubernetes_node_name="minikube"
11. __metrics_path__="/metrics"
12. __scheme__="https"
13. instance="minikube"
14. job="kubernetes-nodes"
目前为止,我们已经能够通过 Prometheus 自动发现 Kubernetes 集群中的各类资源以及其基本信息。
虽然 Prometheus 能够自动发现所有的资源对象,并且将其作为 Target 对象进行数据采集。 但并不是所有的资源对象都是支持Promethues 的,并且不同类型资源对象的采集方式可能是不同的。因此,在实际的操作中,我们需要有明确的监控目标,并且针对不同类型的监控目标设置不同的数据采集方式。
接下来,我们将利用 Promtheus 的服务发现能力,实现对 Kubernetes 集群的全面监控。
2.3、使用Prometheus监控Kubernetes集群
从Kubelet获取节点运行状态
Kubelet 组件运行在 Kubernetes 集群的各个节点中,其负责维护和管理节点上 Pod 的运行状态。 kubelet 组件的正常运行直接关系到该节点是否能够正常的被Kubernetes 集群正常使用。
基于 Node 模式, Prometheus 会自动发现 Kubernetes 中所有 Node 节点的信息并作为监控的目标 Target 。 而这些Target的访问地址实际上就是 Kubelet 的访问地址,并且 Kubelet 实际上直接内置了对 Promtheus 的支持。
修改 prometheus.yml 配置文件,并添加以下采集任务配置:
- job_name: 'kubernetes-kubelet'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
这里使用 Node 模式自动发现集群中所有 Kubelet 作为监控的数据采集目标,同时通过 labelmap 步骤,将 Node 节点上的标签,作为样本的标签保存到时间序列当中
重新加载 promethues 配置文件,并重建 Promthues 的 Pod 实例后,查看 kubernetes-kubelet 任务采集状态,我们会看到以下错误提示信息
Get https : //192.168.99.100:10250/metrics: x509: cannot validate certificate for 192.168.99.100 because it doesn't contain any IP SANs
这是由于当前使用的 ca 证书中,并不包含 192.168.99.100 的地址信息。为了解决该问题,第一种方法是直接跳过 ca 证书校验过程,通过在tls_config 中设置 insecure_skip_verify为 true 即可。 这样 Promthues 在采集样本数据时,将会自动跳过 ca 证书的校验过程,从而从kubelet 采集到监控数据:
- job_name: 'kubernetes-kubelet'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: ture
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
第二种方式,不直接通过 kubelet 的 metrics 服务采集监控数据,而通过 Kubernetes 的 api-server 提供的代理API访问各个节点中 kubelet 的 metrics 服务,如下所示:
- job_name: 'kubernetes-kubelet'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics
通过 relabeling ,将从 Kubernetes 获取到的默认地址 __address__ 替换为 kubernetes.default.svc:443 。同时将 __metrics_path__ 替换为 api-server 的代理地址 /api/v1/nodes/${1}/proxy/metrics 。
通过获取各个节点中 kubelet 的监控指标,用户可以评估集群中各节点的性能表现。例如 , 通过指标
kubelet_pod_start_latency_microseconds 可以获得当前节点中 Pod 启动时间相关的统计数据。
kubelet_pod_start_latency_microseconds{quantile="0.99"}
从Kubelet获取节点容器资源使用情况
各节点的 kubelet 组件中除了包含自身的监控指标信息以外, kubelet 组件还内置了对 cAdvisor 的支持。cAdvisor能够获取当前节点上运行的所有容器的资源使用情况,通过访问 kubelet 的 /metrics/cadvisor 地址可以获取到cadvisor 的监控指标,因此和获取 kubelet 监控指标类似,这里同样通过 node 模式自动发现所有的kubelet信息,并通过适当的 relabel 过程,修改监控采集任务的配置。 与采集 kubelet 自身监控指标相似,这里也有两种方式采集cadvisor 中的监控指标:
方式一:直接访问 kubelet 的 /metrics/cadvisor 地址,需要跳过 ca 证书认证:
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
方式二:通过 api-server 提供的代理地址访问 kubelet 的 /metrics/cadvisor 地址:
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: metrics/cadvisor
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
使用NodeExporter监控集群资源使用情况
为了能够采集集群中各个节点的资源使用情况,我们需要在各节点中部署一个Node Exporter实例。
创建node-exporter-daemonset.yml文件,并写入以下内容:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: prometheus-node-exporter
namespace: kube-system
labels:
app: prometheus-node-exporter
spec:
template:
metadata:
name: prometheus-node-exporter
labels:
app: prometheus-node-exporter
spec:
containers:
- image: prom/node-exporter:v0.16.0
imagePullPolicy: IfNotPresent
name: prometheus-node-exporter
ports:
- name: prom-node-exp
containerPort: 9100
hostPort: 9100
tolerations:
- key: "node-role.kubernetes.io/master"
effect: "NoSchedule"
hostNetwork: true
hostPID: true
hostIPC: true
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/scrape: 'true'
prometheus.io/app-metrics: 'true'
prometheus.io/app-metrics-path: '/metrics'
name: prometheus-node-exporter
namespace: kube-system
labels:
app: prometheus-node-exporter
spec:
clusterIP: None
ports:
- name: prometheus-node-exporter
port: 9100
protocol: TCP
selector:
app: prometheus-node-exporter
type: ClusterIP
已实现采样接口逻辑的资源,可通过annotation标签自动将其加入监控
- Pod资源
- prometheus.io/scrape=true
- prometheus.io/path=/metric
- prometheus.io/port=8080
- Service资源
- prometheus.io/probe
- Endpoint资源
- prometheus.io/scrape
- prometheus.io/path
- prometheus.io/port
由于Node Exporter需要能够访问宿主机,因此这里指定了hostNetwork和hostPID,让Pod实例能够以主机网络 以及系统进程的形式运行。
kubectl create -f node-exporter-daemonset.yml
配置Prometheus来scrape node-exporter的metrics:
- job_name: 'prometheus-node-exporter'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
# 只保留endpoints的annotations中含有prometheus.io/scrape: 'true'和port的name为prometheus-node-exporter的endpoint
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape, __meta_kubernetes_endpoint_port_name]
regex: true;prometheus-node-exporter
action: keep
# Match regex against the concatenated source_labels. Then, set target_label to replacement,
# with match group references (${1}, ${2}, ...) in replacement substituted by their value.
# If regex does not match, no replacement takes place.
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: (.+)(?::\d+);(\d+)
replacement: $1:$2
# 去掉label name中的前缀__meta_kubernetes_service_label_
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
# 将__meta_kubernetes_namespace重命名为kubernetes_namespace
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
# 将__meta_kubernetes_service_name重命名为kubernetes_name
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
从kube-apiserver获取集群运行监控指标
kube-apiserver扮演了整个Kubernetes集群管理的入口的角色,负责对外暴露Kubernetes API。kube-apiserver组件一般是独立部署在集群外的,为了能够让部署在集群内的应用(kubernetes插件或者用户应用)能 够与kube-apiserver交互,Kubernetes会默认在命名空间下创建一个名为kubernetes的服务。
而该kubernetes服务代理的后端实际地址通过endpoints进行维护
通过这种方式集群内的应用或者系统主机就可以通过集群内部的DNS域名kubernetes.default.svc访问到部署外 部的kube-apiserver实例。
因此,如果我们想要监控kube-apiserver相关的指标,只需要通过endpoints资源找到kubernetes对应的所有后 端地址即可。
如下所示,创建监控任务kubernetes-apiservers,这里指定了服务发现模式为endpoints。Promtheus会查找 当前集群中所有的endpoints配置,并通过relabel进行判断是否为apiserver对应的访问地址:
- job_name: 'kube-apiservers'
# 通过https访问apiserver
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
#以k8s的角色(role)来定义收集,比如node,service,pod,endpoints,ingress等等
kubernetes_sd_configs:
# 从endpoints获取apiserver数据
- role: endpoints
#relabel_configs允许在抓取之前对任何目标及其标签进行修改。
relabel_configs:
# 选择哪些label
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
# 上述选择的label的值需要与下述对应
regex: default;kubernetes;https
# 含有符合regex的source_label的endpoints进行保留
action: keep
- target_label: __address__
replacement: kubernetes.default.svc:443
对Ingress和Service进行网络探测
为了能够对Ingress和Service进行探测,我们需要在集群部署Blackbox Exporter实例。 如下所示,创建 blackbox-exporter.yaml用于描述部署相关的内容:
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-blackbox-exporter
namespace: kube-system
spec:
selector:
matchLabels:
app: prometheus-blackbox-exporter
replicas: 1
template:
metadata:
labels:
app: prometheus-blackbox-exporter
spec:
restartPolicy: Always
containers:
- name: prometheus-blackbox-exporter
image: prom/blackbox-exporter:v0.12.0
imagePullPolicy: IfNotPresent
ports:
- name: blackbox-port
containerPort: 9115
readinessProbe:
tcpSocket:
port: 9115
initialDelaySeconds: 5
timeoutSeconds: 5
resources:
requests:
memory: 50Mi
cpu: 100m
limits:
memory: 60Mi
cpu: 200m
volumeMounts:
- name: config
mountPath: /etc/blackbox_exporter
args:
- --config.file=/etc/blackbox_exporter/blackbox.yml
- --log.level=debug
- --web.listen-address=:9115
volumes:
- name: config
configMap:
name: prometheus-blackbox-exporter
nodeSelector:
node-role.kubernetes.io/master: "true"
tolerations:
- key: "node-role.kubernetes.io/master"
effect: "NoSchedule"
---
apiVersion: v1
kind: Service
metadata:
labels:
app: prometheus-blackbox-exporter
name: prometheus-blackbox-exporter
namespace: kube-system
annotations:
prometheus.io/scrape: 'true'
spec:
type: NodePort
selector:
app: prometheus-blackbox-exporter
ports:
- name: blackbox
port: 9115
targetPort: 9115
nodePort: 30009
protocol: TCP
通过kubectl命令部署Blackbox Exporter实例,这里将部署一个Blackbox Exporter的Pod实例,同时通过服 务blackbox-exporter在集群内暴露访问地址blackbox-exporter.default.svc.cluster.local,对于集 群内的任意服务都可以通过该内部DNS域名访问Blackbox Exporter实例。
为了能够让Prometheus能够自动的对Service进行探测,我们需要通过服务发现自动找到所有的Service信息。 如下所示,在Prometheus的配置文件中添加名为kubernetes-services的监控采集任务。
- job_name: 'kubernetes-services'
metrics_path: /probe
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: service
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
action: keep
regex: true
- source_labels: [__address__]
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.default.svc.cluster.local:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
target_label: kubernetes_name
对于Ingress而言,也是一个相对类似的过程,这里给出对Ingress探测的Promthues任务配置作为参考:
- job_name: 'kubernetes-ingresses'
metrics_path: /probe
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: ingress
relabel_configs:
- source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
action: keep
regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.default.svc.cluster.local:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name