背景
我们都知道出于安全性考虑,生产环境的权限一般都是要做最小化控制,尤其是数据库的操作授权,更是重中之重。
博主所在公司使用的是Kubernetes(k8s)进行的集群容器管理,因为容器发布时的IP都是动态分配的,而出于安全性考虑,数据库的授权又不能全部放开或者针对整个集群的IP,所以有了动态为节点进行数据库授权的需求,所以也就诞生我们今天的主角--数据库授权组件,Mysql-grant。
当然,我们今天介绍的不是这个组件的开发,而是相关的测试过程记录。
组件原理
这个数据库动态授权组件的原理不复杂,每次Kubernetes有节点变化(上线或者下线服务)时,调取Kubernetes相关的API接口获取已配置的服务改变的对应节点的IP,然后对其进行授权或者权限回收操作(IP+user)。相当于在获取到信息之后执行下面的命令:
grant select,insert,update on 库名.表名 to '用户名'@'IP地址' identified by '密码' with grant option;
测试设计
在了解了具体的需求之后,我很快的确定了测试思路。具体如下:
- 拉起两个mysql数据库,每个库中新建两个DB,每个DB个新建一张表。
- 写一个无限循环的脚本,每隔两秒访问一次数据库,插入一条数据,查询一次数据。
- 把脚本打包到多个不同的镜像服务中,push到公司的镜像库中。
- 然后根据设计的场景使用k8s(Kubernetes)发布、下线服务、做Mysql-grant相关的配置信息改变来完成相关验证;
环境
这次主要用的环境如下:
- golang开发环境
- docker环境
- 镜像运行环境(centos)
测试脚本
考虑到镜像的大小及Dockerfile的复杂性,本次使用了golang来写这个脚本,直接编辑成二进制文件,可以不依赖环境执行,具体的脚本如下,把他保存为mysqlgrant-test.go即可:
package main
import (
"time"
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
count := 0
for{
fmt.Println("====================")
// fmt.Println(count)
fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
time.Sleep(time.Second * 2)
count++
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/easytest?charset=utf8")
checkErr(err)
//插入数据
stmt, err := db.Prepare("INSERT base_case SET case_name=?,project_id=?,content=?,description=?")
checkErr(err)
res, err := stmt.Exec(count, "Golang", time.Now(),time.Now())
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
//查询数据
rows, err := db.Query("select * from base_case order by case_id desc limit 1")
checkErr(err)
for rows.Next() {
var content string
var case_id string
var case_name string
var project_id string
var description string
err = rows.Scan(&description, &case_id, &case_name, &project_id, &content)
checkErr(err)
fmt.Println(case_id +":"+ case_name +" "+ project_id +" "+ description +" "+ content)
// fmt.Println(case_id)
// fmt.Println(case_name)
// fmt.Println(project_id)
// fmt.Println(content)
// fmt.Println(description)
}
db.Close()
}
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
脚本build为linux可执行文件
golang脚本的编译命令如下:
go build 脚本名称
但是因为楼主使用的是windows
,默认的会直接build成 .exe
文件
所以我们要手动设置环境变量,具体命令如下:
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build mysqlgrant-test.go
GOOS:目标平台的操作系统(darwin、freebsd、linux、windows)
GOARCH:目标平台的体系架构(386、amd64、arm)
交叉编译不支持 CGO 所以要禁用它
上面的命令编译 64 位可执行程序,你当然应该也会使用 386 编译 32 位可执行程序
镜像构建
Dockerfile
上面的脚本准备好了之后,接下来要制作镜像,我们这次试用的是dockerfile,dockerfile内容如下:
FROM centos:6.7
MAINTAINER <"bingo@xxxx.com">
RUN mkdir -p /usr/local/user-web/mysqlgrant-test
ADD ./mysqlgrant-test /usr/local/user-web/mysqlgrant-test
#ADD ./conf /usr/local/usr-web/mysqlgrant-test/conf
WORKDIR /usr/local/user-web/mysqlgrant-test
CMD ./mysqlgrant-test
Docker build
将上面的信息保存到dockerfile文件之后,切换到文件所在目录,执行下面命令来进行镜像的构建:
docker build -t mysqlgrant-test/centos:v1.0 .
参数说明:
-t :指定要创建的目标镜像名
. :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
注意后面的.
不能遗漏,它表示在当前目录构建的意思
镜像构建成功之后我们可以通过下面的命令来查看:
root@msxxx:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysqlgrant-test/centos v1.0 70bf1840fd7c 15 seconds ago 158.5 MB
镜像有效性验证
我们可以使用新的镜像来创建容器:
root@msxxx:~$ docker run -it mysqlgrant-test/centos:v1.0 /bin/bash --name mysqlgrant
参数说明:
--name mysqlgrant
表示为这个容器设置了一个叫mysqlgrant
的别名
-t
:在新容器内指定一个伪终端或终端。
-i
:允许你对容器内的标准输入 (STDIN) 进行交互。
执行上面的命令后会默认进入mysqlgrant-test目录,即我们上面在dockerfile中设置的WORKDIR。
当然我们也可以直接执行下面的命令来获取容器的标准输出:
docker logs mysqlgrant
这就是脚本输出的内容:
至此,所有的东西准备完毕,只需要根据准备好的测试用例,做相关业务场景的验证就可以了。
总结
在新技术应用的过程中难免会遇到一些问题,比如我们今天的介绍的容器化过程中解决数据库鉴权问题开发的组件。我的感触是,接触新的事物我们能学习到更多的东西。此前学习的docker、golang等等,都没有实战的基础,这一次虽然也只是简单的实践,但是还是有一种豁然开朗的感觉。