kubernetes 部署 redis 最新版本高可用集群(三主三从)

目录结构

  • 1. 安装 NFS 网络插件 (主机 + 从机)
  • 2. 创建 PV
  • 3. 创建 Configmap
  • 4. 创建 Headless service
  • 5. 创建 redis.yaml
  • 6. 使用 busybox 镜像的 nslookup 检验域名
  • 7. 初始化 Redis 集群
  • 8. 进入任意 redis 容器 (内部测试)
  • 9. 创建外部访问 Service (外部测试)

1. 安装 NFS 网络插件 (主机 + 从机)

ubuntu:
# apt-get 方式安装
apt-get install nfs-kernel-server

# 启动并设置开机自动启动
systemctl enable rpcbind
systemctl enable nfs-kernel-server
systemctl start rpcbind
systemctl start nfs-kernel-server
centos:
# yum 方式安装
yum -y install nfs-utils rpcbind 

# 启动并设置开机自动启动
systemctl enable rpcbind
systemctl enable nfs
systemctl start rpcbind
systemctl start nfs

2. 创建PV

不给 777 权限挂载时会出现 mount.nfs: access denied by server while mounting 的权限错误

root@VM-0-6-ubuntu:~# mkdir -p /usr/local/k8s/redis/pv{1..6}
root@VM-0-6-ubuntu:~# chmod 777 /usr/local/k8s/redis/pv{1..6}

cat > /etc/exports << EOF
/usr/local/k8s/redis/pv1 0.0.0.0/0 (rw,all_squash)
/usr/local/k8s/redis/pv2 0.0.0.0/0 (rw,all_squash)
/usr/local/k8s/redis/pv3 0.0.0.0/0 (rw,all_squash)
/usr/local/k8s/redis/pv4 0.0.0.0/0 (rw,all_squash)
/usr/local/k8s/redis/pv5 0.0.0.0/0 (rw,all_squash)
/usr/local/k8s/redis/pv6 0.0.0.0/0 (rw,all_squash)
EOF

# 重启 nfs
systemctl restart nfs-kernel-server  # ubuntu 重启命令
systemctl restart nfs                # centos 重启命令

切换任意服务器主机查看PV (教程中的服务器主机内网地址为172.21.0.6,实际替换为你自己的内网地址)

root@VM-0-13-ubuntu:~# showmount -e 172.21.0.6
Export list for 172.21.0.6:
/usr/local/k8s/redis/pv6 (everyone)
/usr/local/k8s/redis/pv5 (everyone)
/usr/local/k8s/redis/pv4 (everyone)
/usr/local/k8s/redis/pv3 (everyone)
/usr/local/k8s/redis/pv2 (everyone)
/usr/local/k8s/redis/pv1 (everyone)

编写 pv.yaml 文件

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-redis-pv1
spec:
  capacity:
    storage: 200M
  accessModes:
    - ReadWriteMany
  nfs:
    server: 172.21.0.6
    path: "/usr/local/k8s/redis/pv1"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-redis-pv2
spec:
  capacity:
    storage: 200M
  accessModes:
    - ReadWriteMany
  nfs:
    server: 172.21.0.6
    path: "/usr/local/k8s/redis/pv2"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-redis-pv3
spec:
  capacity:
    storage: 200M
  accessModes:
    - ReadWriteMany
  nfs:
    server: 172.21.0.6
    path: "/usr/local/k8s/redis/pv3"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-redis-pv4
spec:
  capacity:
    storage: 200M
  accessModes:
    - ReadWriteMany
  nfs:
    server: 172.21.0.6
    path: "/usr/local/k8s/redis/pv4"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-redis-pv5
spec:
  capacity:
    storage: 200M
  accessModes:
    - ReadWriteMany
  nfs:
    server: 172.21.0.6
    path: "/usr/local/k8s/redis/pv5"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-redis-pv6
spec:
  capacity:
    storage: 200M
  accessModes:
    - ReadWriteMany
  nfs:
    server: 172.21.0.6
    path: "/usr/local/k8s/redis/pv6"

创建并查看 PV

root@VM-0-6-ubuntu:~/kubernetes/redis_high# kubectl create -f pv.yaml
persistentvolume/nfs-pv1 created
persistentvolume/nfs-pv2 created
persistentvolume/nfs-pv3 created
persistentvolume/nfs-pv4 created
persistentvolume/nfs-pv5 created
persistentvolume/nfs-pv6 created

root@VM-0-6-ubuntu:~/kubernetes/redis_high# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs-pv1   200M       RWX            Retain           Available                                   8s
nfs-pv2   200M       RWX            Retain           Available                                   8s
nfs-pv3   200M       RWX            Retain           Available                                   8s
nfs-pv4   200M       RWX            Retain           Available                                   8s
nfs-pv5   200M       RWX            Retain           Available                                   8s
nfs-pv6   200M       RWX            Retain           Available                                   8s

3. 创建 Configmap

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

创建名为 redis-conf 的 Configmap

root@VM-0-6-ubuntu:~# kubectl create configmap redis-conf --from-file=redis.conf
configmap/redis-conf created

root@VM-0-6-ubuntu:~# kubectl get cm redis-conf
NAME         DATA   AGE
redis-conf   1      20s

4. 创建 Headless service

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

创建查看无头 service (无clusterIP)

root@VM-0-6-ubuntu:~# kubectl create -f headless-service.yaml
service/redis-service created

root@VM-0-6-ubuntu:~# kubectl get svc redis-service
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
redis-service   ClusterIP   None         <none>        6379/TCP   36s

5. 创建 redis.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: "redis-service"
  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"
        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:
  - metadata:
      name: redis-data
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 200M

注:反亲和性:podAntiAffinity,其决定了某个pod不可以和哪些Pod部署在同一拓扑域,可以用于将一个服务的POD分散在不同的主机或者拓扑域中,提高服务本身的稳定性。
而PreferredDuringSchedulingIgnoredDuringExecution 则表示,在调度期间尽量满足亲和性或者反亲和性规则,如果不能满足规则,POD也有可能被调度到对应的主机上。在之后的运行过程中,系统不会再检查这些规则是否满足。
在这里,matchExpressions规定了Redis Pod尽量不调度到包含app为redis的Node上,也即是说已经存在Redis的Node上尽量不要再分配Redis Pod了。但是,由于我们不足三个Node,而副本有6个,因此根据PreferredDuringSchedulingIgnoredDuringExecution,这些豌豆不得不得挤一挤,挤挤更健康~
这样做的含义:保证每台node上都有redis,即使很多台node挂掉了,但凡有一台node存活,这样也能保证redis的正常运行

创建并查看 redis

root@VM-0-6-ubuntu:~# kubectl create -f redis.yaml
statefulset.apps/redis created

root@VM-0-6-ubuntu:~# kubectl get po -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP             NODE             NOMINATED NODE   READINESS GATES
redis-0                     1/1     Running   0          4m22s   10.244.1.162   vm-0-13-ubuntu   <none>           <none>
redis-1                     1/1     Running   0          4m15s   10.244.0.98    vm-0-6-ubuntu    <none>           <none>
redis-2                     1/1     Running   0          4m12s   10.244.1.163   vm-0-13-ubuntu   <none>           <none>
redis-3                     1/1     Running   0          4m8s    10.244.0.99    vm-0-6-ubuntu    <none>           <none>
redis-4                     1/1     Running   0          4m3s    10.244.1.164   vm-0-13-ubuntu   <none>           <none>
redis-5                     1/1     Running   0          4m      10.244.0.100   vm-0-6-ubuntu    <none>           <none>

6. 使用 busybox 镜像的 nslookup 检验域名

root@VM-0-6-ubuntu:~# kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh

/ # nslookup 10.244.1.162
Server:         10.1.0.10
Address:        10.1.0.10:53

162.1.244.10.in-addr.arpa       name = redis-0.redis-service.default.svc.cluster.local

可以看到, redis-0 的 IP 为 10.244.1.162,name 域名值衡为 redis-0.redis-service.default.svc.cluster.local ,redis-1 ~ redis-6 以此推类

7. 初始化 Redis 集群

root@VM-0-6-ubuntu:~# kubectl run -i --tty ubuntu --image=ubuntu --restart=Always /bin/bash

在新启的 ubuntu 容器中添加阿里源

cat > /etc/apt/sources.list << EOF
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
EOF

更新 apt 并安装相关软件与 redis-trib

root@ubuntu:/# apt-get update
root@ubuntu:/# apt-get install -y vim wget python2.7 python-pip redis-tools dnsutils
root@ubuntu:/# pip install redis-trib

建立 Master 集群

redis-trib.py create \
  `dig +short redis-0.redis-service.default.svc.cluster.local`:6379 \
  `dig +short redis-1.redis-service.default.svc.cluster.local`:6379 \
  `dig +short redis-2.redis-service.default.svc.cluster.local`:6379

成功结果展示:

Redis-trib 0.6.2 Copyright (c) HunanTV Platform developers
INFO:root:Instance at 10.244.0.98:6379 checked
INFO:root:Instance at 10.244.1.163:6379 checked
INFO:root:Instance at 10.244.1.162:6379 checked
INFO:root:Add 5462 slots to 10.244.0.98:6379
INFO:root:Add 5461 slots to 10.244.1.163:6379
INFO:root:Add 5461 slots to 10.244.1.162:6379

为各个 Master 添加 Slave(三段代码依次分开执行)

redis-trib.py replicate \
  --master-addr `dig +short redis-0.redis-service.default.svc.cluster.local`:6379 \
  --slave-addr `dig +short redis-3.redis-service.default.svc.cluster.local`:6379

redis-trib.py replicate \
  --master-addr `dig +short redis-1.redis-service.default.svc.cluster.local`:6379 \
  --slave-addr `dig +short redis-4.redis-service.default.svc.cluster.local`:6379

redis-trib.py replicate \
  --master-addr `dig +short redis-2.redis-service.default.svc.cluster.local`:6379 \
  --slave-addr `dig +short redis-5.redis-service.default.svc.cluster.local`:6379

成功结果展示:

Redis-trib 0.6.2 Copyright (c) HunanTV Platform developers
INFO:root:Instance at 10.244.0.99:6379 has joined 10.244.1.162:6379; now set replica
INFO:root:Instance at 10.244.0.99:6379 set as replica to 966fee4175b3d16f810faa30a6c5ceecb8da4e43
Redis-trib 0.6.2 Copyright (c) HunanTV Platform developers
INFO:root:Instance at 10.244.1.164:6379 has joined 10.244.0.98:6379; now set replica
INFO:root:Instance at 10.244.1.164:6379 set as replica to 8b880bad9cc160c9756b478111bdd48e29c90a97
Redis-trib 0.6.2 Copyright (c) HunanTV Platform developers
INFO:root:Instance at 10.244.0.100:6379 has joined 10.244.1.163:6379; now set replica
INFO:root:Instance at 10.244.0.100:6379 set as replica to 0cdcef9966db6e4c55c9d9df9ecd39f592089ee0

8. 进入任意 redis 容器 (内部测试)

root@VM-0-6-ubuntu:~# kubectl exec -it redis-0 -- bash
root@redis-0:/data# redis-cli -c
127.0.0.1:6379> set aa 666
-> Redirected to slot [1180] located at 10.244.0.98:6379
OK

10.244.0.98:6379> get aa
"666"

10.244.0.98:6379> role
1) "master"
2) (integer) 403
3) 1) 1) "10.244.1.164"
      2) "6379"
      3) "403"

redis-cli -c 该命令表示以集群模式进入 redis,
切勿直接只用 redis-cli 直接进入,否则报错:(error) MOVED 1180 xx.xx.xx.xx:6379

至此,Redis集群就真正创建完毕!

9. 创建外部访问 Service (外部测试)

案例教程中固定了内部访问 clusterIP:10.1.0.9

apiVersion: v1
kind: Service
metadata:
  name: redis-access-service
  labels:
    app: redis
spec:
  clusterIP: 10.1.0.9
  type: NodePort
  ports:
  - name: redis-port
    protocol: "TCP"
    port: 6379
    targetPort: 6379
    nodePort: 30009
  selector:
    app: redis
    appCluster: redis-cluster

编写 redis.php 测试文件

<?php
$serv = [
    '10.1.0.9:6379',
];
$redis = new RedisCluster(null, $serv);
$aa = $redis->get('aa');
var_dump($aa);

结果展示:

root@VM-0-6-ubuntu:~# php redis.php
string(3) "666"

文献参考: https://www.jianshu.com/p/65c4baadf5d9

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343