K8S集群跨云迁移
要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题:
- 各种K8S资源的迁移
- 工作负载所挂载的数据卷的迁移
- 工作负载所使用的镜像的迁移
K8S资源、数据卷的迁移,可以考虑基于Velero项目。镜像仓库的迁移较为简单,可供选择的开源工具包括阿里云的image-syncer、腾讯云的image-transfer。
Velero是一个专注于K8S集群备份与恢复的开源项目,通过备份源集群,并在目标集群进行恢复,即可完成集群的跨云迁移。
Velero由一组运行在被备份/恢复的K8S集群中的服务,外加一个CLI客户端组成。服务端包含若干控制器,这些控制器监听备份、恢复相关的自定义资源(CRD)并进行处理。CLI主要是提供了创建、修改、删除自定义资源的快捷方式,让用户不必编写复杂的YAML。
在Kubernetes故障检测和自愈一文中,我们对Velero做过调研,这三年多时间里,Velero新增加的特性包括:
- 多读写的持久卷不会被重复备份
- 云服务商插件从Velero代码库独立出
- 基于Restic的持久卷备份总是增量的,即使Pod被调度走
- 克隆命名空间(将备份恢复到另外一个命名空间)时自动克隆相关的持久卷
- 支持处理基于CSI驱动创建的持久卷,目前支持的厂商包括AWS、Azure、GCP
- 支持报告备份、恢复的进度
- 支持备份资源的所有API版本
- 支持自动基于Restic进行卷备份(--default-volumes-to-restic)
- 选项restoreStatus,用于定制那些资源的状态会被恢复
- --existing-resource-policy用于修改默认的恢复策略。默认策略时当资源存在时不覆盖(除了ServiceAccount),该选项设置为update,则会更新已存在的资源
- 从1.10开始,支持Kopia,作为Restic的备选。Kopia在备份时消耗的时间较少、在备份数据量很大或者文件数量很多时,Kopia常常有更好的性能
备份分为两种方式:按需备份、周期性备份。它们都是收集(支持过滤)K8S资源并打包上传到存储后端(例如云服务商的对象存储)。
备份的典型流程如下:
- 用户通过命令 velero backup create创建 Backup资源
- 控制器 BackupController监听到新创建的Backup资源,并进行校验
- 校验成功后BackupController开始执行备份操作。默认情况下会为所有持久卷创建快照,使用命令行选项 --snapshot-volumes=false改变此默认行为
- BackupController调用对象存储,上传备份文件
备份资源的时候,Velero使用首选API版本(preferred version)获取和保存资源。举例来说,源API Server中teleport组具有v1alpha1、v1两个版本,其中v1是首选版本,那么Velero备份的时候将使用v1格式存储资源。在恢复的时候,目标集群必须支持teleport/v1版本(但不必是首选版本),这意味着,恢复到和源的版本不同的K8S集群可能会出错,因为API版本会有新增或删除。
备份的时候,可以通过--ttl来指定备份的存留时间。当存留时间到达后,备份中的K8S资源、备份文件、快照、关联的Restore,均被删除。如果删除失败Velero会给Backup对象添加velero.io/gc-failure=REASON标签。
需要注意:Velero基于快照的卷备份,在跨云迁移这一场景下,是没有意义的,不可能把云A生成的快照拿到云T上恢复。
恢复是将先前生成的备份(包括K8S资源 + 数据卷),同步到目标K8S集群的过程。目标集群可以是源集群自身,可以对备份中的资源进行过滤,仅恢复一部分数据。
恢复产生的K8S资源,具有velero.io/restore-name=RESTORE_NAME标签。RESTORE_NAME即Restore资源的名字,默认形式为BACKUP_NAME-TIMESTAMP,TIMESTAMP的默认格式为YYYYMMDDhhmmss。
恢复的典型流程如下:
- 用户通过命令 velero restore create创建 Restore资源
- 控制器 RestoreController监听到新创建的Restore资源,并进行校验
- 校验成功后,RestoreController从对象存储中获取备份的信息,对备份的资源进行一些预处理,例如API版本检查,以保证它们能够在新集群中运行
- 开始逐个资源的进行恢复
默认情况下,Velero不会对目标集群进行任何修改、删除操作,如果某个资源已经存在,它会简单的跳过。设置 --existing-resource-policy=update则Velero会尝试修改已经存在的资源,使其和备份中的同名资源内容匹配。
保存备份信息的对象存储,是Velero的单一数据源(source of truth),也就是说:
- 如果对象存储中具有备份信息,但是K8S API资源中没有对应的Backup对象,那么会自动创建这些对象
- 如果K8S中有Backup对象,但是在对象存储中没有对应信息,那么此Backup会被删除
这一特性也让跨云迁移场景获益 —— 源、目标集群不需要任何直接的关联,云服务商的对象存储服务将作为唯一的媒介。
定义对象存储位置的CRD是 BackupStorageLocation,它可以指向一个桶,或者桶中的某个前缀,Velero备份的元数据数据存放在其中。通过文件系统方式(Restic/Kopia)备份的卷,也存放在桶中。通过快照方式备份的卷的数据,其存储机制是云服务商私有的,不会存放到桶中。
每个Backup可以使用一个BackupStorageLocation。
存储卷快照相关的信息存储存储在 VolumeSnapshotLocation中,由于快照实现技术完全取决于云服务商,因此该CRD的包含的字段取决于对应插件。
每个Backup,对于任何一个Volume Provider,可以使用一个VolumeSnapshotLocation。
Velero提供了一种插件机制,将存储提供者从Velero核心中独立出来。
Velero提供了若干钩子来扩展标准的备份/恢复流程。
备份钩子在备份流程中执行。例如你可以利用备份钩子,在创建快照前,通知数据库刷空内存缓冲。
恢复钩子在恢复流程中执行。例如你可以在应用启动前,通过钩子进行某种初始化操作。
目前最新稳定版本是1.9.5,点击此连接,选择匹配操作系统的压缩包,下载解压,存放velero到$PATH即可。执行下面的命令配置自动提示:
1 |
echo 'source <(velero completion bash)' >>~/.bashrc |
下面的命令实例,展示了如何进行客户端设置:
1 2 3 4 |
# 启用客户端特性 velero client config set features=EnableCSI # 关闭彩色字符输出 velero client config set colorized=false |
使用CLI安装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
velero install # 指定命名空间 --namespace=teleport-system # 支持基于文件系统的卷备份(FSB) --use-node-agent # 默认启用基于文件系统的卷备份,来备份所有Pod卷。缺省行为是必须指定注解才备份 # backup.velero.io/backup-volumes=YOUR_VOLUME_NAME_1,YOUR_VOLUME_NAME_2,... # 如果准备使用FSB作为唯一的卷备份机制,可以开启 # 启用该命令后,如果还想在某次备份时,使用快照备份,使用命令 backup create --snapshot-volumes # 也可以在备份时使用backup create --default-volumes-to-fs-backup,而不是在安装阶段全局性设置 --default-volumes-to-fs-backup # 特性开关,这些开关也会被传递给node-agent --features=EnableCSI,EnableAPIGroupVersions # 设置资源请求/限制。默认值对于1000-资源、100GB-卷的场景足够。如果使用FSB,则可能需要增加资源请求/限制 --velero-pod-cpu-request --velero-pod-mem-request --velero-pod-cpu-limit --velero-pod-mem-limit --node-agent-pod-cpu-request --node-agent-pod-mem-request --node-agent-pod-cpu-limit --node-agent-pod-mem-limit # 在安装阶段,你可以指定一个BackupLocation和SnapshotLocation --provider aws --bucket backups --secret-file ./aws-iam-creds --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 # 如果在安装阶段,不配置BackupLocation,可以不指定--bucket和--provider,同时: --no-default-backup-location # 仅仅生成YAML --dry-run -o yaml |
在安装完毕后,你可以设置默认的 BackupLocation、SnapshotLocation:
1 2 3 4 5 6 7 8 |
velero backup-location create backups-primary \ --provider aws \ --bucket velero-backups \ --config region=us-east-1 \ --default # SnapshotLocation需要为每一个volume snapshot provider设置 velero server --default-volume-snapshot-locations="PROVIDER-NAME:LOCATION-NAME,PROVIDER2-NAME:LOCATION2-NAME" |
在安装完毕后,可以添加额外的volume snapshot provider:
1 2 3 |
velero plugin add registry/image:version # 为此volume snapshot provider配置SnapshotLocation velero snapshot-location create NAME -provider PROVIDER-NAME [--config PROVIDER-CONFIG] |
我们分别在阿里云、腾讯云上创建一个K8S集群,分别作为源、目标集群,并尝试利用Velero将工作负载从源迁移到目标。
到云服务商的控制台创建,这里不赘述具体步骤。
目前K8S集群的主流用法是运行无状态的工作负载。数据库等有状态的基础服务,大多数用户选择使用云平台提供的PaaS产品。这一现状实质上让K8S的迁移变得简单,因为基本不需要考虑数据卷的问题。
这里以一个Nginx的Deployment + Service为例,测试Velero的备份、恢复特性。首先在源集群创建相应K8S资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - image: nginx:1.7.9 name: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: labels: app: nginx name: nginx spec: ports: - port: 80 targetPort: 80 selector: app: nginx type: LoadBalancer |
Leave a Reply