内容简介:全部配置详见:安装 GitLab 、Node.js、Publish over SSH 插件今天踩了不少坑。。。
全部配置详见: https://github.com/xuexb/DevOps/tree/master/jenkins-node
目标
- [x] 负载均衡
- [ ] 快速回滚
- [x] 多机部署
- [ ] 灰度发布
服务说明
- GitLab - 用来存放示例代码、主动触发编译(Web Hook)
- Jenkins - 编译
- Nginx - 域名转发
- Node.js - 提供多个虚拟的容器做为目标服务器,且这些虚拟机中已经安装 Node.js Yarn PM2 ,因为没有这么多真实的机器,毕竟穷。。。
前置依赖
- 添加 Hosts :
127.0.0.1 fe.com jenkins.fe.com www.fe.com gitlab.fe.com node1.fe.com node2.fe.com node3.fe.com node4.fe.com node5.fe.com
- 【可选】创建一个私有的 key :
rm -rf ssh/* && ssh-keygen -t rsa -N '' -f ssh/id_rsa
,如果新创建的需要把ssh/id_rsa.pub
复制到.env
的AUTHORIZED_KEYS
,用来免密码登录 Node.js 的各个节点,注意需要使用 Linux 系统生成,macOS Mojave 生成的是OPENSSH
格式,在 Publish over SSH 插件时有问题,其实你大可以不用生成,使用默认的
域名、端口说明
-
node*.fe.com
- 虚拟出来的多个 Node.js 主机,目前是1-5
个,如node1.fe.com
-
www.fe.com
- 负载均衡到node1-5
中 -
jenkins.fe.com
- Jenkins 地址 -
gitlab.fe.com
- GitLab 地址 -
宿主:80
- 提供 Nginx 反代 -
宿主:22
- 提供 GitLab ssh clone 代理 -
node*:3000
- Node.js 容器内部使用 PM2 启动的服务,暴露的 Web Server 端口,由 Nginx 直接使用容器名称:3000
做转发
GitLab 配置
- 把
ssh/id_rsa.pub
公钥配置到帐户中,结合 Jenkins 安全凭证让 Jenkins 可以克隆 GitLab 项目 - http://gitlab.fe.com/profile/personal_access_tokens 创建 API token ,并记录下来,因为这个 token 只在第一次显示
- http://gitlab.fe.com/admin/application_settings/network#js-outbound-settings 管理员登录,开启
Allow requests to the local network from hooks and services
Jenkins 配置
安装 GitLab 、Node.js、Publish over SSH 插件
- 使用 GitLab 的 api token 创建一个 GitLab 插件使用的凭证,注意:
- API token - 是刚才在 GitLab 创建的 API token
- ID - 最好别设置,这个会自动生成一个唯一标识,在 pipeline 脚本中使用
- 描述 - 可以设置描述当前 API token 的功能
-
- 系统设置中配置 Publish over SSH 插件,host 为宿主对应的 Node.js 容器名称:
-
配置任务的编译后配置,注意:
- Source files - 匹配需要复制的源文件
- Remove prefix - 删除的目录前缀,其实就是替换路径的意思
- Remote directory - 远程路径,有个坑的是这里是基于 Publish over SSh 系统配置里的 Remote directory 的相对路径
- Exec command - 执行命令
-
-
系统设置中配置 GitLab 插件,注意:由于是通过 Jenkins 容器向 GitLab 连接,host 需要是 GitLab 的容器名 gitlab :
- 添加一个 gitlab-root 的凭证用于克隆项目,注意:这里的私钥是
ssh/id_rsa
的内容,因为对应的公钥已经在 GitLab root 用户中添加了,这样就可以使用 gitlab-root 这个凭证克隆项目了,还要注意那个 host ,需要是 GitLab - 全局 工具 里配置 Node.js ,这里以 v10.x 为例
难题
今天踩了不少坑。。。
1. 密钥、公钥
- 需要把密钥配置在 Jenkins 里一个凭据,在 GitLab 里添加公钥以让可以克隆项目
- 密钥需要配置到
.env
中,然后会透传给 https://hub.docker.com/r/dockerxman/docker-ubuntu-ssh/ 让其创建的 Node.js 虚拟服务器都可以使用公钥直接登录 - Publish over SSH 需要使用密钥,使其可以直接 SSH 免密码登录到 Node.js 虚拟服务器
- ssh key 不能使用 macOS Mojave 系统创建,否则不能过 Publish over SSH
2. Docker 配置的环境变量在 SSH 登录后不生效
为了更好的测试各个 Node.js 虚拟服务器分布,需要给每个虚拟服务器里配置个配置 ENV_LABEL
,表示当前服务器标签名,并在 Node.js 里设置了 Response.headers 的 X-Node-Label 字段,但发现在目标服务里的 Node.js 里获取不到,经过百般测试,发现需要:
- 首先需要在 Docker 里对各个虚拟 Node.js 服务器配置变量,在
docker-compose.yml
文件对对各个节点配置environment
。 - 在 Node.js 虚拟服务器的 Dockerfile 里以自定义文件
env.sh
为入口(CMD),并在env.sh
里向目标服务器写入到~/.env
为当前变量(因为在docker-compose.yml
里配置的变量,在 Dockerfile 里可以读取到),如:
#!/bin/bash # 写入一个标签变量,因为在 docker-compose.yml 里配置的使用 ssh 登录获取不到 echo "ENV_LABEL=$ENV_LABEL" > /root/.env echo '[ -s "$HOME/.env" ] && \. "$HOME/.env"' >> /root/.bashrc # 运行 dockerxman/docker-ubuntu-ssh:latest 的入口文件 if [ -f /run.sh ]; then /run.sh fi
- 在部署的 Node.js 项目中的部署脚本里需要先读到
$HOME/.env
,这样在部署脚本里就可以获取变量,但在 PM2 或者 Node.js 代码里还是获取不到,需要在部署脚本里export 变量=${变量}
透传才可以 - 由于 Node.js 项目由 PM2 启动,在 PM2 里的变量需要透传到 Node.js app 中,如
pm2.config.js
PM2 启动配置:
module.exports = { apps: [ { name: 'app', script: './index.js', env: { NODE_ENV: 'production', // 透传变量 ENV_LABEL: process.env.ENV_LABEL, }, }, ], };
Jenkins 任务日志
13:50:38 Started by user admin 13:50:38 Building in workspace /var/jenkins_home/workspace/node-demo 13:50:38 [WS-CLEANUP] Deleting project workspace... 13:50:38 [WS-CLEANUP] Deferred wipeout is used... 13:50:38 [WS-CLEANUP] Done 13:50:38 Cloning the remote Git repository 13:50:38 Cloning repository git@gitlab:root/node-demo.git 13:50:38 > git init /var/jenkins_home/workspace/node-demo # timeout=10 13:50:38 Fetching upstream changes from git@gitlab:root/node-demo.git 13:50:38 > git --version # timeout=10 13:50:38 using GIT_SSH to set credentials gitlab-root 13:50:38 > git fetch --tags --progress git@gitlab:root/node-demo.git +refs/heads/*:refs/remotes/origin/* 13:50:40 > git config remote.origin.url git@gitlab:root/node-demo.git # timeout=10 13:50:40 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 13:50:40 > git config remote.origin.url git@gitlab:root/node-demo.git # timeout=10 13:50:40 Fetching upstream changes from git@gitlab:root/node-demo.git 13:50:40 using GIT_SSH to set credentials gitlab-root-ssh 13:50:40 > git fetch --tags --progress git@gitlab:root/node-demo.git +refs/heads/*:refs/remotes/origin/* 13:50:41 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10 13:50:42 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10 13:50:42 Checking out Revision f6d9691839f578a4f880260871e2a39a263d2e45 (refs/remotes/origin/master) 13:50:42 > git config core.sparsecheckout # timeout=10 13:50:42 > git checkout -f f6d9691839f578a4f880260871e2a39a263d2e45 13:50:43 Commit message: "feat: fest" 13:50:43 > git rev-list --no-walk f6d9691839f578a4f880260871e2a39a263d2e45 # timeout=10 13:50:43 [node-demo] $ /bin/sh -xe /tmp/jenkins6335245445213181284.sh 13:50:43 + yarn -v 13:50:44 1.13.0 13:50:44 + node -v 13:50:44 v10.15.0 13:50:44 + npm -v 13:50:46 6.4.1 13:50:46 + yarn install 13:50:47 yarn install v1.13.0 13:50:47 [1/4] Resolving packages... 13:50:47 [2/4] Fetching packages... 13:50:47 [3/4] Linking dependencies... 13:50:49 [4/4] Building fresh packages... 13:50:49 Done in 2.55s. 13:50:49 + yarn test 13:50:50 yarn run v1.13.0 13:50:50 $ echo 'test' 13:50:50 test 13:50:50 Done in 0.27s. 13:50:50 + yarn build 13:50:51 yarn run v1.13.0 13:50:51 $ mkdir -p dist && ls | grep -vE '(README\.md|dist)' | xargs -I {} cp -r {} dist/ 13:50:53 Done in 2.56s. 13:50:53 SSH: Connecting from host [541f45e72785] 13:50:53 SSH: Connecting with configuration [Node-1] ... 13:50:53 SSH: EXEC: STDOUT/STDERR from command [/bin/bash /root/app/deploy.sh] ... 13:50:54 Deploy in node1 13:50:54 v11.6.0 13:50:54 6.5.0-next.0 13:50:55 3.2.7 13:50:55 1.13.0 13:50:55 yarn install v1.13.0 13:50:55 [1/4] Resolving packages... 13:50:55 success Already up-to-date. 13:50:55 Done in 0.21s. 13:50:56 [PM2] Applying action reloadProcessId on app [app](ids: 0) 13:50:56 [PM2] [app](0) ✓ 13:50:56 ┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ 13:50:56 │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ 13:50:56 ├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ 13:50:56 │ app │ 0 │ 1.0.0 │ fork │ 983 │ online │ 1 │ 0s │ 0% │ 10.9 MB │ root │ disabled │ 13:50:56 └──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ 13:50:56 Use `pm2 show <id|name>` to get more details about an app 13:50:56 SSH: EXEC: completed after 2,613 ms 13:50:56 SSH: Disconnecting configuration [Node-1] ... 13:50:56 SSH: Transferred 5 file(s) 13:50:56 SSH: Connecting from host [541f45e72785] 13:50:56 SSH: Connecting with configuration [Node-2] ... 13:50:56 SSH: EXEC: STDOUT/STDERR from command [/bin/bash /root/app/deploy.sh] ... 13:50:57 Deploy in node2 13:50:57 v11.6.0 13:50:57 6.5.0-next.0 13:50:57 3.2.7 13:50:57 1.13.0 13:50:58 yarn install v1.13.0 13:50:58 [1/4] Resolving packages... 13:50:58 success Already up-to-date. 13:50:58 Done in 0.19s. 13:50:58 [PM2] Applying action reloadProcessId on app [app](ids: 0) 13:50:58 [PM2] [app](0) ✓ 13:50:58 ┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ 13:50:58 │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ 13:50:58 ├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ 13:50:58 │ app │ 0 │ 1.0.0 │ fork │ 972 │ online │ 1 │ 0s │ 0% │ 10.8 MB │ root │ disabled │ 13:50:58 └──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ 13:50:58 Use `pm2 show <id|name>` to get more details about an app 13:50:58 SSH: EXEC: completed after 2,408 ms 13:50:58 SSH: Disconnecting configuration [Node-2] ... 13:50:58 SSH: Transferred 5 file(s) 13:50:58 SSH: Connecting from host [541f45e72785] 13:50:58 SSH: Connecting with configuration [Node-3] ... 13:50:59 SSH: EXEC: STDOUT/STDERR from command [/bin/bash /root/app/deploy.sh] ... 13:50:59 Deploy in node3 13:50:59 v11.6.0 13:50:59 6.5.0-next.0 13:51:00 3.2.7 13:51:00 1.13.0 13:51:00 yarn install v1.13.0 13:51:00 [1/4] Resolving packages... 13:51:00 success Already up-to-date. 13:51:00 Done in 0.18s. 13:51:01 [PM2] Applying action reloadProcessId on app [app](ids: 0) 13:51:01 [PM2] [app](0) ✓ 13:51:01 ┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ 13:51:01 │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ 13:51:01 ├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ 13:51:01 │ app │ 0 │ 1.0.0 │ fork │ 684 │ online │ 1 │ 0s │ 0% │ 20.0 MB │ root │ disabled │ 13:51:01 └──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ 13:51:01 Use `pm2 show <id|name>` to get more details about an app 13:51:01 SSH: EXEC: completed after 2,409 ms 13:51:01 SSH: Disconnecting configuration [Node-3] ... 13:51:01 SSH: Transferred 5 file(s) 13:51:01 SSH: Connecting from host [541f45e72785] 13:51:01 SSH: Connecting with configuration [Node-4] ... 13:51:01 SSH: EXEC: STDOUT/STDERR from command [/bin/bash /root/app/deploy.sh] ... 13:51:02 Deploy in node4 13:51:02 v11.6.0 13:51:02 6.5.0-next.0 13:51:03 3.2.7 13:51:03 1.13.0 13:51:03 yarn install v1.13.0 13:51:03 [1/4] Resolving packages... 13:51:03 success Already up-to-date. 13:51:03 Done in 0.19s. 13:51:04 [PM2] Applying action reloadProcessId on app [app](ids: 0) 13:51:04 [PM2] [app](0) ✓ 13:51:04 ┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ 13:51:04 │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ 13:51:04 ├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ 13:51:04 │ app │ 0 │ 1.0.0 │ fork │ 685 │ online │ 1 │ 0s │ 0% │ 20.3 MB │ root │ disabled │ 13:51:04 └──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ 13:51:04 Use `pm2 show <id|name>` to get more details about an app 13:51:04 SSH: EXEC: completed after 2,809 ms 13:51:04 SSH: Disconnecting configuration [Node-4] ... 13:51:04 SSH: Transferred 5 file(s) 13:51:04 SSH: Connecting from host [541f45e72785] 13:51:04 SSH: Connecting with configuration [Node-5] ... 13:51:04 SSH: EXEC: STDOUT/STDERR from command [/bin/bash /root/app/deploy.sh] ... 13:51:05 Deploy in node5 13:51:05 v11.6.0 13:51:05 6.5.0-next.0 13:51:05 3.2.7 13:51:06 1.13.0 13:51:06 yarn install v1.13.0 13:51:06 [1/4] Resolving packages... 13:51:06 success Already up-to-date. 13:51:06 Done in 0.18s. 13:51:06 [PM2] Applying action reloadProcessId on app [app](ids: 0) 13:51:07 [PM2] [app](0) ✓ 13:51:07 ┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ 13:51:07 │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ 13:51:07 ├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ 13:51:07 │ app │ 0 │ 1.0.0 │ fork │ 685 │ online │ 1 │ 0s │ 0% │ 19.2 MB │ root │ disabled │ 13:51:07 └──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ 13:51:07 Use `pm2 show <id|name>` to get more details about an app 13:51:07 SSH: EXEC: completed after 2,409 ms 13:51:07 SSH: Disconnecting configuration [Node-5] ... 13:51:07 SSH: Transferred 5 file(s) 13:51:07 Finished: SUCCESS
最终效果
每个 Node.js 服务都带有当前环境标签:
负载均衡入口:
参考连接
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 机器学习项目是如何开发和部署的?
- Uber如何在公司范围内部署机器学习
- Oracle开源机器学习模型云端部署工具Graphpipe
- 机器学习模型部署--打通前后端任督二脉
- 如何将机器学习的模型部署到NET环境中?
- 全球AI人才需求两年暴增35倍 中国机器人部署量涨500%
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Black Box Society
Frank Pasquale / Harvard University Press / 2015-1-5 / USD 35.00
Every day, corporations are connecting the dots about our personal behavior—silently scrutinizing clues left behind by our work habits and Internet use. The data compiled and portraits created are inc......一起来看看 《The Black Box Society》 这本书的介绍吧!