10. Redis Operator (3) —— 监控配置

0. 简介

前面,我们已经分别可以部署了单机版和Sentinel版的Redis Operator,我们现在来完善一些监控指标。

0.1 Redis Exporter

Redis Exporter 是 Prometheus 监控生态中的关键组件,用于采集 Redis 实例的性能指标并转换为 Prometheus 格式。如下:

功能类别 具体指标
基础运行指标 内存使用量、连接数、命令执行次数、键数量、网络流量等
持久化监控 RDB/AOF 操作状态、持久化时间、缓冲区大小
复制监控 主从复制状态、复制延迟、同步状态
集群监控 集群节点状态、槽位分配、故障转移状态 (支持 Redis Cluster)
特殊功能 Lua脚本性能分析、慢查询统计、键空间分析

0.2 整体方案

sequenceDiagram participant O as Prometheus Operator participant P_CR as Prometheus CR participant SM as ServiceMonitor participant P_S as Prometheus Server participant E as Redis Exporter participant R as Redis Server %% 配置管理流程 O->>P_CR: 监控Prometheus CR变化 P_CR->>O: 通知配置变更 O->>SM: 查找匹配的ServiceMonitor SM->>O: 提供监控目标配置 O->>P_S: 生成配置文件 O->>P_S: 触发重载 %% 数据采集流程 loop 定时抓取 P_S->>E: 请求 /metrics 端点 E->>R: 执行 INFO/CLUSTER INFO 等命令 R->>E: 返回原始数据 E->>E: 转换为Prometheus格式 E->>P_S: 返回指标数据 end

整体方案如上所示,所以我们大致分为三步来做这个事情:

  1. Operator实现Redis Exporter;
  2. 部署Prometheus相关组件;
  3. 实现ServiceMnitor;

1. Operator改造

为了方便,我们以单机版的Redis Operator为例,我们在redis_types.go中添加如下配置:

go 复制代码
// RedisSpec defines the desired state of Redis
type RedisSpec struct {
    // ... 已有字段

    // Exporter
    Exporter ExporterSpec `json:"exporter,omitempty"`
}

// ExporterSpec 定义 Redis Exporter 配置
type ExporterSpec struct {
    // 是否启用监控
    Enable bool `json:"enable,omitempty"`

    // 镜像
    // +kubebuilder:default="oliver006/redis_exporter:v1.50.0"
    Image string `json:"image,omitempty"`

    // 端口
    // +kubebuilder:default=9121
    Port int32 `json:"port,omitempty"`

    // 资源限制
    Resources corev1.ResourceRequirements `json:"resources,omitempty"`
}

redis_controller.go中添加如下代码,即在开启了Exporter之后,使用多应用容器的方式启动Exporter(这是因为我的k8s版本是1.27,在1.29以上版本,使用边车容器的方式会更优雅)。

go 复制代码
func (r *RedisReconciler) reconcileStatefulSet(ctx context.Context, redis *cachev1.Redis) error {
    // ...

    if redis.Spec.Exporter.Enable {
       // 添加 Redis Exporter 容器
       desired.Spec.Template.Spec.Containers = append(desired.Spec.Template.Spec.Containers, corev1.Container{
          Name:            "redis-exporter",
          Image:           redis.Spec.Exporter.Image,
          ImagePullPolicy: corev1.PullIfNotPresent,
          Ports: []corev1.ContainerPort{
             {
                Name:          "metrics",
                ContainerPort: redis.Spec.Exporter.Port,
             },
          },
          Args: []string{
             fmt.Sprintf("--redis.addr=localhost:%d", RedisPort),
             fmt.Sprintf("--web.listen-address=:%d", redis.Spec.Exporter.Port),
          },
          Resources: redis.Spec.Exporter.Resources,
       })
    }

    // ...
}

另外,在redis_webhook.go中新增校验:

go 复制代码
// validateRedis 执行具体验证逻辑
func (r *Redis) validateRedis(redis *Redis) error {
    // ...

    // 验证Redis Exporter
    if redis.Spec.Exporter.Enable {
       if redis.Spec.Exporter.Image == "" {
          redis.Spec.Exporter.Image = "oliver006/redis_exporter:v1.50.0"
          redislog.Info("Setting default exporter image", "image", redis.Spec.Exporter.Image)
       }

       if redis.Spec.Exporter.Port == 0 {
          redis.Spec.Exporter.Port = 9121
          redislog.Info("Setting default exporter port", "port", redis.Spec.Exporter.Port)
       }
    }

    // ...
}

如上,我们基本就将Operator改造完成了。

2. 集群改造

因为本地是kind搭建的集群,所以我们对外暴露一下Prometheus和Grafana的端口:

yaml 复制代码
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 31000
    hostPort: 6380
    protocol: TCP
  # Prometheus UI
  - containerPort: 30090
    hostPort: 30090
    protocol: TCP
  # Grafana UI
  - containerPort: 30091
    hostPort: 30091
    protocol: TCP
  # Alertmanager
  - containerPort: 30093
    hostPort: 9093
    protocol: TCP
  extraMounts:
    # 主机目录映射到节点容器
    - hostPath: /Users/chenyiguo/workspace/k8s/kind/single_date
      containerPath: /data
- role: worker
  extraMounts:
  # 主机目录映射到节点容器
  - hostPath: /Users/chenyiguo/workspace/k8s/kind/single_date
    containerPath: /data

3. 监控组件

3.1 安装Prometheus等

bash 复制代码
# 创建 prometheus 命名空间
$ k create namespace prometheus

# 添加 Helm 仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 安装 kube-prometheus-stack
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
  -n prometheus \
  --set prometheus.service.type=NodePort \
  --set prometheus.service.nodePort=30090 \
  --set grafana.service.type=NodePort \
  --set grafana.service.nodePort=30091 \
  --set alertmanager.service.type=NodePort \
  --set alertmanager.service.nodePort=30093

我们在名为prometheus的命名空间下安装了Prometheus以及Grafana等。这个时候我们需要注意的是,这里将Prometheus的Operator和Server都一起安装了,和所有的Operator一样,有整个Operator的管理程序,也有其CRD,以及CRD派生的Statefulset(Or Deployment)和Pod,比如:

bash 复制代码
$ k -n prometheus get prometheus  # CRD
NAME                               VERSION   DESIRED   READY   RECONCILED   AVAILABLE   AGE
kube-prometheus-stack-prometheus   v3.5.0    1         1       True         True        4h54m

$ k -n prometheus get sts | grep kube-prometheus-stack-prometheus # Statefulset
prometheus-kube-prometheus-stack-prometheus       1/1     4h54m

$ k -n prometheus get pod | grep prometheus-kube-prometheus-stack-prometheus # Pod
prometheus-kube-prometheus-stack-prometheus-0               2/2     Running   0          5h9m

而Operator的溯源如下:

bash 复制代码
$ k -n prometheus get deploy | grep operator
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
kube-prometheus-stack-operator             1/1     1            1           5h10m

$ k -n prometheus get pod | grep kube-prometheus-stack-operator
kube-prometheus-stack-operator-d6f48dc88-c7c2n              1/1     Running   0          5h33m

当然,还有很多其他grafana和alertmanager组件,这里我们就不详细介绍了。

3.2 新增ServiceMonitor

可以说,ServiceMonitor这种CRD就是连接Prometheus和Redis Exporter之间的桥梁,Prometheus的Operator通过监控这种CRD的变更,就能实现对于不同监控对象的动态加载,比如,在安装的默认Prometheus组件中,就有这对于很多集群和节点等基础组件的监控:

bash 复制代码
$ k -n prometheus get smon # smon是servicemonitors的缩写
NAME                                             AGE
kube-prometheus-stack-alertmanager               11m
kube-prometheus-stack-apiserver                  11m
kube-prometheus-stack-coredns                    11m
kube-prometheus-stack-grafana                    11m
kube-prometheus-stack-kube-controller-manager    11m
kube-prometheus-stack-kube-etcd                  11m
kube-prometheus-stack-kube-proxy                 11m
kube-prometheus-stack-kube-scheduler             11m
kube-prometheus-stack-kube-state-metrics         11m
kube-prometheus-stack-kubelet                    11m
kube-prometheus-stack-operator                   11m
kube-prometheus-stack-prometheus                 11m
kube-prometheus-stack-prometheus-node-exporter   11m

所以我们也需要定义一个监控Redis的ServiceMontor,注意需要打上release: kube-prometheus-stack的label,因为在prometheus的CRD中,有serviceMonitorSelector限制了labels的匹配规则,而serviceMonitorNamespaceSelector: {}则表示不限制namespace。

yaml 复制代码
$ k -n prometheus get prometheus kube-prometheus-stack-prometheus -oyaml | grep serviceMonitorSelector -C
5
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  serviceAccountName: kube-prometheus-stack-prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      release: kube-prometheus-stack
  shards: 1
  tsdb:
    outOfOrderTimeWindow: 0s

所以ServiceMontor定义如下:

yaml 复制代码
# redis-service-monitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: redis-monitor
  namespace: default
  labels:
    release: kube-prometheus-stack
spec:
  selector:
    matchLabels:
      app: redis
  namespaceSelector:
    matchNames:
      - default
  endpoints:
    - port: metrics
      interval: 15s
      path: /metrics
      relabelings:
        - sourceLabels: [__meta_kubernetes_pod_name]
          targetLabel: pod
        - sourceLabels: [__meta_kubernetes_pod_label_name]
          targetLabel: redis_instance

然后执行k apply -f config/prometheus/redis-service-monitor.yaml,即可生成。

4. 验证

4.1 Grafana

通过一系列的命令在新的集群中启动Redis,然后我们即可在浏览器中输入http://localhost:30091/看到grafana面板,输入账密之后登录。(账户是admin,密码是通过kubectl --namespace prometheus get secrets kube-prometheus-stack-grafana -o jsonpath="{.data.admin-password}" | base64 -d ; echo获取)

然后再grafana的Dashboards菜单导入仪表板ID是763的仪表板,数据源选择Prometheus,进行导入,即可得到如下图所示的监控面板:

相关推荐
爷_4 小时前
字节跳动震撼开源Coze平台!手把手教你本地搭建AI智能体开发环境
前端·人工智能·后端
不过普通话一乙不改名7 小时前
第一章:Go语言基础入门之函数
开发语言·后端·golang
豌豆花下猫8 小时前
Python 潮流周刊#112:欢迎 AI 时代的编程新人
后端·python·ai
Electrolux8 小时前
你敢信,不会点算法没准你赛尔号都玩不明白
前端·后端·算法
whhhhhhhhhw8 小时前
Go语言-fmt包中Print、Println与Printf的区别
开发语言·后端·golang
ん贤9 小时前
Zap日志库指南
后端·go
Spliceㅤ9 小时前
Spring框架
java·服务器·后端·spring·servlet·java-ee·tomcat
Micro麦可乐11 小时前
前端与 Spring Boot 后端无感 Token 刷新 - 从原理到全栈实践
前端·spring boot·后端·jwt·refresh token·无感token刷新
方块海绵11 小时前
浅析 MongoDB
后端