Velero备份Kubernetes集群

一、原理:

每个 Velero 的操作(比如按需备份、计划备份、还原)都是 CRD 自定义资源,Velero 可以备份或还原集群中的所有对象,也可以按类型、namespace 或标签过滤对象。Velero 是 Kubernetes 用来灾难恢复的理想选择,也可以在集群上执行系统操作(比如升级)之前对应用程序状态进行快照的理想选择。

1、按需备份

按需备份操作可以将复制的 Kubernetes 对象的压缩文件上传到云对象存储中,也可以调用云环境提供的 API 来创建持久化卷的磁盘快照。我们可以选择指定在备份期间执行的备份 hook,比如你可能需要在拍摄快照之前告诉数据库将其内存中的缓冲区刷新到磁盘。

注意:需要注意的是集群备份并不是严格的原子备份,如果在备份时创建或编辑 Kubernetes 对象,则它们可能不会被包含在备份中,是可能出现这种状况的。

2、定时备份

通过定时操作,我们可以定期备份数据,第一次创建日程表时将执行第一次备份,随后的备份将按日程表指定的间隔进行备份,这些间隔由 Cron 表达式指定。

定时备份保存的名称为 <SCHEDULE NAME>-<TIMESTAMP>,其中 <TIMESTAMP> 格式为 YYYYMMDDhhmmss

3、备份还原

通过还原操作,我们可以从以前创建的备份中还原所有对象和持久卷,此外我们还可以仅还原对象和持久卷的子集,Velero 支持多个命名空间重新映射。例如在一次还原操作中,可以在命名空间 def 下重新创建命名空间 abc 中的对象,或在 456 之下重新创建名称空间 123 中的对象。

还原的默认名称为 <BACKUP NAME>-<TIMESTAMP><TIMESTAMP> 格式为 YYYYMMDDhhmmss,还可以指定自定义名称,恢复的对象还包括带有键 velero.io/restore-name 和值的标签 <RESTORE NAME>

默认情况下,备份存储位置以读写模式创建,但是,在还原期间,可以将备份存储位置配置为只读模式,这将禁用该存储位置的备份创建和删除,这对于确保在还原方案期间不会无意间创建或删除任何备份非常有用。此外我们还可以选择指定在还原期间或还原资源后执行的还原 hook,例如可能需要在数据库应用程序容器启动之前执行自定义数据库还原操作。

4、备份流程

执行命令 velero backup create test-backup 的时候,会执行下面的操作:

  • Velero 客户端调用 Kubernetes APIServer 创建 Backup 这个 CRD 对象
  • Backup 控制器 watch 到新的 Backup 对象被创建并执行验证
  • Backup 控制器开始执行备份,通过查询 APIServer 来获取资源收集数据进行备份
  • Backup 控制器调用对象存储服务,比如 S3 上传备份文件

默认情况下 velero backup create 支持任何持久卷的磁盘快照,可以通过指定其他参数来调整快照,可以使用 --snapshot-volumes=false 选项禁用快照。

 5、设置备份过期时间

创建备份时,可以通过添加标志 --ttl 来指定 TTL,如果未指定,则将默认的 TTL 值为30天,如果 Velero 检测到有备份资源已过期,它将删除以下相应备份数据:

  • 备份资源
  • 来自云对象存储的备份文件
  • 所有 PersistentVolume 快照
  • 所有关联的还原

6、同步对象存储

Velero 将对象存储视为资源的来源,它不断检查以确保始终存在正确的备份资源,如果存储桶中有格式正确的备份文件,但 Kubernetes APIServer 中没有相应的备份资源,则 Velero 会将信息从对象存储同步到 Kubernetes,这使还原功能可以在集群迁移方案中工作,在该方案中,新集群中不存在原始的备份对象。同样,如果备份对象存在于 Kubernetes 中,但不存在于对象存储中,则由于备份压缩包不再存在,它将从 Kubernetes 中删除。

7、备份存储位置和卷快照位置

Velero 有两个自定义资源 BackupStorageLocation 和 VolumeSnapshotLocation,用于配置 Velero 备份及其关联的持久卷快照的存储位置。

  • BackupStorageLocation:定义为存储区,存储所有 Velero 数据的存储区中的前缀以及一组其他特定于提供程序的字段,后面部分会详细介绍该部分所包含的字段。
  • VolumeSnapshotLocation:完全由提供程序提供的特定的字段(例如AWS区域,Azure资源组,Portworx快照类型等)定义。

用户可以预先配置一个或多个可能的 BackupStorageLocations 对象,也可以预先配置一个或多个 VolumeSnapshotLocations 对象,并且可以在创建备份时选择应该存储备份和相关快照的位置。

此配置设计支持许多不同的用法,包括:

  • 在单个 Velero 备份中创建不止一种持久卷的快照。例如,在同时具有 EBS 卷和 Portworx 卷的集群中
  • 在不同地区将数据备份到不同的存储中
  • 对于支持它的卷提供程序(例如Portworx),可以将一些快照存储在本地集群中,而将其他快照存储在云中

二、安装

1、在 Github Release 页面(https://github.com/vmware-tanzu/velero/releases)下载指定的 velero 二进制客户端安装包,比如这里我们下载版本 v1.6.3


[root@localhost ~]# ll
total 27228
-rw-------. 1 root root 1341 Nov 8 18:33 anaconda-ks.cfg
-rw-r--r--. 1 root root 189513 Nov 12 15:07 calico.yaml
drwxr-xr-x. 3 root root 19 Nov 12 14:48 examples
-rw-r--r-- 1 root root 27676260 Nov 15 15:31 velero-v1.7.0-linux-amd64.tar.gz
-rw-r--r--. 1 root root 5274 Nov 8 18:36 youhua.sh
[root@localhost ~]# tar xf velero-v1.7.0-linux-amd64.tar.gz

[root@localhost ~/velero-v1.7.0-linux-amd64]# tree .
.
├── examples
│   ├── minio
│   │   └── 00-minio-deployment.yaml
│   ├── nginx-app
│   │   ├── base.yaml
│   │   ├── README.md
│   │   └── with-pv.yaml
│   └── README.md
├── LICENSE
└── velero

3 directories, 7 files

 2、将根目录下的velero二进制文件拷贝到PATH路径下面

[root@localhost ~/velero-v1.7.0-linux-amd64]# cp velero /usr/local/bin/

[root@localhost ~/velero-v1.7.0-linux-amd64]# chmod +x /usr/local/bin/veler


[root@localhost ~/velero-v1.7.0-linux-amd64]# velero version
Client:
Version: v1.7.0
Git commit: 9e52260568430ecb77ac38a677ce74267a8c2176
<error getting server version: no matches for kind "ServerStatusRequest" in version "velero.io/v1">

3、安装MINIO  

这里我们可以使用 minio 来代替云环境的对象存储,在上面解压的压缩包中包含一个 examples/minio/00-minio-deployment.yaml 的资源清单文件,为了测试方便可以将其中的 Service 更改为 NodePort 类型,我们可以配置一个 console-address 来提供一个 console 页面的访问入口,完整的资源清单文件如下所示:

apiVersion: v1
kind: Namespace
metadata:
  name: velero
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: velero
  name: minio
  labels:
    component: minio
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      component: minio
  template:
    metadata:
      labels:
        component: minio
    spec:
      volumes:
      - name: storage
        emptyDir: {}
      - name: config
        emptyDir: {}
      containers:
      - name: minio
        image: minio/minio:latest
        imagePullPolicy: IfNotPresent
        args:
        - server
        - /storage
        - --config-dir=/config
        - --console-address=:9001
        env:
        - name: MINIO_ACCESS_KEY
          value: "minio"         #登录账号
        - name: MINIO_SECRET_KEY
          value: "minio123"      #登录密码
        ports:
        - containerPort: 9000
        - containerPort: 9001
        volumeMounts:
        - name: storage
          mountPath: "/storage"
        - name: config
          mountPath: "/config"
---
apiVersion: v1
kind: Service
metadata:
  namespace: velero
  name: minio
  labels:
    component: minio
spec:
  type: NodePort
  ports:
    - name: api
      port: 9000
      targetPort: 9000
    - name: console
      port: 9001
      targetPort: 9001
  selector:
    component: minio
---
apiVersion: batch/v1
kind: Job
metadata:
  namespace: velero
  name: minio-setup
  labels:
    component: minio
spec:
  template:
    metadata:
      name: minio-setup
    spec:
      restartPolicy: OnFailure
      volumes:
      - name: config
        emptyDir: {}
      containers:
      - name: mc
        image: minio/mc:latest
        imagePullPolicy: IfNotPresent
        command:
        - /bin/sh
        - -c
        - "mc --config-dir=/config config host add velero http://minio:9000 minio minio123 && mc --config-dir=/config mb -p velero/velero"
        volumeMounts:
        - name: config
          mountPath: "/config"

3、然后直接部署在Kubernetes集群中即可:

[root@localhost ~/examples/minio]# kubectl apply -f 00-minio-deployment.yaml
namespace/velero created
deployment.apps/minio created
service/minio created
job.batch/minio-setup created
[root@localhost ~/examples/minio]# kubectl get pod -n velero
NAME READY STATUS RESTARTS AGE
minio-58dc5cf789-vqpv4     1/1     Running            0 11s
minio-setup-dll8s          0/1     CrashLoopBackOff   1 11s
[root@localhost ~/examples/minio]# kubectl get svc -n velero
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
minio NodePort 10.108.158.129 <none> 9000:30337/TCP,9001:31040/TCP 26s

然后我们可以通过 http://<nodeip>:31040 访问 minio 的 console 页面,使用 minio 与 minio123 进行登录即可:

 当然如果需要在不同 Kubernetes 和存储池集群备份与恢复数据,需要将 minio 服务端安装在 Kubernetes 集群外,保证在集群发生灾难性故障时,不会对备份数据产生影响,可以通过二进制的方式进行安装

 4、在待安装minio的服务器上下载二进制包

[root@localhost ~]# wget https://dl.minio.io/server/minio/release/linux-amd64/minio
[root@localhost ~]# chmod +x minio

[root@localhost ~]# mv minio  /usr/local/bin/
[root@localhost /usr/local/bin]# minio  --version
minio version RELEASE.2021-11-09T03-21-45Z

5、请创建用于运行 minio 服务的用户和组(准备对象存储的磁盘,这里我们跳过该步骤,可以使用 systemd 来方便管理 minio 服务,对于使用 systemd init 系统运行系统的人,)

[root@localhost ~]# groupadd --system minio
[root@localhost ~]# useradd -s /sbin/nologin --system -g minio minio

6、为/data目录提供minio用户所有权,(上述步骤准备好的磁盘挂载位置)

 

[root@localhost ~]# mkdir /data

[root@localhost /]# chown -R minio:minio /data

7、为 minio 创建 systemd 服务单元文件:

[root@localhost ~]# cat /etc/systemd/system/minio.service
[Unit]
Description=Minio
Documentation=https://docs.minio.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
WorkingDirectory=/data
User=minio
Group=minio
EnvironmentFile=-/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
# Let systemd restart this service always
Restart=always
# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536
# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

8、创建minio环境文件/etc/default/minio:

 


[root@localhost /etc/default]# cat minio
# Volume to be used for Minio server.
MINIO_VOLUMES="/data"

# Use if you want to run Minio on a custom port.
MINIO_OPTS="--address :9000"

# Access Key of the server.
MINIO_ACCESS_KEY=minio

# Secret key of the server.
MINIO_SECRET_KEY=minio123

其中 MINIO_ACCESS_KEY 为长度至少为3个字符的访问密钥,MINIO_SECRET_KEY 为最少8个字符的密钥。重新加载 systemd 并启动 minio 服务:

[root@localhost /etc/default]# systemctl daemon-reload
[root@localhost /etc/default]# systemctl start minio

三、安装velero服务端

我们可以使用 velero 客户端来安装服务端,也可以使用 Helm Chart 来进行安装,比如这里我们用客户端来安装,velero 命令默认读取 kubectl 配置的集群上下文,所以前提是 velero 客户端所在的节点有可访问集群的 kubeconfig 配置。

首先准备密钥文件,在当前目录建立一个空白文本文件,内容如下所示:

 

cat credentials-velero 
[default]
aws_access_key_id=minio
aws_secret_access_key=minio123

替换为之前步骤中 minio 的对应 access key id 和 secret access key如果 minio 安装在 kubernetes 集群内时按照如下命令安装 velero 服务端:   上面的是secret文件的内容

velero install    \
     --provider aws   \
     --bucket velero   \
     --image velero/velero:v1.7.0  \
  --plugins velero/velero-plugin-for-aws:v1.2.1  \
  --namespace velero  \
  --secret-file ./credentials-velero  \
  --use-volume-snapshots=false \
     --use-restic \
  --backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://minio.velero.svc:9000

。。。。。。。

DaemonSet/restic: created
Velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero' to view the status.

 

由于我们这里准备使用 minio 来作为对象存储,minio 是兼容 S3 的,所以这里我们配置的 provider(声明使用的 Velero 插件类型)是 aws--secret-file 用来提供访问 minio 的密钥,--use-restic 表示使用开源免费备份工具 restic 备份和还原持久卷数据,启用该参数后会部署一个名为 restic 的 DaemonSet 对象,--plugins 使用的 velero 插件,我们使用 AWS S3 兼容插件。

安装完成后 velero 的服务端就部署成功了。

 

posted @ 2021-11-12 11:02  岁月静好·  阅读(365)  评论(0)    收藏  举报