Jenkins与travis使用
Jenkins与Travis为CI、CD工具,其为Devops模式下的平台组件,能够让我们更好地进行开发测试与交付。由于最近云原生的课上在介绍DevOps和云监控,所以正好趁这个机会体验下Devops的交付流程,之前也有使用过Github Action作为CICD工具,但除了开源项目以外,Github使用比较少。这次呢就可以再熟悉下业内常用的CICD组件了:Jenkins or Travis
DevOps发展背景
传统交付模式的串行及隔离化形成了部门壁垒,降低了工作效率
通过“在云上创建资源”->实现“云服务器自动化管理”->“应用无状态上云”后即可实现应用的持续部署、持续交付,完成一次构建、到处运行的效果
作为一种新式的开发模式,DevOps模式是在互联网应用快速迭代的需要下,结合了开发与运维以及测试流程的一种模式,解决了测试资源匮乏、手工部署工作量大、周期长,环境不统一、资源难管理的问题。
实现的功能
DevOps平台典型流程
基于镜像容器构筑具备完全一致性的开发测试环境
企业中Devops的解决方案
建设成果
Jenkins使用
Jenkins跟Gitlab一样,是发布了服务包的,为了更好的管理和使用,我这边是直接使用的Jenkins Docker镜像
- 拉取Jenkins镜像并运行
docker run -p 8080:8080 -p 50000:50000 --restart=always --name jenkins -v jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):$(which docker) jenkins/jenkins:lts
--restart=always
:能够使我们在重启docker时,自动启动相关容器--name jenkins
: 将启动的容器名取作jenkins-v jenkins_home:/var/jenkins_home
: 挂载持久化卷-v /var/run/docker.sock:/var/run/docker.sock
:为了实现pipeline在另一个容器中运行,侦听docker.sock套接字,并执行挂载-v $(which docker):$(which docker)
:-v 之后使用$()
表示执行命令,这里表示如果在容器上运行which docker
, Docker也会在本地计算机上运行“ which container"
并将执行结果返回给容器,从而能在Jenkins容器中拿到另一个容器的containerID- 最后的
jenkins/jenkins:lts
:表示要拉取的镜像以及镜像版本
将容器跑起来后需要进入容器,给docker.sock授权:
1 | docker exec -it --user=root jenkins bash |
以上过后就可以在浏览器上登录Jenkins了,这边登录localhost:50000
后会有一系列初始化步骤如下
- 安装建议的插件
- 创建第一个管理员用户
- Jenkins实例配置
- 开始使用 Jenkins
监听Github仓库变化
选择“新建任务”->“流水线”->勾选Github项目并输入https://github.com/Freedomisgood/iotrfid.git/
->构建触发器中选择“GitHub hook trigger for GITScm polling”->流水线选择“Pipeline script”输入:
1 | pipeline { |
然后保存,之后运行就可以等待触发啦,或者点击左侧的“立即构建”
注:可以看到script中有使用到docker,这边需要额外安装Docker的插件Docker Pipeline、Docker plugin(建议安装的插件中没有),如果不安装会执行失败
注:如果要监听Github仓库的变化,则需要增加Github的凭据:选择“Dashboard”到首页->系统管理->Manage Credendials->Jenkins->全局凭据->左侧的添加凭据,输入Github用户和密码后,留一个之后要使用的Credendials ID
参考:怎样用 Jenkins Docker 和 CICD 构建无服务器应用程序
Travis使用
Travis+Docker[+阿里云容器镜像、dockerhub]
travis主要是关注在CI持续集成上,同时与Github关联搭配做的比较号,也能完成持续交付(持续集成的基础上,增加打包构建形成产物)的工作。因此本次就以travis+docker来完成这么一个持续集成与持续交付的步骤:
步骤如下:
-
去travis官网绑定travis和github
-
Dockerhub创建镜像仓库 or 阿里云开通容器镜像服务
-
项目中添加.travis.yml和Dockerfile文件
1
2
3
4
5
6
7FROM python:3.9.1-alpine
MAINTAINER Mrli 1063052964qq.com
RUN tar -zcf app.tar.gz .
ADD app.tar.gz /app
WORKDIR /app
RUN pip install -r local_requiements.txt
ENTRYPOINT python app/main.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27language: python
# sudo: enabled or required
python:
- "3.9.1"
branches:
only:
- master
install:
- pip install -r local_requirements.txt
before_script:
- flake8 app tests
- docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD # dockerfile中需要拉取 python-3.9.1:alipine的镜像, 所以需要先docker login
script:
- python app/main.py
- docker build -t nymrli/python:v2 .
after_success:
- docker login -u $username -p $password # 这里我们使用环境变量来控制,避免写死。环境变量,在travis的后台settings里面添加
- docker push
- echo "success"
services: # 需要提供docker才能在里面使用docker命令
- docker -
git push提交代码,travis会侦听github仓库变化触发githook从而执行任务
-
登录要运行app的服务器,
docker-compose up
将镜像启动1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35version: '2'
services:
mysql:
container_name: mysql1
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 数据库密码
ports:
- "3306:3306"
volumes:
- /usr/local/docker/mysql/data:/var/lib/mysql
- /usr/local/docker/mysql/conf:/etc/mysql
- /usr/local/docker/mysql/logs:/var/log/mysql
web:
container_name: jafir_nginx1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest
ports:
- 8080:80
restart: always
depends_on:
- java
volumes:
- /mydockerdata/nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- /mydockerdata/nginx/log/:/var/log/nginx
java:
container_name: jafir_gps1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
restart: always
depends_on:
- mysql
ports:
- 9090:9090
volumes:
- /mydockerdata/java/gps/upload:/Users/jafir/Downloads/upload
- /mydockerdata/arme/out/*.nofoo.cn/*.nofoo.cn.pfx:/Users/jafir/Downloads/upload/cert/*.nofoo.cn.pfx
注:如果需要travis的构建过程中在服务器执行一些命令(如将代码部署发到自己的服务器上),还需要配置生成公钥和私匙,参看:
Travis CI+Coveralls
-
配置Travis
- 编写
.travis.yml
- 使用 GitHub 账号登陆 Travis CI,Oauth登录授权,获得组织访问权限
- 设置 Build Status:打开指定仓库的监听状态选项
- 编写
-
配置 Coveralls
-
在
.travis.yml
中添加coveralls内容,如go的库叫goveralls ,python的库叫1
2
3
4
5
6
7
8
9
10
11
12# GO
before_install:
- go get github.com/mattn/goveralls
script:
- goveralls -service=travis-ci
# Python
install:
- pip install coveralls
script:
- nosetests --with-coverage --cover-package=fanpy
after_success:
- coveralls -
使用 GitHub 账号登陆 Coverallshttps://travis-ci.org/),Oauth登录授权,获得组织访问权限
-
设置Coverage Status: 打开指定仓库的监听状态选项
-
自动部署
通过配合Travis
的使用,我们可以实现如下的效果:
- 测试部署:每次
push
代码到dev
分支,Travis
会自动进行单元测试,然后自动的通过SSH将代码部署到对应的开发机器上并重启服务,以保持开发机上始终是最新的版本。 - 正式部署:决定上线的时候可以将代码
push
代码到deploy
分支上,Travis
会自动将代码部署到正式的开发环境。
步入正题,要完成自动部署,首先Travis
要能监听Git
的变化,然后Travis
还需要有权限登录到我们的SSH服务器
进行部署:
- 配置
Travis
,让Travis
能监听Git
的某个分支。 Git
某个分支提交之后,Travis能自动发现提交并进行编译。Travis
将编译后的产物通过SSH部署到给我们指定的机器。
Travis添加SSH密钥
通常我们是通过ssh命令加上用户名和密码访问服务器的,虽然理论上我们也可以在travis
的命令中写上诸如ssh mofei@zhuwenlong.com -p abc
的脚本,但是这样的代码如果提交到了公开的仓库中会有很大的泄露服务器密码的风险,所以我们需要一个别人无法窃取密码或者密钥的方式让Travis
登录我们的服务器。
通常的免密登录是基于SSH
信任关系的,那么如果我们能把密钥以加密的形式保持在Travis
的服务器中,Travis
就能登录我们的服务器了。这里我们可以使用Travis
的文件加密功能,把我们的密钥进行加密保存。
在这个过程中,我们的密钥首先会被被Travis
加密,解密的密钥被存储在Travis
中,就是说只有Travis
可以进行解密。所以我们可以大胆的把这个加密后的文件上传到github
中,不用担心其他人盗用我们的密钥。
▲. 既然我们想要使用Travis
加密文件,第一件事情就是在本地安装Travis
。
-
因为travis是用ruby写的,首先得查看是否有ruby,
ruby -V
-
给ruby换源,
gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
-
安装travis:
sudo gem install travis
-
安装好
Travis
之后,我们需要在命令行中登录Travis
:travis login --pro
,pro指定的是API网站Travis CI Pro注意 Travis 目前有两个官网:travis-ci.com 和 travis-ci.org. 官方通知后者即将关闭,所以我们使用前者参数为–pro,后者参数为–org。
1
2
3
4
5
6
7
8Shell completion not installed. Would you like to install it now? |y| y
We need your GitHub login to identify you.
This information will not be sent to Travis CI, only to api.github.com.
The password will not be displayed.
Try running with --github-token or --auto if you don't want to enter your password anyway.
Username:或者直接:
travis login --github-token token --pro
, github-token打开github后点击个人头像Github>settings>Personal access tokens> Generate new token > Generate token> Copy Token
1
2(env38) mrli@VM-4-7-ubuntu:~/remap/cook$ travis login --pro --github-token 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
Successfully logged in as Freedomisgood! -
生成并加密SSH密钥
1
2# 在当前目录生成密钥: 这段代码执行完成之后,会在目录中生成2个文件,私钥deploy_rsa和公钥deploy_rsa.pub,前者是用来免密登录服务器时候使用的,后者服务器用来鉴定私钥的有效性的。
ssh-keygen -t rsa -b 4096 -C 'build@travis-ci.org' -f ./deploy_rsa下面的操作得在Github仓库下
1
2
3
4
5
6
7
8# 使用Travis加密, 注意加上--pro 指定api, 执行完命令,会生成加密文件 id_rsa.enc,.travis.yml 中会被写入解密命令:这几行被自动添加的代码的意思是,在`install`之前执行解开`deploy_rsa.enc`文件的命令并放置到`deploy_rsa`以供使用,其中这里的`$encrypted_137f45644142_key`和`$encrypted_137f45644142_iv`是解开这个文件的两个变量被存储在了`Travis`的服务器上。
travis encrypt-file deploy_rsa --add --pro
# 添加信任关系: 这句话的意思是向目标服务器(<ssh-user>@<deploy-host>这里的user和host需要替换成自己服务器的用户名和地址)添加公钥,添加成功之后,所有用该公钥对应的私钥访问服务器都会直接被认证通过。也就是说如果Travis保持了私钥的话,就可以免密的通过ssh登录我们的服务器了。
ssh-copy-id -i deploy_rsa.pub <ssh-user>@<deploy-host> #
# 删除敏感文件: 私钥deploy_rsa和公钥deploy_rsa.pub已经完成了他们的使命,我们可以把它删除以免被其他人恶意使用,并把生成的加密文件deploy_rsa.enc和修改后的.travis.yml添加到git中。
rm -f deploy_rsa deploy_rsa.pub
# 将修改添加到git中
git add deploy_rsa.enc .travis.yml生成的
.travis.yml
文件内容1
2
3before_install:
# 可以看到有两个变量: encrypted_f217180e22ee_key, encrypted_f217180e22ee_iv
- openssl aes-256-cbc -K $encrypted_f217180e22ee_key -iv $encrypted_f217180e22ee_iv -in id_rsa.enc -out id_rsa -d-in
表示输入文件,即我们要解密的文件-out
表示解密后的文件,这里我们需要手动将路径修改为~/.ssh/id_rsa
▲.同时travis仓库中也出现了encrypted_f217180e22ee_key, encrypted_f217180e22ee_iv这两个变量
-
所有的一切都准备好之后,我们就可以修改
.travis.yml
文件让travis
来进行部署了。首先,我们需要在部署之前解密私钥,并使其生效,所以我们添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18before_install:
# 一行是解密ssh文件,后面的3行是使ssh密钥生效
# 把项目下的deploy_rsa.enc加密文件,解密输出到/tmp/deploy_rsa中, 一般是~/.ssh/id_rsa, 不过也跟如何ssh-keygen有关
- openssl aes-256-cbc -K $encrypted_137f45644142_key -iv $encrypted_137f45644142_iv
-in deploy_rsa.enc -out /tmp/deploy_rsa -d
# 开启 ssh-agent,即允许使用 ssh 命令
- eval "$(ssh-agent -s)"
# 给予 id_rsa 文件权限,避免警告
- chmod 600 /tmp/deploy_rsa
# 将私钥添加到ssh(看其他教程这一步貌似不需要)
- ssh-add /tmp/deploy_rsa
after_success:
# 下面就是一些需要远程登陆的命令啦: scp, ssh,
- scp -o stricthostkeychecking=no -r target/wx-java-miniapp-0.0.1-SNAPSHOT.jar <ssh-user>@<deploy-host>:/www/wwwroot/travis-app/wx-java-miniapp
- ssh <ssh-user>@<deploy-host> -o stricthostkeychecking=no "mkdir travis_deploy_success"
- rsync -az --delete ./dist/* <USERNAME>@<HOST>:<TARGET-PATH> -
上传触发测试,
git commit -m "xxx" && git push
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30language: node_js
node_js:
- lts/*
branches:
only:
- main
- master
install:
- npm install yarn
before_script:
# 把项目下的deploy_rsa.enc加密文件,解密输出到/tmp/deploy_rsa中
- openssl aes-256-cbc -K $encrypted_db2095f63ba3_key -iv $encrypted_db2095f63ba3_iv
-in deploy_rsa.enc -out /tmp/deploy_rsa -d
- eval "$(ssh-agent -s)"
# 给予 id_rsa 文件权限,避免警告
- chmod 600 /tmp/deploy_rsa
# 将私钥添加到 ssh
- ssh-add /tmp/deploy_rsa
script:
- yarn build
after_success:
- echo "success!"
services:
- docker
addons:
ssh_known_hosts:
- 49.235.118.244
after_success:
# 非交互方式登录 StrictHostKeyChecking=no
- ssh mrli@49.235.118.244 -o stricthostkeychecking=no "docker run -d --name cgf -p 3000:80 nymrli/sucsoft-inititializer-front"
参考:
- 教程:https://juejin.cn/post/6844903780819927053——文章是2017年的,但思路是对的
- 示例项目:https://github.com/gongsir0630/wx-java-miniapp——文件是2021年比较新,但基本没讲解,只是跑通了
- 使用Travis CI部署项目到服务器——创建专门给travis使用的账户、吧travis安装在docker中
附录:
CICD概念
持续集成:以前是多个开发测试完毕后,才把代码往主分支上合并,可能交叉、冲突,合并之后还可能产生新的问题。而持续集成,就是经常提交代码到主分支,一天可能好几次。并且,自动化地进行单元测试并提供测试报告等,这样的话就能拆分细度颗粒,保证产品能够一步一步地安全可靠地迭代。很多以测试驱动开发的公司就是这样做的。
持续交付:持续集成的基础上,增加打包构建形成产物。
持续部署:持续交付的基础上,增加部署到相应的线上环境。
总而言之,这些持续做的事情,就是为了经常提交代码自动化测试、运行、部署,反馈问题,解决问题,再测试、运行、部署依次循环。持续部署还有个好处,对我们个人网站来说,我们可以直接提交代码,后续一系列过程都是自动化的,就不用管了,它自己自动部署发布。
案例
1 | language: java |
My demo:
1 | language: node_js |
travis.yml中的宏变量
-
1
2
3
4
5
6- $TRAVIS_BRANCH
- $GH_TOKEN(生成的 Personal access tokens)
$GIT_NAME(部署时的提交者名称)
$GIT_EMAIL(部署时的提交者邮箱)
$CUSTOM_DOMAIN(自定义域名)
$CUSTOM_PATH(自定义输出目录)
环境变量和非公开环境变量
.travis.yml
的env
字段可以定义环境变量。
1 | env: |
然后,脚本内部就使用这些变量了。
而有些环境变量(比如用户名和密码)不能公开,这时可以通过 Travis 网站,写在每个仓库的设置页里面,Travis 会自动把它们加入环境变量。这样一来,脚本内部依然可以使用这些环境变量,但是只有管理员才能看到变量的值。具体操作请看官方文档。
Author: Mrli
Link: https://nymrli.top/2021/10/25/CICD-Jenkins与Travis/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.