在 Kubernetes 集群的 ETCD 默认是开启暴露 metrics 数据的,不过一般来说 ETCD 部署在集群外,并且其暴露的接口是基于 HTTPS 协议。为了统一管理,我们需要将 ETCD 服务代理到 Kubernetes 集群中,然后使用 Prometheus 的 Kubernetes 动态服务发现机制,自动查找到带有指定 label 标签的 ETCD Service 服务。
Prometheus 通过服务发现机制采集 ETCD 数据的流程:
https://mydlq-club.oss-cn-beijing.aliyuncs.com/images/prometheus-etcd-cluster-1002.png?x-oss-process=style/shuiyin
prometheus监控etcd也是有两种方式:
第一种是通过在prometheus的配置文件下配置静态服务发现,将etcd的信息添加进去,通过在prometheus添加etcd的监控项来监控。
第二种是给etcd添加service服务。然后再prometheus的配置文件中添加k8s的服务发现的方式。
下面介绍下prometheus监控etcd的方法。
对于 etcd 集群一般情况下,为了安全都会开启 https 证书认证的方式,所以要想让 Prometheus 访问到 etcd 集群的监控数据,就需要提供相应的证书校验。
我这用的是kubeadm方式搭建的集群,可以使用kubectl工具去查看etcd启动的时候使用的证书路径:
kubectl -n kube-system get po etcd-k8s-master -o yaml
可以看到 etcd 使用的证书对应在节点的 /etc/kubernetes/pki/etcd 这个路径下面,所以首先我们将需要使用到的证书通过 secret 对象保存到集群中去:(在 etcd 运行的节点)
$ kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key --from-file=/etc/kubernetes/pki/etcd/ca.crt
secret "etcd-certs" created
如果是独立的二进制方式启动的 etcd 集群,同样将对应的证书保存到集群中的一个 secret 对象中去即可。
1.在k8s-master节点创建secret,将需要的etcd证书保存到secret对象etcd-certs中:
kubectl -n monitor-sa create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/server.key --from-file=/etc/kubernetes/pki/etcd/server.crt --from-file=/etc/kubernetes/pki/etcd/ca.crt
2.修改prometheus-deploy.yaml文件,添加secrets,即将创建的secret对象"etcd-certs"通过volumes挂载方式,添加到prometheus-deploy.yaml部署文件中,如下所示:
- name: k8s-certs
mountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/
和
- name: k8s-certs
secret:
secretName: etcd-certs
变成下面这样
volumeMounts:
- mountPath: /etc/prometheus/prometheus.yml
name: prometheus-config
subPath: prometheus.yml
- mountPath: /prometheus/
name: prometheus-storage-volume
- name: k8s-certs
mountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
items:
- key: prometheus.yml
path: prometheus.yml
mode: 0644
- name: prometheus-storage-volume
hostPath:
path: /data
type: Directory
- name: k8s-certs
secret:
secretName: etcd-certs
3.修改prometheus-cfg.yaml文件,增加如下job
- job_name: 'kubernetes-etcd'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crt
cert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crt
key_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.key
scrape_interval: 5s
static_configs:
- targets: ['192.168.1.138:2379']
kubectl apply -f prometheus-cfg.yaml
kubectl delete -f prometheus-deploy.yaml
kubectl apply -f prometheus-deploy.yaml
第二种方法:
首先需要创建 ETCD 的 Service
和 Endpoints
资源,将 ETCD 代理到 Kubernetes 集群内部,然后给 ETCD Service 添加指定 labels 标签 app.kubernetes.io/name: etcd
,这样后续 Prometheus 会通过 Kubernetes 服务发现机制,查找到带有此标签的 Service 关联的应用列表。
将 ETCD 代理到 Kubernetes 的 Endpoints 和 Service 资源配置文件 etcd-proxy.yaml
内容如下:
apiVersion: v1
kind: Service
metadata:
name: etcd-k8s
namespace: kube-system
labels:
k8s-app: etcd ## Kubernetes 会根据该标签和 Endpoints 资源关联
app.kubernetes.io/name: etcd ## Prometheus 会根据该标签服务发现到该服务
spec:
type: ClusterIP
clusterIP: None ## 设置为 None,不分配 Service IP
ports:
- name: port
port: 2379
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: etcd-k8s
namespace: kube-system
labels:
k8s-app: etcd
subsets:
- addresses: ## 代理的应用IP地址列表
- ip: 192.168.1.138
ports:
- port: 2379 ## 代理的应用端口号
由于 ETCD 是基于 HTTPS
协议,Prometheus 采集指标数据时需要使用 TLS
证书,所以我们需要将 ETCD 的证书文件挂载到 Kubernetes 集群的 ConfigMap 资源中。创建完后需要修改 Prometheus 部署资源的挂载配置,将证书 ConfigMap 挂载到 Prometheus 容器中。
将etcd证书文件存入configmap
进入etcd所在的服务器,将etcd证书文件挂载到kubernetes的configmap资源中,执行的命令如下:
-n: 命令空间。
–from-file: 读取指定文件,生成 ConfigMap 资源。
$ kubectl create secret generic etcd-certs \
--from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
--from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key \
--from-file=/etc/kubernetes/pki/etcd/ca.crt \
-n kube-system
注: 我是使用 kubeadm 安装的 Kubernetes 集群,默认 ETCD 证书会放到
/etc/kubernetes/pki/etcd/
目录下。
接下来我们修改 Prometheus 部署资源配置,添加挂载 ETCD 证书参数,将证书文件挂入 Prometheus 应用中,内容如下:
apiVersion: v1
kind: Service
metadata:
name: prometheus
labels:
k8s-app: prometheus
spec:
type: NodePort
ports:
- name: http
port: 9090
targetPort: 9090
nodePort: 30900
selector:
k8s-app: prometheus
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
labels:
k8s-app: prometheus
spec:
replicas: 1
selector:
matchLabels:
k8s-app: prometheus
template:
metadata:
labels:
k8s-app: prometheus
spec:
serviceAccountName: prometheus
containers:
- name: prometheus
image: prom/prometheus:v2.26.0
ports:
- name: http
containerPort: 9090
securityContext:
runAsUser: 65534
privileged: true
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--web.enable-lifecycle"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention.time=10d"
- "--web.console.libraries=/etc/prometheus/console_libraries"
- "--web.console.templates=/etc/prometheus/consoles"
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 1000m
memory: 512Mi
readinessProbe:
httpGet:
path: /-/ready
port: 9090
initialDelaySeconds: 5
timeoutSeconds: 10
livenessProbe:
httpGet:
path: /-/healthy
port: 9090
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- name: data
mountPath: /prometheus
subPath: prometheus
- name: config
mountPath: /etc/prometheus
- name: certs #### 将ETCD证书的ConfigMap挂进Prometheus容器
readOnly: true
mountPath: /certs
- name: configmap-reload
image: jimmidyson/configmap-reload:v0.5.0
args:
- "--volume-dir=/etc/config"
- "--webhook-url=http://localhost:9090/-/reload"
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 10m
memory: 10Mi
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
volumes:
- name: data
persistentVolumeClaim:
claimName: prometheus
- name: config
configMap:
name: prometheus-config
- name: certs #### 将ETCD证书的ConfigMap挂进Prometheus容器
secret:
secretName: etcd-certs
接下来我们创建 Prometheus 采集 ETCD 的配置,在配置中需要指定使用的 TLS 证书参数和 Kubernetes 服务发现机制,配置内容如下:
###################### kubernetes-etcd ######################
- job_name: "kubernetes-etcd"
scheme: https
tls_config:
## 配置 ETCD 证书所在路径(Prometheus 容器内的文件路径)
ca_file: /certs/ca.crt
cert_file: /certs/healthcheck-client.crt
key_file: /certs/healthcheck-client.key
insecure_skip_verify: false
kubernetes_sd_configs:
## 配置服务发现机制,指定 ETCD Service 所在的Namespace名称
- role: endpoints
namespaces:
names: ["monitor-sa"]
relabel_configs:
## 指定从 app.kubernetes.io/name 标签等于 etcd 的 service 服务获取指标信息
- action: keep
source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name]
regex: etcd
将etcd采集配置写入prometheus的configmap中
这里将上面 Prometheus 中的配置参数写到 Kubernetes 中的 ConfigMap 资源 prometheus-config.yaml
中,内容如下:
kind: ConfigMap
apiVersion: v1
metadata:
name: prometheus-config
namespace: kube-system
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: "kubernetes"
scrape_configs:
###################### kubernetes-etcd ######################
- job_name: "kubernetes-etcd"
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crt
cert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crt
key_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.key
insecure_skip_verify: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names: ["kube-system"]
relabel_configs:
- action: keep
source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name]
regex: etcd
Prometheus重新加载配置
-f: 指定要部署的资源文件。
-n: 指定 Namespace 名称。
$ kubectl apply -f prometheus-config.yaml -n monitor-sa
配置修改后需要使 Prometheus 重新加载 ConfigMap 中的参数配置,执行命令如下:
$ curl -XPOST http://192.168.1.138:30090/-/reload
重新加载prometheus的配置后,我们打开它的UI界面,查看targets一栏中是否存在etcd采集目标记录,并且检测状态是否正常。