在k8s中部署redis cluster实战

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在k8s中部署redis cluster实战相关的知识,希望对你有一定的参考价值。

参考技术A

  项目需要在k8s上搭建一个redis cluster集群,网上找到的教程例如:
   github原版带配置文件
   在原版基础上补充详细使用步骤但是无配置文件版
   手把手教你一步一步创建的一篇博客
  redis运行在容器中时必须选择一种外部存储方案,用来保存redis的持久化文件,否则容器销毁重建后无法读取到redis的持久化文件(随着容器一同销毁了);并且还要保证容器重建后还能读取到之前对应的持久化文件。上面的教程使用的是nfs存储,但是受于条件限制本文只能使用宿主机的本地目录来做存储,与上面的教程有一些不一样的地方。
  本文的目的是讲一下使用local pv来作为存储创建redis cluster集群的步骤,以及说明过程中需要注意的问题。

  Kubernetes支持几十种类型的后端存储卷,其中本地存储卷有3种,分别是emptyDir、hostPath、local volume,尤其是local与hostPath这两种存储卷类型看起来都是一个意思。这里讲一下区别。

emptyDir

hostPath

local volume

pv的回收策略有三种:Retain、Recycle、Delete,可以在脚本中指定:

也可以在pv创建成功后使用命令修改:

假设有一个pv叫test-pv,绑定的pvc角坐test-pvc,test-pv使用的local pv

会删除test-pv在对应存储空间上的数据。NFS目前不支持 Delete,支持Delete的存储空间有AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等(网上看的,没测试过)。

  前面已经说过,redis有数据持久化需求,并且同一个pod重启后需要读取原来对应的持久化数据,这一点在不使用k8s时很容易实现(只使用docker不使用k8s时也很容易),启动redis cluster每个节点时指定其持久化目录就行了,但是k8s的Deployment的调度对于我们这个需求来说就显得很随机,你无法指定deployment的每个pod使用哪个存储,并且重启后仍然使用那个存储。
  Deployment不行,Statefulset可以。官方对Statefulset的优点介绍是:

  看完还是比较迷糊,我们可以简单的理解为原地更新,更新后还是原来那个pod,只更新了需要更新的内容(一般是修改自己写的程序,与容器无关)。
  Statefulset和local pv结合,redis cluster的每个pod挂掉后在k8s的调度下重启时都会使用之前自己的持久化文件和节点信息。

  创建StorageClass的目的是deployment中根据StorageClass来自动为每个pod选择一个pv,否则手动为每个pod指定pv又回到了老路上。

  创建6个pv,因为redis cluster最低是三主三从的配置,所以最少需要6个pod。后面的pv2~pv5我就不贴出来了。

  Headless service是StatefulSet实现稳定网络标识的基础,需要提前创建。

  每个Pod都会得到集群内的一个DNS域名,格式为 (service name).$(namespace).svc.cluster.local。可以在pod中ping一下这些域名,是可以解析为pod的ip并ping通的。

  这个service是可以自由发挥的,使用port-forward、NodePort还是ingress你自己选择,我这里只是一个内网访问统一入口。

  至此,redis cluster的六个节点都已经创建成功。下面需要创建集群(此时就是6个单节点的redis,并不是一个集群)。

  我们之前都是通过外部安装redis-trib创建的集群,但是根据 这篇文章 redis 5.0之后已经内置了redis-trib工具,感兴趣的可以尝试。
  专门启动一个Ubuntu/CentOS的容器,可以在该容器中安装Redis-tribe,进而初始化Redis集群,执行:
kubectl run -i --tty centos --image=centos --restart=Never /bin/bash
成功后,我们可以进入centos容器中,执行如下命令安装基本的软件环境:

然后执行如下命令创建集群:

根据提示一步一步完成。

  否则报错例如 MOVED 1545 10.244.3.239:6379","data":false
  如本文的情况,redis cluster的每个节点都是一个跑在k8s里面的pod,这些pod并不能被外部直接访问,而是通过ingress等方法对外暴露一个访问接口,即只有一个统一的ip:port给外部访问。经由k8s的调度,对这个统一接口的访问会被发送到redis集群的某个节点。这时候对redis的用户来说,看起来这就像是一个单节点的redis。但是, 此时无论是直接使用命令行工具redis-cli,还是某种语言的sdk,还是需要按照集群来配置redis的连接信息,才能正确连接 ,例如

  这里-c就代表这是访问集群,又或者springboot的redis配置文件

以上是关于在k8s中部署redis cluster实战的主要内容,如果未能解决你的问题,请参考以下文章

Redis 集群--------Redis-cluster

解决k8s集群中Redis Cluster故障

云原生之kubernetes实战在k8s下部署Redis集群

在Kubernetes上部署Redis集群

redis cluster模式在kubernetes平台部署方案 的问题

Kubernetes学习总结(16)—— Kubernetes 实战之部署 Redis 集群