5-1 基于StatefulSet运行Redis Cluster

发布于:2022-12-26 ⋅ 阅读:(468) ⋅ 点赞:(0)

前言

Redis Cluster集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。

本文将在Kubernetes环境中使用PV/PVC,基于StatefulSet控制器创建并运行Redis Cluster。



创建PV

NFS服务器

先在NFS服务器192.168.100.155创建目录并共享:

# 创建6个共享目录,属主属组选nfsnobody。
mkdir -p /data/k8sdata/myserver/redis{0..5}
chown nfsnobody.nfsnobody /data/k8sdata/myserver/redis{0..5}

# 提供共享服务,可共享的IP段为物理机IP,rw可读写,all_squash远程用户连到nfs服务器都压榨成nfsnobody用户。
cat << EOF >> /etc/exports
/data/k8sdata/myserver/redis0 192.168.100.0/24(rw,all_squash)
/data/k8sdata/myserver/redis1 192.168.100.0/24(rw,all_squash)
/data/k8sdata/myserver/redis2 192.168.100.0/24(rw,all_squash)
/data/k8sdata/myserver/redis3 192.168.100.0/24(rw,all_squash)
/data/k8sdata/myserver/redis4 192.168.100.0/24(rw,all_squash)
/data/k8sdata/myserver/redis5 192.168.100.0/24(rw,all_squash)
EOF

# 重新加载,查看挂载情况
exportfs -r
exportfs -v

# nfs涉及端口较多,测试环境可关闭防火墙
systemctl disable --now firewalld

生成PV

redis集群需创建3主3从6个pod,对应需创建6个pv:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-cluster-pv0
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 192.168.100.155
    path: /data/k8sdata/myserver/redis0 

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-cluster-pv1
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 192.168.100.155
    path: /data/k8sdata/myserver/redis1 

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-cluster-pv2
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 192.168.100.155
    path: /data/k8sdata/myserver/redis2 

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-cluster-pv3
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 192.168.100.155
    path: /data/k8sdata/myserver/redis3 

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-cluster-pv4
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 192.168.100.155
    path: /data/k8sdata/myserver/redis4 

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-cluster-pv5
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 192.168.100.155
    path: /data/k8sdata/myserver/redis5 

生成并查看pv:

sudo kubectl apply -f redis-cluster-pv.yaml
sudo kubectl get pv -n myserver 
NAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                              STORAGECLASS   REASON   AGE
redis-cluster-pv0        5Gi        RWO            Retain           Available                                                              32s
redis-cluster-pv1        5Gi        RWO            Retain           Available                                                              32s
redis-cluster-pv2        5Gi        RWO            Retain           Available                                                              32s
redis-cluster-pv3        5Gi        RWO            Retain           Available                                                              32s
redis-cluster-pv4        5Gi        RWO            Retain           Available                                                              32s
redis-cluster-pv5        5Gi        RWO            Retain           Available                                                              32s

Redis Cluster 集群

redis配置

开启aof持久化,开启集群,5秒超时,端口6379:

vim 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

将配置文件保存至configmap:

sudo kubectl create configmap redis-conf --from-file=redis.conf -n myserver
sudo kubectl describe configmap redis-conf -n myserver

创建Redis Cluster

创建redis服务,redis-access服务,redis StatefulSet应用:

apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: myserver
  labels:
    app: redis
spec:
  selector:
    app: redis
    appCluster: redis-cluster
  ports:
  - name: redis
    port: 6379
  clusterIP: None
  
---
apiVersion: v1
kind: Service
metadata:
  name: redis-access
  namespace: myserver
  labels:
    app: redis
spec:
  selector:
    app: redis
    appCluster: redis-cluster
  ports:
  - name: redis-access
    protocol: TCP
    port: 6379
    targetPort: 6379

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
  namespace: myserver
spec:
  serviceName: redis
  replicas: 6
  selector:
    matchLabels:
      app: redis
      appCluster: redis-cluster
  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: redis:4.0.14
        command:
          - "redis-server"
        args:
          - "/etc/redis/redis.conf"
          - "--protected-mode"
          - "no"
        resources:
          requests:
            cpu: "500m"
            memory: "500Mi"
        ports:
        - containerPort: 6379
          name: redis
          protocol: TCP
        - containerPort: 16379
          name: cluster
          protocol: TCP
        volumeMounts:
        - name: conf
          mountPath: /etc/redis
        - name: data
          mountPath: /var/lib/redis
      volumes:
      - name: conf
        configMap:
          name: redis-conf
          items:
          - key: redis.conf
            path: redis.conf
  volumeClaimTemplates:
  - metadata:
      name: data
      namespace: myserver
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi

应用yaml,查看创建的pod:

kubectl get pod -A
myserver               redis-0                                      1/1     Running   0               61m
myserver               redis-1                                      1/1     Running   0               61m
myserver               redis-2                                      1/1     Running   0               61m
myserver               redis-3                                      1/1     Running   0               61m
myserver               redis-4                                      1/1     Running   0               61m
myserver               redis-5                                      1/1     Running   0               33m

查看pvc绑定情况:

kubectl get pvc -A
NAMESPACE   NAME                      STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myserver    data-redis-0              Bound    redis-cluster-pv1        5Gi        RWO                           58m
myserver    data-redis-1              Bound    redis-cluster-pv4        5Gi        RWO                           57m
myserver    data-redis-2              Bound    redis-cluster-pv3        5Gi        RWO                           57m
myserver    data-redis-3              Bound    redis-cluster-pv5        5Gi        RWO                           57m
myserver    data-redis-4              Bound    redis-cluster-pv0        5Gi        RWO                           57m
myserver    data-redis-5              Bound    redis-cluster-pv2        5Gi        RWO                           30m

初始化集群

redis集群使用前需要初始化一次,操作系统请选择ubuntu1804,初始化工具4版本用redis-tribe,5版本用redis-cli。

# 启动一次性系统容器ubuntu
kubectl run -it ubuntu1804 --image=ubuntu:18.04 --restart=Never -n myserver bash

以下操作在一次性容器ubuntu里执行:

#先更新安装包列表:
apt update
# 需要下载,时间较久。出现时区提示就选亚洲-上海:
apt install python2.7 python-pip redis-tools dnsutils iputils-ping net-tools
# 更新pip
pip install --upgrade pip
# 安装初始化工具
pip install redis-trib==0.5.1

# 创建3个master,注意拷贝时\后面不能有空格:
redis-trib.py create \
`dig +short redis-0.redis.myserver.svc.cluster.local`:6379 \
`dig +short redis-1.redis.myserver.svc.cluster.local`:6379 \
`dig +short redis-2.redis.myserver.svc.cluster.local`:6379
Redis-trib 0.5.1 Copyright (c) HunanTV Platform developers
INFO:root:Instance at 172.20.104.7:6379 checked
INFO:root:Instance at 172.20.104.6:6379 checked
INFO:root:Instance at 172.20.166.180:6379 checked
INFO:root:Add 5462 slots to 172.20.104.7:6379
INFO:root:Add 5461 slots to 172.20.104.6:6379
INFO:root:Add 5461 slots to 172.20.166.180:6379

# redis-3加入master redis-0
redis-trib.py replicate \
--master-addr `dig +short redis-0.redis.myserver.svc.cluster.local`:6379 \
 --slave-addr `dig +short redis-3.redis.myserver.svc.cluster.local`:6379
INFO:root:Instance at 172.20.166.181:6379 has joined 172.20.104.7:6379; now set replica
INFO:root:Instance at 172.20.166.181:6379 set as replica to eae814d972b63625fdca98bc039877a5d385da8a

# redis-4加入master redis-1
redis-trib.py replicate \
--master-addr `dig +short redis-1.redis.myserver.svc.cluster.local`:6379 \
 --slave-addr `dig +short redis-4.redis.myserver.svc.cluster.local`:6379
INFO:root:Instance at 172.20.135.4:6379 has joined 172.20.166.180:6379; now set replica
INFO:root:Instance at 172.20.135.4:6379 set as replica to ddedfa38fef4fd2323b2bf41f23b359bc50e523e

# redis-5加入master redis-2
redis-trib.py replicate \
--master-addr `dig +short redis-2.redis.myserver.svc.cluster.local`:6379 \
 --slave-addr `dig +short redis-5.redis.myserver.svc.cluster.local`:6379
INFO:root:Instance at 172.20.135.1:6379 has joined 172.20.104.6:6379; now set replica
INFO:root:Instance at 172.20.135.1:6379 set as replica to 6188dedfc8edb962d0e7557038005920437acaf3

验证redis集群

进入其中一个redis pod,检查集群状态:

kubectl exec -it redis-0 bash -n myserver
root@redis-0:/data# redis-cli

127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:5
cluster_my_epoch:0
cluster_stats_messages_ping_sent:1550
cluster_stats_messages_pong_sent:1555
cluster_stats_messages_meet_sent:2
cluster_stats_messages_sent:3107
cluster_stats_messages_ping_received:1551
cluster_stats_messages_pong_received:1552
cluster_stats_messages_meet_received:4
cluster_stats_messages_received:3107

127.0.0.1:6379> CLUSTER NODES
1284f940cc0d1c47cf7d7e9c840b1c5259d04c7d 172.20.135.4:6379@16379 slave ddedfa38fef4fd2323b2bf41f23b359bc50e523e 0 1662476305216 4 connected
eae814d972b63625fdca98bc039877a5d385da8a 172.20.104.7:6379@16379 myself,master - 0 1662476305000 0 connected 0-5461
6188dedfc8edb962d0e7557038005920437acaf3 172.20.104.6:6379@16379 master - 0 1662476305718 2 connected 5462-10922
b8bebc35ded8ff313b155c32bf06921d44973b8a 172.20.135.1:6379@16379 slave 6188dedfc8edb962d0e7557038005920437acaf3 0 1662476305518 5 connected
ddedfa38fef4fd2323b2bf41f23b359bc50e523e 172.20.166.180:6379@16379 master - 0 1662476305000 1 connected 10923-16383
32d59439a69804c1b9643d35c5f19a0d5bd7cc03 172.20.166.181:6379@16379 slave eae814d972b63625fdca98bc039877a5d385da8a 0 1662476304000 3 connected

排错:资源不足

但创建pod时,一直处在pending状态:

myserver               redis-4                                      0/1     Pending   0               8m17s

查看pod具体情况,出现Insufficient cpu:

 Warning  FailedScheduling  91s   
 
 default-scheduler 0/4 nodes are available: 
 1 Insufficient cpu, 
 2 Insufficient memory, 
 2 node(s) had untolerated taint {node.kubernetes.io/unschedulable: }, 
 2 node(s) were unschedulable. 
 
 preemption: 0/4 nodes are available: 
 2 No preemption victims found for incoming pod, 
 2 Preemption is not helpful for scheduling.

首先部署一台新服务器,配置好主机名和IP,免密登录。通过kubeasz将其加入node节点:

# 免密登录
ssh-copy-id 192.168.100.156
# 加入node
ezctl add-node k8s-cluster 192.168.100.156
# 查看节点
kubectl get node

值得注意的是,k8s在添加工作节点node成功后,会自动重新调度并创建pod。



本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到