K8S 部署redis单节点&rdb数据持久化&故障演练恢复

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

 

环境:

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

背景: 采用NFS存储卷的方式 持久化存储redis 需要保存的文件

一、部署NFS服务器

#服务器安装nfs服务,提供nfs存储功能
1、安装nfs-utils
yum install nfs-utils (centos)
或者 	apt-get install nfs-kernel-server (ubuntu)

2、启动服务
systemctl enable nfs-server
systemctl start nfs-server

3、创建共享目录完成共享配置
mkdir /home/nfs   #创建共享目录

4、编辑共享配置
vim /etc/exports                                           
#语法格式:    共享文件路径     客户机地址(权限)     #这里的客户机地址可以是IP,网段,域名,也可以是任意*
/home/nfs  *(rw,async,no_root_squash)
服务自检命令 
exportfs -arv


5、重启服务
systemctl restart nfs-server


6、本机查看nfs 共享目录
#showmount -e 服务器IP地址 (如果提示命令不存在,则需要yum install showmount)

showmount -e 127.0.0.1
/home/nfs *



7、客户端模拟挂载[所有k8s的节点都需要安装客户端]
[root@master-1 ~]# yum install nfs-utils (centos)
或者  apt-get install nfs-common (ubuntu)
[root@master-1 ~]# mkdir /test
[root@master-1 ~]# mount -t nfs 172.16.201.209:/home/nfs /test

#取消挂载
[root@master-1 ~]# umount /test

二、配置PV 动态供给(NFS StorageClass),创建pvc

#部署NFS实现自动创建PV插件: 一共设计到4个yaml 文件 ,官方的文档有详细的说明

https://github.com/kubernetes-incubator/external-storage

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

root@k8s-master1:~ # mkdir  /root/pvcroot@k8s-master1:~ # cd   /root/pvc
  • 创建rbac.yaml 文件
root@k8s-master1:pvc # cat rbac.yaml kind: ServiceAccountapiVersion: v1metadata:  name: nfs-client-provisioner---kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: nfs-client-provisioner-runnerrules:  - apiGroups: [""]    resources: ["persistentvolumes"]    verbs: ["get", "list", "watch", "create", "delete"]  - apiGroups: [""]    resources: ["persistentvolumeclaims"]    verbs: ["get", "list", "watch", "update"]  - apiGroups: ["storage.k8s.io"]    resources: ["storageclasses"]    verbs: ["get", "list", "watch"]  - apiGroups: [""]    resources: ["events"]    verbs: ["create", "update", "patch"]---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: run-nfs-client-provisionersubjects:  - kind: ServiceAccount    name: nfs-client-provisioner    namespace: defaultroleRef:  kind: ClusterRole  name: nfs-client-provisioner-runner  apiGroup: rbac.authorization.k8s.io---kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:  name: leader-locking-nfs-client-provisionerrules:  - apiGroups: [""]    resources: ["endpoints"]    verbs: ["get", "list", "watch", "create", "update", "patch"]---kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: leader-locking-nfs-client-provisionersubjects:  - kind: ServiceAccount    name: nfs-client-provisioner    # replace with namespace where provisioner is deployed    namespace: defaultroleRef:  kind: Role  name: leader-locking-nfs-client-provisioner  apiGroup: rbac.authorization.k8s.io
  • 创建deployment.yaml 文件

#官方默认的镜像地址,国内可能无法下载,可以使用 image:
fxkjnj/nfs-client-provisioner:latest

#定义NFS 服务器的地址,共享目录名称

root@k8s-master1:pvc # cat deployment.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
---
kind: Deployment
apiVersion: apps/v1 
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: fxkjnj/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 172.16.201.209 
            - name: NFS_PATH
              value: /home/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.16.201.209
            path: /home/nfs
  • 创建class.yaml

# archiveOnDelete: “true” 表示当PVC 删除后,后端数据不直接删除,而是归档

root@k8s-master1:pvc # cat class.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "true"
  • 创建pvc.yaml

#指定storageClassName 存储卷的名字

# requests:

storage: 100Gi 指定需要多大的存储

#注意,这里pvc ,我们创建在redis 命名空间下了,如果没有redis 还需要先创建才行, kubectl create namespace redis

root@k8s-master1:pvc # cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-redis
  namespace: redis
spec:
  storageClassName: "managed-nfs-storage"
  accessModes:
    - ReadWriteMany     
  resources:
    requests:
      storage: 100Gi
#部署
root@k8s-master1:pvc # kubectl apply -f .


#查看存储卷
root@k8s-master1:pvc # kubectl  get sc
NAME                  PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  25h


#查看pvc
root@k8s-master1:pvc # kubectl  get pvc -n redis
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
nfs-redis   Bound    pvc-8eacbe25-3875-4f78-91ca-ba83b6967a8a   100Gi      RWX            managed-nfs-storage   21h

三、编写redis yaml 文件

root@k8s-master1:~ # mkdir  /root/redis
root@k8s-master1:~ # cd /root/redis
  • 编写 redis.conf 配置文件,以configmap 的方式挂载到容器中

# require 配置redis 密码

#save 5 1 ,表示 每5秒有一个key 变动 就写入到 dump.rdb 文件中

# appendonly no ,表示下次可以使用dump.rdb 来恢复 redis 快照的数据

# 注意namespace 为redis

root@k8s-master1: redis# cat redis-configmap-rdb.yml 
kind: ConfigMap
apiVersion: v1
metadata:
  name: redis-config
  namespace: redis
  labels:
    app: redis
data:
    redis.conf: |-
    protected-mode no
    port 6379
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    daemonize no
    supervised no
    pidfile /data/redis_6379.pid
    loglevel notice
    logfile ""
    databases 16
    always-show-logo yes
    save 5 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump.rdb
    dir /data
    replica-serve-stale-data yes
    replica-read-only yes
    repl-diskless-sync no
    repl-diskless-sync-delay 5
    repl-disable-tcp-nodelay no
    replica-priority 100
    requirepass 123
    lazyfree-lazy-eviction no
    lazyfree-lazy-expire no
    lazyfree-lazy-server-del no
    replica-lazy-flush no
    appendonly no
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    aof-use-rdb-preamble yes
    lua-time-limit 5000
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    latency-monitor-threshold 0
    notify-keyspace-events ""
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    stream-node-max-bytes 4096
    stream-node-max-entries 100
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit replica 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    dynamic-hz yes
    aof-rewrite-incremental-fsync yes
    rdb-save-incremental-fsync yes
  • 编写 redis-deployment.yml

#注意namespace 为redis

root@k8s-master1: redis# cat redis-deployment.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: redis
  labels:
    app: redis
spec:
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      # 进行初始化操作,修改系统配置,解决 Redis 启动时提示的警告信息
      initContainers:
        - name: system-init
          image: busybox:1.32
          imagePullPolicy: IfNotPresent
          command:
            - "sh"
            - "-c"
            - "echo 2048 > /proc/sys/net/core/somaxconn && echo never > /sys/kernel/mm/transparent_hugepage/enabled"
          securityContext:
            privileged: true
            runAsUser: 0
          volumeMounts:
          - name: sys
            mountPath: /sys
      containers:
        - name: redis
          image: redis:5.0.8
          command:
            - "sh"
            - "-c"
            - "redis-server /usr/local/etc/redis/redis.conf"
          ports:
            - containerPort: 6379
          resources:
            limits:
              cpu: 1000m
              memory: 1024Mi
            requests:
              cpu: 1000m
              memory: 1024Mi
          livenessProbe:
            tcpSocket:
              port: 6379
            initialDelaySeconds: 300
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          readinessProbe:
            tcpSocket:
              port: 6379
            initialDelaySeconds: 5
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          volumeMounts:
            - name: data
              mountPath: /data
            - name: config
              mountPath: /usr/local/etc/redis/redis.conf
              subPath: redis.conf
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: nfs-redis
        - name: config
          configMap:
            name: redis-config
        - name: sys
          hostPath:
            path: /sys
  • 编写 redis-service.yml

#注意namespace 为redis

#部署
root@k8s-master1:~/kubernetes/redis# kubectl get pod -n redis
NAME                     READY   STATUS    RESTARTS   AGE
redis-65f75db6bc-5skgr   1/1     Running   0          21h
redis-65f75db6bc-75m8m   1/1     Running   0          21h
redis-65f75db6bc-cp6cx   1/1     Running   0          21h

root@k8s-master1:~/kubernetes/redis# kubectl get svc -n redis
NAME          TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
redis-front   NodePort   10.0.0.169   <none>        6379:36379/TCP   22h

四、测试,访问

使用redis 客户端工具,写入几个KEY 测试

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

  • 删除pod,在自动新建pod后,查询键值是否存在
root@k8s-master1:~# kubectl get pods -n redisNAME                     READY   STATUS    RESTARTS   AGEredis-65f75db6bc-5skgr   1/1     Running   0          5d20hredis-65f75db6bc-75m8m   1/1     Running   0          5d20hredis-65f75db6bc-cp6cx   1/1     Running   0          5d20hroot@k8s-master1:~# kubectl delete -n redis pod redis-65f75db6bc-5skgr pod "redis-65f75db6bc-5skgr" deleted#删除pod后,根据副本数,又重新拉取新的pod生成root@k8s-master1:~# kubectl get pods -n redisNAME                     READY   STATUS    RESTARTS   AGEredis-65f75db6bc-tnnxp   1/1     Running   0          54sredis-65f75db6bc-75m8m   1/1     Running   0          5d20hredis-65f75db6bc-cp6cx   1/1     Running   0          5d20h

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

查看nfs共享目录下是否存在 dump.rdb

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

五、故障演练恢复

(1)、数据备份

  • 源redis配置有持久化,直接拷贝持久化目录下的dump.rdb

直接到持久化的目录下,拷贝走dump.rdb 文件

  • 源redis不支持持久化,则进入容器生成dump.rdb并拷出

进入容器:kubectl exec -it redis-xxx /bin/bash -n redis

进入redis命令台:redis-cli

密码认证:auth 123

保存数据,生成dump.rdb文件:save

退出redis命令台:quit

退出容器:exit

从容器中取出数据到本地:kubectl cp -n redis Pod_Name:/data/dump.rdb ./

传输至远程主机:scp dump.rdb root@目标服务器:/目录

(2)、数据恢复

  • 停止redis,直接删除创建的deployment
  • 拷贝dump.rdb至目标redis的持久化目录下(注:将覆盖目标redis的数据)
  • 重启pod:kubectl apply -f redis-deployment.yml
#拷贝持久化目录下的dump.rbd文件 到root 下
cp dump.rdb /root

#停止redis,也就是删除deployment
root@k8s-master1:~/kubernetes/redis# kubectl delete -f redis-deployment.yml 
deployment.apps "redis" deleted

root@k8s-master1:~/kubernetes/redis# kubectl  get pods -n redis
No resources found in redis namespace.

#拷贝dump.rdb至目标redis的持久化目录下
cp /root/dump.rdb   /home/nfs/redis-nfs-redis-pvc-8eacbe25-3875-4f78-91ca-ba83b6967a8a

#重启pod
root@k8s-master1:~/kubernetes/redis# kubectl apply -f redis-deployment.yml 
deployment.apps/redis created

root@k8s-master1:~/kubernetes/redis# kubectl  get pods -n redis
NAME                     READY   STATUS     RESTARTS   AGE
redis-65f75db6bc-5jx4m   0/1     Init:0/1   0          3s
redis-65f75db6bc-68jf5   0/1     Init:0/1   0          3s
redis-65f75db6bc-b9gvk   0/1     Init:0/1   0          3s

root@k8s-master1:~/kubernetes/redis# kubectl  get pods -n redis
NAME                     READY   STATUS    RESTARTS   AGE
redis-65f75db6bc-5jx4m   1/1     Running   0          20s
redis-65f75db6bc-68jf5   1/1     Running   0          20s
redis-65f75db6bc-b9gvk   1/1     Running   0          20s

(3)、验证数据,可发现源redis的数据已全部复现

K8S 部署redis单节点&rdb数据持久化&故障演练恢复

2021/10/26 南京 晴

本文版权归 飞翔沫沫情 作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接 如有问题, 可发送邮件咨询,转贴请注明出处:https://www.fxkjnj.com/3261/

发表评论

登录后才能评论