设计背景:集群部署服务时,会有使用与配置数据库的需求。本项目在此需求上,基于 k8s 的扩展功能,实现 DbConfig 的自定义资源,做出一个自动创建库、表与 user 的 operator 应用。 其中:controller 应用与 mysql 服务使用 sidecar 的模式部署在一起。
思路:当应用启动后,会启动一个 controller 与 mysql 服务,controller 会监听 crd 资源,并执行相应的业务逻辑(创建库、表与用户)。
- 支持多个 service 服务接入,实现自动配置数据库
- 建库、建表
- 创建 user
- 打成镜像或是使用编译二进制。
# 项目根目录执行
[root@VM-0-16-centos dbconfigoperator]# pwd
/root/dbconfigoperator
# 下列命令会得到一个二进制文件,服务启动时需要使用。
# 可以直接使用 docker 镜像部署
# docker build -t dbconfigoperator:v1 .
[root@VM-0-16-centos dbconfigoperator]# docker run --rm -it -v /root/dbconfigoperator:/app -w /app -e GOPROXY=https://goproxy.cn -e CGO_ENABLED=0 golang:1.18.7-alpine3.15 go build -o ./mydbconfigoperator .
[root@VM-0-16-centos dbconfigoperator]# ls | grep mydbconfigoperator
mydbconfigoperator # 可以看到这就是需要用的二进制文件
- apply crd 资源
[root@VM-0-16-centos yaml]# pwd
/root/dbconfigoperator/yaml
[root@VM-0-16-centos yaml]# kubectl apply -f dbconfig.yaml
customresourcedefinition.apiextensions.k8s.io/dbconfigs.api.practice.com unchanged
- 启动 controller 服务(需要先执行 rbac.yaml,否则服务会报错)
[root@VM-0-16-centos yaml]# kubectl apply -f rbac.yaml deploy.yaml
deployment.apps/mydbconfig-controller unchanged
service/mydbconfig-svc unchanged
serviceaccount/mydbconfig-sa unchanged
clusterrole.rbac.authorization.k8s.io/mydbconfig-clusterrole unchanged
clusterrolebinding.rbac.authorization.k8s.io/mydbconfig-ClusterRoleBinding unchanged
- 查看 operator 服务
附注:这里可能启动时 pod 会有 Error 的情况,原因是 pod 的创建在 Kubelet 是有随机概率的,但两个 container 又有相互依赖,规划在之后版本会修改这个 bugfix
临时解决方案:等服务自己重启即可。
[root@VM-0-16-centos yaml]# kubectl get pods | grep mydbconfig-controller
mydbconfig-controller-5c85668748-gv624 2/2 Running 0 9m23s
- 配置用户的表与密码
使用 k8s 内部 configmap 与 secret 资源,分别创建用户表与密码( namespace 需要与 controller 相同) 参考
- configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: dbconfig-service2-configmap
namespace: default # 需要与 cr 资源的 namespace 相同
data:
# 下面填写创建 mysql 表的 sql 语句
products.table: |
CREATE TABLE IF NOT EXISTS products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
shipments.table: |
CREATE TABLE IF NOT EXISTS shipments (
id INT PRIMARY KEY AUTO_INCREMENT,
product_id INT,
quantity INT,
shipment_date DATE,
destination VARCHAR(100)
);
- secret
apiVersion: v1
kind: Secret
metadata:
name: dbconfig-service2-secret
namespace: default # 需要与 cr 资源的 namespace 相同
data:
# 在创建 secret 对象时,data 字段需要用 "base64" 编码
# 这是 base64 后的结果,k8s 会自动从 base64 转回来
# 所以连接数据库时,只需要填写原密码就行。
PASSWORD: "ZGJjb25maWctc2VydmljZTItc2VjcmV0" # 原密码: dbconfig-service2-secret
# 创建后如下
[root@VM-0-16-centos ~]# kubectl get cm | grep test-db-table
dbconfig-service1-configmap 2 20m
dbconfig-service2-configmap 2 20m
dbconfig-service3-configmap 1 20m
[root@VM-0-16-centos ~]# kubectl get secret | grep test-db-
dbconfig-service1-secret Opaque 1 20m
dbconfig-service2-secret Opaque 1 20m
dbconfig-service3-secret Opaque 1 20m
- 配置 cr (当中的 password、tables 需要自己创建 configmap secret 资源,如上5所示) 参考
apiVersion: api.practice.com/v1alpha1
kind: DbConfig
metadata:
name: mydbconfig-2
spec:
dsn: root:123456@tcp(127.0.0.1:3306)/ # db 连接的 <user>:<password>@tcp(<ip:port>)/
maxIdleConn: 15 # 最大空闲连接数,可不填,默认为 10
maxOpenConn: 100 # 最大连接数,可不填,默认为 100
services:
- user: dbconfig_servicetest1 # 用户名
password:
secretRef: dbconfig-service1-secret # secret 名,设置 db 用户的密码,用户需要先创建 secret 资源,并在此指定
dbname: dbconfig_servicetest1 # db 名
tables:
configMapRef: dbconfig-service1-configmap # configmap 名,设置创建表,用户需要先创建 configmap 资源,并在此指定
- user: dbconfig_service22test
password:
secretRef: dbconfig-service2-secret
dbname: dbconfig_service22test
tables:
configMapRef: dbconfig-service2-configmap
- user: dbconfig_service33tttt
password:
secretRef: dbconfig-service3-secret
dbname: dbconfig_service33tttt
tables:
configMapRef: dbconfig-service3-configmap
- 可以 exec 或 logs 查看结果