背景 每当有新应用、新系统上线时,我们需要做到以下几步:
- 准备新的服务器,安装操作系统
- 对操作系统进行初始化,满足各种基线要求
- 安装应用依赖的基础组件
- 配置应用依赖的环境变量
- 准备好应用制品包
- 配置中心完成对应用的参数更新
- 应用启动
- 添加监控
传统的vsphere超融合方案
进行介绍。需求 对于不同的技术栈,例如Java和Pyhton,应用的部署方式就有不同,但这阻挡不了我们要将其自动化交付的决心,因此我们从以下几点考虑:
- 遵循相同的目录规范
- 按目录规范安装不同技术栈依赖基础组件及环境变量
- 统一守护进程supervisor,可按启动方式区分配置
- 监控平台遵循统一的端口监控、健康检查接入规范
- 统一的配置中心
方案分析 1.虚拟机 在Vsphere虚拟化中,我们的常规操作是直接克隆虚拟机或从模板中直接创建虚拟机,但这需要进行二次修改IP地址、网卡等操作,这无疑大大的浪费了时间。
其实我们可以通过Vsphere提供的
自定义规范
来直接定制IP、主机名等配置,这样创建出来的虚拟机就可以直接使用,而不需要二次修改。在此我们可以参考以下两篇文章,分别从vcenter图形化界面和Python代码实现自定义规范创建虚拟机。
《vcenter自定义规范定制虚拟机-vsphere client》
《运维思索:目录管理规范的重要性》
2.目录规范 操作系统层面,无论是基础组件、软件部署、环境变量都需要遵循统一的目录规范进行配置管理,因此我们可以将其看作为全局配置。
具体的目录规划,我们可以参考下文:
《运维思索:目录管理规范的重要性》
注意:我们既可以按不同技术栈划分目录,也可以不区分目录将其都视为统一的应用名划分。
3.操作系统初始化 对于新创建的虚拟机,我们首先需要进行操作系统初始化,交付一台符合标准配置基线、安全基线的操作系统。
主要包含以下几方面:
- yum源
- 内核参数
- 符合等保要求的安全基线
- 符合目录规范的基础目录
- 标准的应用用户
- 等等
os_init.yml
剧本进行统一管理。具体的实现方式可参看下文:
《运维思索:操作系统配置规范化、自动化》
4.基础组件安装 技术栈不同,应用运行依赖的组件有所不同,但不外乎以下几种:
- jdk
- apache
- miniconda
- supervisor
- 等等
software_install.yml
剧本进行统一管理。具体的实现方式可参看下文:
《ansible自动化:基础软件的自定义安装》
5.应用启动 技术栈不同,应用的启动参数不同,在此我们以参数比较多的Java应用为例。
为了更好的定位、分析、排查问题,我们需要提前定义JVM:
- GC日志,用于JAVA虚拟机垃圾回收情况;
- dump文件,用于排查OOM等异常情况;
- 堆内存,合理使用服务器资源;
- 环境变量,灵活控制开发、测试、生产等各个文件的配置参数;
对于Java的启动参数配置,我们可以参考以下文章:
《运维思考:Java进程管理规范》
6.添加监控 应用监控一般分为进程监控、端口监控或标准的url监控,其中进程监控一般需要分别在应用服务器上进行检查,而端口监控和url监控则可以集中在某台机器上统一检查。
因此我们最终选择了端口监控和url监控进行互补监控,已经有标准url接口的使用url监控,而没有标准url接口的使用端口监控,这样可以满足我们对不同情况的监控接入。
无论哪种监控,我们的需求是将监控url或端口添加到指定配置文件,监控系统就可以自动生成监控项,例如:Zabbix自动发现。
延申:基于统一的远程监控,我们也可在后期增加屏蔽/恢复告警功能,用于发布过程中产生的正常告警。
针对此场景,我们可以参考以下文章:
《版本发布过程中的屏蔽/恢复告警》
7.小结 针对以上几方面的分析,涉及了很多最基本的规范,如:
- 《目录管理规范》
- 《操作系统安装规范》
- 《系统初始化规范》
- 《进程管理规范》
- 等等
流水线接入 对于流水线的接入,我们并没有从安装操作系统开始接入,而是从操作系统初始化开始。
文章图片
其中:
- 环境初始化通过ansible的
os_init.yml
剧本实现 - Java/Python组件安装通过ansible的
software_install.yml
剧本实现 - supervisor安装及应用启动也是通过ansible的
software_install.yml
剧本实现 - 自动添加监控则是通过zabbix自动发现添加到指定配置文件实现
关于整个流水线的规划,我们可以参看下文:
《CI/CD如何支撑运维自动化》
1.参数化构建
文章图片
2.构建过程耗费1分钟左右
文章图片
3.流水线
@Library('shared-library') _
pipeline {
agent any
stages {
stage('基础组件初始化') {
steps {
script {
hosts = cmdb.GetHosts("${APP_NAME}")
for(host in hosts) {
build job: 'init_system', parameters: [string(name: 'ENV', value: 'uat'),text(name: 'HOST_IP', value: "${host}"), string(name: 'PLAYBOOK', value: 'software_install.yml'), string(name: 'TAG', value: 'java,miniconda,supervisor')]
}
}
}
}
stage('应用初始化') {
steps {
script {
python_deploy.InitApp("${APP_NAME}")
}
}
}
stage('从制品库拉取包文件') {
steps {
script {
python_deploy.PullFromArtifactory("${APP_NAME}")
}
}
}
stage('版本发布') {
steps {
script {
hosts = cmdb.GetHosts("${APP_NAME}")
for(host in hosts) {
python_deploy.DeployApp("${APP_NAME}", "${START_COMMAND}", "${host}")
}
}
}
}
}
}
总结 通过流水线我们实现了应用的分钟级交付,整个过程涉及到了基础的标准规范、配置管理工具、流水线等,因此需要在前期做大量的基础规划工作。另,通过容器化的解决方案其实可以将整个过程提升到秒级交付,这对传统应用来说简直是一个降维打击。因此企业最终推动容器化进程,向云原生领域迈进将是大势所趋。
推荐阅读
- 后端|微服务化的基石——持续集成
- kubernetes|Kubernetes K8S之存储Volume详解
- kubernetes|Kubernetes K8S之存储Secret详解
- kubernetes|Kubernetes K8S之Ingress详解与示例
- 用对工具,CI事半功倍
- CloudBees CI使用Velero进行灾备(DR)概念验证
- kubernetes|Kubernetes K8S之Helm部署EFK日志分析系统
- CI/CD和DevOps之间有什么区别(有哪些不同?)