提示:本文原创作品,良心制作,干货为主,简洁清晰,一看就会
文章目录
- 前言
- 一、流程概述
-
- [1.1 实验环境介绍](#1.1 实验环境介绍)
- [1.2 整体流程概述](#1.2 整体流程概述)
- 二、Redis集群搭建
- 三、监控Redis
-
- [3.1 创建redis-exporter](#3.1 创建redis-exporter)
- [3.2 创建redis-exporter-svc](#3.2 创建redis-exporter-svc)
- [3.3 创建scrapeconfig](#3.3 创建scrapeconfig)
- [3.4 grafana添加dashboard](#3.4 grafana添加dashboard)
前言
在云原生环境中,Redis Cluster 作为高性能分布式缓存,其稳定运行至关重要。然而,面对动态调度的 Kubernetes 集群,传统的监控方案往往难以灵活适配。借助 Prometheus Operator,我们可以声明式地定义监控目标,利用 ScrapeConfig自动采集指标,并结合 Grafana 实现可视化与告警。本文将从部署 Redis Cluster 到配置 Exporter、编写 ScrapeConfig 资源,完整阐述如何以 Operator 原生方式构建生产级的 Redis 集群监控体系,帮助运维人员快速发现瓶颈、保障数据服务可靠性。
一、流程概述
1.1 实验环境介绍
我的实验环境:
| 主机名 | ip | 作用 |
|---|---|---|
| K8s-master1 | 192.168.13.136 | k8s控制节点 |
| K8s-master2 | 192.168.13.137 | k8s控制节点 |
| K8s-master3 | 192.168.13.138 | k8s控制节点 |
| k8s-node1 | 192.168.13.139 | k8s工作节点 |
| k8s-node2 | 192.168.13.140 | k8s工作节点 |
| NFS | 192.168.13.141 | NFS服务端,提供存储 |
当前,我的高可用 Kubernetes 集群已部署完毕,Prometheus Operator 也已完成安装配置。接下来,我将开始实操,对集群内运行的 Redis Cluster 进行监控配置
1.2 整体流程概述
-
部署 Redis 集群
使用 StatefulSet + Headless Service 创建多节点 Redis 实例
目的:为每个 Redis Pod 分配稳定的网络标识,便于 Prometheus 精确抓取每个实例
-
部署单实例 Redis Exporter
在
monitoring命名空间启动一个 Exporter Deployment目的:开启多目标模式,让一个 Exporter 代理采集所有 Redis 实例的指标
-
创建 Exporter Service
为 Exporter 创建 ClusterIP Service
目的 :提供固定域名(
redis-exporter.monitoring.svc),作为 Prometheus 抓取的统一入口 -
配置 ScrapeConfig
编写 ScrapeConfig 资源,列出所有 Redis 地址,并通过 relabelings 将
__address__改写为 Exporter 的 Service 地址,同时将原始 Redis 地址存入__param_target目的 :让 Prometheus 每次抓取时请求 Exporter 的
/scrape?target=<某个Redis地址>,从而轮询采集所有 Redis 节点 -
验证与可视化
检查 Prometheus Targets 页面确认所有 Redis 实例 UP,并导入 Grafana 仪表盘
二、Redis集群搭建
yaml
root@k8s-master1:~# mkdir /k8s/redis
root@k8s-master1:~# cd /k8s/redis/
root@k8s-master1:/k8s/redis# vim redis-cm-svc-pod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-conf
data:
redis.conf: |
port 6379
# 启用集群模式
cluster-enabled yes
# 集群节点状态持久化文件路径
cluster-config-file /var/lib/redis/nodes.conf
# 集群节点超时时间
cluster-node-timeout 5000
# 开启AOF持久化
appendonly yes
# 数据存放目录
dir /var/lib/redis
# 关闭保护模式
protected-mode no
# 不以守护进程方式进行
daemonize no
pidfile /var/run/redis.pid
# 日志输出到标准输出
logfile ""
# RDB持久化规则
save 900 1
save 300 10
save 60 10000
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
labels:
app: redis
spec:
ports:
- name: redis-port
port: 6379
- name: cluster
port: 16379
clusterIP: None
selector:
app: redis
appCluster: redis-cluster
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-service
replicas: 6
selector:
matchLabels:
app: redis
appCluster: redis-cluster
template:
metadata:
labels:
app: redis
appCluster: redis-cluster
spec:
# 初始化容器(在主容器启动前执行)
initContainers:
- name: fix-permissions
# 使用busybox镜像执行权限修复
image: busybox:latest
command:
- sh
- -c
- chown -R 999:999 /var/lib/redis
volumeMounts:
- name: redis-data
mountPath: /var/lib/redis
containers:
- name: redis
image: redis:latest
command:
- /bin/sh
- -c
- |
# 将基础配置文件复制到临时位置
cat /etc/redis/redis.conf.base > /tmp/redis.conf
# 注入集群广播地址(使用pod的dns名称)
echo "cluster-announce-ip ${HOSTNAME}.redis-service.${NAMESPACE}.svc" >> /tmp/redis.conf
# 注入客户端通信端口
echo "cluster-announce-port 6379" >> /tmp/redis.conf
# 注入集群总线端口
echo "cluster-announce-bus-port 16379" >> /tmp/redis.conf
# 启动redis服务并使用生产的配置文件
exec redis-server /tmp/redis.conf
env:
# 获取pod名称
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
# 获取pod所在命名空间
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 6379
name: redis
- containerPort: 16379
name: cluster
volumeMounts:
- name: redis-config
mountPath: /etc/redis/redis.conf.base
subPath: redis.conf
- name: redis-data
mountPath: /var/lib/redis
volumes:
- name: redis-config
configMap:
name: redis-conf
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
storageClassName: "nfs-client"
yaml
root@k8s-master1:/k8s/redis# kubectl apply -f redis-cm-svc-pod.yaml
root@k8s-master1:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 63d
redis-service ClusterIP None <none> 6379/TCP,16379/TCP 4m58s
root@k8s-master1:~# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
redis-0 1/1 Running 0 5m5s 10.244.169.172 k8s-node2 <none> <none>
redis-1 1/1 Running 0 4m18s 10.244.36.104 k8s-node1 <none> <none>
redis-2 1/1 Running 0 3m30s 10.244.169.160 k8s-node2 <none> <none>
redis-3 1/1 Running 0 2m41s 10.244.36.98 k8s-node1 <none> <none>
redis-4 1/1 Running 0 110s 10.244.169.145 k8s-node2 <none> <none>
redis-5 1/1 Running 0 61s 10.244.36.95 k8s-node1 <none> <none>
yaml
## 创建三主三从的集群
root@k8s-master1:~# kubectl exec -it redis-0 -- redis-cli --cluster create \
redis-0.redis-service.default.svc:6379 \
redis-1.redis-service.default.svc:6379 \
redis-2.redis-service.default.svc:6379 \
redis-3.redis-service.default.svc:6379 \
redis-4.redis-service.default.svc:6379 \
redis-5.redis-service.default.svc:6379 \
--cluster-replicas 1
yaml
## 随意进入一个pod中查看集群信息
root@k8s-master1:~# kubectl exec -it redis-0 /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "redis" out of: redis, fix-permissions (init)
root@redis-0:/data# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> cluster nodes
c3d5a88f71633dbefbbbc625f25b27847a0bec55 redis-2.redis-service.default.svc:6379@16379 master - 0 1781071190000 3 connected 10923-16383
c92a766749dc30edd3c2e1727f853849649150cc redis-4.redis-service.default.svc:6379@16379 slave 3a7f6997df5cf28a4de91888c1fe9559f4767a91 0 1781071191581 1 connected
76a6873936f5f14d95b0b2b0d0413699544950d4 redis-3.redis-service.default.svc:6379@16379 slave c3d5a88f71633dbefbbbc625f25b27847a0bec55 0 1781071190070 3 connected
15ecc0072b2d8001d4b39a0d9f69cb23911524c8 redis-1.redis-service.default.svc:6379@16379 master - 0 1781071191585 2 connected 5461-10922
3a7f6997df5cf28a4de91888c1fe9559f4767a91 redis-0.redis-service.default.svc:6379@16379 myself,master - 0 0 1 connected 0-5460
c90bb3d1e4d5760c7abff207f924b9bfad999cc8 redis-5.redis-service.default.svc:6379@16379 slave 15ecc0072b2d8001d4b39a0d9f69cb23911524c8 0 1781071190575 2 connected
三、监控Redis
3.1 创建redis-exporter
redis-exporter是一个独立的程序,负责连接redis cluster集群,采集各种监控指标并翻译成Prometheus能识别的metrics格式,并通过9121端口/metrics暴露出来
没有redis-exporter,Prometheus根本看不懂redis的数据
yaml
root@k8s-master1:~/kube-prometheus/manifests# vim redis-exporter.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-exporter
namespace: monitoring
labels:
app: redis-exporter
spec:
replicas: 1
selector:
matchLabels:
app: redis-exporter
template:
metadata:
labels:
app: redis-exporter
spec:
containers:
- name: redis-exporter
image: oliver006/redis_exporter:latest # 必须使用完整镜像名
ports:
- containerPort: 9121
name: metrics
# 不加任何 args,先测试基础运行
root@k8s-master1:~/kube-prometheus/manifests# kubectl apply -f redis-exporter.yaml
3.2 创建redis-exporter-svc
由于K8S里的pod ip是会变的,所以我们需要创建一个svc给redis-exporter提供一个稳定的clusterip+dns域名redis-exporter.monitoring:9121
redis-exporter-svc用来保证Prometheus总能稳定连接到redis-exporter
yaml
root@k8s-master1:~/kube-prometheus/manifests# vim redis-exporter-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-exporter
namespace: monitoring
labels:
app: redis-exporter
spec:
selector:
app: redis-exporter
ports:
- name: metrics
port: 9121
targetPort: 9121
root@k8s-master1:~/kube-prometheus/manifests# kubectl apply -f redis-exporter-svc.yaml
3.3 创建scrapeconfig
scrapeconfig作用是告诉Prometheus怎么监控redis集群,它定义了三件事:
1,要监控6个redis节点;2,通过redis-exporter去采集;3,每个redis节点都是一个独立监控目标
scrapeconfig要监控6个redis域名,但是不直接连接redis,它是通过redis-exporter.monitoring:9121这个地址去采集,svc把请求转给redis-exporter,然后exporter去连接6个redis节点,拿到指标返回给Prometheus
yaml
root@k8s-master1:~/kube-prometheus/manifests# vim redis-scrapeconfig.yaml
apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
name: redis-exporter
namespace: monitoring
spec:
scrapeInterval: 30s
jobName: redis-exporter
metricsPath: /scrape
scheme: HTTP
staticConfigs:
- targets:
# Prometheus逐个把redis地址传给exporter;exporter用地址去连接对应redis pod,拿到指标 → 返回给 Prometheus
- redis://redis-0.redis-service.default.svc.cluster.local:6379
- redis://redis-1.redis-service.default.svc.cluster.local:6379
- redis://redis-2.redis-service.default.svc.cluster.local:6379
- redis://redis-3.redis-service.default.svc.cluster.local:6379
- redis://redis-4.redis-service.default.svc.cluster.local:6379
- redis://redis-5.redis-service.default.svc.cluster.local:6379
relabelings:
# 将原始目标地址(__address__)提取到 __param_target 参数中
- sourceLabels: [__address__]
targetLabel: __param_target
# 将 __param_target 的值复制到 instance 标签,便于区分
- sourceLabels: [__param_target]
targetLabel: instance
# 修改 __address__ 为 Exporter 的地址,使 Prometheus 抓取 Exporter 的 /scrape 端点
- targetLabel: __address__
replacement: redis-exporter.monitoring:9121
root@k8s-master1:~/kube-prometheus/manifests# kubectl apply -f redis-scrapeconfig.yaml
浏览器访问Prometheus,可以看到6个redis实例已经被添加

3.4 grafana添加dashboard
grafana官网:https://grafana.com/grafana/dashboards/
登录grafana,添加redis的dashboard
这里我选择了一个常用的dashboard,大家也可以去grafana官网自行挑选
redis dashboard:https://grafana.com/grafana/dashboards/17507-1-redis-exporter-dashboard/




至此,基于 Prometheus Operator 监控 Redis Cluster 集群的配置全部完成!
注:
文中若有疏漏,欢迎大家指正赐教。
本文为100%原创,转载请务必标注原创作者,尊重劳动成果。
求赞、求关注、求评论!你的支持是我更新的最大动力,评论区等你~