# 起因
在SASE项目开发过程中,大概率都存在私有化部署的场景,所以我所在的项目组也是不可避免的。
项目架构说明:kubernetes + 微服务。
私有化部署的难点在于客户的集群环境的适配,如:
1. 客户提供的服务器linux发行版本;2. 客户网络无法联网,需要纯离线安装等。
对于以上环境,服务的部署可采用以下方式:
1. 对于服务改造,如果是测试用户,可执行通过docker compose部署all in one包的方式。2. 将所有依赖进行打包处理,并编写自动化部署脚本。
由于第一点,对于业务存在改造的成本,所以考虑的是第二种方式;在执行过程中,又经历了自开发以及开源项目二次开发,在此记录下心路历程。# 自开发涉及到分布式集群的搭建,所以使用的是ansible脚本来完成。一共可分为以下几种ansible的playbook role:
- system init- etcd- kubernetes- thirdpart(第三方组件安装) - mongodb - redis cluster - rabbitmq- 微服务部署
主机离线包需要包括:
- harbor - offlines.tar.gz- 安装所需的镜像,helm包(可以放到playbook中,安装时进行拷贝,解压,导入等操作)- 服务所需要的manifests文件或者helm包。
ansible经验项:
- 活用debug命令: 在不清楚其内容的情况下,使用debug命令来进行打印数据;- 使用meta: end_play + –start-at-task: 进行单个任务进行调试;- 使用pdb,说到底ansible还是python写的,那么也有pdb操作,实时看错误任务的堆栈信息。–>debugger 关键字。
缺点:
- 自开发,脚本都需要一步步验证,开发时间长。- 离线包的抓取,rpm包依赖的下载,都是比较耗时费力的一件事,并且不同的linux的发行版都需要考虑。# kubekey二次开发方案在搭建kubesphere作为k8s的管理平台时,偶然发现了kubekey这个部署工具,提供离线安装方式以及使用golang进行脚本的编写,可以说是相当nice。(这次发现golang非常的适合部署工具的开发)官方wiki## 架构图 架构抽象出四个对象:
- Action: 基础执行单元,表示在一台节点上执行一次具体任务(cmd、template、scp、fetch)。- Task:Action 管理单元,定义调度执行策略,例如:节点调度,重试次数,是否并行执行。- Module:Tasks 集合,是一个具有完整功能的模块。- Pipeline(相当于playbook):Modules 集合,顺序执行 Modules 流程。KubeKey 中每个功能均被定义为一个 Pipeline
可与ansible执行方式进行类比。 ## 如何使用kk进行开发下载kubekey源码后,需要关注的目录都在cmd目录下:```yamlcmd└── kk ├── apis – 数据结构,如manifest结构体,cluster结构体等 ├── cmd – 命令定义 └── pkg – 执行核心```需要改动的文件都在这几个目录下,在kubekey 目录下,执行`make kk`即可生成命令行工具。
## 经验项### 调试在对开源项目进行二开时,首先需要考虑的是,如何调试代码? 首先在cmd目录下直接执行go run . 进行调试,会包如下错误:```yaml# pkg-config –cflags – gpgmePackage gpgme was not found in the pkg-config search path.Perhaps you should add the directory containing `gpgme.pc’to the PKG_CONFIG_PATH environment variableNo package ‘gpgme’ foundpkg-config: exit status 1# pkg-config –cflags – devmapperPackage devmapper was not found in the pkg-config search path.Perhaps you should add the directory containing `devmapper.pc’to the PKG_CONFIG_PATH environment variableNo package ‘devmapper’ foundpkg-config: exit status 1# github.com/containers/storage/drivers/btrfs/root/go/pkg/mod/github.com/containers/storage@v1.43.0/drivers/btrfs/btrfs.go:9:10: fatal error: btrfs/ioctl.h: No such file or directory 9 | #include <btrfs/ioctl.h> | ~~~~~~~~~~~~~~compilation terminated.```在直接编译的时候,我们可以看到存在多个第三方c库的依赖没有安装。但是我又不想安装依赖,所以我们需要去查看kk具体在makefile中如何编译出来的。```makefile
.PHONY: kkkk: CGO_ENABLED=0 go build -trimpath -tags “$(BUILDTAGS)” -ldflags “$(LDFLAGS)” -o ./kk github.com/kubesphere/kubekey/v3/cmd/kk;```这里存在两个变量不清楚如何赋值,所以可以直接执行make kk 来查看具体执行:```makefileCGO_ENABLED=0 go build -trimpath -tags “exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp” .```可以看出在编译时,kubekey将这些第三方库给排除掉了。相对应的,gorun如下:```makefileCGO_ENABLED=0 go run -trimpath -tags “exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp” .```### 开发在开发时,kubekey使用的是cobra命令行框架,那就简单了,直接复制一个对应的命令出来,进行pipeline的改造,即可。 编写路径为:```makefilecobra–>pipeline–>module–>Task–>Action```最终执行的方法为`action.Execute`。
## 一些源码的分析源码分析,思维导图如下:借助思维导图,可以查看一个pipeline执行的主流程。其中localTask与RemoteTask的不同点在于,RemoteTask需要创建connection, 在Action中可以使用 `host := runtime.RemoteHost()`获取远程Host, 通过执行`runtime.GetRunner().SudoCmd()` 来进行远程命令的执行。## 优势
- kubekey维护了现在流行的Linux发行版本,在离线时,可以直接使用。- kubekey提供了以下功能: - 集群部署 - 集群删除 - **添加节点** - 删除节点 - 集群升级 - **证书有效期检查** - 证书更新 - **etcd 备份** - **证书自动更新** - 支持自定义制作离线安装包 - 支持插件扩展 - **操作系统初始化 (安装依赖、配置时间同步、执行自定义脚本等)**
并且提供高可用k8s集群搭建,可以说离线安装需要考虑的场景都已经考虑到了。
# 收获在开发过程中,往往需要使用一些脚本自动化工具,在kubekey中有比较好的实践:
- 配置文件代码化,通过golang text/template 库进行维护,如system.serivce文件,etcd.env文件等等- 通过golang ssh代码封装实现远程代码执行。- 往往开发人员在shell脚本的使用上比较薄弱, 使用golang进行自动化工具的编写,可能达到意想不到的效果,并且编译出的二进制文件,跨平台依赖比较少。
https://zhuanlan.zhihu.com/p/666822161