K8S部署Redis單節(jié)點(diǎn)Rdb數(shù)據(jù)持久化故障演練恢復(fù)
環(huán)境:

背景: 采用NFS存儲(chǔ)卷的方式 持久化存儲(chǔ)redis 需要保存的文件
一、部署NFS服務(wù)器
- #服務(wù)器安裝nfs服務(wù),提供nfs存儲(chǔ)功能
- 1、安裝nfs-utils
- yum install nfs-utils (centos)
- 或者 apt-get install nfs-kernel-server (ubuntu)
- 2、啟動(dòng)服務(wù)
- systemctl enable nfs-server
- systemctl start nfs-server
- 3、創(chuàng)建共享目錄完成共享配置
- mkdir /home/nfs #創(chuàng)建共享目錄
- 4、編輯共享配置
- vim /etc/exports
- #語(yǔ)法格式: 共享文件路徑 客戶機(jī)地址(權(quán)限) #這里的客戶機(jī)地址可以是IP,網(wǎng)段,域名,也可以是任意*
- /home/nfs *(rw,async,no_root_squash)
- 服務(wù)自檢命令
- exportfs -arv
- 5、重啟服務(wù)
- systemctl restart nfs-server
- 6、本機(jī)查看nfs 共享目錄
- #showmount -e 服務(wù)器IP地址 (如果提示命令不存在,則需要yum install showmount)
- showmount -e 127.0.0.1
- /home/nfs *
- 7、客戶端模擬掛載[所有k8s的節(jié)點(diǎn)都需要安裝客戶端]
- [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 動(dòng)態(tài)供給(NFS StorageClass),創(chuàng)建pvc
#部署NFS實(shí)現(xiàn)自動(dòng)創(chuàng)建PV插件: 一共設(shè)計(jì)到4個(gè)yaml 文件 ,官方的文檔有詳細(xì)的說明。
https://github.com/kubernetes-incubator/external-storage


- root@k8s-master1:~ # mkdir /root/pvc
- root@k8s-master1:~ # cd /root/pvc
創(chuàng)建rbac.yaml 文件
- root@k8s-master1:pvc # cat rbac.yaml
- kind: ServiceAccount
- apiVersion: v1
- metadata:
- name: nfs-client-provisioner
- ---
- kind: ClusterRole
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- name: nfs-client-provisioner-runner
- rules:
- - 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: ClusterRoleBinding
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- name: run-nfs-client-provisioner
- subjects:
- - kind: ServiceAccount
- name: nfs-client-provisioner
- namespace: default
- roleRef:
- kind: ClusterRole
- name: nfs-client-provisioner-runner
- apiGroup: rbac.authorization.k8s.io
- ---
- kind: Role
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- name: leader-locking-nfs-client-provisioner
- rules:
- - apiGroups: [""]
- resources: ["endpoints"]
- verbs: ["get", "list", "watch", "create", "update", "patch"]
- ---
- kind: RoleBinding
- apiVersion: rbac.authorization.k8s.io/v1
- metadata:
- name: leader-locking-nfs-client-provisioner
- subjects:
- - kind: ServiceAccount
- name: nfs-client-provisioner
- # replace with namespace where provisioner is deployed
- namespace: default
- roleRef:
- kind: Role
- name: leader-locking-nfs-client-provisioner
- apiGroup: rbac.authorization.k8s.io
創(chuàng)建deployment.yaml 文件
#官方默認(rèn)的鏡像地址,國(guó)內(nèi)可能無(wú)法下載,可以使用 image:
fxkjnj/nfs-client-provisioner:latest
#定義NFS 服務(wù)器的地址,共享目錄名稱
- 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
創(chuàng)建class.yaml
# archiveOnDelete: "true" 表示當(dāng)PVC 刪除后,后端數(shù)據(jù)不直接刪除,而是歸檔
- 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"
創(chuàng)建pvc.yaml
#指定storageClassName 存儲(chǔ)卷的名字
# requests:
storage: 100Gi 指定需要多大的存儲(chǔ)
#注意,這里pvc ,我們創(chuàng)建在redis 命名空間下了,如果沒有redis 還需要先創(chuàng)建才行, 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 .
- #查看存儲(chǔ)卷
- 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秒有一個(gè)key 變動(dòng) 就寫入到 dump.rdb 文件中
# appendonly no ,表示下次可以使用dump.rdb 來(lái)恢復(fù) redis 快照的數(shù)據(jù)
# 注意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:
- # 進(jìn)行初始化操作,修改系統(tǒng)配置,解決 Redis 啟動(dòng)時(shí)提示的警告信息
- 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
四、測(cè)試,訪問
使用redis 客戶端工具,寫入幾個(gè)KEY 測(cè)試


刪除pod,在自動(dòng)新建pod后,查詢鍵值是否存在
- root@k8s-master1:~# kubectl get pods -n redis
- NAME READY STATUS RESTARTS AGE
- redis-65f75db6bc-5skgr 1/1 Running 0 5d20h
- redis-65f75db6bc-75m8m 1/1 Running 0 5d20h
- redis-65f75db6bc-cp6cx 1/1 Running 0 5d20h
- root@k8s-master1:~# kubectl delete -n redis pod redis-65f75db6bc-5skgr
- pod "redis-65f75db6bc-5skgr" deleted
- #刪除pod后,根據(jù)副本數(shù),又重新拉取新的pod生成
- root@k8s-master1:~# kubectl get pods -n redis
- NAME READY STATUS RESTARTS AGE
- redis-65f75db6bc-tnnxp 1/1 Running 0 54s
- redis-65f75db6bc-75m8m 1/1 Running 0 5d20h
- redis-65f75db6bc-cp6cx 1/1 Running 0 5d20h

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

五、故障演練恢復(fù)
(1)數(shù)據(jù)備份
源redis配置有持久化,直接拷貝持久化目錄下的dump.rdb
直接到持久化的目錄下,拷貝走dump.rdb 文件
源redis不支持持久化,則進(jìn)入容器生成dump.rdb并拷出
進(jìn)入容器:kubectl exec -it redis-xxx /bin/bash -n redis
進(jìn)入redis命令臺(tái):redis-cli
密碼認(rèn)證:auth 123
保存數(shù)據(jù),生成dump.rdb文件:save
退出redis命令臺(tái):quit
退出容器:exit
從容器中取出數(shù)據(jù)到本地:kubectl cp -n redis Pod_Name:/data/dump.rdb ./
傳輸至遠(yuǎn)程主機(jī):scp dump.rdb root@目標(biāo)服務(wù)器:/目錄
(2)數(shù)據(jù)恢復(fù)
- 停止redis,直接刪除創(chuàng)建的deployment
- 拷貝dump.rdb至目標(biāo)redis的持久化目錄下(注:將覆蓋目標(biāo)redis的數(shù)據(jù))
- 重啟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至目標(biāo)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)驗(yàn)證數(shù)據(jù),可發(fā)現(xiàn)源redis的數(shù)據(jù)已全部復(fù)現(xiàn)
