migration toolkit for applications 8.2

Migrating workloads by using the mta-ops CLI

Exporting, transforming, rendering, and validating workload manifests, and migrating persistent volumes across Red Hat OpenShift clusters

Red Hat Customer Content Services

Abstract

You can safely migrate applications across environments by moving your stateless workloads, converting build configurations, and replicating persistent volume data with the migration toolkit for applications (MTA) mta-ops command-line interface (CLI). The multi-stage pipeline helps you extract, transform, render, and validate your Red Hat OpenShift manifests locally to ensure target cluster API compatibility. Additionally, you can use the built-in data transfer engine to copy volume files directly between clusters, indirectly through S3-compatible cloud storage, or convert storage classes within the same cluster. You can also orchestrate multi-stage AI-driven modernization plans using agent workflows.

Chapter 1. Introduction to the mta-ops CLI

As a platform engineer or a cluster administrator, you can use the migration toolkit for applications (MTA) mta-ops command-line interface (CLI) to migrate and modernize your workloads across Red Hat OpenShift Container Platform clusters.

The mta-ops utility provides a non-destructive, repeatable, and GitOps-ready migration workflow. By decoupling workload manifest transformation from data transport, the utility allows you to customize and validate your configurations before executing active cluster modifications.

The mta-ops CLI supports two primary operational modes:

Workload manifest migration
A multi-stage pipeline that extracts, cleans, renders, and validates Kubernetes and OpenShift resources. You can customize the pipeline stages programmatically or steer them by using a declarative instructions file.
Persistent volume data portability
A highly observable data transfer engine that replicates persistent storage volumes across namespaces or clusters. This engine supports direct cluster-to-cluster synchronization, indirect migration through intermediate cloud storage, and local storage class conversions.

1.1. Workload migration pipeline

The mta-ops workload migration pipeline decouples manifest transformation from cluster deployment. By processing export, transformation, and preflight validation locally, you can inspect and verify application configurations before executing active cluster changes or GitOps deployments.

The default workload migration pipeline consists of the following sequential stages:

Export
Captures a read-only snapshot of the source namespace and saves the raw YAML manifests to a local directory. The export process is non-disruptive and extracts both namespace-scoped workloads and their cluster-scoped dependencies, such as custom security context constraints (SCCs), custom resource definitions (CRDs), and role-based access control (RBAC) objects.
Transformation
Applies built-in and custom plug-ins to clean cluster-specific metadata, such as unique identifiers (UIDs), creation timestamps, and active status blocks. During this stage, you can modernize legacy configurations, including converting OpenShift BuildConfigs to Kubernetes-native Shipwright Builds. To make the pipeline repeatable, you can define the transformation sequence by using the --instructions-file option.
Application
Renders the transformed Kustomize overlays into deployable YAML manifests on your local disk. The application stage runs an embedded Kustomize engine to generate a consolidated, dependency-ordered deployment manifest without requiring active cluster communication.
Validation
An optional but recommended preflight check that queries the target cluster discovery API to verify Group, Version, and Kind (GVK) compatibility. If the destination cluster lacks a required API version or CRD, the validator logs the incompatible resource in a failure directory and suggests available version updates.
Deployment
Applies the validated, final manifests to your destination cluster by using standard command-line tools, such as the oc or kubectl CLI, or integrates with your existing GitOps continuous delivery pipelines.
Audit logging
During execution, mta-ops maintains a persistent, structured audit log in audit/.crane-audit.log containing JSON-formatted records of every operation to satisfy compliance audits and support troubleshooting.

1.2. Persistent volume migration and data portability

To support stateful application migrations, the mta-ops CLI integrates a dedicated data replication engine through the transfer-pvc command.

Because Kubernetes storage class properties and persistent volume mappings are immutable, the mta-ops utility automates volume data transfers across the following distinct pathways:

Direct cross-cluster migration
Transfers data securely over an encrypted TLS 1.3 tunnel between active source and target cluster nodes. The CLI manages the automatic creation and garbage collection of temporary rsync and stunnel worker pods.
Indirect cross-cluster migration
Enables data transport between disconnected or air-gapped clusters that lack a direct network path. The CLI compiles an embedded rclone synchronization engine to upload encrypted files to an S3-compatible cloud storage bucket and subsequently download them to the destination persistent volume. You can opt to encrypt files at the client side using 256-bit NaCl SecretBox cryptography before uploading them to the cloud.
Intra-cluster storage class conversion
Clones volume files within the same cluster to upgrade workloads to modern storage backends, such as migrating from legacy gp2 to CSI-backed gp3 storage classes. After the data transfer is complete, you can apply a rename mapping to update all workload references to bind to the newly provisioned volume.

Chapter 2. Supported migration paths and API compatibility

To ensure a successful workload migration, you must verify that your source and target clusters meet the required environment, security, and API compatibility specifications.

2.1. Supported migration paths

Review the supported migration paths in the migration toolkit for applications (MTA) mta-ops CLI to plan your modernization strategy. Understanding these paths helps you choose the right approach for stateless workloads, persistent volumes, and storage conversions.

The migration toolkit for applications (MTA) mta-ops CLI supports the following migration paths:

Cross-cluster stateless workload migrations
Supported strictly from Red Hat OpenShift Container Platform 4.x to 4.x environments.
Cross-cluster stateful persistent volume migrations
Supported between active source and target clusters over a direct network connection or indirectly through S3-compatible cloud storage targets.
Same-cluster StorageClass conversions
Supported within a single cluster context to upgrade existing persistent volumes to modern storage classes.

2.2. Workload scopes and RBAC boundaries

The mta-ops pipeline processes namespaced and cluster-scoped resources based on your authentication privileges. Understanding role-based access control boundaries allows you to isolate cluster-level dependencies and implement split-responsibility administration.

The mta-ops pipeline processes application workloads based on their scope and your active authentication privileges:

Namespace-scoped resources
Fully supported. The CLI extracts all resources in the target namespace (such as Deployments, Services, ConfigMaps, and Secrets) by default. You only require namespace-admin privileges to export, transform, and apply these resources.
Cluster-scoped resources

Conditionally supported. Real-world applications often depend on cluster-level objects, including Custom Resource Definitions (CRDs), custom SecurityContextConstraints (SCCs), ClusterRoles, and ClusterRoleBindings.

  • If you have cluster-admin privileges, the mta-ops CLI automatically discovers, exports, and transforms these dependencies alongside your namespaced workloads.
  • If you lack cluster-admin privileges, the CLI safely skips cluster-scoped resources, logs a warning message to the console, and records the skipped resources under a failures/ subdirectory.

2.3. Split-responsibility administration

If your security policies prevent application developers from holding cluster-admin privileges on production environments, you can implement a split-responsibility workflow.

A split-responsibility workflow includes the following stages:

  • The application developer (namespace-admin) runs the export and transform pipeline on namespaced workloads. During the apply phase, the developer appends the --skip-cluster-scoped flag to render only namespaced resources.
  • The cluster administrator reviews and applies the cluster-scoped resources separately. The administrator executes a targeted export and apply using elevated cluster-admin credentials to deploy cluster-level security, CRDs, and permission boundaries before or alongside the workload migration.

Chapter 3. Installing and configuring the mta-ops CLI

To begin migrating your workloads, install the mta-ops command-line interface (CLI) on your local machine and configure it.

3.1. The mta-ops CLI standalone architecture

When you prepare your local workstation, understand the standalone nature of the mta-ops CLI to avoid installation conflicts.

The mta-ops CLI is a standalone tool that operates independently of the standard migration toolkit for applications (MTA) CLI (mta-cli). You do not need to install the standard MTA CLI to use the mta-ops pipeline.

You can install the tool by downloading the pre-compiled mta-ops archive from the Red Hat Developer portal, then extracting the binary.

3.2. Downloading and extracting the mta-ops CLI

To configure your migration environment, download and extract the pre-compiled mta-ops archive.

Prerequisites

  • You have a compatible local operating system.

Procedure

  1. Log in to the Red Hat Developer Portal.
  2. Navigate to the migration toolkit for applications downloads page.
  3. Download the mta-ops CLI .zip archive for your operating system.
  4. Extract the downloaded .zip archive to a local directory.
  5. Move the extracted mta-ops binary to a directory that is included in your $PATH environment variable. For example:

    $ sudo mv mta-ops /usr/local/bin/

Verification

  • Verify the installation by checking the tool version:

    $ mta-ops version

3.3. Managing the CLI plug-in

List installed plugins and customize the transformation pipeline by omitting unneeded stages.

The mta-ops CLI automatically discovers plug-ins stored in the default plugin directory at ~/.local/share/crane/plugins/.

Procedure

  • List all installed plugins available to the transformation engine:

    $ mta-ops transform list-plugins
  • To omit specific plugins during transformation, use the --skip-plugins flag:

    $ mta-ops transform -e export -t transform --skip-plugins OpenShiftPlugin

3.4. Configuring cluster access for migration

Before you can migrate workloads, you must establish communication with your environments. To enable the access, you must use your local cluster contexts.

3.4.1. Cluster context management

Understand how the mta-ops CLI connects to your environments to ensure your migration commands route to the correct destinations.

The mta-ops CLI operates entirely locally. It does not require a centralized web console or an intermediate authentication hub. The tool uses your local kubeconfig file to authenticate and communicate directly with clusters.

Because the pipeline extracts data from one environment and validates against another environment, your kubeconfig file must contain active contexts for both clusters simultaneously. mta-ops uses the --context flag to route operations. This design securely uses your existing role-based access control (RBAC) permissions without requiring secondary credentials.

3.4.2. Configuring source and target cluster contexts

To enable the mta-ops CLI to communicate with your environments, configure your local cluster contexts. You perform this by logging into both the source and target clusters.

Prerequisites

  • You have installed the Red Hat OpenShift CLI (oc).
  • You have credentials for both the source and target Red Hat OpenShift clusters.

Procedure

  1. Log in to the source Red Hat OpenShift cluster:

    $ oc login <source_cluster_url> -u <username> -p <password>
  2. Log in to the target Red Hat OpenShift cluster:

    $ oc login <target_cluster_url> -u <username> -p <password>
  3. List your configured contexts to verify they are active:

    $ oc config get-contexts
  4. Identify and record the names of the source and target contexts. You use these exact names with the --context flag in subsequent pipeline commands.

Verification

  • Verify that the command output displays both cluster contexts and that no authentication errors occurred.

Chapter 4. Migrating stateless workloads

Migrate your Red Hat OpenShift workloads from a source cluster to a target cluster by using the mta-ops multi-stage pipeline. The pipeline allows you to extract, transform, render, and validate your workload manifests locally before executing deployment commands.

4.1. Executing a stateless migration quick start

To test the tool, run a basic stateless migration scenario for a single application. This end-to-end pipeline demonstrates the default workflow.

Prerequisites

  • You have active contexts for your source and target clusters.

Procedure

  1. Export the source application manifests:

    $ mta-ops export --context <source_context> -n <namespace> -e export --overwrite
  2. Clean the exported manifests by using the default transformation pipeline:

    $ mta-ops transform -e export -t transform
  3. Render the deployable manifests locally, prefixing files with 3-digit order numbers for correct dependency resolution:

    $ mta-ops apply -t transform -o output --overwrite
  4. Optional: Validate the generated manifests against the target cluster:

    $ mta-ops validate --context <target_context> -i output --overwrite
  5. Deploy the application to the target cluster:

    $ oc apply -f output/output.yaml

Verification

  • Verify the application rollout on the target cluster.

4.2. Exporting workload manifests

Capture a snapshot of your source cluster resources to generate raw manifests for local transformation.

4.2.1. Workload manifest export

When you extract workloads, understanding the read-only export process helps you to capture the required resource manifests.

The export process is read-only and does not affect running applications. The mta-ops CLI operates completely independently of the migration toolkit for applications Hub.

The tool does not require a Personal Access Token (PAT). It authenticates directly to the clusters by using your local kubeconfig file.

If you lack cluster-level permissions, the command logs a warning. It records inaccessible resources in a dedicated failures/ directory.

To identify skipped cluster-scoped resources during a partial export, you must inspect the failures/ directory. The tool generates a YAML artifact for each inaccessible resource. These files contain the raw application programming interface (API) error.

The export command exits with a non-zero status code under one of the following conditions:

  • All requested resource types return a Forbidden error.
  • A resource type returns a timeout error.

4.2.2. Exporting manifests from the source cluster

To capture your application’s deployment configuration, export the manifests to a local directory. You can use role impersonation if you do not have direct access.

Prerequisites

  • You have installed the mta-ops CLI on your system.
  • You have active kubeconfig access to the source Red Hat OpenShift cluster.
  • Optional: You have cluster-admin privileges to export all cluster-scoped dependencies.

    Warning

    If you lack cluster-admin privileges, the export process generates warnings and extracts only the resources you have permission to access.

Procedure

  1. Export manifests and cluster-level dependencies:

    $ mta-ops export --context <source_cluster_context> -n <namespace> -e <export_dir>
  2. Optional: To perform a partial namespace export based on resource labels, append the -l selector flag:

    $ mta-ops export --context <source_cluster_context> -n <namespace> -e <export_dir> -l <label_key>=<label_value>
  3. Optional: To perform service account-based migrations by using role impersonation, append the --as and --as-group flags:

    $ mta-ops export --context <source_cluster_context> -n <namespace> -e <export_dir> --as <service_account_name> --as-group <group_name>

Verification

  1. Inspect the export/resources/my-app/ directory to confirm raw resource files were created.
  2. If you lack cluster-admin privileges, inspect the failures/ directory to identify any skipped resources.

4.2.3. Additional resources

4.3. Transforming workload manifests by using a multi-stage pipeline

To clean the exported workload manifests and prevent conflicts on the target cluster, transform the manifests by using a multi-stage pipeline.

4.3.1. Transformation plugin management

The mta-ops command-line interface (CLI) automatically discovers plugins from the default path at ~/.local/share/crane/plugins/. You can view all available plugins by using the list-plugins subcommand.

During the transform stage, you can customize execution by using the following flags:

  • --skip-plugins: Omits specific plugins from the execution sequence (for example, --skip-plugins OpenShiftPlugin).
  • --optional-flags: Passes key-value configuration arguments directly to active plugins.
  • --instructions-file: Passes a declarative YAML file to steer the execution sequence and parameter overrides.
  • --overwrite: Replaces pre-existing target directories and overwrites manual custom modifications when running the command.

4.3.2. Multi-stage transformation pipeline

Understand how the multi-stage transformation pipeline produces Kustomize-native output. This allows you to accurately trace modifications.

The mta-ops transform command processes exported manifests through sequential plugin stages. The pipeline produces a standard Kustomize layout. The pipeline isolates each execution step into a dedicated, numbered subdirectory under the central transform/ directory. This open structure allows you to inspect inputs, generated patches, and outputs of each plugin individually.

Example 4.1. Example output directory structure

transform/
├── 10_KubernetesPlugin/
│   ├── input/
│   ├── output/
│   ├── patches/
│   └── kustomization.yaml
├── 15_OpenShiftPlugin/
│   ├── input/
│   ├── output/
│   ├── patches/
│   └── kustomization.yaml
└── 50_CustomModifications/
    ├── input/
    ├── output/
    ├── patches/
    └── kustomization.yaml

The directory structure uses the following components:

  • Isolated stage directories: Each plugin processes within a dedicated, numbered directory. This isolation ensures you can trace which tool caused a specific modification.

    Note

    You can append manual transformation stages to the pipeline to apply declarative patches directly to your application.

  • Input and output folders: The pipeline merges the working state into the main directories. These folders show the exact manifest state before and after execution.
  • Patches directory: This directory contains the generated overlays. The files use predictable, deterministic naming conventions and sorting.
  • Kustomization file: The kustomization.yaml file acts as the standard entry point. You can manually edit this file in custom stages to apply declarative overrides.

Plugin stages safely regenerate upon execution. However, custom stages require manual forced overwrites to protect your edits.

4.3.3. Executing a multi-stage workload transformation

Transform your exported manifests to remove cluster-specific metadata. This prevents conflicts on the target Red Hat OpenShift cluster.

Prerequisites

  • You have exported the workload manifests from the source cluster to a local directory.

Procedure

  1. Navigate to the directory containing your exported manifests.
  2. Transform the manifests:

    $ mta-ops transform -e export -t transform

Verification

  • Verify that the generated stage directories contain the expected kustomization.yaml files and descriptive folders.

4.3.4. Transforming manifests with an instructions file

To enforce repeatable cleanup rules, steer the transformation sequence by using a declarative instructions file.

Prerequisites

  • You successfully exported your workload manifests.
  • You created a YAML instructions file containing your custom transformation rules.

Procedure

  • Transform the manifests by applying specific rules:

    $ mta-ops transform -e <export_dir> -t <transform_dir> --instructions-file <path_to_file.yaml>

Verification

  • Verify that the tool applied your specific rules to the generated stage directories.

4.3.5. Adding a custom transformation stage

To adapt migrated resources to new environment standards, add a custom transformation stage. You can layer declarative patches directly on your application.

Prerequisites

  • You have exported and successfully transformed the workload manifests.

Procedure

  1. Navigate to your generated <transform_dir>/ directory.
  2. Create a new directory for your custom stage. Do not use the Plugin suffix in the name.

    $ mkdir <custom_stage_directory>
  3. Create a kustomization.yaml file inside your new custom stage directory.
  4. Define your custom modifications in the kustomization.yaml file. For example, to override the target namespace and add migration labels, use the following code:

    namespace: <target_namespace>
    commonLabels:
      migration-run: <migration_id>
  5. Apply your custom stage:

    $ mta-ops transform <custom_stage_directory> -e <export_dir> -t <transform_dir> --overwrite

    The --overwrite flag is mandatory to safely overwrite your modified custom stage directory.

Verification

  • Verify that the output/ directory inside your custom stage contains the expected resource changes.

4.3.6. Converting OpenShift BuildConfigs to builds

Convert legacy Red Hat OpenShift BuildConfig resources into Kubernetes-native build custom resources by using the built-in BuildConfigToBuildsPlugin during the mta-ops transform pipeline. Converting build definitions allows you to modernize application container builds to run on Kubernetes-native build engines such as Builds for Red Hat OpenShift.

Important

Converting OpenShift BuildConfigs to builds by using BuildConfigToBuildsPlugin is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

4.3.6.1. BuildConfig to builds conversion

The BuildConfigToBuildsPlugin converts legacy Red Hat OpenShift BuildConfig resources (build.openshift.io/v1) into Kubernetes-native build custom resources (shipwright.io/v1beta1) during the mta-ops transform stage, generating reviewable, GitOps-ready manifests offline.

4.3.6.1.1. Transformation pipeline ordering rules

To ensure all workload resources are cleaned correctly, BuildConfigToBuildsPlugin must run as part of a multi-stage transformation sequence alongside the default cleanup plugins:

  • Default stage sequence: The default transformation pipeline executes KubernetesPlugin (stage 10_), OpenShiftPlugin (stage 15_), and BuildConfigToBuildsPlugin (stage 25_) in sequential order.
  • Instructions file sequencing: When defining a declarative instructions file (--instructions-file), you must specify BuildConfigToBuildsPlugin after OpenShiftPlugin. If BuildConfigToBuildsPlugin executes before OpenShiftPlugin, subsequent OpenShift cleanup logic strips the generated Build resources from the pipeline output.
4.3.6.1.2. Key conversion features and strategy mappings

The BuildConfigToBuildsPlugin evaluates each BuildConfig in the exported source manifests and maps its properties to the corresponding Builds for Red Hat OpenShift specification:

Docker strategy conversion

Converts dockerStrategy BuildConfigs to Build custom resources backed by the buildah ClusterBuildStrategy. The plugin maps Dockerfile paths, build arguments, and base images. If an inline Dockerfile is present in the BuildConfig, the plugin extracts the Dockerfile into a backup ConfigMap referenced by the buildconfig-to-shipwright/inline-dockerfile-configmap annotation.

Important

Builds for Red Hat OpenShift cannot pull inline Dockerfiles directly from a ConfigMap at build time. The generated ConfigMap serves as an offline reference copy; you must commit the Dockerfile to your application’s Git repository before executing a build.

Source-to-Image (S2I) strategy conversion
Converts sourceStrategy BuildConfigs to Build custom resources backed by the source-to-image ClusterBuildStrategy. The plugin maps builder image references, environment variables, and source secrets.
ImageStreamTag fallthrough resolution

If a BuildConfig references an ImageStreamTag for its output or base image, the plugin resolves the reference using a layered fallthrough approach:

  1. Evaluates explicit parameter overrides passed in --optional-flags (--imagestream-mapping or --registry-mapping).
  2. Checks for co-exported ImageStream YAML definitions within the export directory.
  3. Falls back to the internal registry URL and records a conversion warning annotation if the image cannot be resolved externally.
Multiple image sources and Git proxies
  • Single source boundary: Build custom resource specifications support a single input source. If a BuildConfig defines multiple image sources, the plugin converts the primary source and records a warning annotation for additional sources.
  • Git proxy configuration: If a BuildConfig uses a Git proxy, proxy configuration on Shipwright must be defined at the target cluster level by using GIT_CONTAINER_TEMPLATE.
Unconverted BuildConfigs and failure annotations

BuildConfig resources configured with customStrategy or jenkinsPipelineStrategy, or those lacking an output image target, cannot be converted automatically. The plugin passes these resources through untouched in the stage output directory, appending two tracking annotations:

  • buildconfig-to-shipwright/conversion-outcome: Indicates the result (for example, skipped or failed).
  • buildconfig-to-shipwright/conversion-reason: Details the exact technical reason why conversion was skipped.
ServiceAccount and Secret generation
If a BuildConfig references a pull secret but does not specify a ServiceAccount, the plugin automatically generates a scaffolded ServiceAccount carrying the pull secret. To enable container image pushes to external registries (such as Quay.io or Docker Hub), ensure spec.output.pushSecret is defined on the Build or attached to the ServiceAccount.
Build triggers and execution model
Builds for Red Hat OpenShift does not support native OpenShift build triggers (such as ImageChange or Webhook triggers). The plugin notes omitted triggers in crane.konveyor.io/conversion-warnings annotations on the generated Build objects. On the target cluster, builds do not fire automatically upon manifest application; developers or CI/CD pipelines must create an explicit BuildRun resource (buildruns.shipwright.io) pointing to the appropriate ServiceAccount to initiate a build execution.

4.3.6.2. Converting OpenShift BuildConfigs to builds by using the BuildConfigToBuildsPlugin

Transition application build definitions to a Kubernetes-native framework during workload migration by using the BuildConfigToBuildsPlugin during the mta-ops transform stage.

The BuildConfigToBuildsPlugin plugin converts OpenShift BuildConfig resources (build.openshift.io/v1) into Kubernetes-native build custom resources (shipwright.io/v1beta1) offline.

Prerequisites

  • You have exported application manifests from the source cluster containing BuildConfig definitions by using mta-ops export.
  • You have completed the default mta-ops transform stage to strip runtime metadata and cluster-specific IDs from all exported workload resources.
  • The target cluster has the Builds for Red Hat OpenShift operator and Red Hat OpenShift Pipelines installed to serve the shipwright.io/v1beta1 API and provide the buildah and source-to-image ClusterBuildStrategies.

Procedure

  1. Execute the transformation pipeline with the BuildConfigToBuildsPlugin stage. Pass image and registry remapping parameters inside the --optional-flags JSON object string:

    $ mta-ops transform -e <export_dir> -t <transform_dir> BuildConfigToBuildsPlugin --optional-flags '{"registry-mapping":"image-registry.openshift-image-registry.svc:5000=<target_registry_url>/<target_org>","imagestream-mapping":"<namespace>/<stream_name>:_<tag>_=<external_registry_image>"}' --overwrite
    Note

    Do not pass registry-mapping or imagestream-mapping as standalone command flags. They are plugin parameters that must be formatted as key-value pairs inside the --optional-flags JSON string.

  2. Inspect the generated stage directory under <transform_dir>/ (for example, <transform_dir>/*_BuildConfigToBuildsPlugin/output/):

    $ ls -l <transform_dir>/*_BuildConfigToBuildsPlugin/output/
  3. Render the final deployable manifests locally:

    $ mta-ops apply -t <transform_dir> -o <output_dir> --ordered --overwrite
  4. Identify any BuildConfig resources that could not be converted automatically by checking for conversion outcome annotations in the final output directory:

    $ grep -rl 'kind: BuildConfig' <output_dir>/resources | xargs -r grep -H 'buildconfig-to-shipwright/conversion-'
  5. If an exported BuildConfig contains an inline Dockerfile, locate the generated reference ConfigMap under <output_dir>/resources/ and commit the Dockerfile content directly to your application’s Git repository.
  6. Deploy the converted application manifests and generated Build resources to the target cluster:

    $ oc apply -f <output_dir>/output.yaml --context <target_cluster_context>
  7. Grant the required security context constraint (SCC) permissions to the ServiceAccount executing the build on the target cluster:

    $ oc adm policy add-scc-to-user pipelines-scc -z <service_account_name> -n <namespace> --context <target_cluster_context>
  8. Trigger a container image build on the target cluster by completing the following steps:

    1. Create a BuildRun manifest (buildrun.yaml) that references the configured ServiceAccount:

      apiVersion: shipwright.io/v1beta1
      kind: BuildRun
      metadata:
        name: <build_run_name>
        namespace: <namespace>
      spec:
        build:
          name: <build_name>
        serviceAccount:
          name: <service_account_name>
    2. Deploy the BuildRun manifest:

      $ oc apply -f buildrun.yaml --context <target_cluster_context>
      Important

      Always specify the fully qualified API resource name builds.shipwright.io or buildruns.shipwright.io when using oc commands on OpenShift to prevent naming collisions with legacy OpenShift build objects.

Verification

  • Confirm that the BuildRun resource executes successfully on the target cluster:

    $ oc get buildruns.shipwright.io <build_run_name> -n <namespace> --context <target_cluster_context>

4.3.7. Additional resources

4.4. Generating final deployable manifests

To render the final YAML from the transform pipeline, generate the manifests. The mta-ops apply command produces local deployable files without modifying clusters.

4.4.1. Local manifest generation

Understand how the mta-ops apply command renders your transformed manifests locally. This ensures your final YAML is ready for deployment.

The mta-ops apply command runs Kustomize on the final transform stage. It evaluates patches internally by using the embedded krusty application programming interface (API). This embedded rendering removes the runtime dependency on the kubectl or oc binaries.

The command produces clean, deployable manifests on your local disk. It does not deploy resources to any cluster. The output includes individual resource files and a consolidated output.yaml file.

The mta-ops tool orders resources in the consolidated file to satisfy cluster dependencies. For example, it places custom resource definitions (CRDs) before namespace-scoped resources. You can exclude cluster-scoped resources by appending the --skip-cluster-scoped flag. This supports split-responsibility workflows between administrators and non-administrators.

4.4.2. Generating final manifests locally

Render the transformed Kustomize overlays into deployable YAML files on your local disk.

Prerequisites

  • You have successfully exported and transformed your workload manifests.

Procedure

  1. Generate the final manifests:

    $ mta-ops apply -t <transform_dir> -o <output_dir>
  2. Optional (non-admin workflow): Exclude cluster-scoped resources if you lack privileges to apply them:

    $ mta-ops apply -t <transform_dir> -o <output_dir> --skip-cluster-scoped --overwrite

Verification

  • Inspect the <output_dir>/output.yaml file and verify resource configurations, namespaces, images, and replica counts.

4.4.3. Generating ordered manifests locally

When you render your final YAML, you can generate ordered individual resource files. This ensures you apply resources in the correct dependency order.

Prerequisites

  • You have successfully exported and transformed your workload manifests.

Procedure

  1. Generate the final manifests by appending the --ordered flag:

    $ mta-ops apply -t <transform_dir> -o <output_dir> --ordered

Verification

  • Review the generated files in the output/resources/<namespace>/ directory. The --ordered flag prefixes the filenames with 3-digit order numbers.

4.4.4. Additional resources

4.5. Validating target cluster compatibility

To ensure your generated manifests are compatible with a target cluster, run the validation check. Validating target cluster compatibility is an optional step. Validate runs after the apply stage on the final output.

4.5.1. Manifest compatibility validation

Validation is a read-only optional check for your final workload manifests before their deployment on a target cluster. It prevents deployment failures by identifying API incompatibilities.

You can use the mta-ops validate command to evaluate your generated manifests against the target Red Hat OpenShift cluster’s application programming interface (API) surface. The command performs strict group, version, and kind (GVK) matching. The tool reads the API discovery information without modifying the cluster.

The validation command generates a report identifying incompatible resources. It saves the detailed results to a specified validation directory. If incompatibilities are found, the tool logs the failing artifacts in a failures/ subdirectory.

The validation process supports the following modes:

  • Live mode: The mta-ops tool connects directly to the target cluster to read the current API surface.
  • Offline mode: The mta-ops tool reads a previously captured API surface file. This is useful for disconnected environments or automated pipelines.

4.5.2. Validating workload manifests against a live cluster

To verify application programming interface (API) compatibility before deployment, validate your transformed manifests against a live target Red Hat OpenShift cluster.

Prerequisites

  • You have generated the final manifests.
  • You have active access to the target Red Hat OpenShift cluster.

Procedure

  1. Set your CLI context to the target Red Hat OpenShift cluster.
  2. Validate the transformed manifests:

    $ mta-ops validate --context <target_cluster_context> -i <output_dir>
    {
      "mode": "live",
      "clusterContext": "tgt-cluster",
      "results": [
        {
          "apiVersion": "apps/v1",
          "kind": "Deployment",
          "namespace": "target-namespace",
          "resourcePlural": "deployments",
          "status": "OK"
        },
        {
          "apiVersion": "v1",
          "kind": "Secret",
          "namespace": "target-namespace",
          "resourcePlural": "secrets",
          "status": "OK"
        },
        {
          "apiVersion": "v1",
          "kind": "Service",
          "namespace": "target-namespace",
          "resourcePlural": "services",
          "status": "OK"
        }
      ],
      "totalScanned": 3,
      "compatible": 3,
      "incompatible": 0
    }

Verification

  • Verify that the command returns a PASSED summary result.

4.5.3. Validating workload manifests in disconnected or offline environments

In air-gapped environments without direct network connectivity to the target cluster, validate workload manifests using a pre-captured API surface JSON file.

Procedure

  1. On a workstation with access to the target cluster, capture the API surface:

    $ bash scripts/capture-api-surface.sh --context <target_cluster_context> -o <api_surface_file>
  2. On your offline migration workstation, run the validation check against the captured file:

    $ mta-ops validate -i <output_dir> --api-resources <api_surface_file>

Verification

  • Inspect the terminal summary or generated validation report file to confirm GVK compatibility.

4.5.4. Additional resources

4.6. Deploying workloads to the target cluster

Deploy validated manifests to the target cluster by using standard CLI tools or GitOps pipelines.

4.6.1. Workload deployment

Understand the final step of the stateless workload migration pipeline and deploy the validated manifests to the target cluster.

The mta-ops pipeline produces ready-to-use YAML artifacts on your local disk. It deliberately does not connect to the target cluster. This non-destructive architecture ensures that the target cluster remains untouched until manual deployment.

Because the pipeline outputs standard Kubernetes manifests, it is fully GitOps-ready. You can commit the final YAML to a repository.

Applying the consolidated output.yaml file resolves dependency ordering issues during deployment. Applying the entire directory can cause deployment failures if roles execute before role bindings.

4.6.2. Deploying workloads to the target cluster as an administrator

To finalize your migration, deploy the validated workloads by applying the generated manifests to the target Red Hat OpenShift cluster.

Prerequisites

  • Optional: You have validated your workload manifests.
  • You have cluster-admin privileges on the target Red Hat OpenShift cluster.

Procedure

  1. Deploy the workloads by using the Red Hat OpenShift CLI and applying the consolidated file:

    $ oc apply -f <output_dir>/output.yaml --context <target_cluster_context>

    Alternatively, apply the ordered individual resource directory:

    $ oc apply -f <output_dir>/resources/<namespace>/ --context <target_cluster_context>
  2. Optional: Commit the <output_dir> directory to your repository to use a GitOps deployment workflow.

Verification

  • Verify the rollout, service endpoints, and application health on the target cluster.

4.6.3. Deploying workloads to the target cluster as a non-administrator

When you lack cluster-admin privileges, deploy your workloads as a non-administrator. This allows you to apply namespace-scoped resources safely.

Prerequisites

  • You have a PASSED validation report for your output directory.
  • You generated your manifests using the --skip-cluster-scoped flag during the apply stage.

Procedure

  • Deploy the workloads by using the Red Hat OpenShift CLI:

    $ oc apply -f <output_dir>/output.yaml -n <namespace> --context <target_cluster_context>

Verification

  • Verify the rollout and application health on the target namespace.

Chapter 5. Migrating stateful persistent volumes

Replicate active data volumes and storage mappings across clusters or convert storage classes within a single cluster using the mta-ops transfer-pvc engine.

5.1. Persistent volume migration concepts and observability

The mta-ops transfer-pvc command manages volume replication across three distinct pathways: direct cross-cluster transfer, indirect cloud storage transfer, and intra-cluster StorageClass conversion.

During transfer, mta-ops transfer-pvc displays a structured phase progress tracker [i/N], an opening context banner, and a completion summary:

================================================================================
   MTA-OPS PVC TRANSFER
   Source Context : <source_cluster_context>
   Destination Context : <target_cluster_context>
   PVC : <pvc_name> (namespace: <namespace>)
   Endpoint Type : Route ================================================================================
[1/7] Reading source PVC ... ok
[2/7] Creating destination PVC ... ok
[3/7] Creating endpoint ... ok
[4/7] Waiting for endpoint healthy ... ok
[5/7] Setting up secure tunnel and server ... ok
[6/7] Copying data (rsync) ... 100% 250MB/250MB
[7/7] Cleaning up temporary resources ... ok ================================================================================
    TRANSFER SUMMARY: Succeeded (duration: 42s) ================================================================================

5.2. Persistent volume migration paths

When preparing for the migration of persistent volume claim (PVC) data, you can select the appropriate path depending on your network topology, security policies, and target cluster configuration.

The following migration paths are available for PVC migration:

Direct persistent volume claim migration

Direct migration copies file data directly from the source cluster to the destination cluster. This path uses a secure tunnel. The tunnel is established by using stunnel with Transport Layer Security (TLS) version 1.3.

A file synchronization utility (rsync) copies the files across the tunnel. This direct transfer requires a network path between the clusters. You must expose a route or an ingress endpoint on the target cluster. This method preserves file mode bits and ownership.

Indirect persistent volume claim migration

Indirect migration copies data by using an intermediate cloud storage bucket. This path is ideal when clusters do not have direct network connectivity. It is also suitable for air-gapped or classified environments.

The migration occurs in two sequential phases. First, a source pod uploads files to an S3-compatible bucket. Second, a destination pod downloads those files. This path uses the rclone utility compiled as a library.

You can enable client-side encryption by using the NaCl SecretBox standard. This encryption protects your data in transit and at rest.

Intra-cluster StorageClass conversion

Intra-cluster conversion changes the storage class of an existing volume. Kubernetes storage class settings are immutable after creation. To change a storage class, you must create a new volume and copy the data.

The same-cluster pipeline automates this process within a single namespace. The pipeline creates a temporary target volume. It then copies files from the source volume to the new volume.

You use a name mapping file to update all workload references. This updates references in your deployments and stateful sets automatically.

5.3. Mirroring the mta-rsync-transfer image for disconnected environments

To execute direct persistent volume claim (PVC) migrations in disconnected or air-gapped environments, manually mirror the standalone mta-rsync-transfer container image to an internal registry accessible by both source and target clusters.

5.3.1. mta-rsync-transfer image mirroring in disconnected environments

During direct persistent volume claim (PVC) data migrations, the mta-ops transfer-pvc engine provides temporary worker pods running the mta-rsync-transfer container image on both source and target clusters.

In disconnected or air-gapped environments, you must manually mirror a standalone container image to an internal registry accessible by both clusters.

5.3.1.1. Standalone image repository and tagging scheme

The mta-rsync-transfer image is distributed alongside the mta-ops command-line interface (CLI) as a standalone container image. Unlike operator-managed workloads, this image is not included in the MTA Operator bundle’s spec.relatedImages manifest.

Consequently, automated operator mirroring workflows (such as oc-mirror) do not automatically pull or mirror the mta-rsync-transfer image during disconnected cluster setup. The downstream image registry path and tagging scheme are defined as follows:

  • Registry repository path: registry.redhat.io/mta/mta-rsync-transfer-rhel9
  • Tagging scheme: Matches the MTA minor or patch release version, for example:

    • registry.redhat.io/mta/mta-rsync-transfer-rhel9:8.3.0
    • registry.redhat.io/mta/mta-rsync-transfer-rhel9:latest

5.3.1.2. Source and target cluster image accessibility requirements

Direct persistent volume migrations rely on the mta-rsync-transfer image across both cluster endpoints simultaneously:

Source cluster (rsync client)
Runs a temporary worker pod that mounts the source PersistentVolumeClaim in ReadOnly mode and initiates the encrypted stunnel TLS 1.3 tunnel.
Target cluster (rsync server)
Runs a temporary worker pod that mounts the destination PersistentVolumeClaim in ReadWrite mode and listens for incoming data streams from the source client pod.

Because both worker pods pull the mta-rsync-transfer container image dynamically at runtime, your internal mirror registry must be reachable by nodes on both the source and target Red Hat OpenShift clusters. In decoupled CLI scenarios where clusters share no direct network path, both clusters must still have access to either a common internal registry or identical mirrored local registries.

5.3.2. Mirroring the mta-rsync-transfer image to an internal registry

Enable direct persistent volume migrations in disconnected or air-gapped environments by manually mirroring the mta-rsync-transfer container image from Red Hat Registry to an internal container registry accessible by your source and target clusters.

Prerequisites

  • You have installed a container management utility such as oc, skopeo, or podman on a workstation with internet access.
  • You have authentication credentials for registry.redhat.io and your internal mirror registry.
  • Both source and target Red Hat OpenShift clusters are configured to trust the internal mirror registry certificate and global pull secret.

Procedure

  1. Log in to registry.redhat.io on your connected workstation:

    $ podman login registry.redhat.io -u <redhat_username> -p <redhat_password>
  2. Log in to your internal mirror registry:

    $ podman login <internal_registry_host> -u <internal_username> -p <internal_password>
  3. Mirror the mta-rsync-transfer container image to your internal registry:

    1. By using oc image mirror:

      $ oc image mirror registry.redhat.io/mta/mta-rsync-transfer-rhel9:<tag> <internal_registry_host>/<repository>/mta-rsync-transfer-rhel9:<tag>
    2. By using skopeo copy:

      $ skopeo copy docker://registry.redhat.io/mta/mta-rsync-transfer-rhel9:<tag> docker://<internal_registry_host>/<repository>/mta-rsync-transfer-rhel9:<tag>
    3. By using podman and removable media (sneaker-net/air-gapped environments).
  4. Pull the container image on an internet-connected workstation:

    $ podman pull registry.redhat.io/mta/mta-rsync-transfer-rhel9:<tag>
  5. Save the image to an archive file:

    $ podman save -o mta-rsync-transfer.tar registry.redhat.io/mta/mta-rsync-transfer-rhel9:<tag>
  6. Transfer mta-rsync-transfer.tar to your disconnected workstation using approved removable media.
  7. Load the archive and push to your internal air-gapped registry:

    $ podman load -i mta-rsync-transfer.tar
    $ podman tag registry.redhat.io/mta/mta-rsync-transfer-rhel9:<tag> <internal_registry_host>/<repository>/mta-rsync-transfer-rhel9:<tag>
    $ podman push <internal_registry_host>/<repository>/mta-rsync-transfer-rhel9:_<tag>_
  8. Configure an ImageDigestMirrorSet resource on both source and target Red Hat OpenShift clusters to redirect image requests from registry.redhat.io to your internal mirror registry (idms.yaml):

    $ oc apply -f idms.yaml --context <source_cluster_context>
    $ oc apply -f idms.yaml --context <target_cluster_context>

Verification

  • Verify image accessibility by querying image metadata from both cluster contexts:

    $ oc image info <internal_registry_host>/<repository>/mta-rsync-transfer-rhel9:<tag> --context <source_cluster_context>
    $ oc image info <internal_registry_host>/<repository>/mta-rsync-transfer-rhel9:<tag> --context <target_cluster_context>

5.4. Migrating persistent volume data directly between clusters

Migrate persistent volume claim (PVC) data directly between active source and target clusters by running the data transfer pipeline. This direct path copies files through an encrypted TLS tunnel.

Prerequisites

  • You have installed the mta-ops command-line utility.
  • You have active cluster contexts for both clusters in your kubeconfig file.
  • You have scaled down active workloads on the source volume to 0 replicas to prevent write operations.

Procedure

  1. Log in to your source and destination clusters.
  2. Perform the direct data transfer:

    $ mta-ops transfer-pvc --source-context=<source_cluster_context> --destination-context=<target_cluster_context> --pvc-name=<pvc_name> --pvc-namespace=<pvc_namespace> --endpoint=route

Verification

  • Confirm the destination PVC exists and contains transferred files on the target cluster:

    $ oc get pvc -n <pvc_namespace> --context <target_cluster_context>

5.5. Migrating persistent volume data indirectly through cloud storage

Migrate persistent volume claim (PVC) data between disconnected or air-gapped clusters by using an S3-compatible cloud storage bucket.

Prerequisites

  • You have installed the mta-ops command-line utility.
  • You have active cluster contexts for both clusters in your kubeconfig file.
  • You have scaled down active workloads on the source volume to 0 replicas to prevent write operations.
  • You have configured an S3-compatible storage bucket and local credentials file (rclone.conf).

Procedure

  1. Execute the indirect data transfer by specifying the cloud storage bucket path:

    $ mta-ops transfer-pvc --source-context=<source_cluster_context> --destination-context=<target_cluster_context> --pvc-name=<pvc_name> --pvc-namespace=<pvc_namespace> --cloud-storage=<s3_bucket_url> --rclone-config-file=<rclone_config_file> --encrypt
  2. Optional: To retain cloud bucket backup data after transfer completion, append the --keep-cloud-data flag.

Verification

  • Confirm the destination PVC exists and contains transferred files on the target cluster:

    $ oc get pvc -n <pvc_namespace> --context <target_cluster_context>

5.6. Converting volume storage classes within the same cluster

Convert an existing immutable PersistentVolumeClaim to a new StorageClass within the same cluster context.

Prerequisites

  • You have installed the mta-ops command-line utility.
  • You have active cluster contexts for your cluster in your kubeconfig file.
  • You have scaled down active workloads on the source volume to 0 replicas to prevent write operations.

Procedure

  1. Execute the same-cluster PVC transfer, specifying the target storage class:

    $ mta-ops transfer-pvc --source-context=<cluster_context> --destination-context=<cluster_context> --pvc-name=<source_pvc_name> --pvc-namespace=<pvc_namespace> --dest-storage-class=<target_storage_class>
  2. Export the application workload manifests:

    $ mta-ops export --context=<cluster_context> -n <pvc_namespace> -e <export_dir>
  3. Transform exported manifests and update all workload references to point to the new PVC:

    $ mta-ops transform -e <export_dir> -t <transform_dir> --pvc-rename-map=<source_pvc_name>:<destination_pvc_name>
  4. Render the final deployable manifests:

    $ mta-ops apply -t <transform_dir> -o <output_dir> --overwrite
  5. Apply the rendered manifests to your cluster:

    $ oc apply -f <output_dir>/output.yaml --context=<cluster_context>

Verification

  • Verify application pods mount the new volume bound to the new storage class:

    $ oc get pvc <destination_pvc_name> -n <pvc_namespace> --context=<cluster_context>

Chapter 6. Troubleshooting the mta-ops pipeline

If a migration step fails, you can debug the pipeline to resolve errors. You can extract logs, review failures, and isolate transformations.

6.1. mta-ops pipeline troubleshooting

Understand how the mta-ops CLI isolates failures to help you quickly identify migration blockers.

Because the pipeline operates locally, troubleshooting does not require active target cluster intervention. The tool provides three primary diagnostic mechanisms:

  • Global debug logging: You can append a global debug flag to any command to print detailed diagnostic output to your terminal.
  • Failure artifacts: The export and validate commands isolate problematic resources into dedicated failures/ subdirectories. This prevents a single incompatible resource from stopping the entire pipeline.
  • Stage isolation: The transform pipeline produces distinct input/ and output/ directories for each plugin stage. This allows you to pinpoint exactly where a resource modification failed.

6.2. Enabling verbose logging for mta-ops

When you investigate pipeline failures, extract detailed diagnostic output by appending the verbose logging flag to your command.

Procedure

  • Append the --debug flag to any mta-ops command. For example, to debug a validation failure, enter:

    $ mta-ops validate --context <target_cluster_context> -i output --debug

Verification

  • Verify that your terminal output includes expanded diagnostic information and debug-level messages.

6.3. Analyzing the mta-ops audit log

Diagnose migration pipeline failures, verify resource transformation steps, and satisfy security compliance requirements by analyzing the persistent, structured JSON audit log generated during mta-ops execution.

6.3.1. Audit log architecture and behavior

The mta-ops command-line interface (CLI) automatically records a persistent, structured audit log in JSON Lines format to satisfy security compliance standards and support troubleshooting.

Every mta-ops command invocation (export, transform, apply, validate, and transfer-pvc) writes log entries to a local file named audit/.crane-audit.log in your active working directory.

The audit logging mechanism operates according to the following principles:

Always-on persistence
Audit logging is enabled by default and does not require additional CLI flags. Every operation is recorded immediately to disk.
Full debug capture
The audit log captures all log events down to the Debug level, even when terminal output is set to standard Info verbosity. This ensures complete diagnostic details are preserved without requiring you to reproduce issues with the --debug flag.
JSON Lines format
Log entries are formatted as JSON Lines (.jsonl), where each line is an independent, valid JSON object containing a command type, timestamps, log levels, component scopes, error tracebacks, and operational metadata.
Append mode history
Sequential command executions within the same working directory append new log lines to the existing .crane-audit.log file. This maintains a continuous execution history across multi-pass migration pipelines.
Custom log paths
You can override the default log destination by appending the --audit-log <path> flag to any mta-ops command.

6.3.2. Inspecting the audit log

Query and analyze the structured audit log to diagnose migration pipeline failures, verify resource transformation steps, or provide diagnostic data to Red Hat Support.

Prerequisites

  • You have executed one or more mta-ops CLI commands in your local directory.
  • You have installed a JSON parsing utility such as jq on your local machine.

Procedure

  1. Locate the persistent audit log file audit/.crane-audit.log in your working directory:

    $ ls -l audit/.crane-audit.log
  2. Filter and display only error events across all executed pipeline steps:

    $ jq -r 'select(.level=="error") | "[\(.time)] \(.msg)"' audit/.crane-audit.log
  3. Inspect all debug-level entries generated during a specific operation (such as the export stage):

    $ jq -r 'select(.msg | contains("export"))' audit/.crane-audit.log
  4. Optional: To direct audit log output to a dedicated file path during command execution, pass the --audit-log flag:

    $ mta-ops export --context <source_cluster_context> -n <namespace> e <export_dir> --audit-log <custom_path>

6.4. Common migration pipeline errors

When you encounter pipeline failures, review the common errors tables. This helps you diagnose issues and resume your migration work.

Table 6.1. Export and transform errors

Error messageCauseSolution

Forbidden

You lack role-based access control (RBAC) permissions to export a resource.

Inspect the failures/ directory for skipped dependencies. Use role impersonation flags such as --as and --as-group.

Patch evaluation error

A custom stage contains malformed YAML or missing parent objects.

Isolate the stage by passing the directory name as a positional argument. Rerun the command with the --overwrite flag.

Table 6.2. Apply and validate errors

Error messageCauseSolution

Dependency order failure

The deployment command executed manifest files out of their required dependency order.

Rerun the mta-ops apply command with the --ordered flag.

Unknown resource type

A required custom resource definition (CRD) is missing.

Install the required Operator on the target cluster.

6.5. Resolving validation failures

To fix incompatibilities with your target cluster, review your validation artifacts. You must resolve missing custom resource definitions (CRDs) manually.

Prerequisites

  • You ran the mta-ops validate command and received a FAILED result.

Procedure

  1. Navigate to your specified validation output directory.
  2. Open the failures/ subdirectory.
  3. Inspect the generated YAML files. The file names indicate the specific group, version, and kind (GVK) that failed compatibility checks.

    • If a resource failed because a CRD is missing on the target cluster, install the required Operator on the target cluster.
    • If a resource failed because an API version is deprecated, create a custom transformation stage to rewrite the apiVersion field.
  4. Rerun the mta-ops validate command.

Verification

  • Verify that the mta-ops validate command returns a PASSED summary result.

6.6. Resolving transformation conflicts

To fix malformed Kustomize patches, isolate your transformation stages. You can inspect the exact input and output of a specific plugin.

Prerequisites

  • You ran the mta-ops transform command and encountered a patch evaluation error.

Procedure

  1. Navigate to your generated transform/ directory.
  2. Identify the specific numbered stage directory where the failure occurred.
  3. Compare the contents of the input/ directory against the output/ directory for that stage.
  4. If the failure occurred in a custom stage, modify your kustomization.yaml file to correct the syntax error.
  5. Rerun the isolated custom stage:

    $ mta-ops transform <custom_stage_directory> -e export -t transform --overwrite

Verification

  • Verify that the isolated stage executes successfully and produces the expected YAML in the output/ directory.

Appendix A. mta-ops command options

Review the command-line options and parameters available in the migration toolkit for applications (MTA) mta-ops command-line interface (CLI). Use these flags to customize the export, transformation, manifest rendering, target cluster validation, and persistent volume replication stages.

A.1. Global mta-ops flags

Review the available global flags that apply to all mta-ops subcommands.

Table A.1. Global mta-ops flags

OptionShorthandDescription

--audit-log

 

Specifies the destination path for the persistent JSON Lines audit log file (default: audit/.crane-audit.log).

--debug

 

Enables verbose debug-level log output to the terminal during command execution.

--flags-file

-f

Specifies an input file containing a YAML representation of CLI flags. Explicit command-line arguments take precedence over values defined in the file.

--help

-h

Displays help information and available options for the specified command.

A.2. mta-ops export command options

Use the mta-ops export command options to customize the extraction of raw application manifests and cluster-scoped dependencies from the source cluster.

Table A.2. mta-ops export flags

OptionShorthandDescription

--as

 

Username to impersonate for the export operation (regular user or ServiceAccount).

--as-extras

 

Extra impersonation parameters (for example, --as-extras key1=val1,val2;key2=val3). Requires --as or --as-group.

--as-group

 

Group name to impersonate for the export operation. Repeatable for multiple groups.

--as-uid

 

User ID to impersonate for the operation.

--burst

-b

Maximum allowed API burst rate limit (default: 1000).

--crd-include-group

 

Force-includes specific custom resource definition (CRD) API groups for export, even if built-in defaults skip them (repeatable).

--crd-skip-group

 

Additional API groups to skip during CRD export (repeatable).

--export-dir

-e

Local directory path where raw exported YAML manifests are saved (default: export).

--exclude-gk

 

Skips namespace resources matching the specified Kind or Group/Kind (repeatable).

--include-gk

 

Restricts export exclusively to namespace resources matching the specified Kind or Group/Kind (repeatable).

--label-selector

-l

Restricts export to namespace resources matching a label selector (for example, tier=frontend).

--namespace

-n

Target source namespace scope for the export operation.

--overwrite

 

Overwrites the export directory if it already exists on local disk.

--qps

-q

Queries-per-second (QPS) rate limit for the Kubernetes API connection (default: 100).

--context

 

Specifies the kubeconfig context name of the source cluster.

--kubeconfig

 

Path to the kubeconfig file used for source cluster authentication.

A.3. mta-ops transform command options

Use the mta-ops transform command options to control the execution sequence of built-in and custom transformation plugins, pass plugin parameters, and manage stage overlays.

Table A.3. mta-ops transform flags

OptionShorthandDescription

--export-dir

-e

Directory path containing raw exported manifests to process (default: export).

--instructions-file

 

Path to a declarative YAML instructions file defining stage ordering and plugin parameters.

--kustomize-args

 

Additional argument string passed to the embedded Kustomize engine (for example, '--enable-helm').

--optional-flags

 

Global JSON string containing key-value pairs passed to all active plugins (for example, '{"registry-replacement":"docker.io=quay.io"}').

--overwrite

 

Overwrites existing stage directories, including user-modified custom stages.

--plugin-dir

-p

Directory path where binary plugin executables are located (default: ~/.local/share/crane/plugins).

--skip-plugins

-s

Comma-separated list of built-in plugins to skip during transformation (for example, OpenShiftPlugin).

--stage-optionals

 

Per-stage optional flags specified as StageName=JSON string pairs (repeatable).

--transform-dir

-t

Directory path where transformation stage outputs and overlays are created (default: transform).

A.4. mta-ops apply command options

Use the mta-ops apply command options to render transformed Kustomize overlays into deployable YAML resource files on local disk.

Table A.4. mta-ops apply flags

OptionShorthandDescription

--kustomize-args

 

Additional arguments passed to the embedded Kustomize rendering engine.

--ordered

 

Prefixes generated resource filenames with 3-digit order numbers (for example, 001_Namespace_*, 300_Role_*) to enforce dependency-aware deployment order.

--output-dir

-o

Local directory path where final deployable manifests are saved (default: output).

--overwrite

 

Overwrites the output directory if it already exists on local disk.

--skip-cluster-scoped

 

Excludes cluster-scoped resources (ClusterRole, ClusterRoleBinding, CustomResourceDefinition, SecurityContextConstraints) from output rendering for non-admin migrations.

--transform-dir

-t

Directory path containing completed transformation stages to render (default: transform).

A.5. mta-ops validate command options

Use the mta-ops validate command options to perform preflight API compatibility checks against a target cluster or an offline API surface snapshot file.

Table A.5. mta-ops validate flags

OptionShorthandDescription

--api-resources

 

Path to an API surface JSON file (captured by capture-api-surface.sh) for offline validation in air-gapped environments. Mutually exclusive with live cluster connection parameters (--context, --kubeconfig, --server, --token).

--input-dir

-i

Path to the directory containing final rendered manifests to validate (default: output).

--output

-o

File format for the generated validation report (json or yaml, default: json).

--overwrite

 

Overwrites the validation report directory if it already exists on local disk.

--validate-dir

 

Directory path where validation reports and failure artifacts are saved (default: validate).

--context

 

Specifies the kubeconfig context name of the live target cluster for online validation.

--kubeconfig

 

Path to the kubeconfig file used for target cluster authentication.

--server

-s

Address and port of the target Kubernetes API server.

--token

 

Bearer token used for live target cluster API authentication.

A.6. mta-ops transfer-pvc command options

Use the mta-ops transfer-pvc command options to configure direct cluster-to-cluster volume replication, indirect S3 cloud storage replication, or same-cluster StorageClass conversions.

Table A.6. mta-ops transfer-pvc flags

OptionShorthandDescription

--cloud-storage

 

Enables indirect data transfer through an S3-compatible cloud storage target (for example, s3:<bucket_name>/<folder_path>).

--dest-storage-class

 

Target StorageClass for destination volumes during same-cluster or cross-cluster conversions.

--dest-storage-requests

 

Requested storage capacity for the destination persistent volume claim (PVC), for example, 10Gi.

--destination-context

 

Name of the target cluster context in the local kubeconfig file.

--destination-image

 

Container image used for the worker pod on the destination cluster (default: registry.redhat.io/mta/mta-rsync-transfer-rhel9:8.3.0).

--encrypt

 

Enables client-side encryption for indirect transfer.

--endpoint

 

Networking endpoint type for direct tunneling (route for OpenShift, nginx-ingress for Kubernetes).

--ingress-class

 

IngressClass name to use when --endpoint is set to nginx-ingress.

--keep-cloud-data

 

Skips automatic deletion of cloud storage backup objects after indirect transfer completes.

--output

 

Writes data transfer statistics and operational summary to the specified file.

--pvc-name

 

Name of the PVC to transfer. Optionally specify name remapping as <source_pvc_name>:<destination_pvc_name>.

--pvc-namespace

 

Namespace containing the source PVC. Optionally specify namespace remapping as <source_namespace>:<destination_namespace>.

--rclone-config-file

 

Path to a local rclone.conf credential file for indirect cloud transfers.

--rclone-config-secret

 

Name of a pre-existing Kubernetes Secret containing rclone credentials on both clusters.

--source-context

 

Name of the source cluster context in the local kubeconfig file.

--source-image

 

Container image used for the worker pod on the source cluster (default: registry.redhat.io/mta/mta-rsync-transfer-rhel9:8.3.0).

--subdomain

 

Custom subdomain string for ingress endpoint routing.

--verify

 

Enables post-transfer data checksum verification between source and target volumes.

Appendix B. Developer and architecture guides

When you want to extend the mta-ops command-line interface (CLI) or understand its internal mechanics, review the upstream developer guides. This helps you build custom plugins or contribute to the project.

The mta-ops repository contains comprehensive documentation for developers:

  • CONTRIBUTING.md: Located at the root of the repository, detailing the GitHub integration and contributor onboarding workflow.
  • Development guides (docs/development/): Contains dedicated documents for local environment setup, unit and end-to-end (E2E) testing conventions, and end-to-end pipeline architecture.
  • Plugin development: Comprehensive instructions on creating custom transformation plugins using Go or Bash.

Legal Notice

Copyright © 2026 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.