Migrate your Mission Control installation from Replicated to ICR
Replicated is no longer supported as an installation method for Mission Control. If you have an existing Replicated installation, you must migrate it to IBM Container Registry (ICR). You can do this by switching the image pull source from Replicated to ICR without reinstalling Mission Control.
|
Restarting
Additionally, Mission Control control plane pods restart in a rolling fashion during the Helm upgrade and are briefly unavailable regardless of replication factor. DataStax recommends that you schedule a maintenance window before you proceed. |
Migrate a Helm-based Replicated installation
Use this option if you installed Mission Control directly with helm install from the Replicated proxy registry without the KOTS admin console.
Otherwise, see KOTS-based installation.
Set environment variables
-
Make sure you have the following:
-
The Helm release name used during the original Replicated installation.
-
The namespace where Mission Control is installed.
-
All namespaces that host database clusters managed by this Mission Control instance.
-
An IBM entitlement key from the IBM Container Library. This is required to pull the following images from
cp.icr.io:cql-router,cqlsh(cqlsh-pod),hcd, anddse(dse-mgmtapi). Public Mission Control images (mission-control,mission-control-ui,mission-control-dex,k8ssandra-client) are served from the non-entitledicr.ioregistry, and they do not require the entitlement key. -
The Mission Control version currently installed. You must migrate to the same version.
-
The original
values.yamlfiles used for the original Helm install. -
The pull secret name used during the original Replicated installation, typically
${RELEASE_NAME}-registry. For example, if your release name ismission-control, usemission-control-registry.
-
-
Set the following environment variables in your terminal using the information you collected in the previous step:
export RELEASE_NAME=RELEASE_NAME export MC_NAMESPACE=NAMESPACE export CLUSTER_NAMESPACES="NAMESPACE1 NAMESPACE2 NAMESPACE3" export IBM_ENTITLEMENT_KEY=ENTITLEMENT_KEY export TARGET_VERSION=VERSION export ORIGINAL_VALUES_FILE=VALUES_FILE export PULL_SECRET_NAME=PULL_SECRET
Upgrade the pull secret
Update the registry pull secret in the Mission Control namespace only. The Mission Control operator automatically replicates it to all cluster namespaces.
Replicated creates the pull secret during installation using the naming convention RELEASE_NAME-registry.
For a release named mission-control, the secret is mission-control-registry.
This existing secret is updated in place.
It is already referenced in helm-overrides.yaml under global.imageConfig.defaults.pullSecrets.
kubectl create secret docker-registry ${RELEASE_NAME}-registry \
--docker-server=cp.icr.io \
--docker-username=cp \
--docker-password=${IBM_ENTITLEMENT_KEY} \
--namespace=${MC_NAMESPACE} \
--dry-run=client -o yaml | kubectl apply -f -
|
The |
Run helm upgrade with ICR overrides
Run helm upgrade with your original values files and helm-overrides.yaml.
The overrides file is applied last so its values take precedence, redirecting all image references from the Replicated proxy to icr.io and cp.icr.io.
|
The version must match the currently installed release.
Set Don’t use this migration process as an upgrade shortcut. If you want to upgrade the version, you must do so after migrating your installation. |
-
Create an ICR overrides file named
overrides.yamlwith the following content, and replacingPULL_SECRET_NAMEwith your pull secret name:# Disable replicated replicated: enabled: false disablePullSecretsGeneration: true # MC operator image: registry: icr.io repository: datastax-mission-control/mission-control # MC UI ui: image: registry: icr.io repository: datastax-mission-control/mission-control-ui # CRD patcher client: image: registry: icr.io repository: datastax-mission-control/k8ssandra-client global: # Image pull secret for entitled images imageConfig: defaults: pullSecrets: - **PULL_SECRET_NAME** # <RELEASE_NAME>-registry images: k8ssandra-client: registry: icr.io repository: datastax-mission-control name: k8ssandra-client cql-router: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control cqlsh: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control types: hcd: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control name: hcd dse: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control name: dse-mgmtapi # MC Dex dex: image: repository: icr.io/datastax-mission-control/mission-control-dex -
Run the upgrade.
If you used more than one
-fflag during the original installation, supply them all in the same order, then append-f helm-overrides.yamlas the final entry. Files are read in order and later files take precedence.helm upgrade ${RELEASE_NAME} oci://icr.io/mission-control-helm/mission-control \ --version ${TARGET_VERSION} \ -n ${MC_NAMESPACE} \ -f ${ORIGINAL_VALUES_FILE} \ -f helm-overrides.yaml \ --server-side true -
Monitor the rollout until all Mission Control pods are
Runningwith images pulled fromicr.ioorcp.icr.io:-
Monitor the deployment rollout:
kubectl rollout status deployment -n ${MC_NAMESPACE} --timeout=10m -
Confirm image sources:
kubectl get pods -n ${MC_NAMESPACE} \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{"\n"}{end}{end}'All images should reference
icr.io/datastax-mission-control/…orcp.icr.io/cp/ibm-ds-mission-control/…. If any pod is inImagePullBackOff, verify that the pull secret contains a validcp.icr.ioentry.
-
Restart cass-operator
|
Restarting |
After the Helm upgrade, the CassandraDatacenter resources carry updated image configuration pointing to cp.icr.io.
Restarting cass-operator causes it to pick up the new configuration and reconcile the database StatefulSets.
-
Identify the
cass-operatordeployment:kubectl get deployments -n ${MC_NAMESPACE} | grep cass-operator -
Restart
cass-operator:kubectl rollout restart deployment/cass-operator -n ${MC_NAMESPACE} -
Wait for the operator to be ready:
kubectl rollout status deployment/cass-operator -n ${MC_NAMESPACE} --timeout=3m -
Watch database pod restarts, repeating for each namespace that contains database pods:
kubectl get pods -n CLUSTER_NAMESPACE -wReplace
CLUSTER_NAMESPACEwith each cluster namespace. -
Confirm image sources, repeating for each cluster namespace:
kubectl get pods -n CLUSTER_NAMESPACE \ -o jsonpath='{range .items[]}{.metadata.name}{"\t"}{range .spec.containers[]}{.image}{"\n"}{end}{end}'All HCD and DSE containers should reference
cp.icr.io/cp/ibm-ds-mission-control/hcd:…orcp.icr.io/cp/ibm-ds-mission-control/dse-mgmtapi:…. -
Confirm the
CassandraDatacenterresources report a healthy status (READY = true, PROGRESS = false)kubectl get cassandradatacenter -A
KOTS-based installation
Use this option if you installed Mission Control with the KOTS admin console using kubectl kots install or through the Replicated vendor portal.
Otherwise, see Migrate a Helm-based Replicated installation.
When Mission Control is installed through KOTS, the admin console owns the Helm release.
It renders all repl{{ }} template expressions from the admin-console configuration screen into concrete Helm values before each deploy.
The migration involves three logical phases:
-
Extract: Capture the effective Helm values that KOTS currently has deployed.
-
Hand off: Stop KOTS from reconciling the release so that plain
helmcommands take over. -
Upgrade: Perform an ICR-redirect upgrade.
Set environment variables
-
Make sure you have the following:
-
The Helm release name, typically
mission-control. -
The namespace where Mission Control is installed, typically
mission-control. -
All namespaces that host database clusters managed by this Mission Control instance.
-
An IBM entitlement key from the IBM Container Library. This is required to pull the following images from
cp.icr.io:cql-router,cqlsh(cqlsh-pod),hcd, anddse(dse-mgmtapi). Public Mission Control images (mission-control,mission-control-ui,mission-control-dex,k8ssandra-client) are served from the non-entitledicr.ioregistry, and they do not require the entitlement key. -
The Mission Control version currently deployed by KOTS. You must migrate to the same version. You can verify the version with
helm list -n ${MC_NAMESPACE}. -
The namespace where the KOTS admin console is running, typically
mission-controlor a dedicatedkotsadmnamespace. -
The pull secret name, typically
${RELEASE_NAME}-registry. For example, if your release name ismission-control, usemission-control-registry. The pull secret is required for the entitled images:cql-router,cqlsh(cqlsh-pod),hcd, anddse(dse-mgmtapi).
-
-
Set the following environment variables in your terminal using the information you collected in the previous step:
export RELEASE_NAME=RELEASE_NAME export MC_NAMESPACE=NAMESPACE export CLUSTER_NAMESPACES="NAMESPACE1 NAMESPACE2 NAMESPACE3" export IBM_ENTITLEMENT_KEY=ENTITLEMENT_KEY export TARGET_VERSION=VERSION export KOTSADM_NAMESPACE=KOTSADM_NAMESPACE export PULL_SECRET_NAME=PULL_SECRET
Construct the Helm values file from exported KOTS values
KOTS renders your admin-console configuration (Deployment Mode, TLS, observability storage, Dex, ingress, and other settings) into Helm values at deploy time. Before you disable KOTS, capture the full set of values that are currently deployed.
The exported values file forms the base of your new Helm-managed installation, and it must be preserved.
-
Export the values:
helm get values ${RELEASE_NAME} -n ${MC_NAMESPACE} -o yaml > kots-current-values.yaml -
Review the exported values to verify that it contains all values KOTS passed to Helm, including:
-
Deployment mode (
controlPlane,controlPlaneRemote) -
TLS settings (
tls.generateCerts,tls.certDuration,tls.certRenewBefore) -
Dex configuration (issuer URL, LDAP/OIDC connectors, static passwords, TLS volumes)
-
Observability stack (Loki, Mimir, Minio - storage backends, bucket names, PVC sizes, replicas)
-
Ingress configuration
-
Security contexts
-
-
Create the base Helm values file:
cp kots-current-values.yaml my-values.yaml -
Add the following ICR overrides to your Helm values file, replacing
PULL_SECRET_NAMEwith your pull secret name,These fields disable the Replicated SDK and KOTS-managed pull secret generation, and then redirect all image references to ICR.
# Disable replicated SDK and KOTS pull secret generation replicated: enabled: false disablePullSecretsGeneration: true # MC operator image: registry: icr.io repository: datastax-mission-control/mission-control # MC UI ui: image: registry: icr.io repository: datastax-mission-control/mission-control-ui # CRD patcher client: image: registry: icr.io repository: datastax-mission-control/k8ssandra-client global: # Image pull secret for entitled images imageConfig: defaults: pullSecrets: - **PULL_SECRET_NAME** # <RELEASE_NAME>-registry images: k8ssandra-client: registry: icr.io repository: datastax-mission-control name: k8ssandra-client cql-router: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control cqlsh: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control types: hcd: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control name: hcd dse: # entitled — requires cp.icr.io pull secret registry: cp.icr.io repository: cp/ibm-ds-mission-control name: dse-mgmtapi # MC Dex dex: image: repository: icr.io/datastax-mission-control/mission-control-dex
Update the registry pull secret
KOTS creates the pull secret during installation.
Update the pull secret in the Mission Control namespace only. The Mission Control operator automatically replicates it to all cluster namespaces.
kubectl create secret docker-registry ${RELEASE_NAME}-registry \
--docker-server=cp.icr.io \
--docker-username=cp \
--docker-password=${IBM_ENTITLEMENT_KEY} \
--namespace=${MC_NAMESPACE} \
--dry-run=client -o yaml | kubectl apply -f -
|
The |
Disable KOTS reconciliation
KOTS continuously watches for configuration changes and redeploys the Helm release when it detects drift.
Scaling KOTS components to zero stops KOTS from redeploying over your upcoming helm upgrade.
The KOTS admin console UI is unavailable while scaled to zero, but Mission Control itself continues running.
-
Scale down all KOTS components to stop automated reconciliation before you run the Helm upgrade:
kubectl scale deployment kotsadm kotsadm-operator -n ${KOTSADM_NAMESPACE} --replicas=0 kubectl scale statefulset kotsadm-minio kotsadm-rqlite -n ${KOTSADM_NAMESPACE} --replicas=0 -
Verify all KOTS pods have terminated:
kubectl get pods -n ${KOTSADM_NAMESPACE} | grep kotsadmAll KOTS pods must not be in a
Runningstate before proceeding.
Run helm upgrade with ICR overrides
With KOTS inactive, you must run helm upgrade directly.
|
Your current and target versions must match exactly.
Set Don’t use this migration process as an upgrade shortcut. If you want to upgrade the version, you must do so after migrating your installation. |
-
Run
helm upgradewith your Helm ICR overridesvalues.yamlfile that you created earlier, which already contains all the KOTS-managed settings:helm upgrade ${RELEASE_NAME} oci://icr.io/mission-control-helm/mission-control \ --version ${TARGET_VERSION} \ -n ${MC_NAMESPACE} \ -f my-values.yaml \ --server-side true -
Monitor the deployment rollout:
kubectl rollout status deployment -n ${MC_NAMESPACE} --timeout=10m -
Confirm image sources:
kubectl get pods -n ${MC_NAMESPACE} \ -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{range .spec.containers[*]}{.image}{"\n"}{end}{end}'All images should reference
icr.io/datastax-mission-control/…orcp.icr.io/cp/ibm-ds-mission-control/….If any pod is in
ImagePullBackOff, verify that the pull secret contains a validcp.icr.ioentry.
Restart cass-operator
After the Helm upgrade, the CassandraDatacenter resources carry updated image configuration pointing to cp.icr.io.
Restarting cass-operator causes it to pick up the new configuration and reconcile the database StatefulSets.
-
Identify the
cass-operatordeployment:kubectl get deployments -n ${MC_NAMESPACE} | grep cass-operator -
Restart
cass-operator:kubectl rollout restart deployment/cass-operator -n ${MC_NAMESPACE} -
Wait for the operator to be ready:
kubectl rollout status deployment/cass-operator -n ${MC_NAMESPACE} --timeout=3m -
Watch database pod restarts, repeating for each namespace that contains database pods:
kubectl get pods -n CLUSTER_NAMESPACE -wReplace
CLUSTER_NAMESPACEwith each cluster namespace. -
Confirm image sources, repeating for each cluster namespace:
kubectl get pods -n CLUSTER_NAMESPACE \ -o jsonpath='{range .items[]}{.metadata.name}{"\t"}{range .spec.containers[]}{.image}{"\n"}{end}{end}'All HCD and DSE containers should reference
cp.icr.io/cp/ibm-ds-mission-control/hcd:…orcp.icr.io/cp/ibm-ds-mission-control/dse-mgmtapi:…. -
Confirm the
CassandraDatacenterresources report a healthy status (READY = true, PROGRESS = false):kubectl get cassandradatacenter -A
Remove KOTS
Once the Helm-managed installation is verified and stable, remove KOTS entirely.
This step is irreversible.
The KOTS admin console and all its associated resources are deleted.
Mission Control itself is not affected and continues to run.
You can manage it with plain helm upgrade commands.
|
Delete the resources directly with Because you scaled |
-
Delete KOTS deployments and StatefulSets:
kubectl delete deployment kotsadm kotsadm-operator -n ${KOTSADM_NAMESPACE} --ignore-not-found kubectl delete statefulset kotsadm-minio kotsadm-rqlite -n ${KOTSADM_NAMESPACE} --ignore-not-found -
Delete KOTS services:
kubectl delete service kotsadm kotsadm-http -n ${KOTSADM_NAMESPACE} --ignore-not-found -
Delete KOTS PersistentVolumeClaims:
# Verify the exact PVC names first kubectl get pvc -n ${KOTSADM_NAMESPACE} # Delete the PVCs kubectl delete pvc -n ${KOTSADM_NAMESPACE} \ -l app=kotsadm-minio \ --ignore-not-found kubectl delete pvc -n ${KOTSADM_NAMESPACE} \ -l app=kotsadm-rqlite \ --ignore-not-found -
Delete KOTS-owned secrets and ConfigMaps:
kubectl delete secret -n ${KOTSADM_NAMESPACE} -l kots.io/kotsadm=true --ignore-not-found kubectl delete configmap -n ${KOTSADM_NAMESPACE} -l kots.io/kotsadm=true --ignore-not-found