# Velero 入门
## 介绍
Velero(前身为 Heptio Ark)提供了备份和恢复 Kubernetes 集群资源和持久卷的工具。可以使用公共云平台或本地运行 Velero。
Velero 主要功能:
* 备份集群并在丢失时恢复。
* 将集群资源迁移到其他集群。
* 将生产集群复制到开发和测试集群。
Velero 包括以下两块:
* 在您的集群上运行的服务器
* 本地运行的命令行客户端
参考阅读:
* [关于 Heptio 的冷知识](https://blogs.vmware.com/china/2019/02/21/%e5%85%b3%e4%ba%8e-heptio-%e7%9a%84%e5%86%b7%e7%9f%a5%e8%af%86/)
* [Velero 官方文档](https://velero.io/docs/v1.8/)
## 说明
首先本文是一个入门文档,内容相对不会太深入,至于涉及存储和特殊资源的备份和恢复问题,还需要待实际验证后分享。
## 环境搭建
### 工具安装
```bash=
# 安装下载工具 hd
curl -L https://github.com/linuxsuren/http-downloader/releases/latest/download/hd-linux-amd64.tar.gz | tar xzv hd
mv hd /usr/bin/hd
hd install vmware-tanzu/velero
hd install rancher/k3d # 用于搭建和模拟 Kuberentes 环境
hd install kubernetes-sigs/kubectl
hd install kubernetes-sigs/kustomize@kustomize/v4.5.5
```
参考资料:
* [hd 命令](https://github.com/LinuxSuRen/http-downloader)
**注**:搭建测试环境可以参考 [Docker 环境安装](https://github.com/DevopsChina/lab/blob/main/ci/lab03-jenkins/README.md#2-%E7%8E%AF%E5%A2%83%E5%AE%89%E8%A3%85) 文章里的内容。
### 准备环境
#### 1. 安装 minio 环境
```bash=
alias docker-compose='docker compose'
mkdir -p /data/opsbox-dev/{system,data}/minio/
cd /data/opsbox-dev/system/minio
cat > docker-compose.yml<<EOF
version: '3'
services:
minio:
container_name: minio
image: registry.cn-hangzhou.aliyuncs.com/k8ops/minio:RELEASE.2021-08-05T22-01-19Z
restart: unless-stopped
volumes:
- ./data:/data
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: rootroot
MINIO_ROOT_PASSWORD: rootroot123
command: server /data --console-address ":9001"
EOF
# 注意这里要给一个回车键
# 拉取镜像
docker-compose pull
# 启动服务
docker-compose up -d
# 检查服务
docker-compose ps
# 查看日志
docker-compose logs -f
```
访问 minio dashboard 并创建 bucket `velero`

#### 2. 搭建两个 Kubernete 集群
参考:[如何在5分钟之内搭建好一套Kubernetes测试环境?]
下面是整理的主要命令
```bash=
mkdir /data/opsbox-dev/system/k3s-clusters
cd /data/opsbox-dev/system/k3s-clusters
# 1. 创建代理镜像
# 由于k3d创建registry的命令不支持配置proxy参数,所以需要手动创建一个镜像
cat >Dockerfile<<EOF
FROM registry:2
ENV REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io
EOF
docker build -t registry2:proxy .
# 2. 创建代理 registry
k3d registry create mirror-registry --port 12345 --image registry2:proxy
# 3. 创建代理映射配置
cat >registry.yaml <<EOF
mirrors:
"docker.io":
endpoint:
- http://k3d-mirror-registry:5000
EOF
# 4. 创建本地镜像 registry
k3d registry create oes-registry --port 12346
k3d registry list
# 5. 创建集群
k3d cluster create oes-exia --registry-use k3d-oes-registry:12345 --registry-config ./registry.yaml
k3d cluster create oes-dynamis --registry-use k3d-oes-registry:12345 --registry-config ./registry.yaml
docker network connect k3d-oes-exia k3d-mirror-registry
docker network connect k3d-oes-dynamis k3d-mirror-registry
```

验证环境
```bash=
export KUBECONFIG=$(k3d kubeconfig write oes-exia)
kubectl get pod -A
export KUBECONFIG=$(k3d kubeconfig write oes-dynamis)
kubectl get pod -A
```

#### 3. 部署 velero 环境
```bash
mkdir -p /data/opsbox-dev/system/velero
cd /data/opsbox-dev/system/velero
cat >./credentials-velero<<EOF
[default]
aws_access_key_id = rootroot
aws_secret_access_key = rootroot123
EOF
# 切换集群并安装 velero 服务端
export KUBECONFIG=$(k3d kubeconfig write oes-exia)
velero install \
--image velero/velero:v1.6.0 \
--provider aws \
--bucket velero \
--namespace velero \
--secret-file ./credentials-velero \
--velero-pod-cpu-request 200m \
--velero-pod-mem-request 200Mi \
--velero-pod-cpu-limit 1000m \
--velero-pod-mem-limit 1000Mi \
--use-volume-snapshots=false \
--use-restic \
--restic-pod-cpu-request 200m \
--restic-pod-mem-request 200Mi \
--restic-pod-cpu-limit 1000m \
--restic-pod-mem-limit 1000Mi \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://192.168.2.220:9000/ \
--plugins velero/velero-plugin-for-aws:v1.2.0
export KUBECONFIG=$(k3d kubeconfig write oes-dynamis)
# 重新执行一次上面的 `velero install` 命令
# 检查 Pod 是否已经进入运行状态。
kubectl get pod -A
# 查看日志
kubectl logs deployment/velero -n velero
```
注意: 参数 `--bucket velero` 一定是在 minio 中创建好的 bucket。
## Velero 命令使用
### 1. backup 使用
1. **创建备份**
```bash
velero backup create <name> \
--include-namespaces <namespace1>,<namespace2> \
--include-resources='deployments.app,services'
# 列出所有备份
velero backup get
# 查看 <name> 备份的详细信息
velero backup describe <name>
# 查看 <name> 备份执行日志
velero backup logs <name>
```
2. **创建定时任务类型备份**
schedule 和 backup 是有区别的,所以相关命令的参数结构上是有区别的,比如:`--from-backup` 和 `--from-schedule`
```bash
velero schedule create <name> \
--schedule="* */1 * * *"
--include-namespaces <namespace> \
--include-resources=''
# 列出所有备份
velero schedule get
# 查看 <name> 备份的详细信息
velero schedule describe <name>
# 查看 <name> 备份执行日志
velero schedule logs <name>
```
参考资料:
* [Cron Wiki](https://en.wikipedia.org/wiki/Cron)
### 2. restore 使用
创建恢复
```bash=
velero restore create --from-backup <backup-name> --wait \
--include-namespace <ns1>,<ns2> \
--include-resources "Endpoints,Service,Ingresses"
# 列出所有备份
velero restore get
# 查看 <name> 备份的详细信息
velero restore describe <name>
# 查看 <name> 备份执行日志
velero restore logs <name>
```
### 3. uninstall 使用
这个命令简单但是也很重要,当出现安装配置错误需要删除重建时特别有用。
```bash=
velero uninstall
```
## 实操案例
实操案例比较简单,选取了一个 helloworld 服务来部署,主要模拟以下几种场景:
首先下载测试代码
```bash=
mkdir -p /tmp/helloworld
cd /tmp/helloworld
git clone https://github.com/kubernetes-sigs/kustomize.git
cd kustomize/examples/helloWorld/
```
### 1. 命名空间被删除的恢复场景
系统管理员或者其他开发者无意删除命名空间导致环境不可用,如何快速恢复。
```bash=
# 1. 切入 exia 环境,作为本次演示环境
export KUBECONFIG=$(k3d kubeconfig write oes-exia)
# 2. 查看当前备份情况
velero backup get
# 3. 部署 helloworld 环境
kubectl create ns helloworld
kustomize build . | kubectl apply -n helloworld -f -
kubectl get all -n helloworld
# 4. 创建备份,只备份 helloworld 空间所有内容
velero backup create helloworld --include-namespaces helloworld
velero backup get
# 5. 下载备份,检查里面的内容
velero backup download helloworld
```

恢复测试
```bash=
# 1. 模拟删除命名空间
kubectl get ns
kubectl delete ns helloworld
kubectl get all -n helloworld
velero backup get
# 2. 创建恢复 ConfigMap 资源,并检查
velero restore create --from-backup helloworld helloworld-cm --wait --include-namespaces helloworld --include-resources ConfigMaps
kubectl get cm -n helloworld
velero restore logs helloworld-cm
# 3. 创建恢复 整个命名空间资源,并检查
velero restore create --from-backup helloworld helloworld-all --wait --include-namespaces helloworld
kubectl get all -n helloworld
```


**注意**:这里的 LoadBalancer 没有恢复,这块还要验证。
### 2. 命名空间复制场景
测试环境不够用,想快速复制一套测试环境,或者想复制一套生产环境到测试环境中复现问题。
```bash=
# 因为备份没有被删除,直接将备份恢复到其他命名空间即可
velero backup get
velero restore get
# 通过 restore 命令恢复到 helloworld-test1 命名空间下
velero restore create --from-backup helloworld helloworld-test1 --wait --include-namespaces helloworld --namespace-mappings helloworld:helloworld-test1 --include-resources ConfigMaps
kubectl get cm -n helloworld-test1
```

注意:通过 `--namespace-mappings helloworld:helloworld-test1` 实现。
### 3. 跨集群迁移场景
当需要将多个集群进行合并时,比如:将集群 A 的一套服务合并到集群 B 时。
这个演示需要用到两个集群,exia 和 dynamis
```bash=
export KUBECONFIG=$(k3d kubeconfig write oes-exia)
velero backup get
velero restore get
```
```bash=
export KUBECONFIG=$(k3d kubeconfig write oes-dynamis)
velero backup get
velero restore get
```

通过上图可以看出,多个集群只会同步 backup 不会同步 restore 记录。
在 dynamis 集群中恢复 helloworld 这套服务,可以修改命名空间。
```bash=
# 通过 restore 命令恢复到 helloworld-test1 命名空间下
velero restore create --from-backup helloworld helloworld-test1 --wait --include-namespaces helloworld --namespace-mappings helloworld:helloworld-test1 --include-resources ConfigMaps
kubectl get cm -n helloworld-test1
```

### 4. 集群备份场景
常用的 kubernetes 备份是通过备份 etcd 服务就可以了,而且每个安装工具的备份都不一样。
通过 `velero schedule` 可以轻松实现所有类型集群统一一种方式备份。
```bash=
export KUBECONFIG=$(k3d kubeconfig write oes-dynamis)
velero schedule create helloworld-test1-job --schedule '*/5 * * * *' --include-namespaces helloworld-test1 --ttl 24h0m0s
```

通过上图可以看出 velero 是通过 schedule 定时自动创建 backup,让后在每个集群中同步。
# 最后
最近的工作就是小集群资源整合和迁移服务,迁移前需要梳理和清理集群相关配置,迁移后也需要稍稍调整配置适应新集群等。工具只是辅助可以帮助提升效率,迁移过程还需要看实际场景灵活使用。