redis-ha · Sentinel 主从加 HAProxy 的 Redis 高可用栈
redis-ha 是为了替换集群里那套单点 redis Deployment 而搭的 Sentinel 高可用栈:3 个 redis 节点做主从复制,3 个 sentinel 做仲裁与故障转移,2 个 HAProxy 把流量固定路由到当前 master。所有资源都以 redis-ha-* 命名,不与现存的单点 redis 冲突,可以并行部署、按 CUTOVER.md 无停机切换。它当前还没接进 bootstrap/,部署是一次有意的人工步骤,不是 ArgoCD 自动同步。
部署形态
整个栈由三类工作负载组成,全部落在 redis 命名空间,kustomization 设置了 commonLabels: app.kubernetes.io/part-of: redis-ha。
- Name
- 命名空间
- Description
- redis
- Name
- redis 节点
- Description
- StatefulSet
redis-ha,replicas 3,podManagementPolicy: Parallel,镜像redis:8.8-alpine,端口 6379
- Name
- sentinel 节点
- Description
- StatefulSet
redis-ha-sentinel,replicas 3,podManagementPolicy: Parallel,镜像redis:8.8-alpine,端口 26379
- Name
- HAProxy
- Description
- Deployment
redis-ha-haproxy,replicas 2,镜像haproxy:3.4-alpine,监听 6379
- Name
- 调度
- Description
- redis 与 sentinel 都用
requiredDuringSchedulingIgnoredDuringExecution的 podAntiAffinity 按kubernetes.io/hostname强制分散到不同节点;HAProxy 用preferred软反亲和
- Name
- 存储
- Description
- redis 用 volumeClaimTemplates,
local-pathStorageClass,20Gi/节点;sentinel 同样local-path,1Gi/节点(仅放可写的 sentinel.conf);HAProxy 无持久卷,仅 emptyDir 临时目录
- Name
- 资源
- Description
- redis 请求 100m/256Mi、上限 1 核/2Gi(对齐命名空间 LimitRange 上限与单点 redis 的 maxmemory 2gb 口径);sentinel 请求 50m/64Mi、上限 200m/128Mi;HAProxy 请求 50m/64Mi、上限 300m/128Mi
redis 节点的 2Gi 内存上限是按命名空间 LimitRange 每容器 2Gi 的上限设置的,与 maxmemory 2gb 一致。
配置与依赖
三个组件各有一个 ConfigMap,既放配置又放启动脚本 entrypoint.sh,启动时由脚本把密码等运行时值注入再 exec。
- Name
- redis-ha-config
- Description
redis.conf从单点 redis 沿用(maxmemory 2gb、allkeys-lru、AOF appendfsync everysec、RDB save 规则等)。entrypoint.sh做引导:先问任一 sentinel 谁是 master,已知且不是自己就 replicaof 它;无 master 时 ordinal 0 当 master、其余 replicaofredis-ha-0;并用稳定的 pod FQDN 做replica-announce-ip。requirepass/masterauth由密码注入
- Name
- redis-ha-sentinel-config
- Description
sentinel.conf启用resolve-hostnames/announce-hostnames(按 k8s DNS 而非会变的 pod IP 跟踪节点),monitor mymaster ... 2(quorum 2/3),down-after 5000ms、failover-timeout 60000ms、parallel-syncs 1。脚本把模板复制到可写的/data/sentinel.conf再追加auth-pass/announce-ip
- Name
- redis-ha-haproxy-config
- Description
haproxy.cfg用 tcp-check 依次 AUTH、PING、info replication断言role:master,只有当前 master 通过健康检查,replica 不接流量;后端三台 redis 按 FQDN 解析,配resolvers k8s指向 CoreDNS。__REDIS_PASSWORD__由脚本 sed 替换
- Name
- 密钥
- Description
- 三类 pod 都从既有 Secret
redis-secret的REDIS_PASSWORD注入密码(envvalueFrom.secretKeyRef),本目录不含 ExternalSecret,复用单点 redis 的密钥
HAProxy 配置里的 CoreDNS ClusterIP 写死为 k3s 默认的 10.43.0.10:53,切换前需用 kubectl -n kube-system get svc kube-dns -o jsonpath='{.spec.clusterIP}' 核对。
访问与监控
栈内有三个 Service,没有 Ingress(纯内部访问),也没有 ServiceMonitor / PrometheusRule / HPA / VPA / PDB。
| Service | 类型 | 用途 |
|---|---|---|
redis-ha-headless | Headless(clusterIP None,publishNotReadyAddresses) | 给每个 redis-ha-N 一个稳定 DNS redis-ha-N.redis-ha-headless.redis.svc.cluster.local,供 sentinel 与 replica 做 announce/replicaof,不做负载均衡 |
redis-ha-sentinel | Headless | sentinel 的稳定寻址,端口 26379 |
redis-ha-haproxy | ClusterIP | HAProxy 的稳定入口,端口 6379;切换时把现存 redis Service 的 selector 指向它,客户端继续用 redis.redis.svc.cluster.local:6379 不变 |
约 17 个 platform + app 命名空间的服务连接 redis.redis.svc.cluster.local:6379,切换以这个不变的 DNS 为前提,客户端不需要改任何配置。
注意事项
切换流程与设计取舍都记录在本目录的 CUTOVER.md,要点如下。
- 为什么是 Sentinel 而不是 Redis Cluster:客户端用了编号 DB(0、1、7、10、15…),而 Cluster 模式只支持 db0,所以 Cluster 不可行,Sentinel 是唯一可行的 HA。Redis 保持 8.8(当前线上版本),HA 迁移不等于版本升级。
- 切换前要先把
applications/data/redis/resourcequota.yaml的redis-quota调大:HA 栈加上仍在跑的单点 redis 装不进现配额,大致需要 req cpu ≥1500m、mem ≥3Gi,limit cpu ≥7、mem ≥13Gi,pods ≥15。 - 数据播种:HA master 起来是空的,而线上 redis 持有真实队列状态(Sidekiq retry/schedule/dead、Celery unacked),不能丢。做法是临时让
redis-ha-0replicaof 线上 redis 做全量同步,待master_link_status:up且 dbsize 一致后replicaof no one转正,redis-ha-1/2 已 replicate redis-ha-0 故自动继承。 - 客户端可见的唯一一步是把现存
redisService 的 selector 从app: redis改到app: redis-ha-haproxy,并要把这一改动持久化进 git,否则 ArgoCD selfHeal 会还原。回滚就是把 selector 改回app: redis,未动过的单点 redis 立刻恢复服务。 - 已知坑:
maxmemory-policy allkeys-lru是从单点配置继承的,内存压力下可能连无 TTL 的队列 key 一起淘汰,若在意队列持久性需另行改成volatile-lru;failover 窗口内短暂无 master 时写操作会失败(预期行为,客户端重试);手搓的 k8s 上 Sentinel 依赖resolve-hostnames/announce-hostnames加稳定 pod FQDN,建议在非生产环境先验证 failover 确实能让 HAProxy 重新指向新 master。
返回 data 服务总览