Velero 备份还原 Kubernetes 集群

Velero 备份还原 Kubernetes 集群


每个 Velero 的操作(比如按需备份、计划备份、还原)都是 CRD 自定义资源,Velero 可以备份或还原集群中的所有对象,也可以按类型、namespace 或标签过滤对象。

Velero(https://velero.io)(可以提供备份和还原 Kubernetes 集群资源和持久卷的能力,你可以在公有云或本地搭建的私有云环境安装 Velero,可以为你提供以下能力:

  • 备份集群数据,并在集群故障的情况下进行还原
  • 将集群资源迁移到其他集群
  • 将生产集群复制到开发和测试集群

Velero 包含一个在集群上运行的服务器端和在本地运行的命令行客户端。

1 Velero 介绍

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

1.1 按需备份

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

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

1.2 定时备份

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

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

1.3 备份还原

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

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

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

1.4 备份流程

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

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

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

下面是 Velero 备份的工作原理图:

下面是 Velero 如何恢复工作:

1.5 设置备份过期时间

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

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

1.6 同步对象存储

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

1.7 Velero的特性

Velero 目前包含以下特性:

  • 支持 Kubernetes 集群数据备份和恢复
  • 支持复制当前 Kubernetes 集群的资源到其它 Kubernetes 集群
  • 支持复制生产环境到开发以及测试环境

1.8 Velero组件

Velero 组件一共分两部分,分别是服务端和客户端。

  • 服务端:运行在你 Kubernetes 的集群中
  • 客户端:是一些运行在本地的命令行的工具,需要已配置好 kubectl 及集群 kubeconfig 的机器上

1.9 支持备份存储

  • AWS S3 以及兼容 S3 的存储,比如:Minio
  • Azure BloB 存储
  • Google Cloud 存储
  • Aliyun OSS 存储(github.com/AliyunConta…)

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

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

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

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

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

2 Velero 概述

2.1 适用场景

  • 灾备场景:提供备份恢复k8s集群的能力
  • 迁移场景:提供拷贝集群资源到其他集群的能力(复制同步开发,测试,生产环境的集群配置,简化环境配置)

2.2 与etcd的区别

与 Etcd 备份相比,直接备份 Etcd 是将集群的全部资源备份起来。而 Velero 就是可以对 Kubernetes 集群内对象级别进行备份。除了对 Kubernetes 集群进行整体备份外,Velero 还可以通过对 TypeNamespaceLabel 等对象进行分类备份或者恢复。

3 实践velero备份minio

在我们的示例中,我们将在 Kubernetes 集群中使用 MinIO 作为备份图中所示的“云提供者”。MinIO 是一个使用 S3兼容 API 的对象存储,因此可以用来存储备份的资源。

Velero 使用 Restic 备份 Kubernetes 卷。Restic 是一个快速、安全的文件系统备份程序,其文档可以在这里找到。它的工作方式是扫描卷目录中的文件,然后将这些文件分割成 blobs,然后发送到 MinIO。下面是它如何与 Velero 集成。

必要条件:

  1. 带有 DNS 的 Kubernetes 集群版本1.19至1.23
  2. Velero cli 安装了 https://Velero.io/docs/main/basic-install/(velero 也可以通过 helm 进行安装)

3.1 安装 velero 1.9.0

GitHub:https://github.com/vmware-tanzu/velero/releases

1 下载 1.90

root@master:~# wget https://github.com/vmware-tanzu/velero/releases/download/v1.9.0/velero-v1.9.0-linux-amd64.tar.gz

2 解压

root@master:~# tar xf velero-v1.9.0-linux-amd64.tar.gz 

root@master:~/velero-v1.9.0-linux-amd64# tree 
.
├── examples
│   ├── minio
│   │   └── 00-minio-deployment.yaml    # minio yaml
│   ├── nginx-app                       # 示例 yaml
│   │   ├── base.yaml
│   │   ├── README.md
│   │   └── with-pv.yaml
│   └── README.md
├── LICENSE
└── velero                              # 二进制程序

# 拷贝到 sbin 目录下
root@master:~# cp velero-v1.9.0-linux-amd64/velero /usr/local/sbin/

3 验证命令

root@master:~# velero version
Client:
    Version: v1.9.0
    Git commit: 6021f148c4d7721285e815a3e1af761262bff029
<error getting server version: no matches for kind "ServerStatusRequest" in version "velero.io/v1">

3.2 安装minio

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

3.2.1 K8S 安装方式

1 修改 yaml 编辑 svc 字段

root@master:~/velero-v1.9.0-linux-amd64/examples/minio# vim 00-minio-deployment.yaml 
---
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:
  # ClusterIP is recommended for production environments.
  # Change to NodePort if needed per documentation,
  # but only if you run Minio in a test/trial environment, for example with Minikube.
  type: NodePort
  ports:
    - name: api 
      port: 9000
      targetPort: 9000
      protocol: TCP
    - 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"

由上面资源清淡我们可以看到,在安装minio的时候

MINIO_ACCESS_KEY:minio

MINIO_SECRET_KEY:minio123

service的地址为:http://minio:9000,类型为ClusterIP,我们可以映射为NodePort查看

最后执行了一个job来创建一个名称为:velero/velero的bucket,在创建的时候适应了。

2 部署

root@master:~/velero-v1.9.0-linux-amd64/examples/minio# kubectl apply -f 00-minio-deployment.yaml 
namespace/velero created
deployment.apps/minio created
service/minio created
job.batch/minio-setup created

# 查看 velero NS 下所有资源
root@master:~/velero-v1.9.0-linux-amd64/examples/minio# kubectl get all -n velero 
NAME                         READY   STATUS      RESTARTS   AGE
pod/minio-6db8cd4c55-kcwvl   1/1     Running     0          111s
pod/minio-setup-5pl8n        0/1     Completed   2          7m46s

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                         AGE
service/minio   NodePort   10.96.73.145   <none>        9000:31900/TCP,9001:21365/TCP   7m46s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/minio   1/1     1            1           7m46s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/minio-58fb7cfdc8   0         0         0       7m46s
replicaset.apps/minio-6db8cd4c55   1         1         1       111s

NAME                    COMPLETIONS   DURATION   AGE
job.batch/minio-setup   1/1           18s        7m46s

3 访问 console 地址

http://10.0.0.140:21365 访问 minio 的 console 页面使用 minio 与 minio123 进行登录即可:

![image-20220817220746844](Velero 备份还原 Kubernetes 集群.assets/image-20220817220746844.png)

3.2.2 二进制安装方式

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

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

➜  ~ wget https://dl.minio.io/server/minio/release/linux-amd64/minio 
➜  ~ chmod +x minio 
➜  ~ sudo mv minio /usr/local/bin/ 
➜  ~ minio --version
minio version RELEASE.2022-08-13T21-54-44Z (commit-id=49862ba3470335decccecb27649167025e18c406)
Runtime: go1.18.5 linux/amd64
License: GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
Copyright: 2015-2022 MinIO, Inc.

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

➜  ~ sudo groupadd --system minio 
➜  ~ sudo useradd -s /sbin/nologin --system -g minio minio 

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

➜  ~ sudo chown -R minio:minio /data/ 
➜  ~ sudo chmod 775 /data

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

➜  ~ vi /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 

5 创建 minio 环境文件 /etc/default/minio:

➜  ~ vim /etc/default/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 

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

➜  ~ sudo systemctl daemon-reload 
➜  ~ sudo systemctl start minio 

关于 minio 的更多使用方法可以参考官方文档 https://docs.min.io/ 了解更多。

3.3 安装 velero 服务端

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

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

# 回到 K8S 节点操作
root@master:~# cat > credentials-velero <<EOF
> [default]
> aws_access_key_id = minio
> aws_secret_access_key = minio123
> EOF

velero-plugin-for-aws 插件:支持在 AWS 上运行 Velero

https://github.com/vmware-tanzu/velero-plugin-for-aws

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

  velero install \
     --provider aws \
     --image velero/velero:v1.9.0  \
     --plugins velero/velero-plugin-for-aws:v1.5.0 \
     --bucket velero \
     --secret-file ./credentials-velero \
     --use-volume-snapshots=false \
     --backup-location-config  region=minio,s3ForcePathStyle="true",s3Url=http://10.0.0.140:31900

# ......省略......最后安装完成会出现下面这句提示
Velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero' to view the status.
  • –provider 声明“aws”提供的插件类型
  • –plugins 使用 AWS S3 兼容 API 插件“velero-plugin-for-aws”
Plugin Version Velero Version
v1.5.x v1.9.x
v1.4.x v1.8.x
v1.3.x v1.7.x
v1.2.x v1.6.x
v1.1.x v1.5.x
v1.1.x v1.4.x
v1.0.x v1.3.x
v1.0.x v1.2.0
  • –secret-file 访问对象存储的凭证
  • –use-volume-snapshots Velero 没有适用于云的卷快照插件,因此禁用了创建卷快照
  • –use-restic 使用开源免费备份工具备份和恢复持久卷数据。但是,不支持“hostPath”卷, 该集成补充了 Velero 的备份功能,建议打开
  • –default-volumes-to-restic 允许使用 Restic 备份所有 Pod 卷,前提是需要打开 –use-restic 参数
  • –backup-location-config 备份与存储桶访问相关的配置
  • region 指定地域,minio没有地域之分,所以随便写了个minio
  • s3ForcePathStyle 使用 S3 文件路径格式
  • s3Url 指定s3的地址

3 查看 api 版本

root@master:~# kubectl api-versions | grep velero
velero.io/v1

4 查看 pod

root@master:~# kubectl get pod -n velero 
NAME                      READY   STATUS      RESTARTS   AGE
minio-6db8cd4c55-kcwvl    1/1     Running     0          16h
minio-setup-5pl8n         0/1     Completed   2          16h
velero-679bbddd96-nlt9v   1/1     Running     0          13m\

至此velero就已经全部部署完成。

3.4 测试

velero非常的人性化,在安装包中已经为我们准备好了测试demo,我们可以利用测试demo来进行测试验证。

3.4.1 创建 demo

1 创建

root@master:~# kubectl apply -f velero-v1.9.0-linux-amd64/examples/nginx-app/base.yaml 

2 创建成功

root@master:~# kubectl get all -n nginx-example
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-5c844b66c8-98sgx   1/1     Running   0          3m3s
pod/nginx-deployment-5c844b66c8-cbcf4   1/1     Running   0          3m3s

NAME               TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/my-nginx   LoadBalancer   10.102.111.211   <pending>     80:20134/TCP   3m4s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           3m4s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-5c844b66c8   2         2         2       3m4s

3.4.2 执行备份

# 指定对 nginx-example NS 做备份
root@master:~# velero backup create nginx-backup --include-namespaces nginx-example

# velero backup create nginx-backup 创建备份为 nginx-backup
# --include-namespaces nginx-example 指定包含 nginx-example NS

4 velero 命令

$ velero create backup NAME [flags]

# 剔除 namespace
--exclude-namespaces stringArray                  namespaces to exclude from the backup

# 剔除资源类型
--exclude-resources stringArray                   resources to exclude from the backup, formatted as resource.group, such as storageclasses.storage.k8s.io

# 包含集群资源类型 
--include-cluster-resources optionalBool[=true]   include cluster-scoped resources in the backup

# 包含 namespace
--include-namespaces stringArray                  namespaces to include in the backup (use '*' for all namespaces) (default *)

# 包含 namespace 资源类型
--include-resources stringArray                   resources to include in the backup, formatted as resource.group, such as storageclasses.storage.k8s.io (use '*' for all resources)

# 给这个备份加上标签
--labels mapStringString                          labels to apply to the backup
-o, --output string                               Output display format. For create commands, display the object but do not send it to the server. Valid formats are 'table', 'json', and 'yaml'. 'table' is not valid for the install command.

# 对指定标签的资源进行备份
-l, --selector labelSelector                      only back up resources matching this label selector (default <none>)

# 对 PV 创建快照
--snapshot-volumes optionalBool[=true]            take snapshots of PersistentVolumes as part of the backup

# 指定备份的位置
--storage-location string                         location in which to store the backup

# 备份数据多久删掉
--ttl duration                                    how long before the backup can be garbage collected (default 720h0m0s)

# 指定快照的位置,也就是哪一个公有云驱动
--volume-snapshot-locations strings               list of locations (at most one per provider) where volume snapshots should be stored
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇