内容简介:全部配置详见:安装 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%
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Visual C# 2008入门经典
James Foxall / 张劼 / 人民邮电出版社 / 2009-6 / 39.00元
《Visual C#2008入门经典》分为五部分,共24章。第一部分介绍了Visual C# 2008速成版开发环境,引导读者熟练使用该IDE;第二部分探讨如何创建应用程序界面,包含窗体和各种控件的用法;第三部分介绍了编程技术,包括编写和调用方法、处理数值、字符串和日期、决策和循环结构、代码调试、类和对象的创建以及图形绘制等;第四部分阐述了文件和注册表的处理、数据库的使用和自动化其他应用程序等;第......一起来看看 《Visual C# 2008入门经典》 这本书的介绍吧!