Redis 在 Kubernetes 中的 StatefulSet 部署与维护

好的,咱们这就开始今天的Redis on Kubernetes StatefulSet部署与维护讲座。各位观众老爷,准备好你们的小板凳,咱们要起飞了!

开场白:为啥要用StatefulSet跑Redis?

Redis嘛,内存数据库,快是真快,但也娇气。重启了数据就没了,这在生产环境里可不行啊。我们需要持久化,需要高可用,最好还能自动故障转移。

Kubernetes,简称K8s,就是个容器编排神器。而StatefulSet,则是K8s里专门伺候有状态应用的。它能保证Pod的顺序启动、稳定的网络标识(hostname和DNS)、稳定的存储卷挂载,简直是为Redis量身定做的!

第一部分:StatefulSet部署Redis,这事儿不难!

咱们先来个简单的StatefulSet,部署三个Redis实例。

  1. 准备工作:Namespace和存储

    首先,咱们得有个地方住啊!创建一个Namespace,再准备好存储。

    apiVersion: v1
    kind: Namespace
    metadata:
     name: redis-cluster #给咱们的Redis集群起个名字
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
     name: redis-data-pvc
     namespace: redis-cluster
    spec:
     accessModes:
       - ReadWriteOnce # 只允许单个节点读写
     resources:
       requests:
         storage: 10Gi # 10个G,先凑合着用

    解释:

    • Namespace:相当于一个逻辑隔离的房间,把Redis集群和其他应用隔离开。
    • PersistentVolumeClaim (PVC):声明需要多大的存储空间,以及访问模式。
  2. StatefulSet YAML文件:重头戏来了!

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
     name: redis-cluster
     namespace: redis-cluster
    spec:
     serviceName: redis-cluster # Headless Service的名字,很重要!
     replicas: 3 # 3个Redis实例,组团出道
     selector:
       matchLabels:
         app: redis-cluster # 用于Pod选择
     template:
       metadata:
         labels:
           app: redis-cluster
       spec:
         containers:
           - name: redis
             image: redis:latest # 官方镜像,省心
             ports:
               - containerPort: 6379 # Redis默认端口
             volumeMounts:
               - name: redis-data
                 mountPath: /data # Redis数据存储目录
     volumeClaimTemplates:
       - metadata:
           name: redis-data
         spec:
           accessModes:
             - ReadWriteOnce
           resources:
             requests:
               storage: 10Gi
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: redis-cluster # Headless Service的名字
     namespace: redis-cluster
    spec:
     clusterIP: None # Headless Service的标志,不分配Cluster IP
     selector:
       app: redis-cluster
     ports:
       - port: 6379
         targetPort: 6379

    解释:

    • StatefulSet:定义了Redis集群的规格。
    • serviceName:指向一个Headless Service,这是StatefulSet的关键。
    • replicas:指定副本数量,这里是3个。
    • selector:用于StatefulSet选择Pod。
    • template:Pod的模板,定义了容器的镜像、端口、存储卷挂载等。
    • volumeClaimTemplates:定义了PVC的模板,StatefulSet会自动为每个Pod创建PVC。
    • Headless Service:不分配Cluster IP,而是通过DNS解析Pod的hostname,实现Pod之间的发现。
  3. 应用YAML:kubectl apply -f your-redis-statefulset.yaml

    执行命令后,K8s就会开始创建Redis集群了。

  4. 验证:kubectl get pods -n redis-cluster

    看看是不是有redis-cluster-0、redis-cluster-1、redis-cluster-2三个Pod正在运行。

第二部分:StatefulSet的精髓:Headless Service

刚才咱们提到了Headless Service,这玩意儿到底有啥用?

想象一下,没有Headless Service,每个Pod都只有一个随机的IP地址。重启之后IP就变了,其他Pod怎么找到它呢?

Headless Service不分配Cluster IP,而是通过DNS解析Pod的hostname。StatefulSet会为每个Pod分配一个固定的hostname,格式是<statefulset-name>-<ordinal>。比如,redis-cluster-0、redis-cluster-1、redis-cluster-2。

有了hostname,其他Pod就可以通过redis-cluster-0.redis-cluster.redis-cluster.svc.cluster.local这样的DNS地址来访问Redis实例了。

第三部分:Redis持久化:数据才是王道!

光有StatefulSet还不够,咱们还得保证数据不丢。

  1. RDB快照:定期保存数据

    Redis默认会定期生成RDB快照,把内存中的数据保存到磁盘上。咱们可以在redis.conf里配置RDB快照的策略。

    save 900 1       # 900秒内如果至少有1个key被修改,就保存快照
    save 300 10      # 300秒内如果至少有10个key被修改,就保存快照
    save 60 10000    # 60秒内如果至少有10000个key被修改,就保存快照
  2. AOF日志:记录每次写操作

    AOF日志会记录每次写操作,重启时可以通过重新执行AOF日志来恢复数据。AOF比RDB更可靠,但性能会稍微差一些。

    appendonly yes       # 开启AOF
    appendfsync everysec  # 每秒同步一次,兼顾性能和可靠性

    重要提示:

    • 确保redis.conf文件被正确挂载到容器中。可以使用ConfigMap或者Volume来实现。
    • RDB和AOF文件应该存储在持久化存储卷上,这样即使Pod重启,数据也不会丢失。

第四部分:Redis集群:单机Redis太弱了!

单机Redis性能有限,而且容易挂。咱们需要Redis集群来提高性能和可用性。

  1. Redis Cluster模式:官方推荐

    Redis Cluster是Redis官方提供的集群方案,支持自动分片和故障转移。

    步骤:

    • 修改redis.conf,开启cluster模式:

      cluster-enabled yes
      cluster-config-file nodes.conf
      cluster-node-timeout 15000
    • 使用redis-cli --cluster create命令创建集群。

      redis-cli --cluster create 10.0.0.1:6379 10.0.0.2:6379 10.0.0.3:6379 --cluster-replicas 1

      这个命令会把三个Redis实例组成一个集群,每个实例有一个备份节点。

    修改StatefulSet YAML:

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
     name: redis-cluster
     namespace: redis-cluster
    spec:
     serviceName: redis-cluster
     replicas: 6 # 6个实例,3个master,3个slave
     selector:
       matchLabels:
         app: redis-cluster
     template:
       metadata:
         labels:
           app: redis-cluster
       spec:
         containers:
           - name: redis
             image: redis:latest
             ports:
               - containerPort: 6379
             volumeMounts:
               - name: redis-data
                 mountPath: /data
             command: ["/bin/sh", "-c"]
             args:
               - |
                 redis-server /usr/local/etc/redis/redis.conf
                 until redis-cli -h $(hostname) -p 6379 ping; do
                   echo "Waiting for Redis to start..."
                   sleep 1
                 done
                 if [[ $(hostname) == "redis-cluster-0" ]]; then
                   echo "Creating Redis Cluster..."
                   redis-cli --cluster create $(redis-cluster-endpoints) --cluster-replicas 1 --cluster-yes
                 fi
                 tail -f /dev/null
     volumeClaimTemplates:
       - metadata:
           name: redis-data
         spec:
           accessModes:
             - ReadWriteOnce
           resources:
             requests:
               storage: 10Gi
    env:
     - name: redis-cluster-endpoints
       value: "redis-cluster-0.redis-cluster:6379 redis-cluster-1.redis-cluster:6379 redis-cluster-2.redis-cluster:6379 redis-cluster-3.redis-cluster:6379 redis-cluster-4.redis-cluster:6379 redis-cluster-5.redis-cluster:6379"
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: redis-cluster
     namespace: redis-cluster
    spec:
     clusterIP: None
     selector:
       app: redis-cluster
     ports:
       - port: 6379
         targetPort: 6379

    解释:

    • 调整replicas为6个,3个master,3个slave。
    • commandargs中添加初始化Redis集群的逻辑。
    • 使用redis-cli --cluster create命令创建集群。
    • 使用env环境变量传递所有的redis节点,这样方便初始化集群。

    重要提示:

    • Redis Cluster需要至少三个master节点才能正常工作。
    • 确保节点之间可以互相访问。
    • 集群初始化只需要执行一次,所以咱们只在redis-cluster-0这个Pod上执行redis-cli --cluster create命令。
  2. Sentinel模式:主从复制 + 自动故障转移

    Sentinel是Redis官方提供的另外一种高可用方案,它通过监控master节点的状态,并在master节点故障时自动将slave节点提升为master节点。

    步骤:

    • 部署多个Sentinel实例。
    • 配置Sentinel监控Redis master节点。
    • 在客户端配置Sentinel地址,客户端会自动发现master节点。

    Sentinel模式比Redis Cluster简单,但性能和扩展性不如Redis Cluster。

第五部分:Redis维护:日常保健不能少!

Redis集群部署好了,也不能撒手不管。咱们还得定期维护,保证集群的健康运行。

  1. 监控:时刻关注身体状况

    监控Redis的各项指标,例如CPU使用率、内存使用率、连接数、QPS等。可以使用Prometheus + Grafana来搭建监控系统。

    监控指标:

    指标 描述
    used_memory Redis使用的内存大小
    connected_clients 连接到Redis的客户端数量
    keyspace_hits 命中key的次数
    keyspace_misses 未命中key的次数
    uptime_in_seconds Redis运行的时间(秒)
  2. 日志:蛛丝马迹不能放过

    定期检查Redis的日志,看看有没有异常信息。

  3. 备份:未雨绸缪,防患于未然

    定期备份Redis的数据,以防万一。可以使用RDB快照或者AOF日志来进行备份。

    备份策略:

    • 每天全量备份一次。
    • 每小时增量备份一次。
  4. 升级:保持最新,安全第一

    定期升级Redis的版本,修复bug,提升性能,增强安全性。

    升级步骤:

    • 逐个升级Redis实例,避免影响业务。
    • 先升级slave节点,再升级master节点。
    • 升级完成后,重启Redis实例。

第六部分:常见问题与解决方案

  1. Pod启动失败:

    • 检查PVC是否创建成功。
    • 检查镜像是否存在。
    • 检查端口是否被占用。
  2. Redis Cluster无法创建:

    • 检查节点之间是否可以互相访问。
    • 检查redis.conf配置是否正确。
    • 检查redis-cli --cluster create命令是否正确。
  3. 数据丢失:

    • 检查是否开启了RDB快照或者AOF日志。
    • 检查RDB和AOF文件是否存储在持久化存储卷上。
    • 检查备份策略是否正确。
  4. 性能瓶颈:

    • 检查CPU、内存、网络是否达到瓶颈。
    • 检查慢查询日志,优化查询语句。
    • 考虑使用Redis Cluster来提高性能。

总结:

今天咱们讲了如何在Kubernetes中使用StatefulSet部署和维护Redis集群。虽然内容有点多,但只要掌握了StatefulSet、Headless Service、Redis Cluster等关键概念,就能轻松驾驭Redis on Kubernetes。希望大家在实际工作中能够灵活运用这些知识,打造稳定、高效的Redis服务!

好了,今天的讲座就到这里。感谢各位观众老爷的捧场!下课!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注