阅读 53

Kubernetes上部署一套 Redis 集群

介绍

Redis代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理。它可以存储和操作高级数据类型,例如列表,地图,集合和排序集合。
由于Redis接受多种格式的密钥,因此可以在服务器上执行操作,从而减少了客户端的工作量。
它仅将磁盘用于持久性,而将数据库完全保存在内存中。
Redis是一种流行的数据存储解决方案,并被GitHub,Pinterest,Snapchat,Twitter,StackOverflow,Flickr等技术巨头所使用。

Redis是一个有状态应用

这是部署redis集群时我们最需要注意的问题,当我们把redis以pod的形式部署在k8s中时,每个pod里缓存的数据都是不一样的,而且pod的IP是会随时变化,这时候如果使用普通的deployment和service来部署redis-cluster就会出现很多问题,因此需要改用StatefulSet + Headless Service来解决

数据持久化

redis虽然是基于内存的缓存,但还是需要依赖于磁盘进行数据的持久化,以便服务出现问题重启时可以恢复已经缓存的数据。在集群中,我们需要使用共享文件系统 + PV(持久卷)的方式来让整个集群中的所有pod都可以共享同一份持久化储存

概念介绍

Headless Service

Headless Service就是没有指定Cluster IP的Service,相应的,在k8s的dns映射里,Headless Service的解析结果不是一个Cluster IP,而是它所关联的所有Pod的IP列表


e33c81450e71824061a953ecb00bca70.jpg

配置步骤大概罗列如下

配置共享文件系统NFS
创建PV和PVC
创建ConfigMap
创建Headless Service
创建StatefulSet
初始化redis集群

这里直接通过普通Volume的方式来挂载数据

创建ConfigMap
先创建redis.conf配置文件

appendonly yes
cluster-enabled yes
cluster-config-file /var/lib/redis/nodes.conf
cluster-node-timeout 5000dir /var/lib/redis
port 6379

kubectl create configmap redis-conf --from-file=redis.conf来创建ConfigMap
创建HeadlessService
vim 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

kubectl apply -f headlessservice.yaml
创建StatefulSet
vim 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:
      terminationGracePeriodSeconds: 20
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app                  operator: In
                  values:
                  - redis
              topologyKey: kubernetes.io/hostname
      containers:
      - name: redis
        image: "registry.cn-qingdao.aliyuncs.com/gold-faas/gold-redis:1.0"
        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"
      - name: "redis-data"
        emptyDir: {}

初始化redis集群

StatefulSet创建完毕后,可以看到6个pod已经启动了,但这时候整个redis集群还没有初始化,需要使用官方提供的redis-trib工具。

我们当然可以在任意一个redis节点上运行对应的工具来初始化整个集群,但这么做显然有些不太合适,我们希望每个节点的职责尽可能地单一,所以最好单独起一个pod来运行整个集群的管理工具。

在这里需要先介绍一下redis-trib,它是官方提供的redis-cluster管理工具,可以实现redis集群的创建、更新等功能,在早期的redis版本中,它是以源码包里redis-trib.rb这个ruby脚本的方式来运作的(pip上也可以拉到python版本,但我运行失败),现在(我使用的5.0.3)已经被官方集成进redis-cli中。

开始初始化集群,首先在k8s上创建一个ubuntu的pod,用来作为管理节点

kubectl run -i --tty redis-cluster-manager --image=ubuntu --restart=Never /bin/bash
进入pod内部先安装一些工具,包括wget,dnsutils,gcc然后下载和安装redis

apt-get install wget dnsutile gcc makewget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -xvzf redis-5.0.3.tar.gz
cd redis-5.0.3 && make
编译完毕后redis-cli会被放置在src目录下,把它放进/usr/local/bin中方便后续操作

cp src/redis-cli /usr/loca/bin
获取已经创建好的6个节点的host ip,可以通过nslookup结合StatefulSet的域名规则来查找,举个例子,要查找redis-app-0这个pod的ip,运行如下命令

root@redis-cluster-manager:/# nslookup redis-app-0.redis-service
Server:         10.96.0.10Address:        10.96.0.10#53Name:   redis-app-0.redis-service.default.svc.cluster.local
Address: 10.244.2.140
10.244.2.140就是对应的ip。这次部署我们使用0,1,2作为Master节点;3,4,5作为Slave节点,先运行下面的命令来初始化集群的Master节点:

redis-cli --cluster create 10.244.2.140:6379 10.244.1.137:6379 10.244.2.141:6379

image.png

然后给他们分别附加对应的Slave节点,这里的cluster-master-id在上一步创建的时候会给出

redis-cli --cluster add-node 10.244.1.138:6379 10.244.2.140:6379 --cluster-slave --cluster-master-id 1c0c3a34c306b70c5eacf4f3d0649a68f0cf5d39

redis-cli --cluster add-node 10.244.2.142:6379 10.244.1.137:6379 --cluster-slave --cluster-master-id 05fd3612662a3cf53800f26ec08c08fab08297a7

redis-cli --cluster add-node 10.244.1.139:6379 10.244.2.141:6379 --cluster-slave --cluster-master-id 0d299e2974498a84e21fd9b4bd0abb6b5102d280
集群初始化后,随意进入一个节点检查一下集群信息

redis-cli -h  10.244.2.140

image.png

至此,集群初始化完毕,我们进入一个节点来试试,注意在集群模式下redis-cli必须加上-c参数才能够访问其他节点上的数据

image.png

创建Service

现在进入redis集群中的任意一个节点都可以直接进行操作了,但是为了能够对集群其他的服务提供访问,还需要建立一个service来实现服务发现和负载均衡(注意这里的service和我们之前创建的headless service不是一个东西)

vim service.yaml

apiVersion: v1
kind: Service
metadata:
  name: gold-redis
  labels:
    app: redis
spec:
  ports:
  - name: redis-port
    protocol: "TCP"
    port: 6379
    targetPort: 6379
  selector:
    app: redis
    appCluster: redis-cluster



作者:北漂打工人
链接:https://www.jianshu.com/p/b3ce93aa9983


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐