本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Kubernetes环境中,数据备份与恢复至关重要。Velero作为开源的集群资源备份与迁移工具,结合兼容S3 API的高性能对象存储Minio,可构建安全可靠的云原生备份系统。本“velero-install”安装脚本集成自动化部署流程,涵盖环境配置、Minio服务部署、Velero安装与认证设置、存储对接及功能验证等步骤,帮助用户快速在Kubernetes集群中实现数据保护机制。适用于需要高效、可扩展备份策略的企业级应用场景。

Velero与Minio:构建云原生环境下的高可用备份体系

在现代云原生架构中,Kubernetes集群的动态性、弹性伸缩和微服务化带来了前所未有的运维复杂度。而在这背后,一个常常被忽视但至关重要的问题浮出水面: 当整个集群因误操作、硬件故障或网络分区而“消失”时,我们能否在最短时间内恢复业务?

这并不是假设——现实中已有太多企业因为缺乏有效的灾难恢复机制,导致数据库丢失、配置错乱、应用不可用,最终造成数小时甚至数天的服务中断。尤其是在金融、医疗、制造等关键行业,这种停机成本是无法承受的。

正是在这种背景下, Velero + Minio 的组合应运而生 ,成为当前云原生存储保护的事实标准之一。它们不是简单的“备份工具+存储后端”,而是构成了一套完整、可编程、自动化程度高的数据生命周期管理方案。


从零开始理解对象存储的本质

要真正掌握这套体系,我们必须先搞清楚一个问题:为什么不能直接把备份文件存在本地磁盘或者NFS共享目录里?

答案很简单: 可扩展性、一致性和解耦能力不足

想象一下,你有一个运行着上百个微服务的K8s集群,每天生成TB级别的日志和状态数据。如果把这些都集中存到某个节点的本地路径上,一旦那个节点宕机,备份就没了;如果用NFS,又面临单点瓶颈和性能下降的问题。

于是, 对象存储(Object Storage) 成为了更优选择。

它不像传统文件系统那样依赖目录树结构,也不像块存储那样需要挂载设备。它的核心模型非常朴素:

桶(Bucket) → 对象(Object)

每个对象由三部分组成:
- Key :唯一标识符(比如 backups/prod-cluster/2025-04-05.tar.gz
- Data :任意大小的数据体
- Metadata :自定义元信息(如创建时间、加密方式、内容类型)

这个模型天生适合HTTP协议传输,支持无限水平扩展,并且可以通过API进行精细控制——完美契合了云原生系统的松耦合特性。

文件系统 vs 块存储 vs 对象存储:一场根本性的范式转移

特性 文件系统 块存储 对象存储
访问方式 POSIX 接口 SCSI/iSCSI HTTP/REST API
数据单位 文件 扇区(512B~4KB) 对象(任意大小)
扩展性 垂直扩展为主 困难 水平扩展良好
元数据能力 有限 极少 可自定义丰富元数据
适用场景 应用程序本地存储 数据库裸设备 备份归档、静态资源

看到没? 对象存储的优势不在于“更快”,而在于“更稳、更灵活、更容易自动化” 。尤其是对于备份这类写一次、读很少的操作来说,它的性价比极高。


Minio:轻量级S3兼容存储的王者之选 🏆

说到私有化部署的对象存储,Minio 几乎是绕不开的名字。它开源、高性能、极易部署,最重要的是—— 完全兼容 Amazon S3 协议

这意味着什么?意味着你可以用 AWS CLI、boto3、rclone 等几乎所有主流工具无缝对接 Minio,就像在使用真正的 AWS S3 一样!

但这背后的实现原理到底是什么?它是怎么做到“伪装成AWS”的?

分布式架构设计:纠删码才是真正的容灾利器 💡

Minio 的分布式模式采用了去中心化的联邦架构,没有主从之分,所有节点地位平等。当你上传一个文件时,Minio 并不会完整地复制多份,而是使用 纠删码(Erasure Coding) 技术将数据切分成 N 个数据块 + M 个校验块。

举个例子,在一个 4 节点集群中配置 EC:4(即 4+4),原始文件会被拆成 8 份,分别写入不同节点。只要任意 4 个节点存活,就能重建原始数据。

这就带来了惊人的容错能力——即使一半节点宕机,数据依然安全!而且相比 RAID 或副本复制,存储利用率提升了整整一倍。

写入流程揭秘:从客户端请求到数据落盘
graph TD
    A[客户端发起 PUT 请求] --> B{Minio Server 接收请求}
    B --> C[解析 Bucket 和 Object Key]
    C --> D[检查命名空间是否存在]
    D --> E[执行前置钩子: 权限验证]
    E --> F[数据进入内存缓冲区]
    F --> G[应用纠删编码算法 (Erasure Coding)]
    G --> H[生成 N 个数据块 + M 个校验块]
    H --> I[并行写入后端磁盘阵列]
    I --> J[所有块写入成功?]
    J -->|是| K[返回 200 OK 给客户端]
    J -->|否| L[触发修复机制, 记录错误日志]

整个过程几乎是实时完成的。你可能觉得“编码→分发”会拖慢速度,但实际上由于并发写入多个磁盘,整体吞吐量反而更高!

✅ 小贴士:建议至少使用 4 节点部署以启用纠删码。低于此数量则只能做镜像复制(类似RAID1),浪费空间。


高可用是怎么炼成的?无需ZooKeeper也能自愈!

很多分布式系统依赖 etcd 或 ZooKeeper 来做协调,但 Minio 不需要。它是怎么实现节点发现和健康检测的?

秘密就在于 gossip 协议

每个 Minio 实例都会定期广播自己的状态给其他成员,同时监听对方的心跳。如果连续几次收不到某个节点的消息,就把它标记为离线。整个过程去中心化,没有任何单点风险。

更酷的是,Minio 支持跨区域复制(Cross-Region Replication)。你可以设置一个主集群和一个异地灾备集群,自动同步指定 bucket 的数据。哪怕整个机房断电,另一侧仍然保留完整副本。

启动命令也很简洁:

export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=supersecret123

minio server http://node{1...4}/data/minio \
  --console-address :9001 \
  --address :9000

没错,就这么一行命令,四个节点就能组成一个高可用集群。而且全程只有一个二进制文件,连数据库都不需要!⚡️


S3兼容性:不只是接口模拟,更是生态打通 🔌

Minio 最强大的地方,其实是它对 S3 生态的深度兼容。

下面这些接口它都能原生支持:

S3 API 方法 功能描述 Minio 实现情况
PUT /{bucket}/{key} 上传对象 ✅ 完全支持
GET /{bucket}/{key} 下载对象 ✅ 支持断点续传
LIST /{bucket}?prefix= 列出对象 ✅ 支持分页与前缀过滤
DELETE /{bucket}/{key} 删除对象 ✅ 支持批量删除
HEAD /{bucket}/{key} 获取元数据 ✅ 支持
POST /{bucket} 初始化多部分上传 ✅ 支持大文件分段上传

甚至连签名机制都严格遵循 AWS v4 标准。这意味着:

任何使用 AWS SDK 编写的程序,只需改个 endpoint,就能连接 Minio!

来看一段 Python 示例:

import boto3
from botocore.config import Config

# 配置连接参数
s3_client = boto3.client(
    's3',
    endpoint_url='http://minio.example.com:9000',
    aws_access_key_id='minio-access-key',
    aws_secret_access_key='minio-secret-key',
    config=Config(signature_version='s3v4'),
    region_name='us-east-1'
)

# 创建桶
s3_client.create_bucket(Bucket='backup-data')

# 上传文件
with open('/tmp/velero-backup.tar.gz', 'rb') as f:
    s3_client.upload_fileobj(f, 'backup-data', 'velero/2025-04-05.tar.gz')

是不是毫无违和感?🤯 这就是标准化的力量。


在Kubernetes中部署Minio:StatefulSet才是正道!

虽然理论上可以用 Deployment 部署 Minio,但在生产环境中这是极其危险的做法。

为什么?

因为 Minio 是典型的 有状态服务 :它依赖稳定的网络标识、持久化的存储路径以及有序的启动顺序。而 Deployment 提供的是无状态副本集管理,Pod 名称随机、IP 不固定、重启后数据丢失……这些问题足以让备份系统变成“笑话”。

所以,正确的姿势是使用 StatefulSet

StatefulSet 的三大法宝:稳定身份、有序部署、PVC模板

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minio-cluster
  namespace: storage
spec:
  serviceName: minio-headless
  replicas: 4
  selector:
    matchLabels:
      app: minio
  template:
    metadata:
      labels:
        app: minio
    spec:
      containers:
        - name: minio
          image: minio/minio:RELEASE.2025-04-01T00-00-00Z
          args:
            - server
            - http://minio-cluster-{0...3}.minio-headless.storage.svc.cluster.local/data
          env:
            - name: MINIO_ROOT_USER
              value: "admin"
            - name: MINIO_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: minio-credentials
                  key: password
          ports:
            - containerPort: 9000
          volumeMounts:
            - name: data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 100Gi
        storageClassName: fast-ssd

注意这里的几个关键点:

  • serviceName: minio-headless :指向一个 Headless Service,确保每个 Pod 有独立 DNS 名称(如 minio-cluster-0.minio-headless.storage.svc.cluster.local
  • volumeClaimTemplates :动态生成 PVC,每个 Pod 绑定专属 PV,避免争抢同一块磁盘
  • 使用 Secret 存储密码,防止明文泄露
PVC绑定关系可视化
graph LR
    A[StatefulSet: minio-cluster] --> B[minio-cluster-0]
    A --> C[minio-cluster-1]
    A --> D[minio-cluster-2]
    A --> E[minio-cluster-3]

    B --> F[PVC: data-minio-cluster-0]
    C --> G[PVC: data-minio-cluster-1]
    D --> H[PVC: data-minio-cluster-2]
    E --> I[PVC: data-minio-cluster-3]

    F --> J[PV on Node-A]
    G --> K[PV on Node-B]
    H --> L[PV on Node-C]
    I --> M[PV on Node-D]

这种一对一映射的设计,保证了即使某个节点宕机,对应的数据也不会随 Pod 重建而丢失。

再来看看 PVC 状态:

kubectl get pvc -n storage

输出示例:

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
data-minio-cluster-0 Bound pvc-1a2b3c4d-5e6f-7g8h-9i0j-k1l2m3n4o5p6 100Gi RWO fast-ssd 12m
data-minio-cluster-1 Bound pvc-2b3c4d5e-6f7g-8h9i-0j1k-l2m3n4o5p6q7 100Gi RWO fast-ssd 12m

只要你别手贱删掉 PVC,数据就永远安全。👍


Velero:不只是备份,而是一整套声明式数据保护引擎 🛠️

如果说 Minio 是“仓库”,那 Velero 就是“智能物流系统”。它不仅能打包货物(资源清单),还能调度车辆(快照器)、跟踪包裹(CRD状态)、处理异常(恢复策略)。

但它到底是如何工作的?

架构剖析:控制器模式 + 插件化设计 = 强大扩展性

Velero 的核心组件包括:

组件 功能描述
Backup Controller 监听 Backup CR,收集资源清单并上传至对象存储
Restore Controller 监听 Restore CR,下载备份并重建资源
VolumeSnapshotter 处理 PV 数据备份(CSI 或 Restic)
Object Store Plugin 抽象层,对接 S3/GCS/Azure Blob
velero CLI 用户交互入口

其中最关键的是—— 它基于 Kubernetes 自定义资源(CRD)驱动流程

当你执行:

velero backup create my-backup --include-namespaces default

实际上是在集群中创建了一个名为 my-backup Backup 资源:

apiVersion: velero.io/v1
kind: Backup
metadata:
  name: my-backup
  namespace: velero
spec:
  includedNamespaces:
    - default
  storageLocation: default
status:
  phase: Completed
  startTimestamp: "2025-04-05T08:00:00Z"
  completionTimestamp: "2025-04-05T08:02:15Z"

然后 Backup Controller 会监听这个资源的变化,一旦发现新创建,就开始干活。

这种 声明式API + 控制器模式 的设计,使得整个备份过程变得可观测、可审计、可自动化。


备份流程全景图:元数据快照 + 持久卷分离处理

graph TD
    A[用户创建 Backup CR] --> B[Backup Controller监听到新Backup]
    B --> C[查询API Server获取目标资源列表]
    C --> D[过滤排除项(如Secrets、ConfigMaps可选)]
    D --> E[序列化资源为JSON格式]
    E --> F[上传元数据到S3兼容存储]
    F --> G[检查是否启用Restic或CSI快照]
    G --> H{是否包含持久卷?}
    H -->|是| I[调用VolumeSnapshotter进行数据备份]
    H -->|否| J[标记备份完成]
    I --> K[Restic上传文件数据 或 CSI创建快照ID]
    K --> L[记录快照信息至备份元数据]
    L --> M[更新Backup状态为Completed]

可以看到,Velero 把“资源配置”和“实际数据”分开处理:

  • 元数据 :通过 API 获取 Deployment、Service、PVC 等对象的 YAML/JSON 表示,上传到 Minio
  • 数据 :通过 CSI Driver 快照持久卷,或通过 Restic 备份容器内目录

这样做有什么好处?

可移植性强 :你可以在任何 K8s 集群恢复应用,哪怕底层基础设施完全不同
版本兼容好 :备份的是声明而非二进制状态,迁移时更容易适配新版 API
粒度控制灵活 :可以按命名空间、标签、资源类型做过滤


Restic集成:拯救那些无法快照的卷 💣

不是所有 PV 都支持 CSI 快照。比如 hostPath local 类型的卷,或者某些老旧存储插件。

这时候就得靠 Restic ——一个开源的 Go 编写的备份工具,具备去重、压缩、增量备份能力。

Velero 通过 DaemonSet 在每个节点运行 Restic sidecar 容器:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: restic
  namespace: velero
spec:
  selector:
    matchLabels:
      name: restic
  template:
    metadata:
      labels:
        name: restic
    spec:
      serviceAccountName: velero
      containers:
        - name: restic
          image: velero/velero:v1.10.0
          command:
            - /velero
            - restic
            - server

当你给某个 Pod 加上注解:

kubectl annotate pod myapp-pod backup.velero.io/backup-volumes=html-data

Velero 就会在备份时通知该节点上的 Restic 守护进程,把对应 volume 挂载的宿主机路径同步到 Minio。

⚠️ 注意:Restic 备份的是文件内容,不是块设备。因此适用于中小规模数据(<100GB),超大卷建议用 CSI 快照。


CLI工具配置:你的第一道防线 🔑

在正式部署前,必须先装好 velero 客户端工具。

跨平台安装指南(Linux/macOS/Windows)

# Linux x86_64
wget https://github.com/vmware-tanzu/velero/releases/download/v1.10.0/velero-v1.10.0-linux-amd64.tar.gz
tar -xzf velero-v1.10.0-linux-amd64.tar.gz
sudo mv velero-v1.10.0-linux-amd64/velero /usr/local/bin/

macOS 用户也可以用 Homebrew:

brew install velero

建议始终保持 client 与 server 版本一致,避免出现奇怪的兼容性问题。

kubectl插件化:统一命令入口

可以把 velero 重命名为 kubectl-velero ,放进 $PATH

mv /usr/local/bin/velero /usr/local/bin/kubectl-velero
kubectl velero version

从此以后,所有操作都可以走 kubectl 命令树,体验丝滑。

启用自动补全:告别拼写错误

Bash 用户:

source <(velero completion bash)
echo "source <(velero completion bash)" >> ~/.bashrc

Zsh 用户:

velero completion zsh > "${fpath[1]}/_velero"

现在输入 velero back<TAB> 就能自动补全啦~ 😎

关键环境变量设置

export VELERO_NAMESPACE=velero
export AWS_ACCESS_KEY_ID=minioadmin
export AWS_SECRET_ACCESS_KEY=minioadmin
export AWS_ENDPOINT=http://minio.velero.svc:9000

这样后续命令就不需要反复加 --namespace --secret-file 等参数了,特别适合写脚本。


验证与测试:动手才是检验真理的唯一标准 🧪

部署完不代表万事大吉。我们必须亲自跑一遍端到端测试。

第一步:检查核心组件状态

kubectl -n velero get pods

你应该看到类似:

NAME READY STATUS RESTARTS AGE
velero-7b9f68c8b9-xzqk2 1/1 Running 0 5m

如果卡在 ImagePullBackOff ,说明镜像拉取失败;如果是 CrashLoopBackOff ,大概率是认证或endpoint配置错了。

查看日志定位问题:

kubectl -n velero logs deploy/velero --since=5m | grep -iE 'error|fail|panic'

常见坑点:
- 忘记开启 s3ForcePathStyle=true
- 使用 HTTPS 但未提供 CA 证书
- Minio 桶不存在或权限不足

第二步:创建测试应用

apiVersion: v1
kind: Namespace
metadata:
  name: test-app
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: test-app
data:
  config.json: '{"mode": "production"}'
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: test-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
      volumes:
      - name: data
        emptyDir: {}

再写点数据进去:

kubectl exec -n test-app $(kubectl get pod -n test-app -l app=nginx -o jsonpath='{.items[0].metadata.name}') \
  -- sh -c "echo 'backup me' > /usr/share/nginx/html/index.html"

第三步:执行备份

velero backup create test-backup --include-namespaces test-app

查看进度:

velero backup describe test-backup --details

你会看到:
- 资源数量(Deployment、ConfigMap等)
- 是否包含持久卷
- 备份耗时与总大小

还可以设定时任务:

velero schedule create daily-backup --schedule="0 2 * * *" --include-namespaces test-app

相当于每天凌晨两点自动备份。

第四步:模拟灾难并恢复

删掉命名空间:

kubectl delete ns test-app

执行恢复:

velero restore create --from-backup test-backup

等几分钟后检查:

kubectl -n test-app get pods,deploy,cm
curl http://<INGRESS_IP>/index.html

如果返回 backup me ,恭喜你,完整的 DR 流程已打通!🎉


高阶实战:打造企业级数据保护体系 🏗️

多集群异地容灾:双活备份位置配置

你可以定义两个 BackupStorageLocation ,分别指向不同地区的 Minio 集群:

apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
  name: primary-bsl
  namespace: velero
spec:
  provider: aws
  objectStorage:
    bucket: cluster-backups-us-east
    prefix: prod-a
  config:
    s3Url: http://minio-us-east.svc:9000
    region: us-east-1

---
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
  name: secondary-bsl
  namespace: velero
spec:
  provider: aws
  objectStorage:
    bucket: cluster-backups-eu-west
    prefix: prod-a-dr
  config:
    s3Url: http://minio-eu-west.svc:9000
    region: eu-west-1

结合 BackupSync 功能,还能将已有快照同步到远端,实现冷备。

静态数据加密:AES-256 + KMS 密钥轮换

Minio 支持服务器端加密(SSE-S3),可以用 base64 编码的密钥启用:

mc mb myminio/cluster-backups --encrypt-key "cluster-backups=MY-LONG-ENCRYPTION-KEY-BASE64"

推荐搭配 Hashicorp Vault 或 AWS KMS 使用,实现自动密钥轮换和访问审计。

权限最小化:RBAC精细化管控

不要给 Velero 绑定 cluster-admin !应该按需授权:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: velero
  name: velero-restricted-role
rules:
- apiGroups: [""]
  resources: ["secrets", "configmaps"]
  verbs: ["get", "list"]
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets"]
  verbs: ["get", "list"]

绑定到专用 ServiceAccount,降低横向移动风险。


自动化部署脚本:一键初始化备份系统 🤖

手工操作终究繁琐,我们应该把它变成 Infrastructure as Code。

这里是一个典型的 velero-install-main.sh 脚本结构:

#!/bin/bash

# === 变量定义区 ===
VELERO_VERSION="v1.11.0"
MINIO_ENDPOINT="http://minio.minio-system:9000"
BACKUP_BUCKET="cluster-backups"
NAMESPACE="velero"

# === 函数库 ===
check_dependencies() {
  for cmd in kubectl helm mc; do
    if ! command -v $cmd &> /dev/null; then
      echo "ERROR: $cmd is required but not found."
      exit 1
    fi
  done
}

create_credentials_file() {
  cat <<EOF > ./credentials-velero
[default]
aws_access_key_id = $MINIO_ACCESS_KEY
aws_secret_access_key = $MINIO_SECRET_KEY
EOF
}

并通过 trap 和严格模式增强健壮性:

set -euo pipefail
trap 'echo "Error occurred at line $LINENO"' ERR

支持参数化调用:

./velero-install-main.sh \
  --version v1.11.0 \
  --bucket disaster-recovery-bucket \
  --airgap-images-repo internal.registry/velero

甚至可以在 CI/CD 中集成:

stage('Initialize Backup System') {
  steps {
    script {
      sh '''
        export MINIO_ACCESS_KEY=${MINIO_USER}
        export MINIO_SECRET_KEY=${MINIO_PASS}
        ./scripts/velero-install-main.sh \
          --bucket ${BACKUP_BUCKET} \
          --restore-only-mode=false
      '''
    }
  }
}

从此,每次环境重建都有统一的数据保护基线。🛡️


总结:这不是工具组合,而是一种工程哲学 🌟

Velero + Minio 的组合之所以强大,不仅仅是因为它们功能齐全、文档完善,更重要的是——

它代表了一种现代化的基础设施思维:声明式、可编程、自动化、端到端可验证。

在这个体系中:
- 备份不再是“偶尔想起来才做的事”
- 恢复不再是“祈祷奇迹发生”的过程
- 灾难演练变成了日常流水线的一部分

当你某天深夜收到告警说“主集群失联”,却能从容地在备用集群执行一条 velero restore 命令,看着服务一个个重新上线时——你会明白,这才是真正的稳定性。

而这,正是每一个云原生工程师值得追求的目标。🚀

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Kubernetes环境中,数据备份与恢复至关重要。Velero作为开源的集群资源备份与迁移工具,结合兼容S3 API的高性能对象存储Minio,可构建安全可靠的云原生备份系统。本“velero-install”安装脚本集成自动化部署流程,涵盖环境配置、Minio服务部署、Velero安装与认证设置、存储对接及功能验证等步骤,帮助用户快速在Kubernetes集群中实现数据保护机制。适用于需要高效、可扩展备份策略的企业级应用场景。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

更多推荐