Skip to content

Commit

Permalink
Merge pull request #252 from cybozu-go/opaque-config
Browse files Browse the repository at this point in the history
pkg/mycnf: add support for opaque configurations
  • Loading branch information
masa213f authored May 31, 2021
2 parents ab4ff24 + 932fc59 commit fe47af9
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 12 deletions.
48 changes: 38 additions & 10 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ After [setting up MOCO](setup.md), you can create MySQL clusters with a custom r
- [Creating an empty cluster](#creating-an-empty-cluster)
- [Creating a cluster that replicates data from an external mysqld](#creating-a-cluster-that-replicates-data-from-an-external-mysqld)
- [Bring your own image](#bring-your-own-image)
- [Configurations](#configurations)
- [Configurations](#configurations)
- [InnoDB buffer pool size](#innodb-buffer-pool-size)
- [Opaque configuration](#opaque-configuration)
- [Using the cluster](#using-the-cluster)
- [`kubectl moco`](#kubectl-moco)
- [MySQL users](#mysql-users)
Expand Down Expand Up @@ -181,11 +183,12 @@ To stop the replication from the donor, update MySQLCluster with `spec.replicati
We provide a pre-built MySQL container image at [quay.io/cybozu/moco-mysql](http://quay.io/cybozu/moco-mysql).
If you want to build and use your own image, read [`custom-mysqld.md`](custom-mysqld.md).

### Configurations
## Configurations

The configuration values for `mysqld` is available on [pkg.go.dev](https://pkg.go.dev/github.com/cybozu-go/moco/pkg/mycnf#pkg-constants). The settings in `ConstMycnf` cannot be changed while the settings in `DefaultMycnf` can be overridden.
The default and constant configuration values for `mysqld` are available on [pkg.go.dev](https://pkg.go.dev/github.com/cybozu-go/moco/pkg/mycnf#pkg-variables).
The settings in `ConstMycnf` cannot be changed while the settings in `DefaultMycnf` can be overridden.

To change some of the default values or to set a new option value, create a ConfigMap in the same namespace as MySQLCluster like this.
You can change the default values or set undefined values by creating a ConfigMap in the same namespace as MySQLCluster, and setting `spec.mysqlConfigMapName` in MySQLCluster to the name of the ConfigMap as follows:

```yaml
apiVersion: v1
Expand All @@ -196,22 +199,47 @@ metadata:
data:
long_query_time: "5"
innodb_buffer_pool_size: "10G"
```

and set the name of the ConfigMap in MySQLCluster as follows:

```yaml
---
apiVersion: moco.cybozu.com/v1beta1
kind: MySQLCluster
metadata:
namespace: foo
name: test
spec:
# set this to the name of ConfigMap
mysqlConfigMapName: mycnf
...
```

If `innodb_buffer_pool_size` is not given, MOCO sets it automatically to 70% of the value of `resources.requests.memory` (or `resources.limits.memory`) for `mysqld` container.
### InnoDB buffer pool size

If `innodb_buffer_pool_size` is not specified, MOCO sets it automatically to 70% of the value of `resources.requests.memory` (or `resources.limits.memory`) for `mysqld` container.

If both `resources.request.memory` and `resources.limits.memory` are not set, `innodb_buffer_pool_size` will be set to `128M`.

### Opaque configuration

Some configuration variables cannot be fully configured with ConfigMap values.
For example, [`--performance-schema-instrument`](https://dev.mysql.com/doc/refman/8.0/en/performance-schema-startup-configuration.html) needs to be specified multiple times.

You may set them through a special config key `_include`.
The value of `_include` will be included in `my.cnf` as opaque.

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: foo
name: mycnf
data:
_include: |
performance-schema-instrument='memory/%=ON'
performance-schema-instrument='wait/synch/%/innodb/%=ON'
performance-schema-instrument='wait/lock/table/sql/handler=OFF'
performance-schema-instrument='wait/lock/metadata/sql/mdl=OFF'
```

Care must be taken not to overwrite critical configurations such as `log_bin` since MOCO does not check the contents from `_include`.

## Using the cluster

Expand Down
10 changes: 8 additions & 2 deletions pkg/mycnf/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
// Note that the pool size can't be lower than 128MiB, which is the default value of `innodb_buffer_pool_size`.
const InnoDBBufferPoolRatioPercent = 70

const opaqueKey = "_include"

// DefaultMycnf is the default options of mysqld.
// These can be overridden by users.
var DefaultMycnf = map[string]string{
Expand Down Expand Up @@ -149,14 +151,14 @@ func calcBufferSize(total int64) int64 {
// If `userConf` does not specify `innodb_buffer_pool_size`, this
// will automatically set it to 70% of `memTotal`.
func Generate(userConf map[string]string, memTotal int64) string {
opaque := userConf[opaqueKey]
mysqldConf := mergeSection(DefaultMycnf, userConf)
if _, ok := mysqldConf["innodb_buffer_pool_size"]; !ok {
mysqldConf["innodb_buffer_pool_size"] = fmt.Sprint(calcBufferSize(memTotal))
}

// to always enable binary logs
delete(mysqldConf, opaqueKey)
delete(mysqldConf, "log_bin")
// to put error logs to stderr
delete(mysqldConf, "log_error")

conf := make(map[string]map[string]string)
Expand All @@ -180,6 +182,10 @@ func Generate(userConf map[string]string, memTotal int64) string {
panic(err)
}

if sec == "mysqld" && opaque != "" {
fmt.Fprintln(b, opaque)
}

confSec := conf[sec]
// sort keys to generate reproducible my.cnf
confKeys := make([]string, 0, len(confSec))
Expand Down
17 changes: 17 additions & 0 deletions pkg/mycnf/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestGenerator(t *testing.T) {
t.Run("normalize", testNormalize)
t.Run("loose", testLoose)
t.Run("buffer-pool-size", testBufferPoolSize)
t.Run("opaque", testOpaque)
}

//go:embed testdata/nil.cnf
Expand Down Expand Up @@ -62,3 +63,19 @@ func testBufferPoolSize(t *testing.T) {
t.Error("not matched", cmp.Diff(bufsizeCnf, actual))
}
}

//go:embed testdata/opaque.cnf
var opaqueCnf string

func testOpaque(t *testing.T) {
actual := Generate(map[string]string{
"_include": `performance-schema-instrument='memory/%=ON'
performance-schema-instrument='wait/synch/%/innodb/%=ON'
performance-schema-instrument='wait/lock/table/sql/handler=OFF'
performance-schema-instrument='wait/lock/metadata/sql/mdl=OFF'
`}, 100<<20)
if !cmp.Equal(opaqueCnf, actual) {
t.Error("not matched", cmp.Diff(opaqueCnf, actual))
}

}
84 changes: 84 additions & 0 deletions pkg/mycnf/testdata/opaque.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[client]
loose_default_character_set = utf8mb4
port = 3306
socket = /run/mysqld.sock

[mysql]
auto_rehash = OFF
init_command = "SET autocommit=0"

[mysqld]
performance-schema-instrument='memory/%=ON'
performance-schema-instrument='wait/synch/%/innodb/%=ON'
performance-schema-instrument='wait/lock/table/sql/handler=OFF'
performance-schema-instrument='wait/lock/metadata/sql/mdl=OFF'

admin_port = 33062
back_log = 900
binlog_format = ROW
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
datadir = /var/lib/mysql/data
default_storage_engine = InnoDB
default_time_zone = +0:00
disabled_storage_engines = MyISAM
enforce_gtid_consistency = ON
gtid_mode = ON
information_schema_stats_expiry = 0
innodb_adaptive_hash_index = ON
innodb_buffer_pool_dump_at_shutdown = 1
innodb_buffer_pool_dump_pct = 100
innodb_buffer_pool_in_core_file = OFF
innodb_buffer_pool_load_at_startup = 0
innodb_buffer_pool_size = 134217728
innodb_flush_method = O_DIRECT
innodb_flush_neighbors = 0
innodb_lock_wait_timeout = 60
innodb_log_file_size = 800M
innodb_log_files_in_group = 2
innodb_log_write_ahead_size = 512
innodb_online_alter_log_max_size = 1073741824
innodb_print_all_deadlocks = 1
innodb_random_read_ahead = false
innodb_read_ahead_threshold = 0
innodb_tmpdir = /tmp
join_buffer_size = 2M
lock_wait_timeout = 60
log_error_verbosity = 3
log_slave_updates = ON
log_slow_extra = ON
long_query_time = 2
loose_binlog_transaction_compression = ON
loose_innodb_numa_interleave = ON
loose_innodb_validate_tablespace_paths = OFF
loose_replication_optimize_for_static_plugin_config = ON
loose_replication_sender_observe_commit_only = ON
max_allowed_packet = 1G
max_connect_errors = 10
max_connections = 100000
max_heap_table_size = 64M
max_sp_recursion_depth = 20
mysqlx_port = 33060
pid_file = /run/mysqld.pid
port = 3306
print_identified_with_as_hex = ON
read_only = ON
relay_log_recovery = OFF
secure_file_priv = NULL
skip_name_resolve = ON
skip_slave_start = ON
slow_query_log = ON
slow_query_log_file = /var/log/mysql/mysql.slow
socket = /run/mysqld.sock
sort_buffer_size = 4M
super_read_only = ON
table_definition_cache = 65536
table_open_cache = 65536
temptable_use_mmap = OFF
thread_cache_size = 100
tmp_table_size = 64M
tmpdir = /tmp
transaction_isolation = READ-COMMITTED
wait_timeout = 604800

!includedir /etc/mysql-conf.d

0 comments on commit fe47af9

Please sign in to comment.