全部配置详见: https://github.com/xuexb/DevOps/tree/master/jenkins-nginx-stg
什么是预发布?在我看来和灰度发布、单台是一样的意思,大白话就是说从线上摘一个有流量的机器,上线时先上到该机器中,稳定运行后再全流量上线。
在浏览器里写入一个特殊标识的 cookie 或者参数,在接入层根据标识来判断把流量落入到预发布机器(Nginx 反向代理)。
在接入层根据入网 IP 来判断是否在名单内,再代理到不同的环境。
每个应用层都是一个独立的服务,由接入层做负载均衡(LBS),而客户端可以直接绑定应用层的 IP ,直连应用层。
其实以上方案大同小异,本篇文章以绑定 Hosts 直连应用层为例介绍。
这里都是以 Docker 运行对应的服务。
curl ) | 容器名 | 别名 | IP | 说明 |
|---|---|---|---|
| www1 | prd_www1 |
192.168.1.101 |
生产环境1 |
| www2 | prd_www2 |
192.168.1.102 |
生产环境2 |
| proxy | LBS | 192.168.1.100 |
接入层 |
| user | - | - | 模拟用户环境,使用 docker exec -it user /bin/bash 进入,不用自定 IP |
| jenkins | - | - | Jenkins 容器,在接入层反向代理到该容器 |
| gogs | - | - | Gogs 容器,在接入层反向代理到该容器 |
需要宿主绑定 127.0.0.1 gogs.fe.com jenkins.fe.com Hosts
宿主:80 - proxy 容器对宿主暴露的端口,可访问 Jenkins 、Gogs www.fe.com - 接入层入口,在 user 容器中访问( curl ) gogs.fe.com - Gogs 访问入口 jenkins.fe.com - Jenkins 访问入口 把 www1 的环境做为预发布环境,使用 Jenkins Pipeline 脚本,在发布时直接发布到预发环境,并等待,在一定时间(比如1天)之内,如果在全量面板点击继续,则全量发布(其实就是同步到 www2 环境,因为一共就2台)。
dist/ )和产出的一个测试文件( dist/index.html ),模拟编译之后的文件 key - env/id_rsa 密钥 hostname - 容器的名称
pipeline {
agent any
options {
timestamps()
}
stages {
stage('Clone code') {
steps {
git credentialsId: 'b94b24ac-b1d0-4e63-81f8-2f1d889bd475', url: 'git@gogs:xiaowu/webapp.git'
}
}
stage('Run Build') {
steps {
echo '测试 build'
}
}
stage('Deploy Pre-Release') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'prd-1', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'nginx -v', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/app', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage('Deploy All') {
options {
timeout(time: 3, unit: 'DAYS')
}
input {
message '全量发布?'
ok '发布'
}
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'prd-2', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'nginx -v', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/app', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
post {
always {
deleteDir()
}
}
}
登录 user 容器去验证,其实就是模拟了用户终端,默认时绑定的 Hosts 为 192.168.1.100 www.fe.com 这是接入层,使用 curl www.fe.com 可以看到访问结果,当任务发布完成预发布时(在 Gogs 修改示例文件保存后,在 Jenkins 重新构建),构建会自动发布到预发布 www1 中,在 user 容器可以直接绑定 www1 的容器验证 192.168.1.101 www.fe.com ,验证通过后( curl www.fe.com )可以全量上线。
每个应用层自身应该可以独立访问,由接入层代理,那么应用层 Nginx 就需要多绑定几个 server_name 了,如:
www.fe.com - 供直联应用层使用 prd_www* - 供接入层 upstream 配置 因为等待中的任务也会占用节点执行者数量,如果少了多个并发任务可能就要凉凉。。。
其实这只是我对预发布、灰度发布、单台预发的一种探索,比如把测试、单台、全量拆成三个任务是否更合理?这就需要在实际项目中真实的应用并分析了。
接下来的目标: