概述
在本文中,我们将会介绍如何使用Prometheus Operator简化在Kubernetes下部署和管理Prmetheus的复杂度。
Prometheus Operator 功能说明
Operator 就是针对管理特定应用程序的,在Kubernetes基本的Resource和Controller的概念上,以扩展Kubernetes api的形式。帮助用户创建,配置和管理复杂的有状态应用程序。从而实现特定应用程序的常见操作以及运维自动化。
Prometheus Operator的架构示意图:
Prometheus的本职就是一组用户自定义的CRD资源以及Controller的实现,Prometheus Operator负责监听这些自定义资源的变化,并且根据这些资源的定义自动化的完成如Prometheus Server自身以及配置的自动化管理工作。
目前,Prometheus Operator 提供的了 5 类资源:
- Prometheus:声明式创建和管理Prometheus Server实例;
- ServiceMonitor:负责声明式的管理 Service 级别监控配置;
- PodMonitor:负责声明式的管理 Pod 级别监控配置;
- PrometheusRule:负责声明式的管理告警配置;
- Alertmanager:声明式的创建和管理Alertmanager实例。
Operator 安装
下面,我们第一步来安装 Prometheus Operator。
在Kubernetes中安装Prometheus Operator非常简单,用户可以从以下地址中拉取 Prometheus Operator 的源码:
git clone https://github.com/coreos/prometheus-operator.git
这里,我们为Promethues Operator创建一个单独的命名空间monitoring:
kubectl create namespace monitoring
由于需要对Prometheus Operator进行RBAC授权,而默认的bundle.yaml中使用了default命名空间,因此,在安装Prometheus Operator之前需要先替换一下bundle.yaml文件中ClusterRoleBinding以及ServiceAccount的namespace定义。
通过运行一下命令安装Prometheus Operator的Deployment实例:
kubectl -n monitoring apply -f bundle.yaml
# clusterrolebinding.rbac.authorization.k8s.io/prometheus-operator created
# clusterrole.rbac.authorization.k8s.io/prometheus-operator created
# deployment.apps/prometheus-operator created
# serviceaccount/prometheus-operator created
Prometheus Operator通过Deployment的形式进行部署,为了能够让Prometheus Operator能够监听和管理Kubernetes资源同时也创建了单独的ServiceAccount以及相关的授权动作。
创建Prometheus实例
当集群中已经安装 Prometheus Operator 之后,对于部署 Prometheus Server 实例就变成了声明一个 Prometheus 资源,如下所示,我们在Monitoring命名空间下创建一个Prometheus实例:
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
name: inst
namespace: monitoring
spec:
# 支持额外通过 secret 的方式增加 scrape 监控配置
additionalScrapeConfigs:
key: additional-scrape-configs.yaml
name: prometheus-operator-prometheus-scrape-config
# Alert Manage 相关配置
alerting:
alertmanagers:
- apiVersion: v2
name: prometheus-operator-alertmanager
namespace: default
pathPrefix: /
port: web
# 禁用 admin API
enableAdminAPI: false
# 设置 url
externalUrl: http://prometheus-operator-prometheus.default:9090
# 启动本地端口
listenLocal: false
# 日志配置
logFormat: logfmt
logLevel: info
paused: false
# 设置关联全部的 PodMonitor
podMonitorNamespaceSelector: {}
podMonitorSelector:
matchLabels:
release: prometheus-operator
portName: web
# 副本数量
replicas: 2
# 资源限制
resources:
limits:
cpu: "5"
memory: 40Gi
requests:
cpu: "1"
memory: 400Mi
retention: 10d
routePrefix: /
# 设置关联的rule
ruleNamespaceSelector: {}
ruleSelector:
matchLabels:
app: prometheus-operator
release: prometheus-operator
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 1000
# 指定资源账户
serviceAccountName: prometheus-operator-prometheus
# 设置关联全部的 serviceMonitor
serviceMonitorNamespaceSelector: {}
serviceMonitorSelector: {}
# 存储声明
storage:
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 60Gi
storageClassName: local-path
将以上内容保存到prometheus-inst.yaml文件,并通过kubectl进行创建:
kubectl create -f prometheus-inst.yaml
# prometheus.monitoring.coreos.com/inst-1 created
此时,查看default命名空间下的statefulsets资源,可以看到Prometheus Operator自动通过Statefulset创建的Prometheus实例:
kubectl -n monitoring get statefulsets
# NAME DESIRED CURRENT AGE
# prometheus-inst 2 2 1m
添加集群内服务监控
添加监控配置项是 Prometheus 中常用的运维操作之一,为了能够自动化的管理Prometheus的配置,Prometheus Operator使用了自定义资源类型ServiceMonitor来描述监控对象的信息。
这里我们首先在集群中部署一个示例应用,将以下内容保存到 example-app.yaml,并使用kubectl命令行工具创建:
kind: Service
apiVersion: v1
metadata:
name: example-app
labels:
app: example-app
spec:
selector:
app: example-app
ports:
- name: web
port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-app
labels:
app: example-app
spec:
replicas: 3
selector:
matchLabels:
app: example-app
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: example-app
image: fabxc/instrumented_app
ports:
- name: web
containerPort: 8080
通过 kubectl 命令行工具来创建:
kubectl apply -f ./example-app.yaml
上述示例应用会通过Deployment创建3个Pod实例,并且通过Service暴露应用访问信息。
此时,我们可以在集群内访问对应的 Service Cluster IP 来调用查询看看:
kubectl get svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# example-app ClusterIP 10.233.55.121 <none> 8080/TCP 6m19s
curl http://10.233.55.121:8080/metrics
# # HELP codelab_api_http_requests_in_progress The current number of API HTTP requests in progress.
# # TYPE codelab_api_http_requests_in_progress gauge
# codelab_api_http_requests_in_progress 2
# # HELP codelab_api_request_duration_seconds A histogram of the API HTTP request durations in seconds.
# # TYPE codelab_api_request_duration_seconds histogram
# codelab_api_request_duration_seconds_bucket{method="GET",path="/api/bar",status="200",le="0.0001"} 0
# ...
在Prometheus Operator中,则可以直接声明一个 ServiceMonitor 对象来实现添加监控配置,如下所示:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: example-app
namespace: monitoring
labels:
team: frontend
spec:
namespaceSelector:
matchNames:
- default
selector:
matchLabels:
app: example-app
endpoints:
- port: web
通过定义 selector 中的标签定义选择监控目标的 Pod 对象,同时在 endpoints 中指定 port 名称为 web 的端口。默认情况下ServiceMonitor和监控对象必须是在相同Namespace下的。在本示例中由于Prometheus是部署在Monitoring命名空间下,因此为了能够关联default命名空间下的example对象,需要使用namespaceSelector定义让其可以跨命名空间关联ServiceMonitor资源。
保存以上内容到example-app-service-monitor.yaml文件中,并通过kubectl创建:
kubectl create -f example-app-service-monitor.yaml
# servicemonitor.monitoring.coreos.com/example-app created
如果希望ServiceMonitor可以关联任意命名空间下的标签,则通过以下方式定义:
spec:
namespaceSelector:
any: true
如果监控的Target对象启用了BasicAuth认证,那在定义ServiceMonitor对象时,可以使用endpoints配置中定义basicAuth如下所示:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: example-app
namespace: monitoring
labels:
team: frontend
spec:
namespaceSelector:
matchNames:
- default
selector:
matchLabels:
app: example-app
endpoints:
- basicAuth:
password:
name: basic-auth
key: password
username:
name: basic-auth
key: user
port: web
其中basicAuth中关联了名为basic-auth的Secret对象,用户需要手动将认证信息保存到Secret中:
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
data:
password: dG9vcg== # base64编码后的密码
user: YWRtaW4= # base64编码后的用户名
type: Opaque
添加服务监控后,你可以在 Prometheus 页面查询对应的指标信息等。
添加集群外实例监控
在上文中,我们已经知道了如何通过 ServiceMonitor 自定义资源对象来添加 K8s 集群内部的 Server 的监控。那么对于集群外部呢?我们应该如何添加对应的监控配置呢?
集群外添加监控时,就需要依赖到我们之前在 Prometheus CR 中设置的 additionalScrapeConfigs 配置了。
我们再来回顾一下当时的配置:
spec:
# 支持额外通过 secret 的方式增加 scrape 监控配置
additionalScrapeConfigs:
key: additional-scrape-configs.yaml
name: prometheus-operator-prometheus-scrape-config
其中:
- additionalScrapeConfigs 表示需要额外通过 secret 的方式增加 scrape 监控配置。
- name 对应的是 secret 的名称。
- additional-scrape-configs.yaml 对应的是 secret 中对应的 key 的名称。
Prometheus Operator 将会从对应的 Secret 中检测到希望的配置被提交到 Prometheus 中生效的。
下面,我们来以一个示例来演示一下。我们创建一个 additional-scrape-configs.yaml 文件,示例如下:
- job_name: linuxbase
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- 172.10.0.23:9100
然后,我们创建一个 Secret:
kubectl create secret generic prometheus-operator-prometheus-scrape-config --from-file=additional-scrape-configs.yaml --dry-run=true -o yaml > secret.yaml
提交到 K8s 集群中:
kubectl apply -f secret.yaml
稍等片刻,查看prometheus的target列表即可。