全部配置详见: 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
配置 因为等待中的任务也会占用节点执行者数量,如果少了多个并发任务可能就要凉凉。。。
其实这只是我对预发布、灰度发布、单台预发的一种探索,比如把测试、单台、全量拆成三个任务是否更合理?这就需要在实际项目中真实的应用并分析了。
接下来的目标: