使用 Redis Sentinel 保障 Harbor 会话一致性
解读
在国内金融、运营商、政务云等生产级 Harbor 场景中,会话漂移是升级、故障转移时最头疼的问题:用户登录后突然 401,镜像 push 到一半提示未授权,根本原因是 Harbor 默认把 session 存在本地文件系统,多实例部署时无法共享。Redis Sentinel 作为高可用、可横向扩展的内存数据存储,能在秒级完成主从切换,天然适合给 Harbor 提供无状态化的共享 Session 存储,从而实现“一次登录、多实例漫游”。面试官问这道题,想确认你是否理解 Harbor 的会话机制、是否能把 Sentinel 的高可用特性与 Docker 容器化交付结合起来,并能在国内常见的三机房五节点网络环境下给出可落地的方案。
知识点
- Harbor 会话生命周期:beego 框架生成 sessionId → 默认落地
/data/session→ 返回harbor-sessionCookie。 - Redis Sentinel 三角色:master、slave、sentinel;通过
+switch-master事件完成主观下线→客观下线→故障转移;国内机房延迟 15 ms 以内可保证 <30 s 切换。 - Docker 化 Sentinel 的固定节点标识:使用
hostname: sentinel-<index>并挂载/etc/hosts,防止容器漂移后 sentinel 找不到 master。 - 镜像层安全:Redis 基础镜像必须≤30 MB,采用非 root(uid 1001)运行,关闭
CONFIG命令,启用requirepass + ACL file双重鉴权,满足等保 2.0 对容器内进程最小权限要求。 - 网络策略:在 Docker Swarm 或 Kubernetes 中,Redis 集群与 Harbor Core 组件放在同一 Overlay 网络,通过服务名解析,避免跨宿主机 SNAT 导致 Sentinel 返回 Docker 内网 IP 无法直通。
- 数据一致性:Harbor 对 session 的操作为单行读写,无需 Redis 事务;开启
appendonly yes并设置appendfsync everysec,在容器异常退出时可最多丢失 1 秒会话,国内互联网场景可接受。 - 监控告警:使用Prometheus redis_exporter 采集
redis_connected_clients、master_link_down_since_seconds,通过阿里云 SLS 或腾讯云 CLS 做日志聚类,触发短信+飞书告警。
答案
步骤 1:准备 Redis Sentinel 容器化编排
FROM redis:7.0-alpine
RUN addgroup -g 1001 redis && adduser -D -u 1001 -G redis redis
COPY sentinel.conf /usr/local/etc/sentinel.conf
USER 1001
ENTRYPOINT ["redis-sentinel", "/usr/local/etc/sentinel.conf"]
sentinel.conf 关键段:
sentinel monitor harbor-session <master-host> 6379 2
sentinel down-after-milliseconds harbor-session 5000
sentinel parallel-syncs harbor-session 1
sentinel failover-timeout harbor-session 15000
sentinel auth-pass harbor-session <redacted>
使用 Docker Compose 三节点示例:
services:
redis-master:
image: redis:7.0-alpine
hostname: redis-master
command: redis-server --requirepass <redacted> --appendonly yes
volumes: ["redis-data:/data"]
networks: [harbor-overlay]
deploy:
placement:
constraints: [node.labels.redis == master]
redis-slave:
image: redis:7.0-alpine
command: redis-server --slaveof redis-master 6379 --masterauth <redacted> --requirepass <redacted> --appendonly yes
networks: [harbor-overlay]
deploy:
replicas: 2
sentinel:
image: internal-harbor.example.com/library/redis-sentinel:7.0
networks: [harbor-overlay]
deploy:
replicas: 3
endpoint_mode: dnsrr
步骤 2:Harbor 对接外部 Redis
修改 harbor.yml:
external_redis:
host: harbor-session.sentinel:26379
sentinel_master_set: harbor-session
password: <redacted>
registry_db_index: 1
jobservice_db_index: 2
chartmuseum_db_index: 3
步骤 3:验证高可用
- 登录 Harbor 并记录 Cookie;
docker kill掉 redis-master 容器,Sentinel 完成切换后,刷新页面仍保持登录状态;- 通过
redis-cli -p 26379 sentinel get-master-addr-by-name harbor-session确认新主; - 使用
ab -n 1000 -c 50压测/api/v2.0/users/current,401 比例 = 0 即达标。
步骤 4:CI/CD 固化
在 GitLab CI 中增加 redis-failover-test job,自动拉起 Kind 集群 → 部署 Harbor + Sentinel → 模拟故障 → 断言 Session 不丢,流水线通过后方可合并主干,确保后续版本升级不会回退。
拓展思考
- 如果监管要求跨城双活,Redis Sentinel 无法满足 RPO=0,可引入Redis Cluster + 仲裁层 CRDT 方案,但需评估跨城延迟 30 ms 对 Harbor 登录 RT 的影响。
- 当 Harbor 实例数 >20 时,Sentinel 频繁切换会造成脑裂,可改用Kubernetes Operator 托管 Redis,通过预选举降低切换次数,同时利用PodDisruptionBudget保证滚动升级时最小副本数。
- 国内信创环境需替换为麒麟 V10 + ARM64 Redis,镜像需重新编译,注意alpine 的 musl 与 glibc 差异,建议在 Dockerfile 里使用多阶段构建先在同 CPU 架构节点编译
redis-sentinel,再 copy 到运行时镜像,避免跨架构拉取延迟。