24.容器与云原生——Docker 官方镜像最佳实践,K8s StatefulSet + Sentinel 高可用

代码示例:

  1. 容器与云原生——Docker 官方镜像最佳实践,K8s StatefulSet + Sentinel 高可用
    (接 152276042 篇结尾,直接落地)

  2. 把“官方镜像”用到刀刃上
    1.1 优先用 Docker Hub 的“/official-image”命名空间

  • 官方镜像构建脚本公开在 https://github.com/docker-library,CI 在官方 Jenkins 跑,每日做 apt/apk 安全更新,版本号与上游严格对应。
  • 非官方镜像常把“latest”当“最省事”,结果 2024-08 爆发的 libssl3 漏洞 70 % 的“latest”三天后才重建。
    1.2 锁死 digest,拒绝漂移
docker pull redis:7.2.4-bookworm@sha256:6a5f1c5d19…

把 digest 写进 Dockerfile / Helm values,CI 做一次不可变推送,后续任何节点拉到的都是同一层 blob,符合“可重复构建”合规基线。
1.3 最小化攻击面

  • 官方镜像默认带 aptapk,线上不需要。用多阶段构建把运行时裁剪成 distrolessalpine,Go 业务镜像可从 120 MB 压到 18 MB。
  • 官方 Redis 镜像默认打开保护模式,注释掉 bind 0.0.0.0 即可;但自己再打镜像时,记得把 protected-mode yes 写回配置,防止误删。
    1.4 用官方健康检查脚本
    官方 MySQL 镜像自带 /healthcheck.sh,返回值 0 才认为主库可用;不要自己写 mysqladmin ping,版本差异会导致 false positive。
  1. Sentinel 在容器里的“三座大山”
    2.1 网络标识漂移
    Sentinel 靠 <ip:port> 识别主节点,Pod 重建后 IP 必变,导致“主观下线”永远投票不过半。
    2.2 配置持久化
    Sentinel 把 sentinel monitor mymaster … 写进自身配置文件,容器一旦重启,写层丢失,又回到“刚出厂”状态。
    2.3 脑裂阈值
    K8s 滚动升级时,旧 Pod 与新 Pod 并存 30 s,Sentinel 可能同时看到 5 个 Sentinel 与 3 个 Sentinel 两种视图,触发两次 failover,出现双主。

  2. 用 StatefulSet 一揽子解决
    3.1 给每个 Sentinel 一个“身份证”

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-sentinel
spec:
  serviceName: sentinel
  replicas: 3
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: sentinel
    spec:
      containers:
      - name: sentinel
        image: redis:7.2.4-bookworm@sha256:6a5f1c5d19…
        command:
        - redis-sentinel
        - /etc/sentinel.conf
        - --sentinel
        volumeMounts:
        - name: data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: fast-ssd
      resources:
        requests:
          storage: 10Gi
  • 每个 Pod 固定主机名 redis-sentinel-0.sentinel.default.svc.cluster.local,Sentinel 启动时把该主机名写进 sentinel announce-ip,Sentinel 之间用 DNS 域名互相发现,IP 漂移不再影响。
  • volumeClaimTemplates 保证 /data/sentinel.conf 落在 PV 里,Pod 重建后配置不丢。
    3.2 初始化脚本一次性写 monitor
    initContainer 里用 sentinelSet 命令只在 <ordinal>==0 时执行:
redis-cli -p 26379 sentinel monitor mymaster redis-0.redis.default 6379 2

其余 Pod 启动后通过 SENTINEL sentinels mymaster 自动学习,无需再手动添加。
3.3 防止并发的 failover
调高 down-after-milliseconds 到 10000 ms,配合 min-replicas-max-lag 5
K8s 滚动升级前,先通过 kubectl annotate sts/redis-sentinel upgrade=freeze 触发 PreStop 钩子,让 Sentinel 主动 SENTINEL failover mymaster 交出领导权,再删 Pod,保证任何时刻只有 1 个主库。

  1. Redis 主从也用 StatefulSet
    4.1 一主两从
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: redis
  replicas: 3
  template:
    spec:
      containers:
      - name: redis
        image: redis:7.2.4-bookworm@sha256:6a5f1c5d19…
        command: ["/usr/local/bin/redis-start.sh"]

redis-start.sh 逻辑:

  • hostname 后缀为 -0,执行 redis-server /etc/redis.conf --port 6379
  • 否则先 redis-cli -h redis-0.redis ping,成功则执行 replicaof redis-0.redis 6379
    4.2 用 podManagementPolicy: Parallel 缩短启动时间,但结合 minReadySeconds: 10 防止并发全量同步打爆网卡。
  1. 统一暴露:Headless Service + ClusterIP
---
apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  clusterIP: None
  ports:
  - port: 6379
    name: redis
  selector:
    app: redis
---
apiVersion: v1
kind: Service
metadata:
  name: redis-read
spec:
  ports:
  - port: 6379
    name: redis
  selector:
    app: redis
  • 业务写操作用 redis-0.redis:6379 直连主库;
  • 读操作用 redis-read:6379 走 ClusterIP 自动负载到任意副本,降低主库压力。
  1. 监控:把 Sentinel 事件打进 Prometheus
    Sentinel 支持 sentinel notification-script
#!/bin/bash
echo "sentinel_failing $@" | curl --data-binary @- http://pushgateway:9091/metrics/job/redis/sentinel/$HOSTNAME

Prometheus 端记录 sentinel_failing{master="mymaster"},再配 Alertmanager 5 分钟内 >=2 次即告警。

  1. 灾难演练:一键“杀”主库
kubectl exec redis-0 -- kill -9 1

观察:

  • Sentinel 10 s 完成投票;
  • redis-1 提升为主;
  • 业务写操作报错 ❤️ s(连接池重试);
  • Prometheus 显示 redis_master_failover_seconds_bucket P99 12 s。
  1. 镜像供应链加固(2025 新规)
  • 官方镜像已默认开启 SBOM,CI 里用 docker buildx imagetools inspect redis:7.2.4-bookworm --format "{{ json .SBOM }}" 导出,上传至公司合规平台;
  • cosign 做镜像签名,公钥托管在 K8s cosign-pub ConfigMap, admission webhook 拒绝任何未签名镜像。
  1. 小结
    Docker 官方镜像是“第一信任源”,但容器生命周期短、IP 易变,与 Redis Sentinel 的“有状态”天然冲突。用 StatefulSet 固定网络标识 + PV 持久化配置,再辅以启动顺序、failover 冻结、监控告警三板斧,可在 100 % 容器化环境中把 RPO 压到 30 s 以内,RTO 压到 60 s 以内,满足金融级“云原生高可用”硬要求。
    更多技术文章见公众号: 大城市小农民
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔丹搞IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值