Kubernetes 部署Redis Cluster

2022-08-09 10:48:16

Redis Cluster容器化需要解决以下问题:

1. Redis Cluster数据持久化

        -> 可以通过StatefulSet + PVC来做持久化存储Redis配置和集群信息

2. Redis Cluster自愈(重建或重启Pod)

       -> 在Redis启动命令中指定cluster-announce-ip pod-ip

3. Redis Cluster对Kubernetes内部提供服务

        -> 通过Service进行服务发布即可

4. Redis Cluster对Kubernetes外部提供服务

        -> 因Redis Cluster请求时,会自动重定向,通过NodePort对外发布Redis服务,但是在K8S外部也无法连接Redis Pod IP,因此需要通过redis-cluster-proxy来实现代理访问。

5. Redis Cluster创建集群方式

        -> 因当前版本(6.0.6)redis-cli --cluster create 命令不支持hostname或dns,因此需要获取Pod IP后手动执行Redis Cluster创建集群。

Redis Cluster架构

Redis Cluster 最少需要3个Master节点,每个Master节点可以有一个或多个Slave节点。

在K8S中部署Redis Cluster

ConfigMap保存redis.conf配置文件

---
# Redis Config
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
  namespace: demo
data:
  redis.conf: |
    bind 0.0.0.0  # 绑定IP
    port 6379    # 绑定端口
    maxmemory 4GB    # 限制内存大小
    protected-mode yes  # 启用保护模式
    masterauth P@ssw0rd  # 启用密码认证
    requirepass P@ssw0rd  # 启用密码认证
    dir /var/lib/redis    # 配置redis目录
    logfile /var/log/redis.log  
    cluster-enabled yes   # 启用Cluster
    cluster-config-file nodes.conf
    cluster-migration-barrier 1
    cluster-require-full-coverage no

StatefulSet保存Redis数据和Cluster状态

---
# Redis Service
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
  namespace: demo
spec:
  type: ClusterIP
  ports:
  - name: redis
    port: 6379
    protocol: TCP
    targetPort: 6379
  selector:
    app: redis
---
# Redis StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
  namespace: demo
spec:
  replicas: 6    # 部署6个节点,3个Master 3个Slave
  selector:
    matchLabels:
      app: redis
  serviceName: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      imagePullSecrets:
        - name: harbor
      containers:
        - name: redis
          image: redis:latest
          imagePullPolicy: IfNotPresent
          command: ["redis-server"]
          args:
            - /etc/redis/redis.conf
            - --cluster-announce-ip          # 用于重启Pod后向集群更新自身IP
            - "$(MY_POD_IP)"    
          env:
            - name: MY_POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
          ports:
            - name: redis-6379
              containerPort: 6379
              protocol: TCP
            - name: redis-16379
              containerPort: 16379
              protocol: TCP
          resources:                         
            requests:                         # 请求的资源
              cpu: "1"                     
              memory: "4096Mi"                
            limits:                           # 限制的资源
              cpu: "1"                        # 1代表1核
              memory: "4096Mi"
          volumeMounts:
            - name: redis-data
              mountPath: /var/lib/redis/
            - name: redis-conf
              mountPath: /etc/redis/
      volumes:  # 挂载配置文件
        - name: redis-conf
          configMap:
            name: redis-cluster
  volumeClaimTemplates:  # 挂载持久化存储
    - metadata:
        name: redis-data
        namespace: demo
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 10Gi
        storageClassName: vsan

手动K8S中创建Redis Cluster

1. 获取Pod IP

获取6个Redis Pod IP地址,因为当前版本创建redis cluster只能使用IP地址,不支持域名方式。

# kubectl get pod -n demo -o wide | grep redis
redis-0                    1/1     Running   0          2m12s   10.42.0.192   k8s-test-node02   <none>           <none>
redis-1                    1/1     Running   0          119s    10.42.2.196   k8s-test-node01   <none>           <none>
redis-2                    1/1     Running   0          96s     10.42.1.51    k8s-test-node03   <none>           <none>
redis-3                    1/1     Running   0          88s     10.42.0.193   k8s-test-node02   <none>           <none>
redis-4                    1/1     Running   0          77s     10.42.2.197   k8s-test-node01   <none>           <none>
redis-5                    1/1     Running   0          57s     10.42.1.52    k8s-test-node03   <none>           <none>

2. 执行创建命令

在任意节点上执行以下命令创建Redis Cluster

redis-cli --cluster create 10.42.0.188:6379 10.42.1.47:6379 10.42.2.192:6379 10.42.0.189:6379 10.42.2.193:6379 10.42.1.48:6379 --cluster-replicas 1 -a 'P@ssw0rd'

root@redis-0:/data# redis-cli --cluster create 10.42.0.188:6379 10.42.1.47:6379 10.42.2.192:6379 10.42.0.189:6379 10.42.2.193:6379 10.42.1.48:6379 --cluster-replicas 1 -a 'P@ssw0rd'
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 10.42.2.193:6379 to 10.42.0.188:6379
Adding replica 10.42.1.48:6379 to 10.42.1.47:6379
Adding replica 10.42.0.189:6379 to 10.42.2.192:6379
M: dae13b0bbc2674078851cce1953ba6d59caf4536 10.42.0.188:6379
   slots:[0-5460] (5461 slots) master
M: 365d43c32353607fdb21bcd286ee6706014b7ede 10.42.1.47:6379
   slots:[5461-10922] (5462 slots) master
M: e5210fb13d2dac4ca03d6a8165944a90f21c4373 10.42.2.192:6379
   slots:[10923-16383] (5461 slots) master
S: e71993737dd8a69819917178f1c4dd479f40a431 10.42.0.189:6379
   replicates e5210fb13d2dac4ca03d6a8165944a90f21c4373
S: f43e356d038c4af1730b8bf9f8807a1ac9c16957 10.42.2.193:6379
   replicates dae13b0bbc2674078851cce1953ba6d59caf4536
S: 080e184652ee18d3c262e39787b5cfd84d9558e9 10.42.1.48:6379
   replicates 365d43c32353607fdb21bcd286ee6706014b7ede
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 10.42.0.188:6379)
M: dae13b0bbc2674078851cce1953ba6d59caf4536 10.42.0.188:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 365d43c32353607fdb21bcd286ee6706014b7ede 10.42.1.47:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: f43e356d038c4af1730b8bf9f8807a1ac9c16957 10.42.2.193:6379
   slots: (0 slots) slave
   replicates dae13b0bbc2674078851cce1953ba6d59caf4536
S: e71993737dd8a69819917178f1c4dd479f40a431 10.42.0.189:6379
   slots: (0 slots) slave
   replicates e5210fb13d2dac4ca03d6a8165944a90f21c4373
M: e5210fb13d2dac4ca03d6a8165944a90f21c4373 10.42.2.192:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 080e184652ee18d3c262e39787b5cfd84d9558e9 10.42.1.48:6379
   slots: (0 slots) slave
   replicates 365d43c32353607fdb21bcd286ee6706014b7ede
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
root@redis-0:/data#

部署Redis-Cluster-Proxy提供代理

如果需要在Kubernetes集群外部访问Redis Cluster则需要部署redis-cluster-proxy。

目前Redis官方还没有将redis-cluster-proxy打包为docker-iamge,因此需要手动打包docker-image。

找一台CentOS7,然后执行以下操作:

1. 安装GCC

因为Centos7自带的GCC版本为4.8.x,而编译redis-cluster-proxy要求gcc为4.9+

# Install GCC
yum install centos-release-scl
yum install devtoolset-8-gcc devtoolset-8-gcc-c++
scl enable devtoolset-8 -- bash

2. 编译安装

# Make Install 
git clone https://github.com/artix75/redis-cluster-proxy
cd redis-cluster-proxy
make PREFIX=/usr/local/redis_cluster_proxy install

3. docker image打包

在目录/usr/local/redis_cluster_proxy/bin/ 下复制redis-cluster-proxy到当前目录,然后创建dockerfile 内容如下:

FROM centos:7

WORKDIR /data

ADD redis-cluster-proxy /usr/local/bin/

EXPOSE 6379

执行打包操作

docker build . -t redis-cluster-proxy:v1

4. 在K8S中运行redis-cluster-proxy

redis-cluster-proxy configmap

---
# Redis-Proxy Config
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-proxy
  namespace: demo
data:
  proxy.conf: |
    cluster redis-cluster:6379     # 配置为Redis Cluster Service
    bind 0.0.0.0
    port 6379   # redis-cluster-proxy 对外暴露端口
    threads 8   # 线程数量
    daemonize no  
    enable-cross-slot yes    
    auth P@ssw0rd     # 配置Redis Cluster 认证密码  
    log-level error

redis-cluster-proxy Deployment

---
# Redis-Proxy NodePort
apiVersion: v1
kind: Service
metadata:
  name: redis-proxy
  namespace: demo
spec:
  type: NodePort # 对K8S外部提供服务
  ports:
  - name: redis-proxy
    nodePort: 30001   # 对外提供的端口
    port: 6379
    protocol: TCP
    targetPort: 6379
  selector:
    app: redis-proxy
---
# Redis-Proxy Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-proxy
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-proxy
  template:
    metadata:
      labels:
        app: redis-proxy
    spec:
      imagePullSecrets:
        - name: harbor
      containers:
        - name: redis-proxy
          image: redis-cluster-proxy:v1
          imagePullPolicy: Always
          command: ["redis-cluster-proxy"]
          args:
            - -c
            - /data/proxy.conf   # 指定启动配置文件
          ports:
            - name: redis-6379
              containerPort: 6379
              protocol: TCP
          volumeMounts:
            - name: redis-proxy-conf
              mountPath: /data/
      volumes:   # 挂载proxy配置文件
        - name: redis-proxy-conf
          configMap:
            name: redis-proxy
  • 作者:VMware技术分享
  • 原文链接:https://blog.csdn.net/coco3848/article/details/107611924
    更新时间:2022-08-09 10:48:16