Skip to content

Rate this page
☆ ☆ ☆ ☆ ☆
Thanks for your feedback
Thank you! The feedback has been submitted.

Get free database assistance or contact our experts for personalized support.

Change replication type

The Operator deploys Percona Server for MySQL with group-replication and HAProxy by default.

Starting with Operator 1.3.0, you can change the replication type on a running cluster. The Operator tears down the current topology, recreates the MySQL and proxy workloads, and bootstraps the new type on the existing PersistentVolumeClaims. Users, Secrets, and the HAProxy Service stay in place, so applications keep the same endpoint if they already use HAProxy.

To compare the two types, see Replication types.

In Operator 1.2.0 and earlier, you cannot change the type on a running cluster. Pause the cluster, change the type, then unpause it.

Important

The switch causes downtime while Pods are deleted and the new topology comes up. It applies to the entire cluster. You cannot convert a single Group Replication member into a standalone async replica.

Change the proxy

HAProxy works with either replication type and is recommended. MySQL Router works only with Group Replication.

You can change from one proxy to another. See HAProxy and MySQL Router for the steps.

Change the replication type

Prerequisites

  • Percona Operator for MySQL 1.3.0 or later
  • The cluster is ready and is not a member of PerconaServerMySQLClusterSet. Dissolving Group Replication on a ClusterSet member breaks cross-site replication.
  • No backup, restore, upgrade, or PVC resize is in progress
  • You can accept a maintenance window. Writes fail until the cluster returns to ready.
  • Orchestrator is required for async replication. Enable it when you switch to async replication type. Disable it when you switch to group-replication.

How it works

When you change mysql.clusterType and apply the Custom Resource, the Operator compares the new value with the current cluster type in the status.clusterType field.

If the cluster is paused or not ready, the Operator waits. status.clusterType stays on the current type, and proxies and Orchestrator keep the existing topology.

When the cluster is ready, the Operator:

  1. Tears down the current topology:

    • From Group Replication — Dissolves the InnoDB Cluster and clears persisted group_replication_* variables so nodes do not rejoin the old group.
    • From async — Stops and resets replication channels. This step fails if the Orchestrator is still enabled.
  2. Deletes the MySQL StatefulSet. If the HAProxy StatefulSet and the MySQL Router Deployment are enabled, the Operator deletes them too.

  3. Sets status.clusterType to the new type, recreates those workloads, and bootstraps the new replication type on the existing PVCs.

The switch is finished when the status.state is ready and the status.clusterType matches the spec.mysql.clusterType value in the Custom Resource. While the switch is in progress, the Operator emits the ClusterTypeSwitchInProgress condition. The Operator removes that condition when the cluster is ready under the new type.

During the switch, the cluster leaves ready and application connections drop until HAProxy (or Router) is ready. If you used MySQL Router and switch to async, update connection strings to the HAProxy Service.

After the switch, failover works through the new topology: group membership for Group Replication, Orchestrator for async.

Before you start

  1. Export the namespace and cluster name:

    export NAMESPACE=<namespace>
    export CLUSTER_NAME=ps-cluster1
    
  2. Confirm the cluster is ready:

    kubectl get ps $CLUSTER_NAME -n $NAMESPACE
    
    Sample output
    NAME          REPLICATION          ENDPOINT                     STATE   MYSQL   ORCHESTRATOR   HAPROXY   ROUTER   AGE
    ps-cluster1   group-replication    ps-cluster1-haproxy.default  ready   3                      3                 27m
    
  3. Take an on-demand backup so you can restore if the switch does not complete.

  4. If you are switching to async and the cluster uses MySQL Router, enable HAProxy and disable Router first. Wait until the cluster is ready again.

Switch from group replication to async

Enable Orchestrator in the same change. Keep HAProxy enabled and disable MySQL Router if it is on.

kubectl patch ps $CLUSTER_NAME -n $NAMESPACE --type=merge --patch '{
  "spec": {
    "mysql": {
      "clusterType": "async"
    },
    "orchestrator": {
      "enabled": true
    },
    "proxy": {
      "haproxy": {
        "enabled": true
      },
      "router": {
        "enabled": false
      }
    }
  }
}'
  1. Edit deploy/cr.yaml:

    spec:
      mysql:
        clusterType: async
      orchestrator:
        enabled: true
      proxy:
        haproxy:
          enabled: true
        router:
          enabled: false
    
  2. Apply the change:

    kubectl apply -f deploy/cr.yaml -n $NAMESPACE
    

Wait until the cluster is ready and the status.clusterType is async. Orchestrator and HAProxy report ready replicas.

kubectl get ps $CLUSTER_NAME -n $NAMESPACE

See Verify the switch.

Switch from async to group replication

Disable Orchestrator in the same change. The Operator refuses the switch while Orchestrator is enabled.

kubectl patch ps $CLUSTER_NAME -n $NAMESPACE --type=merge --patch '{
  "spec": {
    "mysql": {
      "clusterType": "group-replication"
    },
    "orchestrator": {
      "enabled": false
    }
  }
}'
  1. Edit deploy/cr.yaml:

    spec:
      mysql:
        clusterType: group-replication
      orchestrator:
        enabled: false
    
  2. Apply the change:

    kubectl apply -f deploy/cr.yaml -n $NAMESPACE
    

Wait until the cluster is ready and the status.clusterType is group-replication. The Orchestrator column is empty. See Verify the switch.

Verify the switch

Confirm the applied type and the cluster state:

kubectl get ps $CLUSTER_NAME -n $NAMESPACE \
  -o jsonpath='{.status.state}{" "}{.status.clusterType}{"\n"}'

The output is ready and the type you switched to (async or group-replication).

Sample output
ready async

Check whether the switch is still in progress:

kubectl get ps $CLUSTER_NAME -n $NAMESPACE \
  -o jsonpath='{range .status.conditions[?(@.type=="ClusterTypeSwitchInProgress")]}{.type}{": "}{.status}{"\n"}{end}'

A finished switch returns no output.

Connect through HAProxy as described in Connect to Percona Server for MySQL and query a known table.

Optional. Confirm the new topology from inside a MySQL Pod.

Inspect the connection secret and extract the password:

PWD=$(kubectl -n $NAMESPACE get secret $CLUSTER_NAME-psuser-root -o jsonpath='{.data.password}' | base64 -d)
kubectl exec -it -n $NAMESPACE $CLUSTER_NAME-mysql-0 -c mysql -- \
  mysql -uroot -p"$PWD" -e "SELECT member_host, member_state, member_role FROM performance_schema.replication_group_members;"
Sample output
+-----------------------------------------------+--------------+-------------+
| member_host                                   | member_state | member_role |
+-----------------------------------------------+--------------+-------------+
| ps-cluster1-mysql-1.ps-cluster1-mysql.psmysql | ONLINE       | SECONDARY   |
| ps-cluster1-mysql-2.ps-cluster1-mysql.psmysql | ONLINE       | SECONDARY   |
| ps-cluster1-mysql-0.ps-cluster1-mysql.psmysql | ONLINE       | PRIMARY     |
+-----------------------------------------------+--------------+-------------+
kubectl exec -it -n $NAMESPACE $CLUSTER_NAME-mysql-0 -c mysql -- \
  mysql -uroot -p"$PWD" -e "SHOW REPLICA STATUS\G"

On the primary, replica status is empty. On replicas, the IO and SQL threads should report Yes.

Known limitations

If you switch from group replication to async and the Operator fails to bootstrap the new topology, you cannot switch the cluster back to group replication.

The Operator sets status.clusterType to async when it deletes the old workloads, before it finishes that bootstrap. If the bootstrap fails, the MySQL Pods cannot accept the connections the Operator needs to tear the async setup down. Setting mysql.clusterType back to group-replication does not restore the previous topology, and the cluster stays out of ready.

This limitation is known and will be fixed in a later release. Restore the cluster from the backup you took before the switch.

Operator 1.2.0 and earlier

Do not use this procedure with Operator 1.3.0 or later. Those versions require the cluster to stay ready.

  1. Pause the cluster:

    kubectl patch ps $CLUSTER_NAME -n $NAMESPACE --type json -p='[{"op":"add","path":"/spec/pause","value":true}]'
    
  2. Edit deploy/cr.yaml and set mysql.clusterType to async. Keep HAProxy enabled.

    mysql:
      clusterType: async
      ...
    proxy:
      haproxy:
        enabled: true
        ...
    
  3. Apply the configuration and unpause the cluster:

    kubectl apply -f deploy/cr.yaml -n $NAMESPACE
    kubectl patch ps $CLUSTER_NAME -n $NAMESPACE --type json -p='[{"op":"add","path":"/spec/pause","value":false}]'
    
  4. Wait until the cluster is resumed:

    kubectl get ps -n $NAMESPACE
    

Last update: October 5, 2026
Created: October 5, 2026