CI/CD
背景
持续的软件开发方法基于自动执行脚本,以最大限度地减少在开发应用程序时引入错误的可能性。 从新代码的开发到部署,它们需要较少的人为干预甚至根本不需要干预。
它涉及在每次小迭代中不断构建,测试和部署代码更改,从而减少基于有缺陷或失败的先前版本开发新代码的机会。
有三种主要方法,每种方法都根据最适合您的策略进行应用
- Continuous Integration 持续集成
- Continuous Delivery 持续交付
- Continuous Deployment 持续部署
更多详情请查看Gitlab文档
Continuous Integration
在一个代码仓库中,开发人员每次的代码推送(push),都可以创建一组脚本进行自动构建和测试程序。
对于每个提交的更改,甚至是开发的分支,它都可以自动地进行构建和测试,确保所引入的更改通过您为应用程序建立的所有测试
Continuous Delivery
持续交付是持续集成的又一步。您的应用程序在推送到代码库的每个代码更改时都构建和测试,但需要手动触发部署
Continuous Deployment
持续部署也是持续集成的又一步,类似于持续交付。 不同之处在于,您不必手动部署应用程序,而是将其设置为自动部署。 完全不需要人工干预就可以部署您的应用程序
GitLab Runner
GitLab Runner是一个开源项目,用于运行作业并将结果发送回GitLab。 它与GitLab CI一起使用,GitLab CI是GitLab随附的开源持续集成服务,用于协调作业
Runner分为两种
- Shared Runners,公用的Runner,gitlab提供给开发者共同使用的
- Specific Runners,开发者自行配置的Runner,需要把自己的服务器作为Runner,执行作业
相关概念
Pipelines管道
管道是持续集成,交付和部署的顶级组件。
管道包括:
- 定义要运行的作业。 例如,代码编译或测试运行。
- 定义运行的阶段以及如何运行的。 例如,该测试仅在代码编译后运行
- 如果有足够的并发Runners,则Runners并行执行同一阶段中的多个作业。
如果一个阶段的所有工作:
- 成功,管道进入下一阶段。
- 失败,下一阶段没有(通常)执行,管道提前结束
Stage阶段
默认有三个阶段:
- build
- test
- deploy
作业按阶段执行,先执行build,然后test,最后deploy
同一阶段的stage的job,可以并行执行
Job作业
一个管道中包含三个阶段,每个阶段中有若干个作业,在作业中定义了需要执行的操作
Runner执行的是作业
持续集成CD例子
编辑项目根目录的.gitlab-ci.yml
文件
# 使用最新node镜像
image: node:latest
# eslint 代码规范检查
eslint_check:
stage: test
script:
- npm install eslint eslint-config-alloy babel-eslint eslint-config-egg --registry=https://registry.npm.taobao.org
- npm run lint
- 使用了最新的node镜像
- 定义了一个eslint_check的作业,该作业处于test阶段,执行了以下两个命令:
- npm 安装相关eslint依赖
- 执行eslint检查
每当代码推送到仓库,都会触发持续集成,生成一个管道,管道里有一个esling_check的作业
- 如果代码通过eslint校验,则整个过程成功
- 如果没有通过eslint校验,npm脚本会出错,作业执行失败,管道结束
持续部署CD例子
下面是一个更复杂的例子,能够对代码进行部署
# 使用最新node镜像
image: node:latest
before_script:
# 安装ssh-agent,用于远程登录主机
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
# eslint 代码规范检查
eslint_check:
stage: test
script:
- npm install eslint eslint-config-alloy babel-eslint eslint-config-egg --registry=https://registry.npm.taobao.org
- npm run lint
# 发布后台服务
deploy_stu_oauth:
stage: deploy
script:
# ssh加入远程主机登录密钥
- ssh-add <(echo "base64加密过的远程主机登录私钥" | base64 -d)
# 远程登录主机,执行以下命令
- ssh -p22 candy@139.199.224.230
"cd /home/candy/syllabus/stu-oauth;
pwd;
npm run stop;
git pull;
cnpm install --production;
npm run start"
only:
- master
- 使用了最新的node镜像
- 在所有脚本执行前,先执行before_script的命令
- 安装ssh,用于远程登录主机,登陆后可以进行部署
- 定义了eslint_check的作业,该作业处于test阶段,执行两个命令:
- npm 安装相关eslint依赖
- 执行eslint检查
- 定义了deploy_stu_oauth的作业,改作业处于deploy阶段,需要等待test阶段完成后,才会开始执行,且只在master分支推送的时候执行。
该作业执行了以下命令:- 向ssh加入远程主机登录密钥,加入后,可以通过密钥远程登录主机,而不用输入密码
- 登录远程主机,执行以下命令:
- cd /home/candy/syllabus/stu-oauth 打开代码所在目录
- pwd 查看当前目录路径
- npm run stop 停止当前服务
- git pull 拉取最新代码
- cnpm install —production 安装依赖
- npm run start 开启服务
远程登录
安全提醒:需要创建一个用户,该用户只拥有部署代码所在目录的权限!!!
安装ssh-agent
before_script:
# - ....
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
说明:
先检查ssh-agent是否可用,如果不可用,我们会安装它。
创建〜/ .ssh文件夹
确保正在运行bash
禁用主机检查(当我们第一次连接到服务器时,我们不要求用户接受,因为每个作业都等于第一次连接,我们需要这样做)
远程主机生成登录密钥
1. 制作密钥对
首先在服务器上制作密钥对。首先用密码登录到你打算使用密钥登录的账户,然后执行以下命令:
[root@host ~]$ ssh-keygen <== 建立密钥对
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): <== 按 Enter
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): <== 输入密钥锁码,或直接按 Enter 留空
Enter same passphrase again: <== 再输入一遍密钥锁码
Your identification has been saved in /root/.ssh/id_rsa. <== 私钥
Your public key has been saved in /root/.ssh/id_rsa.pub. <== 公钥
The key fingerprint is:
0f:d3:e7:1a:1c:bd:5c:03:f1:19:f1:22:df:9b:cc:08 root@host
密钥锁码在使用私钥时必须输入,这样就可以保护私钥不被盗用。当然,也可以留空,实现无密码登录。
现在,在 root 用户的家目录中生成了一个 .ssh 的隐藏目录,内含两个密钥文件。id_rsa 为私钥,id_rsa.pub 为公钥。
2. 在服务器上安装公钥
键入以下命令,在服务器上安装公钥:
[root@host ~]$ cd .ssh
[root@host .ssh]$ cat id_rsa.pub >> authorized_keys
如此便完成了公钥的安装。为了确保连接成功,请保证以下文件权限正确:
[root@host .ssh]$ chmod 600 authorized_keys
[root@host .ssh]$ chmod 700 ~/.ssh
3. 设置 SSH,打开密钥登录功能
编辑 /etc/ssh/sshd_config 文件,进行如下设置:
RSAAuthentication yes
PubkeyAuthentication yes
另外,请留意 root 用户能否通过 SSH 登录:
PermitRootLogin yes
当你完成全部设置,并以密钥方式登录成功后,再禁用密码登录:
PasswordAuthentication no
最后,重启 SSH 服务:
[root@host .ssh]$ service sshd restart
远程登录
下载上一步生成的私钥,执行以下命令,对私钥进行base64加密
$ cat <替换成私钥文件名> | base64 -w0
复制加密后的私钥,替换以下内容,把私钥添加到ssh,即可实现免密码登录远程主机
$ ssh-add <(echo "base64加密过的远程主机登录私钥" | base64 -d)
加密私钥的原因是因为原来的私钥是多行的,shell多行的文本暂时不知道怎么处理,看了网上教程可以通过加解密解决
加入了私钥后,执行以下语句即可以操作远程主机,多条语句用分号分割
$ ssh -p22 candy@139.199.224.230
"cd /home/candy/syllabus/stu-oauth;pwd"