11.3. 使用命令行迁移应用程序
您可以使用命令行界面 (CLI) 使用 MTC API 迁移应用程序,以便自动执行迁移。
11.3.1. 迁移先决条件
-
必须使用在所有集群中具有
cluster-admin
权限的用户登录。
直接镜像迁移
- 您必须确保源集群的安全 OpenShift 镜像 registry 已公开。
- 您必须创建指向公开 registry 的路由。
直接卷迁移
- 如果您的集群使用代理,您必须配置 Stunnel TCP 代理。
内部镜像
如果应用程序使用
openshift
命名空间中的内部镜像,您必须确保目标集群中存在所需的镜像版本。您可以手动更新镜像流标签,以便在 OpenShift Container Platform 4.16 集群中使用已弃用的 OpenShift Container Platform 3 镜像。
Clusters
- 源集群必须升级到最新的 MTC z-stream 版本。
- 在所有集群中,MTC 版本必须相同。
网络
- 集群在相互间有无限制的网络访问,并可以访问复制存储库。
-
如果您复制有
移动
的持久性卷,集群必须具有对远程卷的不受限制的网络访问权限。 您必须在 OpenShift Container Platform 3 集群中启用以下端口:
-
8443
(API 服务器) -
443
(路由) -
53
(DNS)
-
您必须在 OpenShift Container Platform 4 集群中启用以下端口:
-
6443
(API 服务器) -
443
(路由) -
53
(DNS)
-
-
如果使用 TLS,则必须在复制存储库中启用端口
443
。
持久性卷(PV)
- PV 必须有效。
- PV 必须绑定到持久性卷声明。
如果使用快照复制 PV,则需要满足以下额外先决条件:
- 云供应商必须支持快照。
- PV 必须具有相同的云供应商。
- PV 必须位于同一区域。
- PV 必须具有相同的存储类。
11.3.2. 创建用于直接镜像迁移的 registry 路由
要直接镜像迁移,您必须在所有远程集群中创建指向公开的 OpenShift 镜像 registry 的路由。
先决条件
OpenShift 镜像 registry 必须公开给所有远程集群上的外部流量。
OpenShift Container Platform 4 registry 默认公开。
OpenShift Container Platform 3 registry 必须手动公开。
流程
要创建到 OpenShift Container Platform 3 registry 的路由,请运行以下命令:
$ oc create route passthrough --service=docker-registry -n default
要创建到 OpenShift Container Platform 4 registry 的路由,请运行以下命令:
$ oc create route passthrough --service=image-registry -n openshift-image-registry
11.3.3. 代理配置
对于 OpenShift Container Platform 4.1 及更早的版本,您必须在安装 Migration Toolkit for Containers Operator 后,在 MigrationController
自定义资源 (CR) 清单中配置代理,因为这些版本不支持集群范围的 proxy
对象。
对于 OpenShift Container Platform 4.2 到 4.16,Migration Toolkit for Containers (MTC) 会继承集群范围的代理设置。如果要覆盖集群范围的代理设置,可以更改代理参数。
11.3.3.1. 直接卷迁移
MTC 1.4.2 中引入了直接卷迁移(DVM)。DVM 只支持一个代理。如果目标集群也位于代理后面,则源集群无法访问目标集群的路由。
如果要从代理后面的源集群执行 DVM,您必须配置一个 TCP 代理,该代理可在传输层进行透明处理,并在不使用自己的 SSL 证书的情况下转发 SSL 连接。Stunnel 代理是此类代理的示例。
11.3.3.1.1. DVM 的 TCP 代理设置
您可以通过 TCP 代理在源和目标集群之间设置直接连接,并在 MigrationController
CR 中配置 stunnel_tcp_proxy
变量来使用代理:
apiVersion: migration.openshift.io/v1alpha1 kind: MigrationController metadata: name: migration-controller namespace: openshift-migration spec: [...] stunnel_tcp_proxy: http://username:password@ip:port
直接卷迁移(DVM)只支持代理的基本身份验证。此外,DVM 仅适用于可透明地传输 TCP 连接的代理。在 man-in-the-middle 模式中的 HTTP/HTTPS 代理无法正常工作。现有的集群范围的代理可能不支持此行为。因此,DVM 的代理设置意与 MTC 中常见的代理配置不同。
11.3.3.1.2. 为什么使用 TCP 代理而不是 HTTP/HTTPS 代理?
您可以通过 OpenShift 路由在源和目标集群之间运行 Rsync 来启用 DVM。流量通过 TCP 代理(Stunnel)加密。在源集群上运行的 Stunnel 会启动与目标 Stunnel 的 TLS 连接,并通过加密频道来传输数据。
OpenShift 中的集群范围 HTTP/HTTPS 代理通常在 man-in-the-middle 模式进行配置,其中它们将自己的 TLS 会话与外部服务器协商。但是,这不适用于 Stunnel。Stunnel 要求代理不处理它的 TLS 会话,基本上使代理成为一个透明的隧道,只需按原样转发 TCP 连接。因此,您必须使用 TCP 代理。
11.3.3.1.3. 已知问题
迁移失败并显示 Upgrade request required
错误
迁移控制器使用 SPDY 协议在远程 pod 中执行命令。如果远程集群位于代理或不支持 SPDY 协议的防火墙后,迁移控制器将无法执行远程命令。迁移失败并显示出错信息 Upgrade request required
。临时解决方案: 使用支持 SPDY 协议的代理。
除了支持 SPDY 协议外,代理或防火墙还必须将 Upgrade
HTTP 标头传递给 API 服务器。客户端使用此标头打开与 API 服务器的 websocket 连接。如果代理或防火墙阻止 Upgrade
标头,则迁移会失败,并显示出错信息 Upgrade request required
。临时解决方案:确保代理转发 Upgrade
标头。
11.3.3.2. 为迁移调优网络策略
OpenShift 支持根据集群使用的网络插件,限制使用 NetworkPolicy 或 EgressFirewalls 的流量。如果任何涉及迁移的源命名空间使用此类机制将网络流量限制到 pod,限制可能会在迁移过程中停止到 Rsync pod 的流量。
在源和目标集群上运行的 rsync pod 必须通过 OpenShift Route 相互连接。可将现有的 NetworkPolicy 或 EgressNetworkPolicy 对象配置为从这些流量限制自动排除 Rsync pod。
11.3.3.2.1. NetworkPolicy 配置
11.3.3.2.1.1. 来自 Rsync pod 的出口流量
如果源或目标命名空间中的 NetworkPolicy
配置阻止这种类型的流量,您可以使用 Rsync pod 的唯一标签来允许出口流量从它们传递。以下策略允许来自命名空间中 Rsync pod 的所有出口流量:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-egress-from-rsync-pods spec: podSelector: matchLabels: owner: directvolumemigration app: directvolumemigration-rsync-transfer egress: - {} policyTypes: - Egress
11.3.3.2.1.2. 到 Rsync pod 的入口流量
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-all-egress-from-rsync-pods spec: podSelector: matchLabels: owner: directvolumemigration app: directvolumemigration-rsync-transfer ingress: - {} policyTypes: - Ingress
11.3.3.2.2. EgressNetworkPolicy 配置
EgressNetworkPolicy
对象或 Egress Firewalls 是 OpenShift 构造,用于阻止离开集群的出口流量。
与 NetworkPolicy
对象不同,egress Firewall 在项目级别工作,因为它适用于命名空间中的所有 pod。因此,Rsync pod 的唯一标签不会使只有 Rsync pod 的 Rsync pod 冲突。但是,您可以将源集群或目标集群的 CIDR 范围添加到策略的 Allow 规则中,以便可以在两个集群之间设置直接连接。
根据存在 Egress Firewall 的集群,您可以添加其他集群的 CIDR 范围来允许两者间的出口流量:
apiVersion: network.openshift.io/v1 kind: EgressNetworkPolicy metadata: name: test-egress-policy namespace: <namespace> spec: egress: - to: cidrSelector: <cidr_of_source_or_target_cluster> type: Deny
11.3.3.2.3. 为数据传输选择备用端点
默认情况下,DVM 使用 OpenShift Container Platform 路由作为端点,将 PV 数据传送到目标集群。如果集群拓扑允许,您可以选择其他类型的支持的端点。
对于每个集群,您可以通过在 MigrationController
CR 中适当的 目标集群上设置 rsync_endpoint_type
变量来配置端点:
apiVersion: migration.openshift.io/v1alpha1 kind: MigrationController metadata: name: migration-controller namespace: openshift-migration spec: [...] rsync_endpoint_type: [NodePort|ClusterIP|Route]
11.3.3.2.4. 为 Rsync pod 配置补充组
当 PVC 使用共享存储时,您可以通过将 supplemental 组添加到 Rsync pod 定义来配置对存储的访问,以便 pod 允许访问:
变量 | 类型 | Default(默认) | 描述 |
---|---|---|---|
| string | 未设置 | 用于源 Rsync pod 的以逗号分隔的补充组列表 |
| string | 未设置 | 目标 Rsync pod 的,以逗号分隔的补充组列表 |
用法示例
可以更新 MigrationController
CR,以便为这些补充组设置值:
spec: src_supplemental_groups: "1000,2000" target_supplemental_groups: "2000,3000"
11.3.3.3. 配置代理
先决条件
-
必须使用在所有集群中具有
cluster-admin
权限的用户登录。
流程
获取
MigrationController
CR 清单:$ oc get migrationcontroller <migration_controller> -n openshift-migration
更新代理参数:
apiVersion: migration.openshift.io/v1alpha1 kind: MigrationController metadata: name: <migration_controller> namespace: openshift-migration ... spec: stunnel_tcp_proxy: http://<username>:<password>@<ip>:<port> 1 noProxy: example.com 2
在域前面加
.
来仅匹配子域。例如:.y.com
匹配x.y.com
,但不匹配y.com
。使用*
可对所有目的地绕过所有代理。如果您扩展了未包含在安装配置中networking.machineNetwork[].cidr
字段定义的 worker,您必须将它们添加到此列表中,以防止连接问题。如果未设置
httpProxy
和httpsProxy
字段,则此字段将被忽略。-
将清单保存为
migration-controller.yaml
。 应用更新的清单:
$ oc replace -f migration-controller.yaml -n openshift-migration
11.3.4. 使用 MTC API 迁移应用程序
您可以使用 MTC API 从命令行迁移应用程序。
流程
为主机集群创建一个
MigCluster
CR 清单:$ cat << EOF | oc apply -f - apiVersion: migration.openshift.io/v1alpha1 kind: MigCluster metadata: name: <host_cluster> namespace: openshift-migration spec: isHostCluster: true EOF
为每个远程集群创建一个
Secret
对象清单:$ cat << EOF | oc apply -f - apiVersion: v1 kind: Secret metadata: name: <cluster_secret> namespace: openshift-config type: Opaque data: saToken: <sa_token> 1 EOF
- 1
- 指定远程集群的 base64 编码的
migration-controller
服务帐户(SA)令牌。您可以运行以下命令来获取令牌:
$ oc sa get-token migration-controller -n openshift-migration | base64 -w 0
为每个远程集群创建一个
MigCluster
CR 清单:$ cat << EOF | oc apply -f - apiVersion: migration.openshift.io/v1alpha1 kind: MigCluster metadata: name: <remote_cluster> 1 namespace: openshift-migration spec: exposedRegistryPath: <exposed_registry_route> 2 insecure: false 3 isHostCluster: false serviceAccountSecretRef: name: <remote_cluster_secret> 4 namespace: openshift-config url: <remote_cluster_url> 5 EOF
验证所有集群是否处于
Ready
状态:$ oc describe MigCluster <cluster>
为复制存储库创建
Secret
对象清单:$ cat << EOF | oc apply -f - apiVersion: v1 kind: Secret metadata: namespace: openshift-config name: <migstorage_creds> type: Opaque data: aws-access-key-id: <key_id_base64> 1 aws-secret-access-key: <secret_key_base64> 2 EOF
AWS 凭证默认为 base64 编码。对于其他存储供应商,您必须使用每个密钥运行以下命令来对凭证进行编码:
$ echo -n "<key>" | base64 -w 0 1
- 1
- 指定密钥 ID 或 secret 密钥。这两个密钥都必须都是 base64 编码。
为复制存储库创建一个
MigStorage
CR 清单:$ cat << EOF | oc apply -f - apiVersion: migration.openshift.io/v1alpha1 kind: MigStorage metadata: name: <migstorage> namespace: openshift-migration spec: backupStorageConfig: awsBucketName: <bucket> 1 credsSecretRef: name: <storage_secret> 2 namespace: openshift-config backupStorageProvider: <storage_provider> 3 volumeSnapshotConfig: credsSecretRef: name: <storage_secret> 4 namespace: openshift-config volumeSnapshotProvider: <storage_provider> 5 EOF
验证
MigStorage
CR 是否处于Ready
状态:$ oc describe migstorage <migstorage>
创建一个
MigPlan
CR 清单:$ cat << EOF | oc apply -f - apiVersion: migration.openshift.io/v1alpha1 kind: MigPlan metadata: name: <migplan> namespace: openshift-migration spec: destMigClusterRef: name: <host_cluster> namespace: openshift-migration indirectImageMigration: true 1 indirectVolumeMigration: true 2 migStorageRef: name: <migstorage> 3 namespace: openshift-migration namespaces: - <source_namespace_1> 4 - <source_namespace_2> - <source_namespace_3>:<destination_namespace> 5 srcMigClusterRef: name: <remote_cluster> 6 namespace: openshift-migration EOF
验证
MigPlan
实例是否处于Ready
状态:$ oc describe migplan <migplan> -n openshift-migration
创建一个
MigMigration
CR 清单,以启动MigPlan
实例中定义的迁移:$ cat << EOF | oc apply -f - apiVersion: migration.openshift.io/v1alpha1 kind: MigMigration metadata: name: <migmigration> namespace: openshift-migration spec: migPlanRef: name: <migplan> 1 namespace: openshift-migration quiescePods: true 2 stage: false 3 rollback: false 4 EOF
通过观察
MigMigration
CR 进度来验证迁移:$ oc watch migmigration <migmigration> -n openshift-migration
输出类似于以下:
输出示例
Name: c8b034c0-6567-11eb-9a4f-0bc004db0fbc Namespace: openshift-migration Labels: migration.openshift.io/migplan-name=django Annotations: openshift.io/touch: e99f9083-6567-11eb-8420-0a580a81020c API Version: migration.openshift.io/v1alpha1 Kind: MigMigration ... Spec: Mig Plan Ref: Name: migplan Namespace: openshift-migration Stage: false Status: Conditions: Category: Advisory Last Transition Time: 2021-02-02T15:04:09Z Message: Step: 19/47 Reason: InitialBackupCreated Status: True Type: Running Category: Required Last Transition Time: 2021-02-02T15:03:19Z Message: The migration is ready. Status: True Type: Ready Category: Required Durable: true Last Transition Time: 2021-02-02T15:04:05Z Message: The migration registries are healthy. Status: True Type: RegistriesHealthy Itinerary: Final Observed Digest: 7fae9d21f15979c71ddc7dd075cb97061895caac5b936d92fae967019ab616d5 Phase: InitialBackupCreated Pipeline: Completed: 2021-02-02T15:04:07Z Message: Completed Name: Prepare Started: 2021-02-02T15:03:18Z Message: Waiting for initial Velero backup to complete. Name: Backup Phase: InitialBackupCreated Progress: Backup openshift-migration/c8b034c0-6567-11eb-9a4f-0bc004db0fbc-wpc44: 0 out of estimated total of 0 objects backed up (5s) Started: 2021-02-02T15:04:07Z Message: Not started Name: StageBackup Message: Not started Name: StageRestore Message: Not started Name: DirectImage Message: Not started Name: DirectVolume Message: Not started Name: Restore Message: Not started Name: Cleanup Start Timestamp: 2021-02-02T15:03:18Z Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Running 57s migmigration_controller Step: 2/47 Normal Running 57s migmigration_controller Step: 3/47 Normal Running 57s (x3 over 57s) migmigration_controller Step: 4/47 Normal Running 54s migmigration_controller Step: 5/47 Normal Running 54s migmigration_controller Step: 6/47 Normal Running 52s (x2 over 53s) migmigration_controller Step: 7/47 Normal Running 51s (x2 over 51s) migmigration_controller Step: 8/47 Normal Ready 50s (x12 over 57s) migmigration_controller The migration is ready. Normal Running 50s migmigration_controller Step: 9/47 Normal Running 50s migmigration_controller Step: 10/47
11.3.5. 状态迁移
您可以使用 Migration Toolkit for Containers(MTC)迁移组成应用程序状态的持久性卷声明(PVC),执行可重复的、仅状态的迁移。您可以通过从迁移计划中排除其他 PVC 来迁移指定的 PVC。您可以映射 PVC 以确保源和目标 PVC 同步。持久性卷 (PV) 数据复制到目标集群。PV 引用不会被移动,应用程序 pod 将继续在源集群中运行。
State 迁移专门设计用于外部 CD 机制,如 OpenShift Gitops。在使用 MTC 迁移状态时,您可以使用 GitOps 迁移应用程序清单。
如果您有 CI/CD 管道,您可以通过在目标集群中部署无状态组件来迁移它们。然后,您可以使用 MTC 迁移有状态组件。
您可以在集群间或同一集群中执行状态迁移。
状态迁移仅迁移构成应用状态的组件。如果要迁移整个命名空间,请使用 stage 或 cutover migration。
先决条件
-
源集群中的应用程序状态在通过
PersistentVolumeClaims
置备的PersistentVolume
中保留。 - 应用程序的清单在中央存储库中可用,它们同时可从源和目标集群访问。
流程
将持久性卷数据从源迁移到目标集群。
您可以根据需要多次执行此步骤。源应用程序继续运行。
静止源应用程序。
您可以通过在源集群上直接将工作负载资源副本设置为
0
来完成此操作,或者更新 GitHub 中的清单并重新同步 Argo CD 应用程序。将应用程序清单克隆到目标集群。
您可以使用 Argo CD 将应用程序清单克隆到目标集群。
将剩余的卷数据从源迁移到目标集群。
通过执行最终数据迁移,在状态迁移过程中迁移应用程序创建的任何新数据。
- 如果克隆的应用程序处于静默状态,请取消静止它。
- 将 DNS 记录切换到目标集群,将用户流量重新定向到已迁移的应用程序。
在执行状态迁移时,MTC 1.6 无法自动静止应用程序。它只能迁移 PV 数据。因此,您必须使用 CD 机制来静止或取消静止应用程序。
MTC 1.7 引入了明确的 Stage 和 Cutover 流。您可以根据需要,使用暂存来执行初始数据传输。然后,您可以执行一个可自动静止源应用程序。
其他资源
- 请参阅将 PVC 从迁移中排除以选择 PVC。
- 请参阅映射 PVC,将源 PV 数据迁移到目标集群上置备的 PVC。
- 请参阅迁移 Kubernetes 对象 以迁移组成应用程序状态的 Kubernetes 对象。