配置即代码 IN ACTION
Jenkins提供的可视化操作界面,为初学者提供了方便。但如果要频繁的创建、配置任务,通过界面操作,效率总是太低,不如脚本来得快捷。
最近在为一些运维项目搭建部署流水线,每个项目都需要十几个jenkins任务,有的甚至更多。如果通过界面一个个去配置,也挺繁琐的。按照SRE的原则,重复的配置工作属于琐事的范畴,应该尽量避免。
再者,按照配置即代码的原则,配置信息也需要纳入版本管理。而通过UI配置的jenkins任务,所有的信息都在服务器上,不好做版本管理。
本文主要是对最近工作的一个总结,主要解决2个问题:
- 利用命令行工具创建jenkins任务。
- 通过pipeline实现配置版本化管理。
利用命令行工具创建jenkins任务
打开“系统管理”->“Jenkins命令行接口”,如下图: 通过UI完成的操作,很多也能通过命令行来做,如任务/视图的增删改、任务运行等等。
-
下载jenkins-cli.jar到本地,确保本地环境安装了jdk。
-
准备任务模板文件, create-job命令需要一个xml文件,先通过UI界面创建一个示例任务job-template,把主目录/jobs/job-template/config.xml文件复制出来,作为模板文件。主目录具体的路径可通过“系统管理”->“系统设施”里查看。
-
修改模板文件并创建任务 修改xml中相关的值,如git地址,部署目录等。然后利用以下命令创建任务: java -jar jenkins-cli.jar -auth user:pass -s http://jenkins-server:port/jenkins/ create-job job-name < job-name.xml 其中: user:pass: 登录jenkins的账号密码 job-name:待创建任务的名称 job-name.xml:根据模板修改的xml文件
不足之处:
- 项目的部署流程要求与示例任务相似,不然xml修改起来比较麻烦。
- xml文件不利于后期的更新维护。
利用pipeline实现配置即代码
pipeline实现了部署流程和job的解耦,把配置信息放到一个叫jenkinsfile的文件里。 jenkinsfile放到版本库中统一管理。任务运行时,jenkins从scm获取最新的jenkinsfile文件,然后按照配置的内容运行相关命令,比如构建,打包等等。
这样,各项目的任务xml文件就变得相当简单,唯一需要修改的就剩下jenkinsfile的scm地址了:
如何创建pipelne请参考相关的文档,这里提供一个jenkinsfile的示例:
pipeline {
agent any
stages {
// 准备阶段,从git拉取代码
stage("Preparation") {
steps {
git 'https://project-git-address.git'
}
}
// 编译,打包阶段,利用mvn命令生成部署包
// $profile为参数,从命令行传入
stage("Build") {
steps {
sh "mvn clean package -P$profile"
}
}
// 部署阶段:在远程deploy sever上执行deploy.sh脚本,
// deploy.sh位于/root目录下。
//脚本功能是从jenkins server获取jar包,然后部署到指定目录,并启动服务
stage("Deploy") {
steps {
script {
def remote = [:]
remote.name = deploy server name'
remote.user = 'root'
remote.host = "deploy server ip"
remote.port = 22
//服务器是采用私钥登录的,这里需提供私钥文件
remote.identityFile = '/root/.ssh/xxx.private'
//如果采用账号登录,则提供登录账号信息
//remote.account = 'root'
//remote.password = 'xxxxx'
remote.allowAnyHosts = true
sshCommand remote: remote, command: "deploy.sh"
}
}
}
}
}
配置完成后,可通过以下命令运行该任务:
java -jar jenkins-cli.jar -auth user:pass -s http://jenkins-address/jenkins build *job-name* -s -v -p profile=dev|prod
- 如果觉得密码采用明文不安全,也可用jenkins生成的token代替。
- -p key=value [-p key2=value2],如果任务有参数,可以通过这种形式输入。