From 932fc59bba68315b688efc79e00d475687d8c409 Mon Sep 17 00:00:00 2001 From: ymmt Date: Fri, 28 May 2021 20:52:49 +0000 Subject: [PATCH] pkg/mycnf: add support for opaque configurations Users are now able to include opaque `my.cnf` contents by adding a special ConfigMap key `_include`. --- docs/usage.md | 48 +++++++++++++++----- pkg/mycnf/generator.go | 10 ++++- pkg/mycnf/generator_test.go | 17 +++++++ pkg/mycnf/testdata/opaque.cnf | 84 +++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 pkg/mycnf/testdata/opaque.cnf diff --git a/docs/usage.md b/docs/usage.md index a995bf1fc..86ff3726b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -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) @@ -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 @@ -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 diff --git a/pkg/mycnf/generator.go b/pkg/mycnf/generator.go index 6b4ba3e6f..b01e65c3f 100644 --- a/pkg/mycnf/generator.go +++ b/pkg/mycnf/generator.go @@ -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{ @@ -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) @@ -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)) diff --git a/pkg/mycnf/generator_test.go b/pkg/mycnf/generator_test.go index d5b7053af..ab8fa1c40 100644 --- a/pkg/mycnf/generator_test.go +++ b/pkg/mycnf/generator_test.go @@ -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 @@ -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)) + } + +} diff --git a/pkg/mycnf/testdata/opaque.cnf b/pkg/mycnf/testdata/opaque.cnf new file mode 100644 index 000000000..e717f2381 --- /dev/null +++ b/pkg/mycnf/testdata/opaque.cnf @@ -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