Jenkins自动化任务工具介绍

Jenkins是一个独立的开源自动化服务器,可用于自动化各种任务,如构建,测试和部署软件。Jenkins可以通过本机系统包 Docker安装(https://www.w3cschool.cn/docker/),甚至可以通过安装Java Runtime Environment的任何机器独立运行。

说明

本说明是针对使用需要Java 8的“独立”Jenkins发行版。还建议使用超过512MB RAM的系统。

  • 下载Jenkins (http://mirrors.jenkins.io/war-stable/latest/jenkins.war)

  • 在下载目录中打开终端并运行 java -jar jenkins.war –httpPort=8080

  • 浏览http://localhost:8080并按照说明完成安装。

  • 许多Pipeline示例需要 在与Jenkins相同的计算机上安装Docker。Docker安装下载教程:https://www.w3cschool.cn/docker/

安装完成后,开始将Jenkins运行并创建Pipeline。

Jenkins Pipeline是一套插件,支持将连续输送Pipeline实施和整合到Jenkins。Pipeline提供了一组可扩展的工具,用于将“复制代码”作为代码进行建模。

Jenkinsfile 是一个包含Jenkins Pipeline定义的文本文件,并被检入源代码控制。这是“Pipeline代码”的基础; 处理连续输送Pipeline的一部分应用程序,以像其他代码一样进行版本检查。创建Jenkinsfile提供了一些直接的好处:

  • 自动创建所有分支和拉请求的Pipeline

  • Pipeline上的代码审查/迭代

  • Pipeline的审计跟踪

  • Pipeline的唯一真实来源 ,可以由项目的多个成员查看和编辑。

虽然在Web UI或a中定义Pipeline的语法 Jenkinsfile是相同的,但通常认为最佳做法是在Jenkinsfile中定义Pipeline并检查源控制。

利用ansible和jenkins实现tomcat应用的持续交付

在做持续交付这件事,想必大家都是用jenkins这款程序来做基石。当然,我们这次也是用jenkins作为承载工具,jenkins强大的插件是有目共睹的,有些ansible做起来不容易的事情交给jenkins反而简单有效。下面我会详细说明怎么持续交付tomcat应用。

应用架构

本次使用的应用架构是常见的负载均衡实例。

未分类

软件版本

  • os: centos 6.7 X64
  • ansible: 2.3.1.0
  • python: 2.6.6
  • ant: 10.1
  • java: 1.8.0_13
  • tomcat: 8.5.14
  • jenkins: 2.73

Ansible roles

  • Ansible Role 系统环境 之【ant】 (http://www.jianshu.com/p/75a129e71685)
  • Ansible Role 系统环境 之【java】(http://www.jianshu.com/p/1be92c3f65ec)
  • Ansible Role 系统环境 之【iptables】 (http://www.jianshu.com/p/1ce357af03bf)
  • Ansible Role WEB 之【tomcat】 (http://www.jianshu.com/p/fd7cca20c227)
  • Ansible Role WEB 之【nginx】 (http://www.jianshu.com/p/447df6f2335a)
  • Ansible Role 持续集成 之【jenkins】 (http://www.jianshu.com/p/f4bac35454b4)
  • Ansible Role 持续交付 之【deploy-tomcat】 (http://www.jianshu.com/p/eadbdb861fa2)

服务器角色

未分类

集群搭建

本次使用anisble playbook

---

- hosts: node130 node131
  vars:
   - java_version: "1.8"
   - tomcat_version: "8.5.14"
   - iptables_allowed_tcp_ports: ["8080"]
  roles:
  - java
  - { role: tomcat, java_home: "/usr/java/jdk1.8.0_131" }
  - iptables

- hosts: node1
  vars:
   - java_version: "1.8"
   - nginx_version: "1.12.1"
   - nginx_upstreams:
     - name: upstremtest
       servers:
       - 192.168.77.130:8080 max_fails=2 fail_timeout=2
       - 192.168.77.131:8080 max_fails=2 fail_timeout=2
   - nginx_vhosts:
     - listen: 80
       locations:
       - name: /
         proxy_pass: http://upstremtest
   - jenkins_version: "2.73"
   - jenkins_plugins_extra:
     - ansible
     - ansicolor
   - iptables_allowed_tcp_ports: ["80","8080"]
  roles:
  - ant
  - java
  - nginx
  - jenkins
  - iptables
  tasks:
  - name: install ansible
    package: name=ansible

怎么使用ansible roles,请移步到 Ansible Role【怎么用?】

确保正常访问以下服务:

  • nginx http://192.168.77.129/lework
  • jenkins http://192.168.77.129:8080 帐号密码:admin/admin
  • tomcat http://192.168.77.130:8080/lework http://192.168.77.131:8080/lework

node1服务器操作

在服务器上配置ansible playbook

# cd /etc/ansible/
# cat tomcat-deploy.yml
---

- hosts: all
  serial: 1
  roles:
   - deploy-tomcat

# cat hosts
[node130]
192.168.77.130

[node131]
192.168.77.131

[testservers:children]
node130
node131

[testservers:vars]
ansible_ssh_user=root
ansible_ssh_pass=123456

# git clone https://github.com/kuailemy123/Ansible-roles.git /etc/ansible/roles/
# chown jenkins.jenkins /etc/ansible/

jenkins 操作

登录jenkins之后,设置工具

点击“系统管理”==》“Global Tool Configuration”

未分类

未分类

未分类

创建发布项目

未分类

配置参数化构建

未分类

配置源码仓库地址

未分类

repo: https://github.com/kuailemy123/AntSpringMVC.git

配置构建环境

未分类

配置编译

未分类

配置ansible

未分类

配置ansible变量

未分类

这里就不配置邮件通知了。

创建回滚项目

未分类

配置参数化构建

未分类

配置构建环境

未分类

配置ansible

未分类

配置anisble变量

未分类

测试

执行tomcat_deploy任务

未分类

选择发布的节点,默认all

任务执行的日志

Started by user admin
Building in workspace /var/lib/jenkins/workspace/tomcat_deploy
Cloning the remote Git repository
Cloning repository https://github.com/kuailemy123/AntSpringMVC.git
 > git init /var/lib/jenkins/workspace/tomcat_deploy # timeout=10
Fetching upstream changes from https://github.com/kuailemy123/AntSpringMVC.git
 > git --version # timeout=10
 > git fetch --tags --progress https://github.com/kuailemy123/AntSpringMVC.git +refs/heads/*:refs/remotes/origin/*
 > git config remote.origin.url https://github.com/kuailemy123/AntSpringMVC.git # timeout=10
 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git config remote.origin.url https://github.com/kuailemy123/AntSpringMVC.git # timeout=10
Fetching upstream changes from https://github.com/kuailemy123/AntSpringMVC.git
 > git fetch --tags --progress https://github.com/kuailemy123/AntSpringMVC.git +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision 989ea3a6549e16e3dd4cd329ab969b47658c9d67 (refs/remotes/origin/master)
Commit message: "Create README.md"
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 989ea3a6549e16e3dd4cd329ab969b47658c9d67
First time build. Skipping changelog.
[tomcat_deploy] $ ant -file build.xml -Ddeploy_node=all
Buildfile: /var/lib/jenkins/workspace/tomcat_deploy/build.xml

clean:
   [delete] Deleting directory /var/lib/jenkins/workspace/tomcat_deploy/war/WEB-INF/classes

init:
    [mkdir] Created dir: /var/lib/jenkins/workspace/tomcat_deploy/target
    [mkdir] Created dir: /var/lib/jenkins/workspace/tomcat_deploy/war/WEB-INF/classes

resolve:
     [echo] Getting dependencies...
[ivy:retrieve] :: Apache Ivy 2.4.0 - 20141213170938 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: url = jar:file:/usr/local/ant/lib/ivy-2.4.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: org.apache#WebProject;working@node1
[ivy:retrieve]  confs: [compile, runtime, test]
[ivy:retrieve]  found org.slf4j#slf4j-api;1.7.6 in public
[ivy:retrieve]  found jstl#jstl;1.2 in public
[ivy:retrieve]  found ch.qos.logback#logback-classic;1.1.2 in public
[ivy:retrieve]  found ch.qos.logback#logback-core;1.1.2 in public
[ivy:retrieve]  found org.springframework#spring-core;4.1.3.RELEASE in public
[ivy:retrieve]  found commons-logging#commons-logging;1.2 in public
[ivy:retrieve]  found org.springframework#spring-beans;4.1.3.RELEASE in public
[ivy:retrieve]  found org.springframework#spring-context;4.1.3.RELEASE in public
[ivy:retrieve]  found org.springframework#spring-aop;4.1.3.RELEASE in public
[ivy:retrieve]  found aopalliance#aopalliance;1.0 in public
[ivy:retrieve]  found org.springframework#spring-expression;4.1.3.RELEASE in public
[ivy:retrieve]  found org.springframework#spring-web;4.1.3.RELEASE in public
[ivy:retrieve]  found org.springframework#spring-webmvc;4.1.3.RELEASE in public
[ivy:retrieve] downloading https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.6/slf4j-api-1.7.6.jar ...
[ivy:retrieve] ............ (28kB)
[ivy:retrieve] .. (0kB)
..... 省略下载的信息
[ivy:retrieve] :: resolution report :: resolve 74135ms :: artifacts dl 120701ms
    ---------------------------------------------------------------------
    |                  |            modules            ||   artifacts   |
    |       conf       | number| search|dwnlded|evicted|| number|dwnlded|
    ---------------------------------------------------------------------
    |      compile     |   13  |   13  |   13  |   0   ||   13  |   13  |
    |      runtime     |   13  |   13  |   13  |   0   ||   13  |   13  |
    |       test       |   13  |   13  |   13  |   0   ||   13  |   13  |
    ---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: org.apache#WebProject
[ivy:retrieve]  confs: [compile, runtime, test]
[ivy:retrieve]  13 artifacts copied, 0 already retrieved (5920kB/79ms)

compile:
    [javac] Compiling 1 source file to /var/lib/jenkins/workspace/tomcat_deploy/war/WEB-INF/classes
copy-resources:
     [copy] Copying 1 file to /var/lib/jenkins/workspace/tomcat_deploy/war/WEB-INF/classes
package:
[ivy:retrieve] :: retrieving :: org.apache#WebProject
[ivy:retrieve]  confs: [runtime]
[ivy:retrieve]  0 artifacts copied, 13 already retrieved (0kB/5ms)
      [war] Building war: /var/lib/jenkins/workspace/tomcat_deploy/target/helloproject-20170819172002.war

main:

BUILD SUCCESSFUL
Total time: 3 minutes 19 seconds
[tomcat_deploy] $ /usr/bin/ansible-playbook /etc/ansible/tomcat-deploy.yml -i /etc/ansible/hosts -l all -f 5 -e deploy_port=8080 -e deploy_file=/var/lib/jenkins/workspace/tomcat_deploy/target/helloproject-*.war

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : check | 发布文件是否存在] ****************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : check | 目标应用服务的家目录是否存在] **********************************
ok: [192.168.77.130]

TASK [deploy-tomcat : check | 工作目录如果不存在则创建] ************************************
changed: [192.168.77.130] => (item=/tmp/tomcat-ansible-snap/new)
changed: [192.168.77.130] => (item=/tmp/tomcat-ansible-snap/pre)
changed: [192.168.77.130] => (item=/tmp/tomcat-ansible-snap/old)

TASK [deploy-tomcat : deloy | 解压代码至目标服务器] **************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : deloy | 关闭服务] ********************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : deloy | 等待端口关闭] ******************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : deloy | 移动线上代码] ******************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : deloy | 部署最新代码] ******************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : deloy | 启动服务] ********************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : deloy | 等待端口开启] ******************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : backup | 创建存储备份的文件夹] *************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : backup | 备份上线的代码] ****************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : rollback | 检查/tmp/tomcat-ansible-snap/old是否存在代码] *********
skipping: [192.168.77.130]

TASK [deploy-tomcat : rollback | 关闭服务] *****************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : rollback | 等待端口关闭] ***************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : rollback | 部署上一版代码] **************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : rollback | 启动服务] *****************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : rollback | 等待端口开启] ***************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
skipping: [192.168.77.130]

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : check | 发布文件是否存在] ****************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : check | 目标应用服务的家目录是否存在] **********************************
ok: [192.168.77.131]

TASK [deploy-tomcat : check | 工作目录如果不存在则创建] ************************************
ok: [192.168.77.131] => (item=/tmp/tomcat-ansible-snap/new)
ok: [192.168.77.131] => (item=/tmp/tomcat-ansible-snap/pre)
ok: [192.168.77.131] => (item=/tmp/tomcat-ansible-snap/old)

TASK [deploy-tomcat : deloy | 解压代码至目标服务器] **************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : deloy | 关闭服务] ********************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : deloy | 等待端口关闭] ******************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : deloy | 移动线上代码] ******************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : deloy | 部署最新代码] ******************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : deloy | 启动服务] ********************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : deloy | 等待端口开启] ******************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : backup | 创建存储备份的文件夹] *************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : backup | 备份上线的代码] ****************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : rollback | 检查/tmp/tomcat-ansible-snap/old是否存在代码] *********
skipping: [192.168.77.131]

TASK [deploy-tomcat : rollback | 关闭服务] *****************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : rollback | 等待端口关闭] ***************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : rollback | 部署上一版代码] **************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : rollback | 启动服务] *****************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : rollback | 等待端口开启] ***************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
skipping: [192.168.77.131]

PLAY RECAP *********************************************************************
192.168.77.130             : ok=14   changed=8    unreachable=0    failed=0   
192.168.77.131             : ok=14   changed=7    unreachable=0    failed=0   

Finished: SUCCESS

执行tomcat_rollback任务

未分类

选择回滚的节点,默认all

执行的日志

Started by user admin
Building in workspace /var/lib/jenkins/workspace/tomcat_rollback
[tomcat_rollback] $ /usr/bin/ansible-playbook /etc/ansible/tomcat-deploy.yml -i /etc/ansible/hosts -l all -f 5 -e deploy_rollback=true

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : check | 发布文件是否存在] ****************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : check | 目标应用服务的家目录是否存在] **********************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : check | 工作目录如果不存在则创建] ************************************
skipping: [192.168.77.130] => (item=/tmp/tomcat-ansible-snap/new) 
skipping: [192.168.77.130] => (item=/tmp/tomcat-ansible-snap/pre) 
skipping: [192.168.77.130] => (item=/tmp/tomcat-ansible-snap/old) 

TASK [deploy-tomcat : deloy | 解压代码至目标服务器] **************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : deloy | 关闭服务] ********************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : deloy | 等待端口关闭] ******************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : deloy | 移动线上代码] ******************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : deloy | 部署最新代码] ******************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : deloy | 启动服务] ********************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : deloy | 等待端口开启] ******************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : backup | 创建存储备份的文件夹] *************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : backup | 备份上线的代码] ****************************************
skipping: [192.168.77.130]

TASK [deploy-tomcat : rollback | 检查/tmp/tomcat-ansible-snap/old是否存在代码] *********
changed: [192.168.77.130]

TASK [deploy-tomcat : rollback | 关闭服务] *****************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : rollback | 等待端口关闭] ***************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : rollback | 部署上一版代码] **************************************
changed: [192.168.77.130]

TASK [deploy-tomcat : rollback | 启动服务] *****************************************
fatal: [192.168.77.130]: FAILED! => {"changed": true, "cmd": "/etc/init.d/tomcat start", "delta": "0:00:20.035003", "end": "2017-08-19 17:24:47.586469", "failed": true, "rc": 1, "start": "2017-08-19 17:24:27.551466", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [deploy-tomcat : rollback | 等待端口开启] ***************************************
ok: [192.168.77.130]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
ok: [192.168.77.130]

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : check | 发布文件是否存在] ****************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : check | 目标应用服务的家目录是否存在] **********************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : check | 工作目录如果不存在则创建] ************************************
skipping: [192.168.77.131] => (item=/tmp/tomcat-ansible-snap/new) 
skipping: [192.168.77.131] => (item=/tmp/tomcat-ansible-snap/pre) 
skipping: [192.168.77.131] => (item=/tmp/tomcat-ansible-snap/old) 

TASK [deploy-tomcat : deloy | 解压代码至目标服务器] **************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : deloy | 关闭服务] ********************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : deloy | 等待端口关闭] ******************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : deloy | 移动线上代码] ******************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : deloy | 部署最新代码] ******************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : deloy | 启动服务] ********************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : deloy | 等待端口开启] ******************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : backup | 创建存储备份的文件夹] *************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : backup | 备份上线的代码] ****************************************
skipping: [192.168.77.131]

TASK [deploy-tomcat : rollback | 检查/tmp/tomcat-ansible-snap/old是否存在代码] *********
changed: [192.168.77.131]

TASK [deploy-tomcat : rollback | 关闭服务] *****************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : rollback | 等待端口关闭] ***************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : rollback | 部署上一版代码] **************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : rollback | 启动服务] *****************************************
changed: [192.168.77.131]

TASK [deploy-tomcat : rollback | 等待端口开启] ***************************************
ok: [192.168.77.131]

TASK [deploy-tomcat : verify | 查看http状态.] **************************************
ok: [192.168.77.131]

PLAY RECAP *********************************************************************
192.168.77.130             : ok=8    changed=4    unreachable=0    failed=0   
192.168.77.131             : ok=8    changed=4    unreachable=0    failed=0   

Finished: SUCCESS

至此,持续交付实验就完成了,但是持续之路还是很漫长了。望大家永远前进。 大家也可在发的过程中,测试发布是否是灰度发布。

for i in `seq 10000`;do curl -s -I http://192.168.77.129 | head -1;sleep 1;done;

配置jenkins实现gitlab自动化构建

构建

需要将jenkins服务器上 jenkins用户的公钥发送给 目标服务器的gs用户,使得在jenkins上能用gs免密登录目标服务器

复制密钥到目标机器上(需要登录到的机器)

ssh-copy-id -i  .ssh/id_rsa.pub [email protected](目标机器)

未分类

自动化构建

需要配置gitlab的钩子 ,并在jenkins上做配置

未分类

未分类

点击Test Hook,测试配置,如果返回Hook successfully executed.表示配置成功,只要下次push代码就可以自动发布,Jenkins效果如下图

未分类

自动构建后,邮件通知。

Jenkins安装Job Configuration History插件实现配置信息变更历史

像 Jenkins 这样的系统,使用的过程就是配置文件变更的过程。如果能够对配置文件的变更进行跟踪管理,将极大的提高系统的可用性。Job Configuration History 插件就是这么一款实用而精巧的组件。很显然,相对于它的功能而言,它的名字实在是太低调了。因为它不仅能处理 Job Configuration 的变更历史,还能够处理系统级别的配置变更历史。

安装 Job Configuration History 插件

在 Jenkins->Plugin Manager 界面中选择 “Available” 标签页,输入 “Job Configuration History” 进行过滤:

未分类

点击安装并重启的按钮就可以啦!

Overview 视图

安装完成后,主页的菜单项中已经添加了 “Job Config History” 菜单:

未分类

点击该菜单进入插件的 Overview 视图:

未分类

在这里我们可以总览系统中的配置变更(其实是系统配置和所有根及项目的配置),并且可以通过左上方的菜单项或者是正上方的链接过滤出 “系统配置”、”Job 配置”、”创建 Job 的配置” 以及 “删除 Job 的配置” 的历史记录。并且可以查看历史记录中配置文件的内容。

Agent Config History 视图

下面我们通过 Agent Config History 视图来介绍该插件对配置文件历史数据的强大处理能力。选择并进入一个 Agent 的信息界面:

未分类

选择 “Agent Config History”:

未分类

我们可以选择不同的配置版本进行比较,或者是用历史版本覆盖当前的版本。
我们选择不同的版本,然后点击 “Show Diffs” 按钮:

未分类

上图主要是对比不同版本配置文件的差异,但是看到这么多的按钮确实让人有点不知所措。它们的操作为:

  • Prev:左右两个文件都更新为前一个版本(时间上比当前版本更早的一个版本)。
  • Next:左右两个文件都更新为下一个版本(时间上比当前版本更晚的一个版本)。

  • 左 Shrink Diff:左边文件更新为时间上比当前版本更晚的一个版本。

  • 左 Expand Diff:左边文件更新为时间上比当前版本更早的一个版本。

  • 右 Shrink Diff:右边文件更新为时间上比当前版本更早的一个版本。

  • 右 Expand Diff:右边文件更新为时间上比当前版本更晚的一个版本。

  • Restore this configuration:用某个历史版本的配置信息覆盖当前的配置信息。

乍一看让人倍感凌乱的按钮,在细看之下发现每个按钮的功能都不可替代。它们组合在一起可以让我们方便的对比文件的不同版本。并且可以轻松的把配置回滚到某个历史时刻。

Job Config History 视图

和 Agent Config History 视图类似,Job Config History 视图提供了 Job 配置的历史版本管理界面。在 Job 的信息界面点击 “Job Config History”即可打开,具体功能和使用方法和 Agent Config History 视图相同,因而不再赘述。

对于 Job Config,Job Configuration History 插件提供的另一个有用功能是在 Build 的历史记录中显示配置文件的变化记录:

未分类

从上图中我们可以清楚的看到具体某次 Build 时配置文件发生了变化,点击小图标还能看到配置文件变化的具体内容:

未分类

这能够极大的提高我们调试配置文件时的生产力,尤其是当错误发生时,我们可以立即定位是哪些配置的变化导致 Build 失败了。

实现原理

Job Configuration History 是一款非常实用的插件,我们不禁会好奇,它是如何实现的呢?

答案可能会让人有点失望,因为它的思路很简单:当配置发生变化时,就把旧的配置文件复制一份存起来!旧配置文件的存放路径默认就在 Jenkins 安装目录下的 config-history 目录中:

未分类

不管是系统级别配置的历史记录,还是 Job、Agent 配置的历史记录,全都被按照一定的规则组织放置在这个目录下。

总结

Job Configuration History 插件兼具低调、实用和设计简单等优点,实为居家、旅行之必备良品!相信每一个 Jenkins 管理员都会对之爱不释手。

Jenkins & Docker持续集成实践

前言

持续集成(CI/CD)是一种软件开发实践。用于帮助团队成员频繁、快速的集成,测试他们的工作成果,以尽快发现集成错误。 更频繁、更早的集成意味着更早的发现问题。通过持续集成,及时发现和解决代码故障,提高代码质量,减少故障处理成本等等。

常见持续集成工具

目前持续集成的生态越来越完善,工具也有很多,开源的或商业的。如:

最最流行的,也是使用最多的 Jenkins

有着持续集成DNA的ThoughtWorks GO。理念:”Deployment as pipeline” (华为容器平台应该是基于GO做的二次开发实现)

  • Atlassian工具链之一的Bamboo (数人云应该是基于Banboo实现的CI/CD)

  • 与Gitlab紧密集成的Gitlab CI

  • 专为开源打造的Travis CI,与Github紧密集成

  • 使用 python 语言实现的Buildbot,相信 pythoner 看到会喜欢

  • 我们的选型是 Jenkins,所以我们来看下 Jenkins

Jenkins

Jenkins 特点

  • Jenkins是开源的应用最广泛的持续集成工具,支持CI, CD;

  • Jenkins有很多插件,而且用户也可以自定义插件,可扩展性非常强;

  • Jenkins对Docker支持非常好,有一套完善的Docker插件;

  • Jenkins2.0开始支持Pipeline,一个非常强大的插件,使用基于Groovy的DSL,支持CI/CD流水线;

  • Jenkins 基于 Java 语言开发;

Jenkins 几个概念

  • master 是jenkins安装和运行的地方,它负责解析job脚本,处理任务,调度计算资源;

  • agent 负责处理从master分发的任务;

  • executor 就是执行任务的计算资源,它可以在master或者agent上运行。多个executor也可以合作执行一些任务;

  • job 任务,用来定义具体的构建过程;

  • Groovy 是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy 可以使用其他 Java 语言编写的库。Jenkins 用Groovy作为DSL;

  • pipeline 流水线即代码(Pipeline as Code),通过编码而非配置持续集成/持续交付(CI/CD)运行工具的方式定义部署。流水线使得部署是可重现、可重复的;

流水线包括节点(Node)、阶段(Stage)和步骤(Step)。

流水线执行在节点上。节点是Jenkins安装的一部分。流水线通常包含多个阶段。一个阶段包含多个步骤。流水线上手指南可以查看到更多的内容。

node 在Pipeline中的context中,node是 job 运行的地方。 node会给job创建一个工作空间。工作空间就是一个文件目录,这是为了避免跟资源相关的处理互相产生影响。工作空间是node创建的,在node里的所有step都执行完毕后会自动删除。

stage 阶段,stage是一个任务执行过程的独立的并且唯一的逻辑块,pipeline定义在语法上就是由一系列的stage组成的。 每一个stage逻辑都包含一个或多个step。

step 步骤,一个step是整个流程中的一系列事情中的一个独立的任务,step是用来告诉Jenkins如何做。

  • Jenkinfile Jenkins支持创建流水线。它使用一种基于Groovy的流水线领域特定语言(Pipeline DSL)的简单脚。而这些脚本,通常名字叫Jenkinsfile。它定义了一些根据指定参数执行简单或复杂的任务的步骤。流水线创建好后,可以用来构建代码,或者编排从代码提交到交付过程中所需的工作。Jenkins中的Jenkinsfile有点类似Docker中的Dockfile的感觉。

Jenkins 部署

Jenkins组件其实非常少,安装部署也非常简单。 Jenkins按角色就两类: master节点和slave节点。master安装完成后,在控制台中添加节点即可。

下面以Dcoker的部署方式为例说一下Jenkins的部署:

master 节点

查看 docker hub 中 jenkins 的 image

[root@k3128v /home/huomingming]# docker search jenkinsNAME                               DESCRIPTION                                     STARS     OFFICIAL   AUTOMATEDjenkins Official Jenkins Docker image                   2600      [OK]       stephenreed/jenkins-java8-maven-git   Automated build that provides a continuous...   53 

可以看到第一个是官方提供的,所以我们选择这个即可。

拉取 jenkins image

docker pull jenkins

启动 jenkins 容器

jenkins没有数据库,所有数据都是存放在文件中的,首先在本地创建jenkins数据目录,用于保存jenkins的数据 这个目录需要定期的备份,用于容灾(当前jenkins容器所在节点由于不可抗因素无法使用时,可以在新机器上使用备份的数据启动新的jenkins master节点)。

sudo mkdir /var/jenkins
sudo chown 1000:1000 /var/jenkins
sudo docker run -p 8080:8080 -p 50000:50000 -v /var/jenkins:/var/jenkins_home --name my_jenkins -d jenkins

这样jenkins就成功跑起来了。可以直接通过机器的8080端口访问jenkins. 本地的/var/jenkins就相当于容器里jenkins用户的用户主目录,所以要保证该目录的权限为uid为j1000的用户目录。

配置 jenkins

启动完 jenkins master 后,在浏览器中数据输入 http://jenkins_master_ip:8080 登录 Jenkins 控制台进行接下来的安装和配置。 具体图就不贴出来了~~

查看jenkins的版本

java -jar /usr/share/jenkins/jenkins.war --version

slave 节点

安装 java jdk

yun install java-1.8.0-openjdk

创建 jenkins 用户

$ useradd -m jenkins -d /home/jenkins$ passwd jenkins

创建工作目录

mkdir /data/jenkinschown jenkins.jenkins /data/jenkins

添加 jenkins 用户到 docker 用户组

sudo usermod -a -G docker jenkins

配置 ssh 互信,master免密码登陆slave

master 有多种管理 slave 的方式,我们选择SSH方式 在master节点中,切换到jenkins用户 ssh-keygen -t rsa 创建秘钥对 把公钥拷贝到slave节点

scp ~/.ssh/id_rsa.pub jenkins@slave_ip:~/.ssh/authorized_keys

确保在scp前,slave节点根目录下.ssh目录已存在

chmod 700 authorized_keys

使用 jenkins 来构建 docker 是需要安装插件的。那我们需要安装哪些插件呢?

Jenkins 有哪些 Docker 的 Plugins

未分类

是非常丰富的,但并不是我们都能用的上,所以需要根据你使用的环境和平台来选择适合自己的 plugin 安装就可以了。 每个 plugin 都需要适配 Jenkins 的版本,且每个 plugin 也需要依赖一些其它 plugin,上面都已经做了标注,需要配套来用。

这里介绍几个常用的 Docker 插件

Docker Commons Plugin

其基本功能:

  • API for managing Docker image and container fingerprints

  • Credentials and location of Docker Registry

  • Credentials and location of Docker Daemon (aka Docker Remote API)

  • ToolInstallation for Docker CLI clients

  • DockerImageExtractor extension point to get Docker image relations from jobs

  • Simple UI referring related image fingerprints in Docker builds

Docker Plugins

该插件是将 docker 作为 jenkins 的 slave 来使用,来在 docker 容器种完成项目的build,build 完成后该容器 slave 容器就会被销毁。所有的工作都是在 slave 容器内完成。

docker-build-step

该插件在 build 过程种增加了对 Docker 命令的支持。

Docker Pipeline Plugin

基于 Docker Commons Plugin 实现的一些上层的基于 Docker 的 Pipeline 编排

Docker Hub Notification Trigger Plugin

该插件提供了当registry中的image发生变化时触发build新镜像的功能。

CloudBees Docker Build and Publish

该插件提供了通过 Dockerfile 来构建项目并将生成的镜像上传到镜像仓库的功能。

CloudBees Docker Custom Build Environment

This plugin allows the definition of a build environment for a job using a Docker container.

该插件适用于 “自由风格的软件项目”,如图:

未分类

CloudBees Docker Traceability

用于追踪通过jenkins启停的容器的事件

Kubernetes

This plugin allows Jenkins agents to be dynamically provisioned on a Kubernetes cluster. The aim of the Kubernetes plugin is to be able to use a Kubernetes cluster to dynamically provision a Jenkins agent (using Kubernetes scheduling mechanisms to optimize the loads), run a single build, then tear-down that slave.

与 Kubernetes 结合,通过 kubernetes 提供 jenkins 的 slave 节点。利用 kubernetes 的调度功能提供快速的启停 slave 节点执行 build 等任务。目前是0.11版本,稳定性有待验证。

Jenkins 有没有 API?

因为,我们不是直接在 Jenkins 的 Dashbord 来操作, 而是集成到现有平台,所以我们需要使用它的API。

Jenkins的Remote API以REST的形式进行提供。例如,我们搭建的Jenkins站点为http://myjenkins.com:8080。那么,访问http://myjenkins.com:8080/api 即可查看到该站点所有可用的API;

查询操作

未分类

执行一些动作

未分类

例如,我要创建一个 job,名字为 my_job

my_job的配置文件

<?xml version='1.0' encoding='UTF-8'?>
<project>
 <actions/>
 <description></description>
 <keepDependencies>false</keepDependencies>
 <properties/>
 <scm class="hudson.scm.NullSCM"/>
 <canRoam>true</canRoam>
 <disabled>false</disabled>
 <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
 <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
 <triggers class="vector"/>
 <concurrentBuild>false</concurrentBuild>
 <builders/>
 <publishers/>
 <buildWrappers/>
</project>

调用 api 创建 my_job

curl -X POST http://www.xxx.xxx/jenkins/createItem?name=my_job  --user uname:pass --data-binary "my_job_config.xml" -H "Content-Type: application/xml"

然后,你就可以在 Jenkins dashboard 上看到这个 job 了。它的管理页面为http://myjenkins.com:8080/job/my_job。那么我们访问 /my_job/api/ 即可查看到该job可用的API。

更多的 api 介绍可以参考Jenkins的官方wiki,这里只是个引子,在此就不过多进行介绍。

忘记Jenkins admin密码时重置的方法

一、admin密码未更改情况

1、进入Jenkinssecrets目录,打开initialAdminPassword文件,复制密码;

find / -name initialAdminPassword
[root@jenkins jenkins]# cat /var/lib/jenkins/secrets/initialAdminPassword
796008f906d2453ca0d22e2f8fa46d33

2.、访问Jenkins页面,输入管理员admin,及刚才的密码;

3、进入后可更改其他管理员密码;

二、admin密码更改忘记情况

1、删除Jenkins目录下config.xml文件中下面代码,并保存文件。

<useSecurity>true</useSecurity>  
<authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">  
  <denyAnonymousReadAccess>true</denyAnonymousReadAccess>  
</authorizationStrategy>  
<securityRealm class="hudson.security.HudsonPrivateSecurityRealm">  
  <disableSignup>true</disableSignup>  
  <enableCaptcha>false</enableCaptcha>  
</securityRealm>  

2、重启Jenkins服务;

3、进入首页>“系统管理”>“Configure Global Security”;

4、勾选“启用安全”;

5、点选“Jenkins专有用户数据库”,并点击“保存”;

6、重新点击首页>“系统管理”,发现此时出现“管理用户”;

7、点击进入展示“用户列表”;

8、点击右侧进入修改密码页面,修改后即可重新登录。

持续集成开发:Jenkins自动打包实践

对于Jenkins的使用,本人是小白一个,本人实践就是按照大神的文章自己做了一次尝试。本文主要说明一下在实践中遇到的坑。

参考文章:

http://www.jianshu.com/p/41ecb06ae95f

1、打包的时候找不到证书

之前安装Jenkins使用的是官网的.pkg。这样的话会安装到 用户/共享目录下。这样就会造成打包的时候找不到证书。

解决方法:使用命令行安装。cd /Library 可在该路径执行相关命令。

参考文章http://blog.csdn.net/jiisd/article/details/60878398

2、在Jenkins中配置,在Jenkins的证书管理中添加SSH

未分类

电脑中ssh的生成及查看方式:前往cd /Users/wangjiajia/.ssh 打开id_rsa.pub即可

未分类

当所有配置没有问题的情况下:进行构建的时候可能会出现 times out 的问题。这时候在Jenkins中设置一下超时时间就好

未分类

参考文章:

https://linmi.cc/901

https://stackoverflow.com/questions/36017253/jenkins-git-fetch-timeout

3、本地脚本存放位置

/Users/用户名/.jenkins/workspace/具体的项目的文件夹

在配置好git仓库的地址之后,即可进行一次构建。这时候如果没有错误,就可将git仓库的代码拉取到本地:/Users/用户名/.jenkins/workspace/

未分类

这时可将脚本文件及plist文件拷贝进该目录

参考文章:

http://www.jianshu.com/p/5d59966eaecc?from=timeline

该文章提供的脚本有输入功能,但是Jenkins自动打包的时候并没有让进行输入,因此,可以改变脚本配置实现为不同配置打包。

4、打包过程中,会出现找不到target的情况

未分类

未分类

修改权限,上传代码到远端,重新构建即可。

实践中与参考文章配置不同的地方:

我的Jenkins本没有配置着这些信息:

上传keychain及provisioning profile

未分类

未分类

未分类

构建环境配置

未分类

最终Jenkins配置样例

general

未分类

源码管理

未分类

构建

未分类

配置描述

未分类

jenkins实现PHP项目持续集成部署

安装jenkins相关依赖

wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
yum install jenkins
yum install Java
yum install java-1.8.0-openjdk
yum install PHP
yum install php-devel
yum install php-pear
yum install re2c
yum install php-pear-phing

jenkins配置和启动

service jenkins start

输入localhost:8080即可访问。

插件安装

  • 系统管理-插件设置
  • 安装以下插件
  • Phing(php构建工具)
  • Publish Over SSH Plugin(通过ssh发布代码)

配置SSH免登录

假设有两台服务器。A为发布机,即jenkins所在机器。B为应用服务器,即运行PHP的服务器。

首先在A服务器生成公私钥。

ssh-keygen -t rsa

这时.ssh目录下会生成私钥和公钥的键值对id_rsa,id_rsa.pub

将id_rsa.pub公钥复制到B服务器上,并重命名为authorized_keys。

scp ~/.ssh/ras.pub root@B:/root/.ssh/authorized_keys

这时候ssh到B服务器则无需登录密码。

ssh root@B

注:若生成RSA密码的时候设置了ssh key,SSH到B服务器的时候还需要输入相应ssh key。

配置Publish Over SSH Plugin

系统管理—系统设置

未分类

  • Jenkins SSH Key:生成rsa的时候设置的ssh key,若没有设置则留空。
  • Key:填上A服务器私钥的内容。默认路径 ~/.ssh/id_rsa
  • Hosename:填上B服务器的IP
  • username:填上B服务器的帐号

配置phing build.xml

进入当前job的项目目录

cd /var/lib/jenkins/workspace/Git

未分类

build.xml文件内容如下

<?xml version="1.0" encoding="UTF-8"?>
<project name="api" default="build">
        <target name="build" depends="make_runtime,check,tar"/>
        <property name="version-m"  value="1.1" />
        <property name="version"    value="1.1.0" />
        <property name="stability"  value="stable" />
        <property name="releasenotes" value="" />
        <property name="tarfile"     value="${phing.project.name}.${buildnumber}.${buildid}.tar.gz" />
        <property name="pkgfile"     value="${phing.project.name}.${version}.tgz" />
        <property name="distfile"    value="dist/${tarfile}" />
        <property name="tests.dir" value="test" />
        <fileset id="api.tar.gz" dir=".">
            <include name="test/**"/>
            <include name="*.php"/>
            <include name="*.xml"/>
        </fileset>
        <target name="make_runtime">
                <mkdir dir="${project.basedir}/Runtime" />
                <mkdir dir="${project.basedir}/build/logs" />
                <mkdir dir="${project.basedir}/build/pdepend" />
                <mkdir dir="${project.basedir}/build/code-browser" />
        </target>

        <target name="check" description="Check variables" >
            <fail unless="version" message="Version not defined!" />
            <fail unless="buildnumber" message="buildnumber not defined!" />
            <fail unless="buildid" message="buildid not defined!" />
            <delete dir="dist" failonerror="false" />
            <mkdir dir="dist" />
        </target>

        <target name="tar" depends="check" description="Create tar file for release">
            <echo msg="Creating distribution tar for ${phing.project.name} ${version}"/>
            <delete file="${distfile}" failonerror="false"/>
            <tar destfile="${distfile}" compression="gzip">
                <fileset refid="api.tar.gz"/>
            </tar>
        </target>
</project>

这里我们只做简单发布,没有加入php-unit等插件。

开始构建项目

新建—输入项目名称,选择构建自由风格的软件项目—下一步

配置源码管理

这里我们用的是git

未分类

增加构建步骤,选择Invoke Phing targets,再新增一个构建步骤,选择Send files or execute commands over SSH

未分类

Phing targets配置如下

未分类

Send files or execute commands over SSH 配置如下

未分类

Source files:dist/api.${BUILD_NUMBER}.${BUILD_ID}.tar.gz
Remove prefix:dist/
Remote directory: /home/data/
Exec command:
mkdir -p /home/data/
mkdir-p /home/www/
cd /home/data/
tar -zxf api.${BUILD_NUMBER}.${BUILD_ID}.tar.gz -C /home/www/
  • /home/data/ 为B服务器接收打包文件的目录
  • /home/www/ 为B服务器PHP项目运行的目录

保存即可。

接下来进入项目–立即构建,完成后我们进入B服务器。

cd /home/data

未分类

至此已经大功搞成了。

配置GitLab触发jenkins自动构建项目

目的为在公司的测试环境当中一旦开发向gitlab仓库提交成功代码,gitlab通知jenkins进行构建项目、代码质量测试然后部署至测试环境,注意这只是测试环境,而生产环境依然需要手动部署代码。

1、jenkins配置

1.1 安装Gitlab Hook Plugin插件

系统管理-管理插件-可选插件-Gitlab Hook Plugin和Build Authorization Token Root Plugin

未分类

1.2 生成随机token

# openssl rand -hex 12

0f2a47c861133916d2e299e3

1.3 创建项目触发器

项目-配置-构建触发器:

http://192.168.3.199:8080/jenkins/project/web-demo

未分类

2、配置gitlab

2.1 在Git项目配置界面设置链接和token

登录gitlab,在这个项目下找到钩子配置的地方

未分类

选择项目-设置-webhooks:

插件使用介绍,https://wiki.jenkins-ci.org/display/JENKINS/Build+Token+Root+Plugin

http://192.168.3.199:8080/jenkins/buildByToken/build?job=web-demo&token=0f2a47c861133916d2e299e3

http://jenkins服务器地址:8080/buildByToken/build?job=项目名&token=token值

未分类

2.2 测试

未分类

报错:

hook executed successfully but returned http 404

本次是因为没有在项目后面加上jenkins这个路径

2.3 测试,看到显示201表示成功

3、向git服务器提交代码,验证是否可以自动部署

3.1 提交代码

[www@master code]$ git clone [email protected]:web/web-demo.git
[www@master web-demo]$ echo "Build token root plugin" > index.html 
[www@master web-demo]$ git add 'index.html'
[www@master web-demo]$ git commit -m 'build token root plugin test'
[master beb37cb] build token root plugin test
1 file changed, 1 insertion(+), 1 deletion(-)
[www@master web-demo]$ git push origin master
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 281 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To [email protected]:web/web-demo.git
c02523b..beb37cb master -> master

3.2 jenkins服务器的日志记录

[root@node1 tomcat]# tail -f /usr/local/tomcat/logs/catalina.out

未分类

3.3 jenkins项目构建

未分类

未分类

3.4 访问web界面验证代码是否最新的

未分类

3.5 jenkins控制台输出信息

未分类

使用Jenkins Ansible Docker Swarm实现自动化编译部署

自动化部署在项目部署过程中很重要,一旦自动化部署完成,我们就可以减轻我们手动的操作的步骤以及出错的概率。下面介绍一种通用的自动化部署。从打包编译到上线,一条命令就完成所有操作。简单而高效

1、Jenkins部署这里不在赘述,直接从新建项目开始。

项目截图,如下:增加两个变量如图,

  • BranchTobuild 默认是master分支,在编译的时候也可以指定分支。

  • PushDockerImage 默认布尔值是选中,直接把镜像推到镜像仓库。

未分类

增加Pipeline配置,主要是分了几个步骤。所以用pipeline,也可以不用这种方式,直接脚本也行

所有执行步骤写入Jenkinsfile中,并把文件放入项目的根目录,这样才能调用。

未分类

Jenkinsfile内容如下:包括编译、打包、推送docker镜像到仓库,ansible部署。

#cat Jenkinsfile
pipeline {

   //定义了执行jenkins的机器
    agent {
        label ‘master’
    }
    stages {
        stage (‘Prepare’) {
            steps {
                sh “echo Prepare”
                //准备阶段,没有暂不处理
            }
        }

        //build打包过程,最后会生产apk包
        stage (‘build’) {
            steps {
                sh ‘echo “start Build”‘
                script {
                    if (params.buildDebug) {
                        sh ‘echo “build debug version”‘
                        sh ‘chmod +x ./gradlew’
                        sh “./gradlew clean”
                        sh “./gradlew build –debug”
                    } else {
                        sh ‘echo “build release version”‘
                        sh ‘chmod +x ./gradlew’
                        sh “./gradlew clean”
                        sh “./gradlew build”
                    }
                }
            }
        }
        stage (‘Test’) {
            steps {
                sh “echo Test”
                //测试阶段,没有暂不处理
            }
        }

       //发布阶段,项目中包括了gradle.properties文件,几个变量:版本、项目、产品,按照这几个名词生产镜像的名
        stage (‘Deploy’) {
            steps {
                sh ‘echo “Start Docker Build And Push Images”‘
                script {
                    if (params.PushDockerImage) {
                        def props = readProperties  file: ‘gradle.properties’
                                    def VERSION = props[‘version’]
                                    def PRODUCT = props[‘product’]
                                    def ARTIFACT = props[‘artifact’]
                        sh ‘echo “start Build”‘
                                    //开始修改Dockerfile
                                    sh “sed -i ‘s#${PRODUCT}#${PRODUCT}#g’ Dockerfile”
                                    sh “sed -i ‘s#${VERSION}#${VERSION}#g’ Dockerfile”
                                    sh “sed -i ‘s#${ARTIFACT}#${ARTIFACT}#g’ Dockerfile”
                        sh “docker build -t registry.sreop.com:5000/${PRODUCT}/${ARTIFACT}:${VERSION} -f Dockerfile .”
                        sh ‘echo “Publish Images To registry.leautolink.com”‘
                        sh “docker push registry.leautolink.com:5000/${PRODUCT}/${ARTIFACT}:${VERSION}”

                        //ansible playbook 部署到线上或者测试环境
                        sh “sudo /usr/bin/ansible-playbook  /data/base-docker-compose/product/light/prod/playbook.yml”
                    }
                }
            }
        }
    }
}

2、每个项目需要一个Dockefile

cat Dockerfile
# 基础镜像
FROM registry.sreop.com:5000/alpine-java:8u121b13_jdk_unlimited
# 维护者信息
MAINTAINER [email protected]
# 镜像操作命令
RUN mkdir -p /data/bin/${PRODUCT}/${ARTIFACT}
# 指定后续命令的执行目录
WORKDIR /data/bin/${PRODUCT}/${ARTIFACT}
# 对外连接端口号
EXPOSE 12429
# 向镜像中增加文件
ADD ./build/libs/${ARTIFACT}-${VERSION}.jar .
# 容器启动命令
CMD java -Djava.security.egd=file:/dev/./urandom -jar ${ARTIFACT}-${VERSION}.jar –spring.profiles.active=prod

3、写ansible playbook,为推送到Docker集群平台,并部署到线上或者测试平台。

注意:docker-compose.yml要拷贝到每个docker节点机器上。功能是:获取各个变量,拉取镜像。最后生产docker services

– name: light Pull Image
  hosts: docker-swarm-prod
  remote_user: root
  tasks:
    – name: get product var 
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml |head -n1|awk -F’/’ ‘{print $2}’
      register: product
    – name: get artifact var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#1#g’
      register: artifact
    – name: get version var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#2#g’
      register: version
    – name: docker pull image
      shell: docker pull registry.leautolink.com:5000/”{{ product.stdout }}”/”{{ artifact.stdout }}”:”{{ version.stdout }}” || /bin/true

– name: Remove Docker Old Verison
  hosts: docker-swarm-prod-lead 
  remote_user: root
  tasks:
    – name: get product var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1|awk -F’/’ ‘{print $2}’
      register: product
    – name: get artifact var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#1#g’
      register: artifact
    – name: get version var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#2#g’
      register: version
    – name: remove light
      shell: docker stack rm {{ artifact.stdout }} || /bin/true

– name: Start New verison
  hosts: docker-swarm-prod-lead 
  remote_user: root
  tasks:
    – name: get product var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1|awk -F’/’ ‘{print $2}’
      register: product
    – name: get artifact var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#1#g’
      register: artifact
    – name: get version var
      shell: grep image /data/base-docker-compose/product/light/prod/docker-compose.yml|head -n1 |awk -F’/’ ‘{print $3}’|sed ‘s#(.*):(.*)#2#g’
      register: version
    – name: start light
      shell: docker stack deploy -c /data/base-docker-compose/product/light/prod/docker-compose.yml {{ artifact.stdout }} || /bin/true 

4、swarm集群部署compose.yml

# cat docker-compose.yml 
version: “3”
services:
  config-server:
    image: registry.sreop.com:5000/leradio/light:1.0.1-RELEASE
    command: java -Djava.security.egd=file:/dev/./urandom -jar light-1.0.1-RELEASE.jar –spring.cloud.config.profile=prod –spring.profiles.active=prod
    ports:
      – 12429:12429
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure
networks:
  frontend: