美文网首页
k8s环境下单节点运行Redis集群

k8s环境下单节点运行Redis集群

作者: 行走的记忆 | 来源:发表于2019-08-10 16:39 被阅读0次

单机下用Redis二进制程序包搭建Redis集群的案例很多,用docker在单节点上搭集群的也很多,但是在k8s下单节点搭集群的就很少了,有的只是挂载一个临时目录,数据无法持久化,pod销毁后,数据就没了。在k8s环境下测试机又不够的情况下使用Redis集群就不太方便了,本文就是笔者的根据自身需要实践出来的,期间也找了很多网上资料,最后自己综合琢磨出的解决方案,由于对docker和k8s不是很精通,可能有其他更简单的方案,欢迎大家交流。

一、所需的背景知识

1、对docker,k8s有一定使用经验:会编写yaml文件,知道如何排查pod不能running的问题
2、在单机环境下搭建过Redis集群
3、如果以上的知识都不知道也没关系,本文尽量保证你按照步骤执行不出错。但是k8s环境你必须得有,基本的linux命令知识得有

二、软件版本

k8s v1.10.2
docker 18.03.1-ce, build 9ee9f40
Redis5.0.5

三、准备工作

 docker pull redis:5.0.5
 mkdir redis-cluster
 cd redis-cluster/
 mkdir data

创建多个节点的数据存储目录,避免Redis实例启动时配置文件冲突导致无法启动,在单台物理机上搭建过Redis集群的应该知道。建好6个节点的目录,后面会用到,这里的目录要注意权限问题,k8s启动的pod需要读写这里的文件夹

for port in `seq 7001 7006`; do \
  mkdir -p ./${port}/
done

创建完成后目录结构

目录结构

四、编辑yaml文件

创建k8s的yaml文件
回到redis-cluster目录下

1、创建ConfigMap

先创建redis.conf配置文件
vi redis-cm.yaml
将以下内容贴到文件中,保存退出

apiVersion: v1
kind: ConfigMap
metadata:
 name: redis-conf
data:
 redis.conf: |
         appendonly yes
         cluster-enabled yes
         cluster-config-file /var/lib/redis/nodes.conf
         cluster-node-timeout 5000
         dir /var/lib/redis
         port 6379

2、创建statefulset

vi redis-statefulset.yaml

apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: redis-app
spec:
  serviceName: "redis-service"
  replicas: 6
  template:
    metadata:
      labels:
        app: redis
        appCluster: redis-cluster
    spec:
      nodeSelector:
        node: mfc    # 这里需要根据自己的k8s节点情况修改,本案例需修改成node-222
      terminationGracePeriodSeconds: 20
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - redis
              topologyKey: kubernetes.io/hostname
      containers:
      - name: redis
        image: "redis:latest"
        imagePullPolicy: IfNotPresent #默认情况是会根据配置文件中的镜像地址去拉取镜像,配置为本地有镜像不拉取远程,避免你的环境不能访问外网,拉取镜像失败
        command:
          - "redis-server"
        args:
          - "/etc/redis/redis.conf"
          - "--protected-mode"
          - "no"
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
        ports:
            - name: redis
              containerPort: 6379
              protocol: "TCP"
            - name: cluster
              containerPort: 16379
              protocol: "TCP"
        volumeMounts:
          - name: "redis-conf"
            mountPath: "/etc/redis"
          - name: "redis-data"
            mountPath: "/var/lib/redis"
      volumes:
      - name: "redis-conf"
        configMap:
          name: "redis-conf"
          items:
            - key: "redis.conf"
              path: "redis.conf"
  volumeClaimTemplates:   #可看作pvc的模板
    - metadata:
      name: redis-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

3、创建pv的yaml文件

vi pv1.yaml

kind: PersistentVolume
apiVersion: v1
metadata:
  name: redis-pv-volume1
  labels:
    type: local
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /home/bboss/redis-cluster/data/7001/

/home/bboss/redis-cluster/data/7001/此目录为前面我们创建的redis数据存储的6个目录
将此文件复制5份,依次命名为pv2.yaml 到pv6.yaml
在对应的文件中将

name: redis-pv-volume1
path: /home/bboss/redis-cluster/data/7001/

这2处修改为对应文件编号的序号,例如pv2.yaml修改为

name: redis-pv-volume2
path: /home/bboss/redis-cluster/data/7002/

五、开始搭建集群

1、创建cm和pv如下图

km create -f redis-cm.yaml
km create -f pv1.yaml
image.png

2、创建statefulset

确定当前宿主机在k8s集群中的label

kubectl get nodes --show-labels
k8s集群机器ip和对应的label

如图,我当前部署的机器ip是222对应的node标签名为node-222
将redis-statefulset.yaml文件中node: mfc 修改为 node: node-222,稍后启动redis的pod是都会选择在node-222这个节点的机器上启动,这正是我们需要的,修改正确后

km create -f redis-statefulset.yaml

[注:我这里km是做了配置,km相当于是kubectl -n mfc-namespace 这是指定k8s的namespace的,我的namespace名是mfc-namespace,kubectl命令不指定-n 默认是使用default为名的namespace]

kubectl get pods  -n mfc-namespace | grep redis 

查看6个redis节点是否都启动完成

查看一下pod对应的ip,下一步配置集群需要知道各节点的ip,这ip是k8s分配的

kubectl get pods -o wide -n mfc-namespace | grep redis

验证一下pvc是否都bound了

kubectl get pvc -o wide -n mfc-namespace
redis节点的ip

3、初始化Redis集群

启动一个独立的redis

docker run -it redis:latest bash
redis-cli --cluster create 10.254.79.20:6379 10.254.79.21:6379 10.254.79.22:6379 10.254.79.23:6379 10.254.79.24:6379 10.254.79.25:6379 --cluster-replicas 1
初始化Redis集群 接上图

4、验证Redis集群

日志显示集群已经初始化好,slots也分配完成,验证一下集群
用redis-cli随便连接某个redis节点

/usr/local/bin/redis-cli -c -h 10.254.79.20 -p 6379
验证集群

搭建完成了,下面来看看本地存储的数据
随便进到某个目录下看看,如下图redis集群的数据已经落到物理机上了。

3号节点的数据文件

验证一下pod重启后集群数据是否还在

重启Redis集群

看ip还是原来的ip,这就是k8s定义statefulset的作用
通过刚才启动的独立redis再次连接集群看数据还在不在,如下图数据都还在

验证集群中已数据是否还在,如图数据都还在

5、创建headlessService

到这里我们的Redis集群已经是完全可用的了,但是我们的应用要使用该集群时配置ip不好记,这时就需要用到k8s中的Service
vi redis-headlessService.yaml

apiVersion: v1
kind: Service
metadata:
  name: redis-service
  labels:
    app: redis
spec:
  ports:
  - name: redis-port
    port: 6379
  clusterIP: None
  selector:
    app: redis
    appCluster: redis-cluster

执行 km create -f redis-headlessService.yaml 创建服务
查看服务

查看redis-service服务

另外用k8s启一个有nslookup或者ping工具的pod,验证一下服务名是否可以访问

验证服务名

k8s是自带dns功能的,k8s会根据serviceName生成对应的域名
如上图,可以看到节点1 (10.254.79.20)的完整域名是redis-app-0.redis-service.mfc-namespace.svc.cluster.local,在k8s中同一个namespace的服务只需要前面的子域名即可,后面的会默认补齐,本例中的serviceName是redis-app-0.redis-service,这是一个节点的服务名。对于整个集群的serviceName是redis-service

用刚才的docker启动的redis验证一下域名是否可以连接,如下图用域名连接失败,因为我们这个是用docker启动的不在k8s中,用pod的ip是可以连接的,因为pod的ip访问是走docker的网络。因为服务名是k8s做的路由,所以必须在k8s集群中注册才可以使用服务名互相访问。serviceName其实是在操作系统中做了一个转发的动作,通过iptales做策略实现的。

用域名连接失败

用redis集群中的任意一个节点验证,域名是可以访问的

用redis集群中的节点验证

六、总结

网上大部分文章都是类似的方案,使用pv,pvc做存储,有的pv是绑定的nfs,我也试过nfs碰到问题没解决只能想其他办法,但是我理解的是如果6个redis节点的配置文件nodes.conf和数据文件都在共享一个目录,那还是会有冲突,导致redis只能启动一个节点,而其他节点无法启动,除非能把文件命名定义成不同节点对应不同的文件名,因为没搭成功基于nfs的pvc存储,不知道是不是每个节点一个隔离的pvc,所以无法知道以后会再实践。所以本例主要是通过定义不同的pv把目录隔离开,但是定义StatefulSet时不好指定pvc,看到有文章用到volumeClaimTemplates(可看作pvc的模板)传输门于是问题就应然而解了,StatefulSet在创建pod时是前一个创建成功才继续下一个是有顺序的,同时创建pvc也是有顺序的,每个pvc绑定一个pv,这样6个节点的数据文件就自动绑定到各自的目录下了。
另外redis集群初始化不需要Ruby了,避免了安装ruby的麻烦。

七、参考资料

[https://www.cnblogs.com/tylerzhou/p/11027559.html]
[https://v1-12.docs.kubernetes.io/zh/docs/tasks/run-application/force-delete-stateful-set-pod/]
[https://juejin.im/post/5d206b1e5188252f275fdc95]
[https://www.cnblogs.com/breezey/p/6582082.html]
[https://juejin.im/post/5c989ff2f265da60f206ffe4#heading-7]
[https://www.jianshu.com/p/a5172b0eeae4]
https://www.cnblogs.com/xiaochangwei/p/7993065.html

相关文章

  • k8s环境下单节点运行Redis集群

    单机下用Redis二进制程序包搭建Redis集群的案例很多,用docker在单节点上搭集群的也很多,但是在k8s下...

  • k8s架构分析(二)

    master节点 k8s的集群由master和node组成,节点上运行着若干k8s服务。 master节点之上运行...

  • redis集群安装

    集群的概念 Redis集群提供了一种运行Redis安装的方式,其中数据自动分割多个Redis节点。Redis集群的...

  • 【Redis】集群NetCore实战

    环境准备 Redis集群(Windows集群搭建)启动Redis集群,给每个节点加上Title 安装StackEx...

  • redis迁移工具参考说明

    这两天在弄redis 集群迁移····从自建环境8节点迁移到自建环境6节点。折腾了很久···redis 集群模式是...

  • K8S最全面的企业部署(上),不信进去看就知道啦

    typora-root-url: ./一:基础集群环境搭建:k8s基础集群环境主要是运行kubernetes管理端...

  • k8s二进制集群搭建

    Kubernetes(K8s)-k8s服务集群安装 一、环境准备 1、机器环境 节点CPU核数必须是 :>= 2核...

  • redis伪分布式集群数据迁移

    环境: 老redis集群是伪分布式集群:192.168.0.151 节点:7001、7002、7003、7004、...

  • Kubernetes

    什么是K8s K8s本质上就是一组服务器集群,k8s可以在集群的各个节点上运行特定的dockert容器。 一、发展...

  • redis安装集群

    一.环境 redis集群从3.0开始需要至少3个主节点才能让集群正常工作,集群中主节点超过半数失败,整个集群就不可...

网友评论

      本文标题:k8s环境下单节点运行Redis集群

      本文链接:https://www.haomeiwen.com/subject/gkvljctx.html