這是我參與更文挑戰的第3天,活動詳情查看:更文挑戰git
本文記錄瞭如何使用 Jenkins Pipeline 實現構建和遠程部署。github
企業裏常見的項目自動化流程應該構建機從代碼倉拉取代碼進行構建,構建完成後會將產物推送到製品庫中,好比鏡像倉, 而後中間會有測試環境,用於進行自動化測試或人工測試,最後進行遠程部署。golang
這裏咱們用的 Go 的項目結構,它大概的結構應該是下面這樣的:web
|-- my-app
|-- .gitignore
|-- README.md
|-- LICENSE
|-- go.mod
|-- go.sum
|-- main.go
|-- pkg
|-- ...
複製代碼
由於這裏構建的是 Go 的項目,若是用到私有庫,在 go mod tidy
時會要求提供 Git 憑證,咱們能夠如今 Jenkins 的憑證管理中建立 Username with password
類型的憑證,其中 Username
就是 GitHub 的用戶名,password
則是 GitHub 的 AccessToken
,這裏主要用到的是 AccessToken
,Username
其實並不須要。docker
但在 Jenkins Pipeline 中使用 usernamePassword
時要求同時定義用戶名變量名 usernameVariable
和 密碼變量名 passwordVariable
。bash
stage('Build') {
steps {
withCredentials(bindings: [
usernamePassword(credentialsId: 'GITHUB_CREDENTIAL',
usernameVariable: 'GITHUB_USER',
passwordVariable: 'GITHUB_ACCESS_TOKEN'
)
]) {
sh ''' git config --global url."https://${GITHUB_ACCESS_TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/" go mod tidy go build -o bin/my-app main.go '''
}
}
}
複製代碼
在構建完成後,咱們會將構建產物推送到製品庫,而後咱們能夠從製品庫中拉取構建產物進行部署測試環境並進行測試,在驗證經過後,會從製品庫中拉取驗證經過的產物進行部署上線。服務器
但在本文中,咱們的應用相對簡單,能夠忽略推送產物到製品庫以及中間的測試驗證環節,目標是實現構建後當即部署上線。markdown
通常來講,線上環境和構建環境不會是同一臺機器,因此這個時候咱們須要將構建產物複製到另外一臺服務器上,而後在另外一臺服務器上進行部署。app
因爲須要對另外一臺服務器進行操做,因此咱們須要在 Jenkins 上配置 DEPLOY_HOST
、DEPLOY_PORT
和 SSH_CREDENTIAL
三個憑證,其中 DEPLOY_HOST
和 DEPLOY_PORT
是 Secret text
類型的憑證,SSH_CREDENTIAL
是 SSH Username with private key
類型的憑證。ssh
stage('Deploy') {
environment {
DEPLOY_HOST = credentials('DEPLOY_HOST')
DEPLOY_PORT = credentials('DEPLOY_PORT')
}
steps {
withCredentials([
sshUserPrivateKey(credentialsId: 'SSH_CREDENTIAL',
keyFileVariable: 'SSH_KEY',
usernameVariable: 'SSH_USERNAME'),
]) {
sh """ mkdir -p ~/.ssh && chmod 700 ~/.ssh echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config cat ${SSH_KEY} > ~/.ssh/id_rsa && chmod 400 ~/.ssh/id_rsa scp -P ${DEPLOY_PORT} bin/my-app ${SSH_USER}@${DEPLOY_HOST}:/data/my-app ssh -p ${DEPLOY_PORT} ${SSH_USER}@${DEPLOY_HOST} \"nohup /data/my-app >> /data/my-app.log 2>&1 &\" """
}
}
}
複製代碼
部署的步驟主要包括:
nohup /data/my-app >> /data/my-app.log 2>&1 &
其中簡化了一些細節,好比在部署前,咱們須要先備份數據。因此這裏咱們能夠寫一個複雜的部署腳本 deploy.sh
放在項目中,而後在 Jenkins Pipeline 中使用 scp
將部署腳本文件複製到部署服務器,假設放在 /data/deploy.sh
,最後只需 ssh -p ${DEPLOY_PORT} ${SSH_USER}@${DEPLOY_HOST} /bin/bash /data/deploy.sh
便可。
pipeline {
agent {
docker {
image 'golang:1.15-alpine'
args '-v /data/my-app-cache:/go/.cache'
}
}
options {
timeout(time: 20, unit: 'MINUTES')
disableConcurrentBuilds()
}
stages {
stage('Build') {
steps {
withCredentials(bindings: [
usernamePassword(credentialsId: 'GITHUB_CREDENTIAL',
usernameVariable: 'GITHUB_USER',
passwordVariable: 'GITHUB_ACCESS_TOKEN'
)
]) {
sh ''' git config --global url."https://${GITHUB_ACCESS_TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/" go mod tidy go build -o bin/my-app main.go '''
}
}
}
stage('Deploy') {
environment {
DEPLOY_HOST = credentials('DEPLOY_HOST')
DEPLOY_PORT = credentials('DEPLOY_PORT')
}
steps {
withCredentials([
sshUserPrivateKey(credentialsId: 'SSH_CREDENTIAL',
keyFileVariable: 'SSH_KEY',
usernameVariable: 'SSH_USERNAME'),
]) {
sh """ mkdir -p ~/.ssh && chmod 700 ~/.ssh echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config cat ${SSH_KEY} > ~/.ssh/id_rsa && chmod 400 ~/.ssh/id_rsa scp -P ${DEPLOY_PORT} bin/my-app ${SSH_USER}@${DEPLOY_HOST}:/data/my-app ssh -p ${DEPLOY_PORT} ${SSH_USER}@${DEPLOY_HOST} \"nohup /data/my-app >> /data/my-app.log 2>&1 &\" """
}
}
}
}
}
複製代碼
筆者不才,很是歡迎你們對本文的內容進行指正,或者與筆者進行探討!