Skip to content

Commit

Permalink
Update documents and prepare for a new release
Browse files Browse the repository at this point in the history
  • Loading branch information
ymmt2005 committed Apr 26, 2021
1 parent 79e1423 commit f2ad972
Show file tree
Hide file tree
Showing 30 changed files with 697 additions and 380 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
- run: make test
- run: make check-generate
- run: make envtest
- run: make release-build
test-dbop:
name: Test pkg/dbop
strategy:
Expand Down
47 changes: 8 additions & 39 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- run: docker build . -t moco:dev
- run: docker build -t moco:dev .
- name: Login to ghcr.io
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
- run: docker tag moco:dev ghcr.io/cybozu-go/moco:${GITHUB_REF#refs/tags/v}
Expand All @@ -25,44 +25,13 @@ jobs:
- uses: actions/setup-go@v2
with:
go-version: ${{ env.go-version }}
- run: |
make release-build
- run: make release-build
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: |
See [CHANGELOG.md](./CHANGELOG.md) for details.
draft: false
prerelease: ${{ contains(github.ref, '-') }}
- name: Upload kubectl-moco for linux-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./build/kubectl-moco-linux-amd64
asset_name: kubectl-moco-linux-amd64
asset_content_type: application/octet-stream
- name: Upload kubectl-moco for windows-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./build/kubectl-moco-windows-amd64.exe
asset_name: kubectl-moco-windows-amd64.exe
asset_content_type: application/octet-stream
- name: Upload kubectl-moco for darwin-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./build/kubectl-moco-darwin-amd64
asset_name: kubectl-moco-darwin-amd64
asset_content_type: application/octet-stream
run: |
tagname="${GITHUB_REF#refs/tags/}"
if echo ${{ github.ref }} | grep -q -e '-'; then prerelease=-p; fi
gh release create -t "Release $tagname" $prerelease \
-n "See [CHANGELOG.md](./CHANGELOG.md) for details." \
"$tagname" build/*
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [0.8.0] - 2021-04-27

### Changed
- Everything. There is no backward compatibility. (#228)
- The older release must be uninstalled before installing this version.

## [0.7.0] - 2021-02-22

Since v0.7.0, MOCO will no longer use CronJob for log rotation.
Expand Down Expand Up @@ -131,7 +137,8 @@ The `MySQLCluster` created by MOCO `< v0.5.0` has no compatibility with `>= v0.5

- Bootstrap a vanilla MySQL cluster with no replicas (#2).

[Unreleased]: https://github.com/cybozu-go/moco/compare/v0.7.0...HEAD
[Unreleased]: https://github.com/cybozu-go/moco/compare/v0.8.0...HEAD
[0.8.0]: https://github.com/cybozu-go/moco/compare/v0.8.0...v0.8.0
[0.7.0]: https://github.com/cybozu-go/moco/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/cybozu-go/moco/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/cybozu-go/moco/compare/v0.5.0...v0.5.1
Expand Down
45 changes: 45 additions & 0 deletions DEVELOP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# How to develop MOCO

## Running tests

MOCO has the following 4 kinds of tests:

1. Tests that do not depend on MySQL or Kubernetes
2. `pkg/dbop` tests that depend on MySQL version
3. Tests that depend on Kubernetes and therefore run by controller-runtime's envtest
4. End-to-end tests

To run these tests, use the following make targets respectively:

1. `make test`
2. `make test-dbop`
3. `make envtest`
4. Read [`e2e/README.md`](e2e/README.md)

## Generated files

Some files in the repository are auto-generated.

- [`docs/crd_mysqlcluster.md`](docs/crd_mysqlcluster.md) is generated by `make apidoc`.
- Some files under `config` are generated by `make manifests`.
- `api/**/*.deepcopy.go` are generated by `make generate`.

CI checks and fails if they need to be rebuilt.

## Testing with unreleased moco-agent

MOCO depends on [moco-agent][] that is released from a different repository.
The dependency is therefore managed in `go.mod` file.

To run e2e tests with an unreleased moco-agent, follow the instructions in
[`e2e/README.md`](e2e/README.md).

## Updating moco-agent

Run `go get github.com/cybozu-go/moco-agent@latest`.

## Updating fluent-bit

Edit `FluentBitImage` in [`version.go`](versoin.go).

[moco-agent]: https://github.com/cybozu-go/moco-agent
23 changes: 22 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ SHELL = /bin/bash
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS = "crd:crdVersions=v1"

# for Go
GOOS = $(shell go env GOOS)
GOARCH = $(shell go env GOARCH)
SUFFIX =

.PHONY: all
all: build

Expand Down Expand Up @@ -49,7 +54,7 @@ generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and
.PHONY: apidoc
apidoc: crd-to-markdown $(wildcard api/*/*_types.go)
echo $(wildcard api/*/*_types.go)
$(CRD_TO_MARKDOWN) -f api/v1beta1/mysqlcluster_types.go -n MySQLCluster > docs/crd_mysqlcluster.md
$(CRD_TO_MARKDOWN) --links docs/links.csv -f api/v1beta1/mysqlcluster_types.go -n MySQLCluster > docs/crd_mysqlcluster.md

.PHONY: check-generate
check-generate:
Expand Down Expand Up @@ -97,6 +102,22 @@ build:
mkdir -p bin
GOBIN=$(shell pwd)/bin go install ./cmd/...

.PHONY: release-build
release-build: kustomize
mkdir -p build
$(MAKE) kubectl-moco GOOS=windows GOARCH=amd64 SUFFIX=.exe
$(MAKE) kubectl-moco GOOS=darwin GOARCH=amd64
$(MAKE) kubectl-moco GOOS=darwin GOARCH=arm64
$(MAKE) kubectl-moco GOOS=linux GOARCH=amd64
$(MAKE) kubectl-moco GOOS=linux GOARCH=arm64
$(KUSTOMIZE) build . > build/moco.yaml

.PHONY: kubectl-moco
kubectl-moco: build/kubectl-moco-$(GOOS)-$(GOARCH)$(SUFFIX)

build/kubectl-moco-$(GOOS)-$(GOARCH)$(SUFFIX):
CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ ./cmd/kubectl-moco

##@ Tools

CONTROLLER_GEN := $(shell pwd)/bin/controller-gen
Expand Down
118 changes: 95 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,117 @@
[![GitHub release](https://img.shields.io/github/release/cybozu-go/moco.svg?maxAge=60)][releases]
[![CircleCI](https://circleci.com/gh/cybozu-go/moco.svg?style=svg)](https://circleci.com/gh/cybozu-go/moco)
[![CI](https://github.com/cybozu-go/moco/actions/workflows/ci.yaml/badge.svg)](https://github.com/cybozu-go/moco/actions/workflows/ci.yaml)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/cybozu-go/moco)](https://pkg.go.dev/github.com/cybozu-go/moco)
[![Go Report Card](https://goreportcard.com/badge/github.com/cybozu-go/moco)](https://goreportcard.com/report/github.com/cybozu-go/moco)

# MOCO

MOCO is a Kubernetes operator for MySQL.
Its primary function is to manage a cluster of MySQL using binlog-based, semi-synchronous replication.
MOCO is a Kubernetes operator for [MySQL][].
Its primary function is to manage MySQL clusters using [GTID-based](https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html) [semi-synchronous](https://dev.mysql.com/doc/refman/8.0/en/replication-semisync.html) replication. It does _not_ manage [group replication](https://dev.mysql.com/doc/refman/8.0/en/group-replication.html) clusters.

MOCO is designed for the following properties:
MOCO is designed to have the following properties.

- Durability
- Do not lose any data under a given degree of faults.
- Compatibility with the standard MySQL
- This is the reason that MOCO does not adopt group replication that has [a number of limitations](https://dev.mysql.com/doc/refman/8.0/en/group-replication-limitations.html).
- 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](https://www.percona.com/blog/2014/05/19/errant-transactions-major-hurdle-for-gtid-based-failover-in-mysql-5-6/).
- Availability
- Keep the MySQL cluster available under a given degree of faults.
- Business Continuity
- Perform a quick recovery if some failure is occurred.
- MOCO can quickly switch the primary in case of the primary failure or restart.
- MOCO allows up to 5 instances in a cluster.

## Features

TBD
## Supported software

## Supported MySQL versions
- MySQL: 8.0.18, 8.0.20, and 8.0.24
- Kubernetes: 1.19 and 1.20

8.0.18 and 8.0.20
Other versions may work, though not tested.

## Supported Kubernetes version
## Features

1.20 and 1.19
- Cluster of 1, 3, or 5 MySQL instances
- Replication from an external MySQL instance
- Manual and automatic switchover of the primary instance
- Automatic failover of the primary instance
- Errant transaction detection
- Different MySQL versions for each cluster
- Upgrading MySQL version of a cluster
- Monitor for replication delays
- Service for the primary and replicas, respectively
- Custom `my.cnf` configurations
- Custom Pod, Service, and PersistentVolumeClaim templates
- Redirect slow query logs to a sidecar container
- (planning) Backup and [Point-in-Time Recovery](https://dev.mysql.com/doc/refman/8.0/en/point-in-time-recovery-positions.html)

## Quick start

You can quickly run MOCO using [kind](https://kind.sigs.k8s.io/).

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:

```console
$ cat > mycluster.yaml <<'EOF'
apiVersion: moco.cybozu.com/v1beta1
kind: MySQLCluster
metadata:
namespace: default
name: test
spec:
replicas: 3
podTemplate:
spec:
containers:
- name: mysqld
image: quay.io/cybozu/moco-mysql:8.0.24
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:

```console
$ ../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.

```console
$ ../bin/kubectl moco mysql -it test
```

To destroy the Kubernetes cluster, run:

```console
$ make stop
```

## Documentation

[docs](docs/) directory contains documents about designs and specifications.
- [`docs/setup.md`](docs/setup.md) for installing MOCO.
- [`docs/usage.md`](docs/usage.md) is the user manual of MOCO.
- [`examples`](examples/) directory contains example MySQLCluster manifests.

## Docker images

Docker images are available on [Quay.io](https://quay.io/repository/cybozu/moco)
[`docs`](docs/) directory also contains other design or specification documents.

## License
## Docker images

MOCO is licensed under MIT license.
Docker images are available on [ghcr.io/cybozu-go/moco](https://github.com/orgs/cybozu-go/packages/container/package/moco).

[releases]: https://github.com/cybozu-go/moco/releases
[godoc]: https://godoc.org/github.com/cybozu-go/moco
[MySQL]: https://www.mysql.com/
33 changes: 18 additions & 15 deletions clustering/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,22 +93,25 @@ func (a *mockAgentConn) Clone(ctx context.Context, in *agent.CloneRequest, opts
}

func setPodReadiness(ctx context.Context, name string, ready bool) {
pod := &corev1.Pod{}
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "test", Name: name}, pod)
ExpectWithOffset(1, err).NotTo(HaveOccurred())

if ready {
pod.Status.Conditions = []corev1.PodCondition{
{
Type: corev1.PodReady,
Status: corev1.ConditionTrue,
},
EventuallyWithOffset(1, func() error {
pod := &corev1.Pod{}
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "test", Name: name}, pod)
if err != nil {
return err
}
} else {
pod.Status.Conditions = nil
}
err = k8sClient.Status().Update(ctx, pod)
ExpectWithOffset(1, err).NotTo(HaveOccurred())

if ready {
pod.Status.Conditions = []corev1.PodCondition{
{
Type: corev1.PodReady,
Status: corev1.ConditionTrue,
},
}
} else {
pod.Status.Conditions = nil
}
return k8sClient.Status().Update(ctx, pod)
}).Should(Succeed())
}

type mockAgentFactory struct {
Expand Down
2 changes: 1 addition & 1 deletion clustering/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var mysqlPassword *password.MySQLPassword
func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail)

SetDefaultEventuallyTimeout(10 * time.Second)
SetDefaultEventuallyTimeout(30 * time.Second)
SetDefaultEventuallyPollingInterval(100 * time.Millisecond)
SetDefaultConsistentlyDuration(3 * time.Second)
SetDefaultConsistentlyPollingInterval(100 * time.Millisecond)
Expand Down
2 changes: 1 addition & 1 deletion controllers/mysql_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func (r *MySQLClusterReconciler) makeV1InitContainer(cluster *mocov1beta1.MySQLC
Image: image,
Command: []string{
constants.InitCommand,
"--base-dir=" + constants.MySQLDataPath,
"--data-dir=" + constants.MySQLDataPath,
"--conf-dir=" + constants.MySQLInitConfPath,
fmt.Sprintf("%d", cluster.Spec.ServerIDBase),
},
Expand Down
Loading

0 comments on commit f2ad972

Please sign in to comment.