jenkins 自动化部署的实现(10)
1.介绍
前面第6章介绍过使用pipeline编写各阶段,包括:checkout、nuget restore, Build, Publish。这些属于CI 也就是持续集成。在第9章介绍过多分支构建,本篇在6,9章基础上继续。
后续还需要的阶段包括:pack(打包),根据分支不同上传到不同的服务器再执行脚本部署,这些属于CD 也就是持续部署。
本节重点讲如何打包zip上传到目标服务器。使用 Publish Over SSH插件来实现。
准备工作包括:
1)用到的工具:PowerShell Server 2020
2)Jenkins插件:Publish Over SSH
2)部署环境:windows客户端(是jenkins本机属于内网)到windows服务端(iis目标服务器阿里云 windows server 2016) ip为131
3)生成秘钥
2. 秘钥生成
在jenkins本机上,cmd命令窗口中,使用ssh命令,必须先安装了OpenSSH
安装下载介绍: https://docs.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse
步骤1 生成秘钥命令如下所示,其中 passphrase为1234567
C:\Users\AndyH>ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\AndyH/.ssh/id_rsa):
C:\Users\AndyH/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\AndyH/.ssh/id_rsa.
Your public key has been saved in C:\Users\AndyH/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:tafBvaPd9LH9WOQDSdpBtS5Q6N+Zt6U7d50bhPXmp6Q mogultech\andyh@AndyH
步骤2 公钥文件复制到131目标服务器
远程连接到目标服务器,将id_rsa.pub文件复制到目标服务器(自己选择存放目录),我这里放的位置是C:\Users\Administrator\.ssh\id_rsa.pub
3.Publish Over SSH
Publish Over SSH是jenkins插件,主要的功能有两个:
把jenkins本机上的文件,传输到远程iis服务器的指定目录。
远程执行bat命令和脚本。
安装后如下所示:
4.PowerShell Server工具
官方解释:很容易安装和配置SSH 2.0服务器,使您能够从任何SSH客户端远程管理窗口,添加一个SFTP服务器窗口,和安全的远程访问本地资源。
下面解释一下服务端与客户端: 服务端是要部署的目标服务器131,需要安装powershell Server 2020。而jenkins要自动化部署到目标服务器,所以jenkins本机是客户端,需要安装Publish Over SSH插件。
目标服务器下载PowerShell Server 2020 试用版下载:https://www.nsoftware.com/powershell/server/download.aspx
安装后,打开默认如下所示
为了Jenkins不乱码,选择gb2312,并且log Mode选择"Verbose" 原因是能看到更多日志信息,帮助排错, 如下所示:
接着再设置SFTP目录,也是就jenkins要上传打包文件.zip的目录
接着配置公钥Key,这里的key目录是上面2.2中已存放好的目录,并启动。
5.jenkins ssh全局配置
这里的目的:确保连够连接到目标服务器131
Manger Jenkins-->System Configuration-->Configure System
配置好后(秘钥密码是:1234567),进行测试成功,表示jenkins本机ssh已连接上了目标服务器131,如下所示
在131目标服务器的PowerShell Server中查看日志如下所示:
6.job ssh 传输配置
在前面第9章中,学习到了多分支构建,job项目为multibranch-jenkenhellowrold,下面包括master分支和develop分支, 上面目标服务器131用于部署master分支。在multibranch-jenkenhellowrold项目中进行配置。
配置路径:multibranch-jenkenhellowrold-->流水线语法-->片断生成器-->下拉中选择sshPublisher:Send build artifacts over SSH
最后点击“生成流水线的脚本” 放入jenkinsfile文件中,配置的解释看下面介绍
https://www.cnblogs.com/zongyl/p/9157488.html
https://plugins.jenkins.io/publish-over-ssh/
7.编写Jenkinsfile文件
def packzipFileName //定义打包的文件名称 整个流水线共享变量,注意首行def定义的变量不能使用=赋值。 pipeline { agent any options{ //pipeline超时时间 timeout(time:10, unit:'MINUTES') //pipeline重试次数 retry(1) //同一个pipeline,禁止同时执行 disableConcurrentBuilds() //daysToKeepStr保持构建的天数,numToKeepStr保持构建的最大个数 buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '3', numToKeepStr: '10') } environment{ publishOutput='./jenkenhellowrold/JenkinsBuilds/' //编译后发布的路径是指:C:\Users\AndyH\AppData\Local\Jenkins\.jenkins\workspace\branch-jenkenhellowrold_master_2\jenkenhellowrold } stages { stage('NuGet Restore') { steps { echo 'NuGet Restore Begin' //restore会从解决方案或项目的根目录寻找 NuGet.config 文件,如果找不到,则会使用全局的 NuGet.config,也可以自己指定NuGet.config路径 //还可以是还原项目如:dotnet ./jenkenhellowrold/jenkenhellowrold.csproj //-nowarn不显示警告 bat 'dotnet restore -nowarn:msb3202,nu1503,cs1591 jenkenhellowrold.sln' //清理解决方案中所有生成的文件,如obj和bin件 bat 'dotnet clean --nologo jenkenhellowrold.sln' echo 'NuGet Restore End' } } stage('Bulid Project'){ steps{ echo 'Bulid Project Begin' //生成项目及其所有依赖项 bat 'dotnet build -nowarn:msb3202,nu1503,cs1591 --no-restore jenkenhellowrold.sln' echo 'Bulid Project End' } } stage('Publish'){ steps{ echo 'Publish Begin' script { //每次先删除之前的所有发布文件 def publishOutputdir= env.publishOutput.replace("/","\\"); def exist=fileExists(publishOutputdir) if(exist==true){ //echo "publishOutputdir:${exist}" bat 'rd /S/Q '+publishOutputdir } def output=env.publishOutput+env.GIT_BRANCH+env.BUILD_NUMBER // echo "${output}"//使用变量时用双引号 //--nologo不显示启动版权标志或版权消息,。netcore 3.0可用 //-c|--configuration 指定是Debug或Release bat 'dotnet publish --nologo -nowarn:msb3202,nu1503,cs1591 --no-restore ./jenkenhellowrold/jenkenhellowrold.csproj -c Release -o '+output } echo 'Publish End' } } stage('Pack zip') { steps{ echo 'Pack zip Begin' script { //定义打包的文件名 packzipFileName=env.GIT_BRANCH+env.BUILD_NUMBER+".zip" //echo "aaaaa${packzipFileName}" def packOutput=env.publishOutput.replace("/","\\") //需要压缩的地址文件 def rarInFile=packOutput+env.GIT_BRANCH+env.BUILD_NUMBER //压缩后存放的地址文件 def rarOutFile=packOutput+'\\pack\\' def exist=fileExists(rarOutFile) //echo "${exist}" if(exist==false){ bat 'md '+rarOutFile } //打包前删除配置文件 delFilesForWeb = ["web.config","appsettings.json","appsettings.Development.json"] as String[] //需要删除的文件 delFilesForWeb.each{ echo 'del file:'+it bat 'del /f/q '+ rarInFile+'\\'+it } //rar 文件路径已添加到jenkins全局配置中,本机路径 D:\Program Files\WinRAR a代表备份所有文件 ep是排除路径 bat env.RAR_PATH+' a -r -ep ' +rarOutFile+packzipFileName+' '+rarInFile } echo 'Pack zip End' } } stage('Deploy To Dev'){ when{ branch 'develop' } steps{ echo "Deploy To Dev" } } stage('Deploy To pro131'){ when{ branch 'master' } steps{ echo "Deploy To pro131 Begin" //配置时有的目录是指jenkins服务器上的,有些是指目标服务器上的如131服务器 //remoteDirectory: 131服务器目录文件夹,不存在会自动创建,服务器安装了PowerShell Server并指定的SFTP目录 //removePrefix:上传到131服务器目录时,这里是移出多层目录,最终上传目录层次是:C:\SFTP\jenkenhellowrold\master56.zip //sourceFiles:填写jenkins服务器相对路径,根目录是C:\Users\AndyH\AppData\Local\Jenkins\.jenkins\workspace\branch-jenkenhellowrold_master_2 //remoteDirectorySDF:true 远程目录使用日期格式,那么remoteDirectory也要配置格式 //execCommand:转输文件后(.zip),要在131服务器执行的bat文件,这里指定服务器存放bat文件的目录 sshPublisher(publishers: [sshPublisherDesc(configName: 'remote_131', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand:"cmd /c call C:/SFTP/jenkenhellowrold/deploy.bat ${packzipFileName}", execTimeout: 120000, flatten: false, makeEmptyDirs: true, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/jenkenhellowrold', remoteDirectorySDF: false, removePrefix: '/jenkenhellowrold/JenkinsBuilds/pack', sourceFiles: '**/JenkinsBuilds/pack/*', useSftpForExec: false)], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) echo 'Deploy To pro 131 End' } } } post{ failure{ echo 'ִfail send email' } success { echo 'ִsuccess send email' } } }
ssh execCommand要执行的131上deploy.bat文件 如下所示:
@echo off rem 该文件需要放入目标服务器, 用于jenkinfile文件的ssh execCommand 执行路径, cmd模拟执行:deploy.bat master146.zip rem 停止iis应用程序池和站点 "C:\Windows\System32\inetsrv\appcmd.exe" stop apppool /apppool.name:"jenkinshelloworld" "C:\\Windows\\System32\\inetsrv\\appcmd.exe" stop site jenkinshelloworld rem 目标服务器是用的winrar解压 "C:\Program Files\WinRAR\WinRAR.exe" X -o C:\SFTP\jenkenhellowrold\%1 C:\IIS\jenkinshelloworld rem 启动iis应用程序池和站点 "C:\Windows\System32\inetsrv\appcmd.exe" start apppool /apppool.name:"jenkinshelloworld" "C:\\Windows\\System32\\inetsrv\\appcmd.exe" start site jenkinshelloworld exit 0
8 .点击构建
查看日志重点的信息列出来
SSH: Connecting from host [AndyH] SSH: Connecting with configuration [remote_131] ... SSH: EXEC: completed after 401 ms SSH: Disconnecting configuration [remote_131] ... SSH: Transferred 1 file(s)
SSH: Transferred 1 file(s) 1代表上传到目标服务器一个文件
9.查看文件结果
1)jenkins服务器发布的目录,pack是打包存放文件夹,每次构建前都会先删除JenkinsBuilds下所有文件
2.目标服务器131上传的文件,deploy.bat文件作用:解压每次构建的.zip文件,解压到iis站点目录中
最终源码地址:https://git.code.tencent.com/Studies/pipeline-hello-world.git