0.背景
视频版 TODO 待录制
原计划是从手动到容器化再到云原生,每种阶段的搭建方式都来一次,但实际上容器化和云原生基本上没什么太大差距。因此跳过容器化阶段直接进入云原生的数据库搭建。
mysql属于有状态的应用,因此它的存储在一般的docker中需要特殊处理。有一种说法是没有必要在docker中搭建mysql,这个说法不完全对,在测试环境容器化可以带来很大的灵活性。实际上生产环境下上只要存储弄好了之后利用k8s的资源管理和调度能力是可以搭出合适的mysql集群的
其实前段时间已经给paraparty的群服务器搭过一次了,这里是总结下经验,详细记录请参考https://paraparty.feishu.cn/docx/FsBNdoDQAo4E8VxN0zZceTP8nsh
1.前期准备
在k8s中搭建mysql架构如图,来自官方的文档,直接照着搭即可。版本选择 8.0.33
MySQL、Kubernetes 通用术语. 例如Node可能代指一个Kubernetes Node或一个MySQL Node,Cluster可能代指一个MySQL InnoDB集群或Kubernetes集群,ReplicaSet是MySQL和Kubernetes都有的一个特性。
1.1.计算资源
-
k8s系统使用Controllers来管理Pod(在其中运行的容器化负载)的生命周期。Controllers是一个通用工具提供了广泛的服务能力,但复杂的服务需要包括operator之类额外的组件。Operator是一个运行在k8s集群中的软件和k8s-api进行交互来观测资源和服务来协助k8s进行生命周期的管理
-
MySQL Operator for Kubernetes 是一个专注于管理一个或多个由MySQL Server组成的MySQL InnoDB集群和MySQL Routers的工具。它自身在k8s集群中运行并作为k8s Deployment被管理,以此来保证自身的可用性 默认情况下它被部署在’mysql-operator’的k8s命名空间内,并监视k8s集群中所有的InnoDB集群和相关联的资源,为了执行这些任务operator订阅k8s-api服务来更新事件并按需连接到被管理的MySQL Server实例上。在k8s-controller的最顶层operator配置MySQL servers,使用Group Replication配置高可用集群,以及Mysql Router
-
MySQL InnoDB Cluster 一旦InnoDB Cluster (InnoDBCluster) 资源被部署到k8s-api上,Operator会创建如下的资源: k8s-StatefulSet来运行MySQL Server实例 他们管理Pods并分配相关的存储卷(storage Volume,sc),这个StatefulSet运行多个容器作为Pod,每个Pod都被其管理。 开始的几个提供一系列的初始化步骤来准备MySQL Server的配置和数据文件夹,紧接着两个容器作为业务容器保持存活。其中一个名为mysql的容器运行MySQL Server本体,另一个名为sidecar的容器来和operator写作负责节点的本地管理
-
k8s-Deployment来运行MySQL Routers MySQL Routers是无服务的状态应用,依照客户端要求来转发流量到当前的主节点或从节点,operator可以调整router的数量来根据实际的情况扩容或缩容
1.2.服务暴露
-
一个MySQL InnoDB集群部署会创建如下的k8s-Services: 一个名为InnoDB Cluster的服务,它负责作为MySQL Router的主入口。同时提供了一个固定的本地DNS域名,格式为'{clustername}.svc.cluster.local’,并同时暴露需要的端口 详细信息查看官网文档 “MySQL InnoDB Cluster Service Explanation” and Connecting to MySQL InnoDB Cluster.
-
第二个名为'{clustername}-instances’的服务为每个独立的实例提供了固定的本地DNS域名。一般来说他们不应该被直接访问,而应该使用主服务的域名来保证访问到正确的主节点或从节点。然而,为了运维或或监控来使用这个域名是有必要的,每个pod上都预装了MySQL Shell
-
Operator 创建和管理的其他资源不应该被手动修改,包括: 名为'{clustername}-initconf’的k8s-ConfigMap包括了MySQL 服务的配置信息,想要修改生成的my.cnf配置文件,查看 “Manifest Changes for InnoDBCluster”. 一系列k8s-Secrets用于存储系统不同部分的凭证, 名字是 ‘{clustername}.backup’, ‘{clustername.privsecrets}’, and ‘{clustername.router}’.
-
获取operator创建的MySQL账号和关联的密码,查看 “MySQL Accounts Created by InnoDBCluster Deployment”.
2.mysql-operator
如架构图所示,mysql-operator负责具体pod的创建和维护,因此需要先安装mysql-operator,文档参考官方文档
0 1 2 3 4 |
#选取的tag为 8.0.33-2.0.10 kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/8.0.33-2.0.10/deploy/deploy-crds.yaml kubectl apply -f https://raw.githubusercontent.com/mysql/mysql-operator/8.0.33-2.0.10/deploy/deploy-operator.yaml |
2.1.原理追踪
0 1 2 3 4 5 6 7 8 9 10 |
image: container-registry.oracle.com/mysql/community-operator:8.0.33-2.0.10 imagePullPolicy: IfNotPresent args: [ "mysqlsh", "--log-level=@INFO", "--pym", "mysqloperator", "operator", ] |
这个模块在community-operator镜像制作的时候会被打进去,关键命令是
COPY mysqloperator/ /usr/lib/mysqlsh/python-packages/mysqloperator
mod = importlib.import_module(entrypoints[sys.argv[1]], "mysqloperator")
可以定位到operator_main.py
operator_cluster.py
是我要找的内容,点开后可以明显看到@kopf.on.create
装饰器(py里叫decorator,java叫注解)statefulset = cluster_objects.prepare_cluster_stateful_set(icspec, logger)
cluster_objects.py
很容易发现yaml定义了init_main.py
的mainparser.add_argument('--datadir', type = str, default = "/var/lib/mysql", help = "Path do data directory")
2.2.mysqlsh的使用
/var/run/mysqld/mysql.sock
和/var/run/mysqld/mysqlx.sock
,通过以下方式可进入shell且无需密码-
执行
mysqlsh 'localroot@(/var/run/mysqld/mysql.sock)'
-
mysqlsh下执行
\connect localroot@(/var/run/mysqld/mysql.sock)
-
其他语法可参考https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-connection-socket.html
3.部署记录
https://dev.mysql.com/doc/mysql-operator/en/mysql-operator-innodbcluster-common.html
0 1 2 3 4 5 |
kubectl create secret generic mysql-pwds \ -n mysql-test \ --from-literal=rootUser=root \ --from-literal=rootHost=% \ #这里记得改成内网网段,如192.168.2.% --from-literal=rootPassword="随机密码" |
创建以下资源即可间接控制mysql-operator搭建集群
详细配置可以参考https://dev.mysql.com/doc/mysql-operator/en/mysql-operator-innodbcluster-simple-kubectl.html
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
apiVersion: mysql.oracle.com/v2 kind: InnoDBCluster metadata: name: cluster1 namespace: mysql-test spec: secretName: mysql-pwds tlsUseSelfSigned: true instances: 3 version: 8.0.33 router: instances: 1 version: 8.0.33 datadirVolumeClaimTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi mycnf: | [mysqld] max_connections=1000 |
假设namespace是mysql-test,集群名是cluster1的话,创建完成后会暴露如下内网域名
0 1 2 3 4 5 6 7 |
kubectl run -n mysql-test --rm -it myshell --image=container-registry.oracle.com/mysql/community-operator -- /bin/bash #主节点内网域名,通过route mysqlsh root@cluster1.mysql-test #实例内网域名 mysqlsh root@cluster1-0.cluster1-instances.mysql-test mysqlsh root@cluster1-1.cluster1-instances.mysql-test mysqlsh root@cluster1-2.cluster1-instances.mysql-test |
检查集群状态
0 1 2 3 4 5 6 7 8 9 |
MySQL cluster1.mysql-test:33060+ ssl SQL > SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+------------------------------------------------------------+-------------+--------------+-------------+----------------+----------------------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK | +---------------------------+--------------------------------------+------------------------------------------------------------+-------------+--------------+-------------+----------------+----------------------------+ | group_replication_applier | 94791318-0e7b-11ee-964e-9a5a5ee8112f | cluster1-1.cluster1-instances.mysql-test.svc.cluster.local | 3306 | ONLINE | SECONDARY | 8.0.33 | MySQL | | group_replication_applier | 95246c12-0e7b-11ee-9664-9af01f0d2432 | cluster1-0.cluster1-instances.mysql-test.svc.cluster.local | 3306 | ONLINE | PRIMARY | 8.0.33 | MySQL | | group_replication_applier | 95ee0474-0e7b-11ee-9642-3a105f1437a9 | cluster1-2.cluster1-instances.mysql-test.svc.cluster.local | 3306 | ONLINE | SECONDARY | 8.0.33 | MySQL | +---------------------------+--------------------------------------+------------------------------------------------------------+-------------+--------------+-------------+----------------+----------------------------+ 3 rows in set (0.0016 sec) |
集群创建后会有几个默认账号,一般建议用root作为超管使用。如前面步骤所示root是存在secret里的,其他的几个账户也是在相同的位置。mysqlbackup、mysqlrouter、mysqladmin
这几个账户的密码都能从test1-backup
、test1-router
、test1-privsecrets
中找到。其他账户请参考1.2中的链接
0 Comments