在基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊中,我们使用一系列脚本,尽可能地对所有环境的安装和配置工作进行了自动化。工作坊中的每一个与会者都只要按照说明,执行几个脚本,就可以自动地准备好自己的一整套 CI/CD 和微服务部署基础设施。
“基础设施即代码”指的是,使用代码描述所有基础设施的安装和配置过程,包括这些基础设施软件的各项设置和日常使用数据,都要使用代码进行描述。从而享受基于代码的版本管理和自动化执行等能力。这一概念强调,不仅软件本身的生产(持续集成即代码)和部署过程(持续部署即代码)可由代码来描述,用于托管并运行软件的基础设施(即服务器环境本身)的创建和配置过程也要能以代码的方式描述并维护。
概要介绍
在工作坊中,现场参与的每个人,都基于提前准备好的 Kubernetes 集群搭建了可供开发用的 Git 服务器和 CI/CD 工具体系,并成功部署了微服务。工作坊还带着与会者体验了将 .NET Core 应用从 IDE 代码开发、把代码提交到 Git 服务器,经过 CI/CD 自动编译、发布容器镜像,并最终自动部署到 Kubernetes 平台的完整过程。
支持这一过程的基础设施的整体示意图为:
具体实现代码、脚本和配置,都在这个 GitHub 仓库:https://github.com/netconf-cn2019-workshop/dev-services/ 其中各个微服务,请回到上一级别,自行下载。
整个代码库的结构如下:
.
├── cicd-infra # 存放 CI/CD 软件部署代码的目录
│ ├── cicd-installer.yaml # 用于 CI/CD 软件的初始化配置
│ ├── gogs.yaml # 安装 Gogs 的 Kubernetes 配置
│ ├── jenkins.yaml # 安装 Jenkins 的 Kubernetes 配置
│ ├── nexus.yaml # 安装 Nexus 的 Kubernetes 配置
│ ├── sonarqube.yaml # 安装 Sonarqube 的 Kubernetes 配置
│ └── vars # 定义安装 CI/CD 软件过程中的变量
├── provision-cicd.sh # 启动安装 CI/CD 软件的脚本文件
├── provision-infra.sh # 启动安装微服务公用基础设施的脚本文件
├── provision-services.sh # 启动安装微服务的脚本文件
├── service-infra # 存放微服务公用基础设施部署代码的目录
│ └── infra.yaml # 用于安装微服务公用基础设施的 Kubernetes 配置
├── services # 存放微服务部署代码的目录
│ ├── service-list # 定义部署的微服务及其镜像版本的变量
│ └── vars # 定义安装微服务过程中使用的变量
└── tmpl.sh # 读入变量值并将其应用到使用变量的文件
本文,我们概要地探讨这整个过程的原理和大致步骤。还有两篇文章分别介绍 CI/CD 部分及微服务部署部分的实现原理。
CI/CD软件
基本上,社区中关于这些软件的选用已经有了一些“偏好” 。基于社区的偏好,我们在工作坊中做了这样一些选择:
软件 | 选择 |
---|---|
代码服务器 | 国人开发的优秀 Git 服务器软件 Gogs |
持续集成软件 | 广为使用的 Jenkins |
发布物存储软件 | 广为使用的 Nexus |
容器注册表 | Coding 制品库容器镜像服务 |
由于要在 Kubernetes 集群中安装,所以上述这些软件,我们都需要使用它们的容器版本。容器注册表的安装和配置比较麻烦,为了简化工作坊现场的流程,所以我们选用现成的外部容器注册表服务。
CI/CD 软件的安装过程在脚本文件 provision-cicd.sh 中,这是一个 Bash 脚本文件。这个脚本文件既可用于 CI/CD 软件的部署(deploy),也可以用于整个工作坊环境的清理(delete)。当以部署模式(deploy)运行时,脚本会首先在 Kubernetes 集群上创建多个命名空间(namespace),并在 cicd 命名空间中依次启动安装 Jenkins、Nexus、Gogs 和 Sonarqube 等软件,最后会在 cicd 命名空间中启动一个初始化脚本(cicd-installer)。cicd-installer 初始化脚本将负责等待软件完成安装,并向它们导入必要的初始化数据。
在安装过程中,会用到一些“变量”,比如表示当前用户的 deploy_suffix 等。在我们为各个软件编写的 Kubernetes 安装文件(.yaml)中的相应位置上均引用了变量。而在 provision-cicd.sh 脚本文件中,在执行 kubectl apply 之前,它借助 tmpl.sh 脚本文件完成变量的填充,变量的值声明在 cicd-infra/vars 文件中。这也要求,在部署之前,工作坊的参与者需要提前编辑这个变量文件,确保其中的各个值都是正确的。
微服务的部署
微服务公用基础设施
这些基础设施的安装过程在脚本文件 provision-infra.sh 中,这也是一个 Bash 脚本文件。它的原理很简单,而且微服务基础设施的安装过程没有变量。所以,它直接在在相应部署环境对应的命令空间(如 dev)执行 kubectl apply ./service-infra/infra.yaml 就完成了安装。安装动作之后,脚本会等待安装完成,确保数据库处于运行状态之后,再执行数据库表结构的初始化操作,并向其中导入种子数据。
微服务的部署脚本文件是 provision-services.sh 中,这又是一个 Bash 脚本文件。脚本会从 services/service-list 文件中读入要部署的微服务的信息(容器镜像名称及标签),并逐个调用对应微服务所在项目目录中的 k8s.yaml 文件来执行部署。在部署过程中,也会涉及前面讲过的类似的变量处理过程,即读入 services/vars 文件,用于为微服务部署过程提供变量值。所以,同样,工作坊的参与者需要提前编辑这个变量文件,确保其中的各个值都是正确的。
由于将待部署的微服务列表使用单独的配置文件 services/service-list,因此不管是手工执行脚本部署,或是工作坊中练习的使用 CI 进行自动化部署,都可以通过编辑这个文件来指定要部署的微服务列表和版本。
在工作坊的准备过程中,为了实现自动完成这些初始配置工作,我们结合使用了多种技术。这里先简单列举其中用到的几种技术,后面另外会写文章重点解读特定环节的实现原理:
通过结合使用这些技术,我们不光用 yaml 文件描述了这些软件的安装过程,还能够以代码的方式描述在这些软件上需要完成的配置。
总结
符合这两个特点,最终部署出一个“基于 Kubernetes 的基础设施环境”,也就实现了基于 Kubernetes 的基础设施即代码。
事实证明,这个实践为可靠地重复创建工作坊环境提供了充分的保障,为工作坊的顺利举办和后期持续优化建立了不错的基础。