MOCO is a MySQL operator on Kubernetes. Its primary function is to manage MySQL clusters using GTID-based semi-synchronous replication. It does not manage group replication clusters.
MOCO is designed to have the following properties.
- Compatibility with the standard MySQL
- This is the reason that MOCO does not adopt group replication that has a number of limitations.
- Safety
- MOCO only allows writes to a single instance called the primary at a time.
- MOCO configures loss-less semi-synchronous replication with sufficient replicas.
- MOCO detects and excludes instances having errant transactions.
- Availability
- MOCO can quickly switch the primary in case of the primary failure or restart.
- MOCO allows up to 5 instances in a cluster.
Blog article: Introducing MOCO, a modern MySQL operator on Kubernetes
- MySQL: 8.0.28, 8.0.36, 8.0.37, 8.0.39, 8.4.2
- Kubernetes: 1.29, 1.30, 1.31
MOCO supports (tests) the LTS releases of MySQL 8. Innovation releases would probably work. But they are not tested in our CI.
- Cluster with odd number of MySQL instances
kubectl
plugin- Replication from an external MySQL instance
- Manual and automatic switchover of the primary instance
- Automatic failover of the primary instance
- Backup and Point-in-Time Recovery
- Errant transaction detection
- Different MySQL versions for each cluster
- Upgrading MySQL version of a cluster
- Monitor for replication delays
- Built-in mysqld_exporter for
mysqld
metrics - Services for the primary and replicas, respectively
- Custom
my.cnf
configurations - Custom Pod, Service, and PersistentVolumeClaim templates
- Redirect slow query logs to a sidecar container
- Auto-generate PodDisruptionBudget
You can quickly run MOCO using kind.
- Prepare a Linux machine and install Docker.
- Checkout MOCO and go to
e2e
directory. - Run
make start
You can then create a three-instance MySQL cluster as follows:
$ cat > mycluster.yaml <<'EOF'
apiVersion: moco.cybozu.com/v1beta2
kind: MySQLCluster
metadata:
namespace: default
name: test
spec:
replicas: 3
podTemplate:
spec:
containers:
- name: mysqld
image: ghcr.io/cybozu-go/moco/mysql:8.4.2
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
EOF
$ export KUBECONFIG=$(pwd)/.kubeconfig
$ ../bin/kubectl apply -f mycluster.yaml
Check the status of MySQLCluster until it becomes healthy as follows:
$ ../bin/kubectl get mysqlcluster test
NAME AVAILABLE HEALTHY PRIMARY SYNCED REPLICAS ERRANT REPLICAS
test True True 0 3
Once it becomes healthy, you can use kubectl-moco
to play with mysql
client.
$ ../bin/kubectl moco mysql -it test
To destroy the Kubernetes cluster, run:
$ make stop
See https://cybozu-go.github.io/moco/
examples
directory contains example MySQLCluster manifests.
Docker images are available on ghcr.io/cybozu-go/moco.