支持的后端存储:
本地
sftp (通过ssh)
http rest server (rest-server restic提供的 )
s3 (同时支持minio)
openstack swift
backblaze b2
azure blob storage
google cloud storage
以及其他可以通过rclone 访问的后端存储
restic+minio
minio(docker-compose搭建单机版)
cat docker-compose.yml
version: '3.0'
services:
tbc-minio:
image: minio/minio
ports:
- "9000:9000"
- "9001:9001"
volumes:
- /data/minio/data:/data
- /data/minio/config:/root/.minio
environment:
- MINIO_DOMAIN=tbc-minio
- MINIO_ACCESS_KEY=admin12345678 #用户
- MINIO_SECRET_KEY=admin12345678 #密码
command: server /data --console-address ":9001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
restart: on-failure
mkdir /data/minio/{data,config} -p
docker-compose up -d
浏览器访问验证:http://ip:9000
配置s3环境变量:
export AWS_ACCESS_KEY_ID=admin12345678
export AWS_SECRET_ACCESS_KEY=admin12345678
安装restic
sudo yum -y install yum-plugin-copr
sudo yum copr enable copart/restic
sudo yum -y install restic
配置自动补全
restic generate --bash-completion restic.bash_completion
source restic.bash_completion
初始化备份仓库
restic -r s3:http://ip/backup init
查看仓库状态
restic -r s3:http://ip/backup stats
【可选】加入环境变量,免去每次输入密码
export RESTIC_PASSWORD=*********
export RESTIC_REPOSITORY=s3:http://ip/backup
查看状态:restic stats
执行备份test目录操作
restic -r s3:http://ip/backup backup test
#参数说明:
默认备份目录下所有文件
--exclude 排除某些文件
--file-from 指定备份的文件列表
对比备份的差异
restic diff 55572d0c f7d5b7c5
55572d0c 为snapshot id
列举所有的snapshot
restic snapshots
restic -r s3:http://ip/backup snapshots
查看快照中的文件列表
restic ls f18cccc5 / restic ls -l f18cccc5
查找所有文件
restic find hello*
查找指定快照指定文件的内容
restic dump f18cccc5 /backup-demo/hello2.txt
挂载快照内容到本地
restic mount /mnt
mount | grep /mnt
cat /mnt/snapshots/latest/backup-demo/hello2.txt
umount /mnt
------------------------------------------------------------
数据恢复
restic restore f18cccc5 -t /tmp/restore_data
单个文件恢复
restic dump f18cccc5 /backup-demo/hello2.txt >hello2.txt
备份删除
--dry-run参数查看指定策略会删除的快照,但实际不会执行删除操作,用于检验参数是否符合预期
比如保留最新的3个快照
restic forget --keep-last=3 --dry-run
保留前两小时的备份
restic forget --dry-run --keep-hourly 2
备份计划:结合crontab命令执行
Velero Kubernetes应用备份容灾,其他工具Stash
./velero install \
--provider aws \
--plugins xxx/velero-plugin-for-aws:v1.0.0 \
--bucket velero \
--secret-file ./aws-iam-creds \
--backup-location-config region=test,s3Url=http://192.168.0.1,s3ForcePathStyle="true" \
--snapshot-location-config region=test \
--image xxx/velero:v1.6.3 \
--features=EnableCSI \
--use-restic \
--dry-run -o yaml
--plugins以及--image参数指定镜像仓库地址,仅当使用私有镜像仓库时需要配置。
--use-restic参数开启使用restic备份PV数据卷功能。
早期Kubernetes的volume卷不支持快照,因此备份PV卷时需要安装特定的后端存储卷插件,Kubernetes从v1.12开始CSI引入Snapshot后可以利用Snapshot特性实现备份,指定--features=EnableCSI参数开启,开启该模式的底层存储必须支持snapshot,并且配置了snapshot相关的CRD以及volumesnapshotclass(类似storageclass)
数据恢复需要依赖velero-restic-restore-helper工具,如果使用私有镜像仓库,可以通过restic configmap配置私有镜像地址:
apiVersion: v1
kind: ConfigMap
metadata:
name: restic-config
namespace: velero
labels:
velero.io/plugin-config: ""
velero.io/restic: RestoreItemAction
data:
image: xxx/velero-restic-restore-helper:v1.6.3
备份
# nginx-app-demo.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx-app
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
namespace: nginx-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: ceph-rbd-sata
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: nginx-app
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
annotations:
backup.velero.io/backup-volumes: mypvc
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: mypvc
mountPath: /usr/share/nginx/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: pvc-demo
readOnly: false
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
namespace: nginx-app
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
声明了一个PVC,并挂载到nginx pod的/usr/share/nginx/html
路径。
pod添加了注解backup.velero.io/backup-volumes: mypvc
用于指定需要备份的volume。因为并不是所有的volume都必须备份,实际生产中可根据数据的重要性设置合理的备份策略,因此不建议开启--default-volumes-to-restic
选项,该选项会默认备份所有的volume。
#进入容器写入一些测试数据
kubectl exec -t -i nginx-86f99c968-sj8ds -- /bin/bash
cd /usr/share/nginx/html/
echo "HelloWorld" >index.html
echo "hello1" >hello1.html
echo "hello2" >hello2.html
#创建备份
velero backup create nginx-backup-1 --include-namespaces nginx-app
#查看备份信息
velero describe backups nginx-backup-1
备份状态为Completed,说明备份完成,记录中会有备份开始时间和完成时间。
备份的资源数和完成数。
备份的volume数(Restic Backups)。
------------------------------------------------
备份数据管理、迁移
#s3中查看
aws s3 ls velero/backups/nginx-backup-1/
#下载备份
velero backup download nginx-backup-1
如上数据只包含Kubernetes声明资源的yaml文件,不包含最重要的volume业务数据。这些数据保存在s3的velero/restic/nginx-app/路径下,而这些数据是加密存储的
restic的仓库密码:
kubectl get secrets velero-restic-credentials \
-o jsonpath='{.data.repository-password}' | base64 -d
对备份数据的查看
restic -r s3:http://192.168.0.1/velero/restic/nginx-app snapshots
restic -r s3:http://192.168.0.1/velero/restic/nginx-app ls 14fc2081
restic -r s3:http://192.168.0.1/velero/restic/nginx-app dump 14fc2081 /hello2.html
数据恢复
模拟场景
#删除
kubectl delete -f nginx-app-demo.yaml
#检查
kubectl get all -n nginx-app
kubectl get ns nginx-app
#数据恢复
velero restore create --from-backup nginx-backup-1
velero restore get
#验证
kubectl get pod -n nginx-app
kubectl get svc -n nginx-app
#业务检查
kubectl exec -t -i -n nginx-app nginx-86f99c968-8zh6m -- ls /usr/share/nginx/html/
kubectl get svc -n nginx-app
curl 10.106.140.195
------------------------------------
备份计划和策略,配置支持的如下:
备份时间,crontab语法。
备份保留时间,通过ttl指定,默认30天。
备份内容,支持指定namespace或者基于label指定具体的备份资源
帮助信息:velero create schedule -h
示例:
# Create a backup every 6 hours.
velero create schedule NAME --schedule="0 */6 * * *"
# Create a backup every 6 hours with the @every notation.
velero create schedule NAME --schedule="@every 6h"
# Create a daily backup of the web namespace.
velero create schedule NAME --schedule="@every 24h" --include-namespaces web
# Create a weekly backup, each living for 90 days (2160 hours).
velero create schedule NAME --schedule="@every 168h" --ttl 2160h0m0s
minio为开源的对象存储,为velero/restic提供备份存储后端,实际生产时调整为企业对象存储系统。
远端存储为异地存储系统,比如异地磁带库、NBU,或者跨region的异地对象存储系统。
备份流程:
(1)Kubernetes的所有资源包括Pod、Deployment、ConfigMap、Secret、PV卷数据等通过Velero备份到对象存储。(2)通过minio-sync实现实时同步数据到远端同城异地存储系统。
恢复流程:
(1)场景一:集群状态无异常,人为误操作导致数据被删。
直接通过velero恢复指定时间的数据进行恢复即可。
(2)场景二:PV底层的存储系统crash导致数据丢失。
恢复存储系统集群或者极端情况下重搭存储集群,然后使用velero从对象存储中恢复数据。
(3)场景三:极端场景下,整个数据中心或者region crash导致数据丢失。
重建环境,业务数据需要从异地数据中复制到本地,然后借助velero从新建对象存储中进行数据恢复。
(4)场景四:K8S环境迁移。
新建Kubernetes集群,通过velero指定备份点迁移数据到新环境中。
(5)场景五:业务从K8S运行迁移到虚拟机或者物理机运行。
通过Restic从对象存储中把业务数据导出到虚拟机的数据卷中即可。
------------------------------------------------------------------------------------------------
集群备份
Kubernetes证书、kubeadm配置的备份可以直接使用前面介绍的restic工具对整个/etc/kubernetes目录进行备份,而etcd的备份官方也有介绍backing-up-an-etcd-cluster
ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshotdb
备份etcd到Minio对象存储
#!/bin/sh
# bootstrap.sh
export ETCDCTL_API=3
MASTER_ENDPOINT=$(etcdctl --endpoints=$ETCD_ENDPOINTS \
--cacert=/etc/ssl/etcd/ca.crt \
--cert=/etc/ssl/etcd/etcd.crt \
--key=/etc/ssl/etcd/etcd.key \
endpoint status \
| awk -F ',' '{printf("%s %s\n", $1,$5)}' \
| tr -s ' ' | awk '/true/{print $1}')
echo "etcd master endpoint is ${MASTER_ENDPOINT}"
BACKUP_FILE=etcd-backup-$(date +%Y%m%d%H%M%S).db
etcdctl --endpoints=$MASTER_ENDPOINT \
--cacert=/etc/ssl/etcd/ca.crt \
--cert=/etc/ssl/etcd/etcd.crt \
--key=/etc/ssl/etcd/etcd.key \
snapshot save $BACKUP_FILE
aws --endpoint $S3_ENDPOINT s3 cp $BACKUP_FILE s3://$BUCKET_NAME
for f in $(aws --endpoint $S3_ENDPOINT \
s3 ls $BUCKET_NAME | head -n "-${KEEP_LAST_BACKUP_COUNT}" \
| awk '{print $4}'); do
aws --endpoint $S3_ENDPOINT s3 rm s3://$BUCKET_NAME/$f
done
首先获取master节点的endpoint,然后通过master endpoint创建etcd快照。快照生成后通过aws s3命令拷贝到远端对象存储中,最后会删除一些老的备份,只保留指定数量的备份数量
做成docker镜像:Dockerfile
FROM python:alpine
ARG ETCD_VERSION=v3.4.3
RUN apk add --update --no-cache ca-certificates tzdata openssl
RUN wget https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz \
&& tar xzf etcd-${ETCD_VERSION}-linux-amd64.tar.gz \
&& mv etcd-${ETCD_VERSION}-linux-amd64/etcdctl /usr/local/bin/etcdctl \
&& rm -rf etcd-${ETCD_VERSION}-linux-amd64*
RUN pip3 install awscli
ENV ETCDCTL_API=3
ADD bootstrap.sh /
RUN chmod +x /bootstrap.sh
CMD ["/bootstrap.sh"]
把etcd的证书以及Minio的AKSK存储到Kubernetes Secret中
#!/bin/bash
kubectl create secret generic etcd-tls -o yaml \
--from-file /etc/kubernetes/pki/etcd/ca.crt \
--from-file /etc/kubernetes/pki/etcd/server.crt \
--from-file /etc/kubernetes/pki/etcd/server.key \
| sed 's/server/etcd/g'
kubectl create secret generic s3-credentials \
-o yaml --from-file ~/.aws/credentials
通过Kubernetes自带内置的cronjob实现定时备份
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: etcd-backup
namespace: etcd-backup
spec:
jobTemplate:
metadata:
name: etcd-backup
spec:
template:
spec:
containers:
- image: etcd-backup:v3.4.3
imagePullPolicy: IfNotPresent
name: etcd-backup
volumeMounts:
- name: s3-credentials
mountPath: /root/.aws
- name: etcd-tls
mountPath: /etc/ssl/etcd
- name: localtime
mountPath: /etc/localtime
readOnly: true
env:
- name: ETCD_ENDPOINTS
value: "192.168.1.1:2379,192.168.1.2:2379,192.168.1.3:2379"
- name: BUCKET_NAME
value: etcd-backup
- name: S3_ENDPOINT
value: "http://192.168.1.53"
- name: KEEP_LAST_BACKUP_COUNT
value: "7"
volumes:
- name: s3-credentials
secret:
secretName: s3-credentials
- name: etcd-tls
secret:
secretName: etcd-tls
- name: localtime
hostPath:
path: /etc/localtime
restartPolicy: OnFailure
schedule: '0 0 * * *'
每天0点对etcd进行备份到Minio对象存储
参考资料:
restic: https://restic.readthedocs.io/en/latest/010_introduction.html
https://github.com/restic/restic/releases
Velero: https://velero.io/docs/
Stash: https://stash.run/
backing-up-an-etcd-cluster: https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/#backing-up-an-etcd-cluster