Skip to content

cybozu-go/moco

Repository files navigation

GitHub release CI PkgGoDev Go Report Card

MOCO

moco logo

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
  • 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

Supported software

  • MySQL: 8.0.28, 8.0.37, 8.0.39, 8.0.40, 8.4.3
  • 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.

Features

  • 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

Quick start

You can quickly run MOCO using kind.

  1. Prepare a Linux machine and install Docker.
  2. Checkout MOCO and go to e2e directory.
  3. 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.3
  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

Documentation

See https://cybozu-go.github.io/moco/

examples directory contains example MySQLCluster manifests.

Docker images

Docker images are available on ghcr.io/cybozu-go/moco.