MINIO 与 Velero 部署使用文档网上有不少,对于安装,执行备份命令这部分都没什么问题,但是很少涉及K8S pod volume的备份存储与清理这部分,在实际使用中会遇到一些坑,因此我补充了一些备份过程中的细节,同时增加了docker备份的使用部分,希望能帮到需要的同学。

--------------------- 原创不易,如果大家看完觉得有帮助,希望能多多点赞关注,感谢各位的支持 ----------------------

环境

  • K8S 1.27. 6
  • MINIO docker 容器部署,镜像:quay.io/minio/minio
  • Velero 1.13.1

部署安装

MINIO

MINIO的部署安装比较简单,网上有很多,这里不做过多描述,直接上docker compose部署文件

version: '3'

# minio docker compose 部署容器文件
# 
services:
  minio-01:
    container_name: minio-01
    restart: always # always | on-failure | unless-stopped | no
    image:  quay.io/minio/minio
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4000M
        reservations:
          cpus: '0.5'
          memory: 1000M
    ports:
      - 9000:9000
      - 9001:9001
    environment:
      - MINIO_JAVA_OPTS="-Xms3g -Xmx3g"
      - MINIO_PROMETHEUS_AUTH_TYPE=public
      - MINIO_ROOT_USER=${admin-user}
      - MINIO_ROOT_PASSWORD=${pass_word}
    entrypoint: 
      - /bin/sh
      - -c
      - |
        /usr/bin/docker-entrypoint.sh server --address ":9000" --console-address ":9001"  \
        /data
      
    volumes:
      - /minio/data:/data

说明 :

  • 尽量不要使用默认端口,之前minio有暴出严重安全漏洞(新版本已处理),面对漏洞虽说改个端口作用不是特别大,不过总比让人直接按默认扫出来强,为了方便说明,这里仍使用默认端口作为示例
  • MINIO默认JVM 1G,如有需要可以使用 MINIO_JAVA_OPTS 调整,这里我加大了,提高一些处理吞吐能力同时限制了容器最大资源使用量。
  • 初始密码不要包含$字符
  • MINIO服务需要与K8S,Docker服务器时间保持一致,最好通过时钟同步来处理。

创建BACKUP存储桶与操作账号

  • 访问 http://${minio-server.ip}:9001 使用配置在docker compose 部署yaml文件中的初始账号登录MINIO,创建存储桶 k8s-backup, docker-backup
  • 新建账号 velero ( 菜单 identity > users) ,
  • 创建velero 的 Access Keys (用于velero以及MINIO客户端 访问 MINIO api 进行备份操作)
  • 给velero 配置访问策略Policies以限制其只能操作存储桶 k8s-backup, docker-backup
    Policies 示例(这应该是 AWS S3 对象存储的访问策略配置规则,MINIO是兼容S3做的 )
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:ListBucket",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:GetBucketLocation",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::docker-backup/*",
                "arn:aws:s3:::k8s-backup/*"
            ]
        }
    ]
}

更完善的方式是建立GROUP backup-user,配置GROUP的Policies,然后将用户velero 添加到backup-user GROUP中,这里为了简单演示,稍微简化一下。

Velero

安装客户端
mkdir /opt/velero
cd  /opt/velero
wget  https://github.com/vmware-tanzu/velero/releases/download/v1.13.1/velero-v1.13.1-linux-amd64.tar.gz
tar -zxvf velero-v1.13.1-linux-amd64.tar.gz
cd velero-v1.13.1-linux-amd64
cp velero /usr/local/bin/

测试:velero version

安装服务端
  • 使用MINIO用户velero的access-key 生成MINIO api 访问鉴权文件
cat >> /opt/velero/.velero-auth.txt <<-'EOF'
[default]
aws_access_key_id = aaaaa
aws_secret_access_key = .........
EOF
  • 在K8S的master节点上执行velero安装
  velero install \
--kubeconfig  /home/${user}/.kube/config \
--provider aws \
--plugins velero/velero-plugin-for-aws:latest \
--use-volume-snapshots=false  \
--uploader-type=restic \
--use-node-agent \
--bucket k8s-backup \
--secret-file /opt/velero/.velero-auth.txt \
--log_file_max_size 512 \
--backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://192.168.3.54:61390

说明

  • kubeconfig 是K8S集群的证书配置,在安装K8S的账号home目录下,因此安装velero也需要使用安装K8S时的账号
  • use-volume-snapshots=false
    uploader-type=restic
    use-node-agent
    想要备份pod的volume这3个安装参数至关重要

use-volume-snapshots=false 有一些csi是不支持卷快照功能的,例如nfs,local,如果使用此等csi需要配置成为false;

uploader-type=restic 使用restic备份技术,将卷内容加密打包存储到bucket中,restic无视csi类型,它支持K8S中的任意volume卷(网上的文档大都比较旧了还在用老参数 --use-restic 实际已经不支持了)

use-node-agent 为了备份local 类型的volume存储必须通过DaemenSet在每个K8S 节点部署velero agent pod才可以,大多文档没有提到这点。

同时这里还能遇到个问题:use-node-agent 默认不会在K8S的master节点上部署,因为master节点上初始自带了污点taint以避免普通容器被调度到该节点,以保证master本身的资源冗余 (自家小集群为了提高设备利用率往往会删除掉该污点),因此如果要备份master节点上的本地存储,要么删除master自带的taint,要么给nodagent的DaemenSet添加该taint

    tolerations:
	  - key: node-role.kubernetes.io/control-plane
	    operator: Exists
	    effect: NoSchedule
	  - key: node-role.kubernetes.io/master
	    operator: Exists
	    effect: NoSchedule
  • backup-location-config region=minio,s3ForcePathStyle=“true”,s3Url=http://192.168.3.54:61390
    bucket k8s-backup
    secret-file /opt/velero/.velero-auth.txt
    设置对象存储仓库信息,存储桶信息,访问鉴权配置,region 是配置时区信息,这里设置minio是以minio的服务器时区为准

  • log_file_max_size 512
    设置velero日志最大限制,单位 M ,因为velero pod有心跳监测的info log,不限制的话,日积月累文件会越来越大

安装完成后,会在k8s集群的namespace:velero 下生成velero服务端pod以及nodagent (每个节点1个)

K8S 备份
  • 如果要备份pod存储的话,需要在pod的anotation中添加
 backup.velero.io/backup-volumes=YOUR_VOLUME_NAME_1,YOUR_VOLUME_NAME_2

大多数文档提都没提。。。就1条命令备份,1条命令恢复就过去了,实际根本没有备份存储数据,只是备份K8S资源信息,恢复后的容器数据都丢了。

可以通过一下命令来添加,注意时pod volumes: 中声明的 存储卷的name 不是pvc的name

kubectl -n foo annotate pod/sample backup.velero.io/backup-volumes=pvc-volume,emptydir-volume
  • 如果使用的本地存储的话,velero 仅支持local类型不支持hostpath类型,可能需要调整pod配置(这条对于已经部署的pod影响挺大的,不过没办法,看官方问题反馈的意思就是 “不想支持" )
  • 如果使用的是第3方的local-path,需要看一下怎么调整,例如我是用的是rancher 的 local-path-provisioner,其默认创建的pvc都是 hostpath的 (我有几句脏话想说…),需要通过调整PVC或者StorageClass中的annotations来指定类型
#PVC
annotations:
  volumeType: <local or hostPath>
  
#StorageClass:
annotations:
  defaultVolumeType: <local or hostPath>

注意:如果StorageClass设置了defaultVolumeType,那么所有的pvc都会适用,如果PVC同时也指定了,会优先使用当前PVC设定的值。

到这里终于可以执行备份了

K8S备份

指定命名空间备份,多个用, 分隔
DATE=`date +%Y%m%d%H%M%S`
velero backup create k8s-backup-devops-tools  --wait --include-namespaces devops-tools --include-cluster-resources=true --kubeconfig /home/$user/.kube/config

加 --wait 会同步等待结果,不加就是异步的,需要自行查询,查询命令会在执行完velero backup create 后给出提示

说明

  • 这里只会备份添加了备份存储anotation的pod的存储
  • 由于resitc是单线程运行,所以如果数据量很大的话,需要等待很长时间(也取决于网速与磁盘性能),目前restic 的默认超时时间是240min即4个小时,可以通过修改K8S集群的velero pod的 container args来调整
kubectl edit deploy velero -n velero

Add - --restic-timeout to spec.template.spec.containers.

###
spec:
  template:
    spec:
      containers:
      - args:
        - --restic-timeout=240m
###
  • 每个backup任务有效期默认30天,30天后会过期删除,但是restic数据不一定会删除,同时可以通过创建bakup时添加 -ttl 参数来指定有效期,如:-ttl 24h 或 -ttl 7d 或 -ttl 360m
定时备份全部资源
  • 可以添加定时任务备份任务,下面示例添加了1个每周3凌晨3点执行的备份任务,有效期7天
DATE=`date +%Y%m%d%H%M%S`
velero schedule create  k8s-full-backup-${DATE}  --wait --include-cluster-resources=true --kubeconfig /home/$user/.kube/config --schedule="0 3 * * 3" -ttl 7d
使用备份恢复

通过备份全部恢复

velero restore create --wait --from-backup=default-backup-xxxx -kubeconfig /home/$user/.kube/config 

通过备份恢复指定namespace 多个用, 分隔

velero restore create --wait --include-namespaces xxxx --from-backup=default-backup-xxxx -kubeconfig /home/$user/.kube/config 

恢复过程中,遇到集群上已存在的资源会自动跳过,同时,恢复后原先绑定固定ip的 service 与 pod的ip 并不会自动恢复成原有的值,service需要删除重建,pod需要修改配置后重启

使用备份迁移

即使用一个集群的备份在另一个集群上做恢复

数据清除
  • 当手动删除无用的备份后,对应的存储桶中的restic备份数据并不会马上删除,按照默认策略,velero 会定时去清理 restic 存储桶中不需要的文件,默认1h
velero backup delete xxxx
  • 当然还是可能出现1小时后,存储桶数据还是没有清除的情况…,这时候就得手动删除,但是千万不要在存储桶中操作删除,要通过velero容器来操作,否则可能造成velero工作异常无法执行备份。

手动处理过程如下:

1.查看对应要清理的仓库(对应创建的backup任务,此时backup任务已经被删除了,但存储仓库对象仍在)对应的url

 velero repo get -o yaml
 #找到对应backup任务的存储仓库(名称会跟backup名相匹配)
  resticIdentifier: s3:http://${ip:port}/${bucket_name}/restic/${name_space}

2.通过 velero pod exec 执行 restic 命令进行清理

kubectl exec -it $velero_pod_name -n velero -- restic prune -r s3:http://${ip:port}/${bucket_name}/restic/${namespace}

$velero_pod_name 对应的是velero部署在K8S的pod name,这里会提示输入密码,其密码存储在 namespace velero 中的secret “velero-repo-credentials” 中,默认密码为 static-passw0rd(细节超多啊,有没有,一步一个坑…)

输入密码后会执行restic 存储清理,执行结果类似:
在这里插入图片描述
到这里K8S,备份,恢复,清理的内容就结束了,接下来是Docker的部分。

使用MINIO备份Docker容器

安装minio client

mkdir /opt/minio_client
cd /opt/minio_client
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
cp ./mc /usr/local/bin 或 /usr/bin

添加minio存储端

mc config host add ${minio_name} http://${ip}:${port} ${access_key_id} ${secret_access_key}
  • ${minio_name} 是要添加的存储端的标识,可以自由填写
  • ip:port 是${minio_name}的访问端地址
  • access_key_id | secret_access_key 是通过客户端访问minio-server的鉴权信息

查看本地配置的存储端

mc config host list

删除存储端

mc config host remove ${minio_name}

其他常用命令

创建bucket

mc mb minio-server/backup

删除bucket

mc rb minio-server/backup

查看bucket

mc ls minio-server

上传文件到bucket中

mc cp xxx minio-server/backup

上传一个目录到bucket中

mc cp /xxx minio-server/backup --recursive

删除bucket文件

mc rm minio-server/backup/xxx.tar

删除bucket中的目录

mc rm minio-server/backup/xxx --recursive --force

docker备份要比K8s简单,主要是2个步骤:

- 将容器导出为tar 不推荐:经测试导出的容器不包含挂载在本地存储上的数据,,也就是说只备份了容器运行环境,本地数据都会丢失!!

改为:直接将需要备份的数据打成tar包,再上传带minio上,然后再覆盖到docker容器对应的本地目录即可

tar -zcf ./xxx.tar.gz ./xxxxx

-使用通过mc添加的MINIO存储仓库,将tar文件上传的minio bucket中

mc cp 备份名.tar ${minio_name}/${bucket_name}

从备份恢复数据

tar -zxvf ./xxxx.tar.gz -C /xxxxxx

直接解压缩tar覆盖,docker容器对应的本地存储目录

可以将备份工作编写程序shell脚本,再添加到系统定时任务中,便可以实现定时备份了。

--------------------- 原创不易,如果大家看完觉得有帮助,希望能多多点赞关注,感谢各位的支持 ----------------------

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐