本文以 Oracle MySQL 为例,介绍如何在KubeBlocks中配置参数模板(点击参考完整 PR)。
前提条件
- 了解 K8s 基本概念,例如 Pod,ConfigMap 等。
- 完成 Tutorial 1。
- 了解 Go Template(非必须)。
背景知识
在创建 Cluster 时,我们通常会根据资源情况、性能需求、环境等信息调整参数。云数据库厂商,如 AWS、Aliyun 也提供了不同的参数模版(例如 RDS 有高性能模版,异步模版等)供用户选择,快速启动。
在本文中,我们会介绍 Kubeblocks 中参数配置的相关内容,包括如何添加参数模版、如何修改参数、如何配置参数校验。
在 K8s 中,用户可将参数文件以 ConfigMap 的形式挂载到 Pod 的卷上。
但是 K8s 只管理 ConfigMap 的更新,并将其同步到 Pod 卷上。如果数据库引擎不支持动态加载配置文件(例如 MySQL,Postgres),那我们只能登录数据库并执行更新操作。通过直接登录数据库的方式操作,就很容易导致配置漂移。
为了防止配置漂移,KubeBlocks 是通过 ConfigMap 来管理参数,且秉持理念是:ConfigMap is the only source-of-truth
,即所有配置的变更都是先应用到 ConfigMap 上,然后根据参数的不同生效方式,再应用到 Cluster 的每个 Pod 上。参数/配置更新的话题我们会在下一个教程中详细说明。
ConfigTemplate 配置模板/参数模板
KubeBlocks 通过 Go Template 来渲染参数模版,除了常见函数,还内置了一些数据库中常用到的计算函数(例如 callBufferSizeByResource
,getContainerCPU
)
KubeBlocks 增强的渲染能力,能让你快速定制一个自适应参数模板(Adaptive ConfigTemplate),可根据上下文(例如内存、CPU 大小)来渲染合适的配置文件。
添加参数模版
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: oracle-mysql-config-template
labels:
{{- include "oracle-mysql.labels" . | nindent 4 }}
data:
my.cnf: |-
{{`
[mysqld]
port=3306
{{- $phy_memory := getContainerMemory ( index $.podSpec.containers 0 ) }}
{{- $pool_buffer_size := ( callBufferSizeByResource ( index $.podSpec.containers 0 ) ) }}
{{- if $pool_buffer_size }}
innodb_buffer_pool_size={{ $pool_buffer_size }}
{{- end }}
# if memory less than 8Gi, disable performance_schema
{{- if lt $phy_memory 8589934592 }}
performance_schema=OFF
{{- end }}
[client]
port=3306
socket=/var/run/mysqld/mysqld.sock
`
}}
Figure 1. ConfigTemplate for Oracle MySQL
Figure 1. 展示了一个通过 ConfigMap 定义的 MySQL 的自适应参数模板。
模板中配置了几个常见的 mysql 参数,包括 port,innodb_buffer_pool_size 等。
它根据容器启动时配置的 memory
- 计算得到
innodb_buffer_size
大小(line 11 ~ line 15)。 - 并且在 memory 小于 8Gi 时,关闭
performance_schema
来减少性能影响 (line 32 ~ line 34)。
callBufferSizeByResource
是 KubeBlocks 预定义的一个 bufferPool 计算规则,主要为 MySQL 服务。
此外,你也可以通过查询 memory 和 cpu 来定制你的计算公式:
getContainerMemory
获取 Pod 上某个 container 的 memory 大小。getContainerCPU
获取 Pod 中某个 container 的 cpu 大小。
💡 可以按照需求定制更多的参数计算方式,比如
- 根据 memory 大小,计算出一个合适的
max_connection
值。 - 根据 memory 总量,计算其他组件的合理配置。
使用参数模版
修改 ClusterDefinition
我们在 ClusterDefinition
可以通过 configSpecs
来指定参数模板,引用在 Figure 1. 中定义的 ConfigMap。
yaml
componentDefs:
- name: mysql-compdef
configSpecs:
- name: mysql-config
templateRef: oracle-mysql-config-template # 定义了参数模板的 ConfigMap 名
volumeName: configs # 挂载的卷名称
namespace: {{ .Release.Namespace }} # 该参数模板 ConfigMap 的 namespace
podSpec:
containers:
- name: mysql-container
volumeMounts:
- mountPath: /var/lib/mysql
name: data
- mountPath: /etc/mysql/conf.d # 挂载的配置文件路径,引擎相关
name: configs # 和 line 6 的 volumeName 对应
ports:
...
Figure 2. Specify ConfigTemplate in ClusterDefinition
如 Figure 2 所示,我们需要修改 ClusterDefinition.yaml
文件,添加了 configSpecs
字段(line 3 ~ 7)。
我们需要分别指定
- templateRef:模板所在的 ConfigMap 对象名称。
- volumeName:挂载到 Pod 的卷名。
- namespace:模板文件的名空间(ConfigMap 是 namespace scope 的,一般为 KubeBlocks 安装的名空间)。
查看配置信息
当一个新的 Cluster 创建后,KubeBlocks 会根据配置模板渲染好对应的 configmap,并将该 configMap 挂载到 configs
卷中。
- 安装 Helm chart
bash
helm install oracle-mysql path-to-your-helm-char/oracle-mysql
- 创建集群
bash
kbcli cluster create mycluster --cluster-definition oracle-mysql --cluster-version oracle-mysql-8.0.32
- 查看配置
kbcli
提供了 describe-config
子命令来查看集群的配置信息。
bash
kbcli cluster describe-config mycluster --component mysql-compdef
ConfigSpecs Meta:
CONFIG-SPEC-NAME FILE ENABLED TEMPLATE CONSTRAINT RENDERED COMPONENT CLUSTER
mysql-config my.cnf false oracle-mysql-config-template mycluster-mysql-compdef-mysql-config mysql-compdef mycluster
History modifications:
OPS-NAME CLUSTER COMPONENT CONFIG-SPEC-NAME FILE STATUS POLICY PROGRESS CREATED-TIME VALID-UPDATED
可以查看到:
- 配置模版名:oracle-mysql-config-template
- 渲染后的 ConfigMap:mycluster-mysql-compdef-mysql-config
- 加载的文件名:my.cnf
总结
本文介绍了通过参数模板来渲染"自适应"参数的能力。
K8s 会将 ConfigMap 的变更定时同步到 Pod 上,但是大部分引擎并不会主动加载新的配置(比如 MySQL,PostgreSQL,Redis)。因为,我们无法仅通过修改 ConfigMap 就实现到 Reconfig(参数变更)的能力。会在下一个 Tutorial 中介绍如何配置变更。
Appendix
A.1 如何配置多个参数模版
在生产环境中,我们通常需要多个参数模板,来满足不同需求。例如 Aliyun RDS 就提供了高性能参数模板、异步模板等。
在 KubeBlocks 中,我们可以通过配置多个 ClusterVerion
来实现这一需求。
还记得我们对 cluster 的定义吗,cluster 可以表示为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> C l u s t e r = C l u s t e r D e f i n i t i o n . y a m l ⋈ C l u s t e r V e r s i o n . y a m l ⋈ C l u s t e r . y a m l Cluster = ClusterDefinition.yaml \Join ClusterVersion.yaml \Join Cluster.yaml </math>Cluster = ClusterDefinition.yaml ⋈ ClusterVersion.yaml ⋈ Cluster.yaml,
其中 JoinKey 就是 Component Name。
多个 ClusterVersion 可以和同一个 ClusterDefinition 组合。
yaml
## 第一个 ClusterVersion,使用 ClusterDefinition 中的配置
apiVersion: apps.kubeblocks.io/v1alpha1
kind: ClusterVersion
metadata:
name: oracle-mysql
spec:
clusterDefinitionRef: oracle-mysql
componentVersions:
- componentDefRef: mysql-compdef
versionsContext:
containers:
- name: mysql-container
...
---
## 第二个 ClusterDefinition,定义了自己的 configSpecs,会覆盖 ClusterDefinition 的配置
apiVersion: apps.kubeblocks.io/v1alpha1
kind: ClusterVersion
metadata:
name: oracle-mysql-perf
spec:
clusterDefinitionRef: oracle-mysql
componentVersions:
- componentDefRef: mysql-compdef
versionsContext:
containers:
- name: mysql-container
...
# name needs to consistent with the name of the configmap defined in clusterDefinition
configSpecs:
- name: mysql-config
templateRef: oracle-mysql-perf-config-template
volumeName: configs
Figure 3. Specify ConfigTemplates in ClusterVersion
Figure 3. 创建了两个 ClusterVersion
对象。
第一个使用了默认的参数模版(没有配置任何信息)。第二个通过 configSpecs
指定了一个新的参数模版 oracle-mysql-perf-config-template
。
在创建 Cluster 时,我们可以指定 ClusterVersion
参数来创建不同配置的Cluster,如:
bash
kbcli cluster create mysqlcuster --cluster-definition oracle-mysql --cluster-version oracle-mysql-perf
💡 注意:KubeBlocks 会通过 configSpecs.name
来合并 ClusterVersion 和 ClusterDefinition 中的配置。因此我们必须确保在 ClusterVersion 中定义的 configSpecs.name
和 ClusterDefinition 中定义的名称一致。