Jenkins-自动化构建、测试和部署-学习笔记
來源于黑馬程序員jenkins文檔筆記
1、Jenkins介紹
Jenkins 是一款流行的開源持續集成(Continuous Integration)工具,廣泛用于項目開發,具有自動
化構建、測試和部署等功能。官網: http://jenkins-ci.org/。
Jenkins的特征:
開源的Java語言開發持續集成工具,支持持續集成,持續部署。
易于安裝部署配置:可通過yum安裝,或下載war包以及通過docker容器等快速實現安裝部署,可
方便web界面配置管理。
消息通知及測試報告:集成RSS/E-mail通過RSS發布構建結果或當構建完成時通過e-mail通知,生
成JUnit/TestNG測試報告。
分布式構建:支持Jenkins能夠讓多臺計算機一起構建/測試。
文件識別:Jenkins能夠跟蹤哪次構建生成哪些jar,哪次構建使用哪個版本的jar等。
豐富的插件支持:支持擴展插件,你可以開發適合自己團隊使用的工具,如git,svn,maven,
docker等。
2、Jenkins安裝和持續集成環境配置
持續集成流程說明
1)首先,開發人員每天進行代碼提交,提交到Git倉庫
2)然后,Jenkins作為持續集成工具,使用Git工具到Git倉庫拉取代碼到集成服務器,再配合JDK,
Maven等軟件完成代碼編譯,代碼測試與審查,測試,打包等工作,在這個過程中每一步出錯,都重新
再執行一次整個流程。
3)最后,Jenkins把生成的jar或war包分發到測試服務器或者生產服務器,測試人員或用戶就可以訪問
應用。
持續集成環境(1)-Jenkins安裝
1)安裝JDK
Jenkins需要依賴JDK,所以先安裝JDK1.8
yum install java-1.8.0-openjdk* -y
安裝目錄為:/usr/lib/jvm
2)獲取jenkins安裝包
下載頁面:https://jenkins.io/zh/download/
安裝文件:jenkins-2.190.3-1.1.noarch.rpm
3)把安裝包上傳到192.168.66.101服務器,進行安裝
rpm -ivh jenkins-2.190.3-1.1.noarch.rpm
4)修改Jenkins配置
vi /etc/syscofig/jenkins
修改內容如下:
JENKINS_USER=“root”
JENKINS_PORT=“8888”
5)啟動Jenkins
systemctl start jenkins
6)打開瀏覽器訪問
http://192.168.66.101:8888
注意:本服務器把防火墻關閉了,如果開啟防火墻,需要在防火墻添加端口
7)獲取并輸入admin賬戶密碼
cat /var/lib/jenkins/secrets/initialAdminPassword
8)跳過插件安裝
因為Jenkins插件需要連接默認官網下載,速度非常慢,而且經過會失敗,所以我們暫時先跳過插件安
裝
9)添加一個管理員賬戶,并進入Jenkins后臺
保存并完成
開始使用Jenkins
持續集成環境(2)-Jenkins插件管理
Jenkins本身不提供很多功能,我們可以通過使用插件來滿足我們的使用。例如從Gitlab拉取代碼,使用
Maven構建項目等功能需要依靠插件完成。接下來演示如何下載插件。
修改Jenkins插件下載地址
Jenkins國外官方插件地址下載速度非常慢,所以可以修改為國內插件地址:
Jenkins->Manage Jenkins->Manage Plugins,點擊Available
這樣做是為了把Jenkins官方的插件列表下載到本地,接著修改地址文件,替換為國內插件地址
最后,Manage Plugins點擊Advanced,把Update Site改為國內插件下載地址
最后,Manage Plugins點擊Advanced,把Update Site改為國內插件下載地址 https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
Sumbit后,在瀏覽器輸入: http://192.168.66.101:8888/restart ,重啟Jenkins。
下載中文漢化插件
Jenkins->Manage Jenkins->Manage Plugins,點擊Available,搜索"Chinese"
持續集成環境(3)-Jenkins用戶權限管理
我們可以利用Role-based Authorization Strategy 插件來管理Jenkins用戶權限
安裝Role-based Authorization Strategy插件
授權策略切換為"Role-Based Strategy",保存
創建角色
在系統管理頁面進入 Manage and Assign Roles
點擊"Manage Roles"
Global roles(全局角色):管理員等高級用戶可以創建基于全局的角色 Project roles(項目角色):
針對某個或者某些項目的角色 Slave roles(奴隸角色):節點相關的權限
我們添加以下三個角色:
baseRole:該角色為全局角色。這個角色需要綁定Overall下面的Read權限,是為了給所有用戶綁
定最基本的Jenkins訪問權限。注意:如果不給后續用戶綁定這個角色,會報錯誤:用戶名 is
missing the Overall/Read permission
role1:該角色為項目角色。使用正則表達式綁定"itcast.",意思是只能操作itcast開頭的項目。
role2:該角色也為項目角色。綁定"itheima.",意思是只能操作itheima開頭的項目。
保存。
創建用戶
在系統管理頁面進入 Manage Users
分別創建兩個用戶:jack和eric
給用戶分配角色
系統管理頁面進入Manage and Assign Roles,點擊Assign Roles
綁定規則如下:
eric用戶分別綁定baseRole和role1角色
jack用戶分別綁定baseRole和role2角色
保存。
創建項目測試權限
以itcast管理員賬戶創建兩個項目,分別為itcast01和itheima01
結果為:
eric用戶登錄,只能看到itcast01項目
jack用戶登錄,只能看到itheima01項目
持續集成環境(4)-Jenkins憑證管理
憑據可以用來存儲需要密文保護的數據庫密碼、Gitlab密碼信息、Docker私有倉庫密碼等,以便
Jenkins可以和這些第三方的應用進行交互。
安裝Credentials Binding插件
要在Jenkins使用憑證管理功能,需要安裝Credentials Binding插件
安裝插件后,左邊多了"憑證"菜單,在這里管理所有憑證
可以添加的憑證有5種:
Username with password:用戶名和密碼
SSH Username with private key: 使用SSH用戶和密鑰
Secret file:需要保密的文本文件,使用時Jenkins會將文件復制到一個臨時目錄中,再將文件路徑
設置到一個變量中,等構建結束后,所復制的Secret file就會被刪除。
Secret text:需要保存的一個加密的文本串,如釘釘機器人或Github的api token
Certificate:通過上傳證書文件的方式
常用的憑證類型有:Username with password(用戶密碼)和SSH Username with private key(SSH
密鑰)
接下來以使用Git工具到Gitlab拉取項目源碼為例,演示Jenkins的如何管理Gitlab的憑證。
安裝Git插件和Git工具
為了讓Jenkins支持從Gitlab拉取源碼,需要安裝Git插件以及在CentOS7上安裝Git工具。
Git插件安裝:
CentOS7上安裝Git工具:
yum install git -y 安裝
git --version 安裝后查看版本
用戶密碼類型
1)創建憑證
Jenkins->憑證->系統->全局憑證->添加憑證
選擇"Username with password",輸入Gitlab的用戶名和密碼,點擊"確定"。
2)測試憑證是否可用
創建一個FreeStyle項目:新建Item->FreeStyle Project->確定
找到"源碼管理"->“Git”,在Repository URL復制Gitlab中的項目URL
這時會報錯說無法連接倉庫!在Credentials選擇剛剛添加的憑證就不報錯啦
保存配置后,點擊構建”Build Now“ 開始構建項目
查看/var/lib/jenkins/workspace/目錄,發現已經從Gitlab成功拉取了代碼到Jenkins中。
SSH密鑰類型
SSH免密登錄示意圖
1)使用root用戶生成公鑰和私鑰
在/root/.ssh/目錄保存了公鑰和使用
id_rsa:私鑰文件
id_rsa.pub:公鑰文件
2)把生成的公鑰放在Gitlab中
以root賬戶登錄->點擊頭像->Settings->SSH Keys
復制剛才id_rsa.pub文件的內容到這里,點擊"Add Key"
3)在Jenkins中添加憑證,配置私鑰
在Jenkins添加一個新的憑證,類型為"SSH Username with private key",把剛才生成私有文件內容復制過來
4)測試憑證是否可用
新建"test02"項目->源碼管理->Git,這次要使用Gitlab的SSH連接,并且選擇SSH憑證
同樣嘗試構建項目,如果代碼可以正常拉取,代表憑證配置成功!
持續集成環境(5)-Maven安裝和配置
在Jenkins集成服務器上,我們需要安裝Maven來編譯和打包項目。
安裝Maven
先上傳Maven軟件到192.168.66.101
tar -xzf apache-maven-3.6.2-bin.tar.gz 解壓 mkdir -p /opt/maven 創建目錄 mv apache-maven-3.6.2/* /opt/maven 移動文件配置環境變量
vi /etc/profile export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk export MAVEN_HOME=/opt/maven export PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin source /etc/profile 配置生效 mvn -v 查找Maven版本全局工具配置關聯JDK和Maven
Jenkins->Global Tool Configuration->JDK->新增JDK,配置如下:
Jenkins->Global Tool Configuration->Maven->新增Maven,配置如下:
添加Jenkins全局變量
Manage Jenkins->Configure System->Global Properties ,添加三個全局變量
JAVA_HOME、M2_HOME、PATH+EXTRA
修改Maven的settings.xml
mkdir /root/repo 創建本地倉庫目錄 vi /opt/maven/conf/settings.xml本地倉庫改為:/root/repo/
添加阿里云私服地址:
測試Maven是否配置成功
使用之前的gitlab密碼測試項目,修改配置
構建->增加構建步驟->Execute Shell
輸入
再次構建,如果可以把項目打成war包,代表maven環境配置成功啦!
持續集成環境(6)-Tomcat安裝和配置
安裝Tomcat8.5
把Tomcat壓縮包上傳到192.168.66.102服務器
yum install java-1.8.0-openjdk* -y 安裝JDK(已完成) tar -xzf apache-tomcat-8.5.47.tar.gz 解壓 mkdir -p /opt/tomcat 創建目錄 mv /root/apache-tomcat-8.5.47/* /opt/tomcat 移動文件 /opt/tomcat/bin/startup.sh 啟動tomcat注意:服務器已經關閉了防火墻,所以可以直接訪問Tomcat啦
地址為:http://192.168.66.102/8080
配置Tomcat用戶角色權限
默認情況下Tomcat是沒有配置用戶角色權限的
但是,后續Jenkins部署項目到Tomcat服務器,需要用到Tomcat的用戶,所以修改tomcat以下配置,
添加用戶及權限
用戶和密碼都是:tomcat
注意:為了能夠剛才配置的用戶登錄到Tomcat,還需要修改以下配置
把上面這行注釋掉即可!
重啟Tomcat,訪問測試
/opt/tomcat/bin/shutdown.sh 停止 /opt/tomcat/bin/startup.sh 啟動訪問: http://192.168.66.102:8080/manager/html ,輸入tomcat和tomcat,看到以下頁面代表成功
啦
3、Jenkins構建Maven項目
Jenkins項目構建類型(1)-Jenkins構建的項目類型介紹
Jenkins中自動構建項目的類型有很多,常用的有以下三種:
自由風格軟件項目(FreeStyle Project)
Maven項目(Maven Project)
流水線項目(Pipeline Project)
每種類型的構建其實都可以完成一樣的構建過程與結果,只是在操作方式、靈活度等方面有所區別,在
實際開發中可以根據自己的需求和習慣來選擇。(PS:個人推薦使用流水線類型,因為靈活度非常高)
Jenkins項目構建類型(2)-自由風格項目構建
下面演示創建一個自由風格項目來完成項目的集成過程:
拉取代碼->編譯->打包->部署
拉取代碼
1)創建項目
2)配置源碼管理,從gitlab拉取代碼
編譯打包
構建->添加構建步驟->Executor Shell
echo "開始編譯和打包" mvn clean package echo "編譯和打包結束"部署
把項目部署到遠程的Tomcat里面
1)安裝 Deploy to container插件
Jenkins本身無法實現遠程部署到Tomcat的功能,需要安裝Deploy to container插件實現
2)添加Tomcat用戶憑證
3)添加構建后操作
點擊"Build Now",開始構建過程
4)部署成功后,訪問項目
演示改動代碼后的持續集成
1)IDEA中源碼修改并提交到gitlab
2)在Jenkins中項目重新構建
3)訪問Tomcat
Jenkins項目構建類型(3)-Maven項目構建
1)安裝Maven Integration插件
2)創建Maven項目
3)配置項目
拉取代碼和遠程部署的過程和自由風格項目一樣,只是"構建"部分不同
Jenkins項目構建類型(4)-Pipeline流水線項目構建(*)
Pipeline簡介
1)概念
Pipeline,簡單來說,就是一套運行在 Jenkins 上的工作流框架,將原來獨立運行于單個或者多個節點
的任務連接起來,實現單個任務難以完成的復雜流程編排和可視化的工作。
2)使用Pipeline有以下好處(來自翻譯自官方文檔):
代碼:Pipeline以代碼的形式實現,通常被檢入源代碼控制,使團隊能夠編輯,審查和迭代其傳送流
程。 持久:無論是計劃內的還是計劃外的服務器重啟,Pipeline都是可恢復的。 可停止:Pipeline可接
收交互式輸入,以確定是否繼續執行Pipeline。 多功能:Pipeline支持現實世界中復雜的持續交付要
求。它支持fork/join、循環執行,并行執行任務的功能。 可擴展:Pipeline插件支持其DSL的自定義擴
展 ,以及與其他插件集成的多個選項。
3)如何創建 Jenkins Pipeline呢?
Pipeline 腳本是由 Groovy 語言實現的,但是我們沒必要單獨去學習 Groovy
Pipeline 支持兩種語法:Declarative(聲明式)和 Scripted Pipeline(腳本式)語法
Pipeline 也有兩種創建方法:可以直接在 Jenkins 的 Web UI 界面中輸入腳本;也可以通過創建一
個 Jenkinsfile 腳本文件放入項目源碼庫中(一般我們都推薦在 Jenkins 中直接從源代碼控制(SCM)
中直接載入 Jenkinsfile Pipeline 這種方法)。
安裝Pipeline插件
Manage Jenkins->Manage Plugins->可選插件
安裝插件后,創建項目的時候多了“流水線”類型
Pipeline語法快速入門
1)Declarative聲明式-Pipeline
創建項目
流水線->選擇HelloWorld模板
生成內容如下:
stages:代表整個流水線的所有執行階段。通常stages只有1個,里面包含多個stage
stage:代表流水線中的某個階段,可能出現n個。一般分為拉取代碼,編譯構建,部署等階段。
steps:代表一個階段內需要執行的邏輯。steps里面是shell腳本,git拉取代碼,ssh遠程發布等任意內
容。
編寫一個簡單聲明式Pipeline:
點擊構建,可以看到整個構建過程
2)Scripted Pipeline腳本式-Pipeline
創建項目
這次選擇"Scripted Pipeline"
Node:節點,一個 Node 就是一個 Jenkins 節點,Master 或者 Agent,是執行 Step 的具體運行
環境,后續講到Jenkins的Master-Slave架構的時候用到。
Stage:階段,一個 Pipeline 可以劃分為若干個 Stage,每個 Stage 代表一組操作,比如:
Build、Test、Deploy,Stage 是一個邏輯分組的概念。
Step:步驟,Step 是最基本的操作單元,可以是打印一句話,也可以是構建一個 Docker 鏡像,
由各類 Jenkins 插件提供,比如命令:sh ‘make’,就相當于我們平時 shell 終端中執行 make 命令
一樣。
編寫一個簡單的腳本式Pipeline
構建結果和聲明式一樣!
腳本式Pipeline可以使用腳本生成器生成
拉取代碼
pipeline {agent anystages {stage('拉取代碼') {steps {checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])}}} }編譯打包
pipeline {agent anystages {stage('拉取代碼') {steps {checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])}}stage('編譯構建') {steps {sh label: '', script: 'mvn clean package'}}} }部署
pipeline {agent anystages {stage('拉取代碼') {steps {checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])}}stage('編譯構建') {steps {sh label: '', script: 'mvn clean package'}}stage('項目部署') {steps {deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984fb1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war'}} } }Pipeline Script from SCM
剛才我們都是直接在Jenkins的UI界面編寫Pipeline代碼,這樣不方便腳本維護,建議把Pipeline腳本放
在項目中(一起進行版本控制)
1)在項目根目錄建立Jenkinsfile文件,把內容復制到該文件中
把Jenkinsfile上傳到Gitlab
2)在項目中引用該文件
Jenkins項目構建細節(1)-常用的構建觸發器
Jenkins內置4種構建觸發器:
觸發遠程構建
其他工程構建后觸發(Build after other projects are build)
定時構建(Build periodically)
輪詢SCM(Poll SCM)
觸發遠程構建
其他工程構建后觸發
1)創建pre_job流水線工程
2)配置需要觸發的工程
定時構建
定時字符串從左往右分別為: 分 時 日 月 周
輪詢SCM
輪詢SCM,是指定時掃描本地代碼倉庫的代碼是否有變更,如果代碼有變更就觸發項目構建。
注意:這次構建觸發器,Jenkins會定時掃描本地整個項目的代碼,增大系統的開銷,不建議使用。
Jenkins項目構建細節(2)-Git hook自動觸發構建(*)
剛才我們看到在Jenkins的內置構建觸發器中,輪詢SCM可以實現Gitlab代碼更新,項目自動構建,但是
該方案的性能不佳。那有沒有更好的方案呢? 有的。就是利用Gitlab的webhook實現代碼push到倉
庫,立即觸發項目自動構建。
安裝Gitlab Hook插件
需要安裝兩個插件:
Gitlab Hook和GitLab
Jenkins設置自動構建
等會需要把生成的webhook URL配置到Gitlab中。
Gitlab配置webhook
1)開啟webhook功能
使用root賬戶登錄到后臺,點擊Admin Area -> Settings -> Network
勾選"Allow requests to the local network from web hooks and services"
2)在項目添加webhook
點擊項目->Settings->Integrations
注意:以下設置必須完成,否則會報錯!
Manage Jenkins->Configure System
Jenkins項目構建細節(3)-Jenkins的參數化構建
有時在項目構建的過程中,我們需要根據用戶的輸入動態傳入一些參數,從而影響整個構建結果,這時
我們可以使用參數化構建。
Jenkins支持非常豐富的參數類型
接下來演示通過輸入gitlab項目的分支名稱來部署不同分支項目。
項目創建分支,并推送到Gitlab上
新建分支:v1,代碼稍微改動下,然后提交到gitlab上。
這時看到gitlab上有一個兩個分支:master和v1
在Jenkins添加字符串類型參數
改動pipeline流水線代碼
點擊Build with Parameters
Jenkins+SonarQube代碼審查(1) - 安裝SonarQube
SonaQube簡介
SonarQube是一個用于管理代碼質量的開放平臺,可以快速的定位代碼中潛在的或者明顯的錯誤。目前
支持java,C#,C/C++,Python,PL/SQL,Cobol,JavaScrip,Groovy等二十幾種編程語言的代碼質量管理與檢
測。
官網:https://www.sonarqube.org/
安裝SonarQube
1)安裝MySQL(已完成)
2)安裝SonarQube
在MySQL創建sonar數據庫
下載sonar壓縮包:
https://www.sonarqube.org/downloads/
解壓sonar,并設置權限
修改sonar配置文件
vi /opt/sonarqube-6.7.4/conf/sonar.properties 內容如下: sonar.jdbc.username=root sonar.jdbc.password=Root@123 sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar? useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs= maxPerformance&useSSL=false注意:sonar默認監聽9000端口,如果9000端口被占用,需要更改。
啟動sonar
訪問sonar
http://192.168.66.101:9000
默認賬戶:admin/admin
創建token
token要記下來后面要使用
0151ae8c548a143eda9253e4334ad030b56047ee
Jenkins+SonarQube代碼審查(2) - 實現代碼審查
安裝SonarQube Scanner插件
添加SonarQube憑證
Jenkins進行SonarQube配置
Manage Jenkins->Configure System->SonarQube servers
SonaQube關閉審查結果上傳到SCM功能
在項目添加SonaQube代碼審查(非流水線項目)
添加構建步驟:
在項目添加SonaQube代碼審查(流水線項目)
1)項目根目錄下,創建sonar-project.properties文件
2)修改Jenkinsfile,加入SonarQube代碼審查階段
pipeline { agent any stages { stage('拉取代碼') { steps { checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]]) } } stage('編譯構建') { steps { sh label: '', script: 'mvn clean package' } } stage('SonarQube代碼審查') { steps{ script { scannerHome = tool 'sonarqube-scanner' } withSonarQubeEnv('sonarqube6.7.4') { sh "${scannerHome}/bin/sonar-scanner" } } } stage('項目部署') { steps { deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984fb1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war' } } } post { always { emailext( subject: '構建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}!', body: '${FILE,path="email.html"}', to: '1014671449@qq.com' ) } } }3)到SonarQube的UI界面查看審查結果
4、Jenkins+Docker+SpringCloud微服務持續集成(上)
Jenkins+Docker+SpringCloud持續集成流程說明
大致流程說明:
1)開發人員每天把代碼提交到Gitlab代碼倉庫
2)Jenkins從Gitlab中拉取項目源碼,編譯并打成jar包,然后構建成Docker鏡像,將鏡像上傳到
Harbor私有倉庫。
3)Jenkins發送SSH遠程命令,讓生產部署服務器到Harbor私有倉庫拉取鏡像到本地,然后創建容器。
4)最后,用戶可以訪問到容器
服務列表(紅色的軟件為需要安裝的軟件,黑色代表已經安裝)
SpringCloud微服務源碼概述
項目架構:前后端分離
后端技術棧:SpringBoot+SpringCloud+SpringDataJpa(Spring全家桶)
微服務項目結構:
tensquare_parent:父工程,存放基礎配置
tensquare_common:通用工程,存放工具類
tensquare_eureka_server:SpringCloud的Eureka注冊中心
tensquare_zuul:SpringCloud的網關服務
tensquare_admin_service:基礎權限認證中心,負責用戶認證(使用JWT認證)
tensquare_gathering:一個簡單的業務模塊,活動微服務相關邏輯
數據庫結構:
tensquare_user:用戶認證數據庫,存放用戶賬戶數據。對應tensquare_admin_service微服務
tensquare_gathering:活動微服務數據庫。對應tensquare_gathering微服務
微服務配置分析:
tensquare_eureka
tensquare_zuul
tensquare_admin_service
tensquare_gathering
本地部署(1)-SpringCloud微服務部署
本地運行微服務
1)逐一啟動微服務
2)使用postman測試功能是否可用
本地部署微服務
1)SpringBoot微服務項目打包
必須導入該插件
打包后在target下產生jar包
2)本地運行微服務的jar包
3)查看效果
本地部署(2)-前端靜態web網站
前端技術棧:NodeJS+VueJS+ElementUI
使用Visual Studio Code打開源碼
1)本地運行
2)打包靜態web網站
npm run build打包后,產生dist目錄的靜態文件
3)部署到nginx服務器
把dist目錄的靜態文件拷貝到nginx的html目錄,啟動nginx
4)啟動nginx,并訪問
環境準備(1)-Docker快速入門(請查閱我的docker筆記)
Docker簡介
Docker 是一個開源的應用容器引擎,基于 Go 語言 并遵從 Apache2.0 協議開源。
Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然后發布到任何流
行的 Linux 機器上,也可以實現虛擬化。
容器是完全使用沙箱機制,相互之間不會有任何接口(類似 iPhone 的 app),更重要的是容器性能開銷
極低。
簡單一句話總結:Docker技術就是讓我們更加高效輕松地將任何應用在Linux服務器部署和使用。
環境準備(2)-Dockerfile鏡像腳本快速入門
Dockerfile簡介
Dockerfile其實就是我們用來構建Docker鏡像的源碼,當然這不是所謂的編程源碼,而是一些命令的組
合,只要理解它的邏輯和語法格式,就可以編寫Dockerfile了。
簡單點說,Dockerfile的作用:它可以讓用戶個性化定制Docker鏡像。因為工作環境中的需求各式各
樣,網絡上的鏡像很難滿足實際的需求。
Dockerfile常見命令
RUN、CMD、ENTRYPOINT的區別?
RUN:用于指定 docker build 過程中要運行的命令,即是創建 Docker 鏡像(image)的步驟
CMD:設置容器的啟動命令, Dockerfile 中只能有一條 CMD 命令,如果寫了多條則最后一條生效,
CMD不支持接收docker run的參數。
ENTRYPOINT:入口程序是容器啟動時執行的程序, docker run 中最后的命令將作為參數傳遞給入口
程序 ,ENTRYPOINY類似于 CMD 指令,但可以接收docker run的參數 。
以下是mysql官方鏡像的Dockerfile示例:
FROM oraclelinux:7-slim ARG MYSQL_SERVER_PACKAGE=mysql-community-server-minimal-5.7.28 ARG MYSQL_SHELL_PACKAGE=mysql-shell-8.0.18 # Install server RUN yum install -y https://repo.mysql.com/mysql-community-minimal-releaseel7.rpm \ https://repo.mysql.com/mysql-community-release-el7.rpm \ && yum-config-manager --enable mysql57-server-minimal \ && yum install -y \ $MYSQL_SERVER_PACKAGE \ $MYSQL_SHELL_PACKAGE \ libpwquality \ && yum clean all \ && mkdir /docker-entrypoint-initdb.d VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh COPY healthcheck.sh /healthcheck.sh ENTRYPOINT ["/entrypoint.sh"] HEALTHCHECK CMD /healthcheck.sh EXPOSE 3306 33060 CMD ["mysqld"]使用Dockerfile制作微服務鏡像
我們利用Dockerfile制作一個Eureka注冊中心的鏡像
1)上傳Eureka的微服務jar包到linux
2)編寫Dockerfile
3)構建鏡像
docker build --build-arg JAR_FILE=tensquare_eureka_server-1.0-SNAPSHOT.jar -t eureka:v1 .4)查看鏡像是否創建成功
docker images5)創建容器
docker run -i --name=eureka -p 10086:10086 eureka:v16)訪問容器
環境準備(3)-Harbor鏡像倉庫安裝及使用
Harbor簡介
Harbor(港口,港灣)是一個用于存儲和分發Docker鏡像的企業級Registry服務器。
除了Harbor這個私有鏡像倉庫之外,還有Docker官方提供的Registry。相對Registry,Harbor具有很
多優勢:
用FTP的方式并不適合),顯然不經濟。必須提供識別分層傳輸的機制,以層的UUID為標識,確定
傳輸的對象。
面可以支持登陸、搜索功能,包括區分公有、私有鏡像。
解。
具有更好的安全性。
Harbor安裝
Harbor需要安裝在192.168.66.102上面
1)先安裝Docker并啟動Docker(已完成)
參考之前的安裝過程
2)先安裝docker-compose
3)給docker-compose添加執行權限
sudo chmod +x /usr/local/bin/docker-compose4)查看docker-compose是否安裝成功
docker-compose -version5)下載Harbor的壓縮包(本課程版本為:v1.9.2)
https://github.com/goharbor/harbor/releases
6)上傳壓縮包到linux,并解壓
tar -xzf harbor-offline-installer-v1.9.2.tgz mkdir /opt/harbor mv harbor/* /opt/harbor cd /opt/harbor7)修改Harbor的配置
vi harbor.yml修改hostname和port
hostname: 192.168.66.102 port: 858)安裝Harbor
./prepare ./install.sh9)啟動Harbor
docker-compose up -d 啟動 docker-compose stop 停止 docker-compose restart 重新啟動10)訪問Harbor
http://192.168.66.102:85
默認賬戶密碼:admin/Harbor12345
在Harbor創建用戶和項目
1)創建項目
Harbor的項目分為公開和私有的:
公開項目:所有用戶都可以訪問,通常存放公共的鏡像,默認有一個library公開項目。
私有項目:只有授權用戶才可以訪問,通常存放項目本身的鏡像。
把鏡像上傳到Harbor
1)給鏡像打上標簽
docker tag eureka:v1 192.168.66.102:85/tensquare/eureka:v12)推送鏡像
docker push 192.168.66.102:85/tensquare/eureka:v1
3)把Harbor地址加入到Docker信任列表
需要重啟Docker
4)再次執行推送命令,會提示權限不足
需要先登錄Harbor,再推送鏡像
5)登錄Harbor
從Harbor下載鏡像
微服務持續集成(1)-項目代碼上傳到Gitlab
在IDEA操作即可,參考之前的步驟。包括后臺微服務和前端web網站代碼
微服務持續集成(2)-從Gitlab拉取項目源碼
1)創建Jenkinsfile文件
2)拉取Jenkinsfile文件
微服務持續集成(3)-提交到SonarQube代碼審查
1)創建項目,并設置參數
創建tensquare_back項目,添加兩個參數
2)每個項目的根目錄下添加sonar-project.properties
注意:修改sonar.projectKey和sonar.projectName
3)修改Jenkinsfile構建腳本
微服務持續集成(4)-使用Dockerfile編譯、生成鏡像
利用dockerfile-maven-plugin插件構建Docker鏡像
1)在每個微服務項目的pom.xml加入dockerfile-maven-plugin插件
2)在每個微服務項目根目錄下建立Dockerfile文件
#FROM java:8 FROM openjdk:8-jdk-alpine ARG JAR_FILE COPY ${JAR_FILE} app.jar EXPOSE 10086 ENTRYPOINT ["java","-jar","/app.jar"]注意:每個項目公開的端口不一樣
3)修改Jenkinsfile構建腳本
注意:如果出現找不到父工程依賴,需要手動把父工程的依賴上傳到倉庫中
微服務持續集成(5)-上傳到Harbor鏡像倉庫
1)修改Jenkinsfile構建腳本
//gitlab的憑證 def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8" //構建版本的名稱 def tag = "latest" //Harbor私服地址 def harbor_url = "192.168.66.102:85" //Harbor的項目名稱 def harbor_project_name = "tensquare" //Harbor的憑證 def harbor_auth = "ef499f29-f138-44dd-975e-ff1ca1d8c933" node { stage('拉取代碼') { checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'git@192.168.66.100:itheima_group/tensquare_back.git']]]) } stage('代碼審查') { def scannerHome = tool 'sonarqube-scanner' withSonarQubeEnv('sonarqube6.7.4') { sh """ cd ${project_name} ${scannerHome}/bin/sonar-scanner """ } } stage('編譯,構建鏡像') { //定義鏡像名稱 def imageName = "${project_name}:${tag}" //編譯,安裝公共工程 sh "mvn -f tensquare_common clean install" //編譯,構建本地鏡像 sh "mvn -f ${project_name} clean package dockerfile:build" //給鏡像打標簽 sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}" //登錄Harbor,并上傳鏡像 withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) { //登錄 sh "docker login -u ${username} -p ${password} ${harbor_url}" //上傳鏡像 sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" } //刪除本地鏡像 sh "docker rmi -f ${imageName}" sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}" } }2)使用憑證管理Harbor私服賬戶和密碼
先在憑證建立Harbor的憑證,在生成憑證腳本代碼
微服務持續集成(6)-拉取鏡像和發布應用
注意:192.168.66.103服務已經安裝Docker并啟動
安裝 Publish Over SSH 插件
安裝以下插件,可以實現遠程發送Shell命令
配置遠程部署服務器
1)拷貝公鑰到遠程服務器
ssh-copy-id 192.168.66.1032)系統配置->添加遠程服務器
修改Jenkinsfile構建腳本
生成遠程調用模板代碼
添加一個port參數
編寫deploy.sh部署腳本
#! /bin/sh #接收外部參數 harbor_url=$1 harbor_project_name=$2 project_name=$3 tag=$4 port=$5 imageName=$harbor_url/$harbor_project_name/$project_name:$tag echo "$imageName" #查詢容器是否存在,存在則刪除 containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'` if [ "$containerId" != "" ] ; then #停掉容器 docker stop $containerId #刪除容器 docker rm $containerId echo "成功刪除容器" fi #查詢鏡像是否存在,存在則刪除 imageId=`docker images | grep -w $project_name | awk '{print $3}'` if [ "$imageId" != "" ] ; then #刪除鏡像 docker rmi -f $imageId echo "成功刪除鏡像" fi # 登錄Harbor私服 docker login -u itcast -p Itcast123 $harbor_url # 下載鏡像 docker pull $imageName # 啟動容器 docker run -di -p $port:$port $imageName echo "容器啟動成功"上傳deploy.sh文件到/opt/jenkins_shell目錄下,且文件至少有執行權限!
chmod +x deploy.sh 添加執行權限導入數據,測試微服務
微服務持續集成(7)-部署前端靜態web網站
安裝Nginx服務器
修改nginx的端口,默認80,改為9090:
vi /etc/nginx/nginx.conf server { listen 9090 default_server; listen [::]:9090 default_server; server_name _; root /usr/share/nginx/html;還需要關閉selinux,將SELINUX=disabled
setenforce 0 先臨時關閉 vi /etc/selinux/config 編輯文件,永久關閉 SELINUX=disabled啟動Nginx
systemctl enable nginx 設置開機啟動 systemctl start nginx 啟動 systemctl stop nginx 停止 systemctl restart nginx 重啟訪問:http://192.168.66.103:9090/
安裝NodeJS插件
Jenkins配置Nginx服務器
Manage Jenkins->Global Tool Configuration
創建前端流水線項目
建立Jenkinsfile構建腳本
//gitlab的憑證 def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8" node { stage('拉取代碼') { checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'git@192.168.66.100:itheima_group/tensquare_front.git']]]) } stage('打包,部署網站') { //使用NodeJS的npm進行打包 nodejs('nodejs12'){ sh ''' npm install npm run build ''' } //=====以下為遠程調用進行項目部署======== sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/usr/share/nginx/html', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) } }完成后,訪問:http://192.168.66.103:9090 進行測試。
5、Jenkins+Docker+SpringCloud微服務持續集成(下)
Jenkins+Docker+SpringCloud部署方案優化
上面部署方案存在的問題:
1)一次只能選擇一個微服務部署
2)只有一臺生產者部署服務器
3)每個微服務只有一個實例,容錯率低
優化方案:
1)在一個Jenkins工程中可以選擇多個微服務同時發布
2)在一個Jenkins工程中可以選擇多臺生產服務器同時部署
3)每個微服務都是以集群高可用形式部署
Jenkins+Docker+SpringCloud集群部署流程說明
修改所有微服務配置
注冊中心配置(*)
yml 文件,下面配置代碼錯誤,沒有縮進
在啟動微服務的時候,加入參數: spring.profiles.active 來讀取對應的配置
其他微服務配置
除了Eureka注冊中心以外,其他微服務配置都需要加入所有Eureka服務
# Eureka配置 eureka: client: service-url: defaultZone: http://192.168.66.103:10086/eureka,http://192.168.66.104:10086/eureka # Eureka訪 問地址 instance: prefer-ip-address: true把代碼提交到Gitlab中
設計Jenkins集群項目的構建參數
1)安裝Extended Choice Parameter插件
支持多選框
2)創建流水線項目
3)添加參數
字符串參數:分支名稱
多選框:項目名稱
最后效果:
完成微服務構建鏡像,上傳私服
//gitlab的憑證 def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8" //構建版本的名稱 def tag = "latest" //Harbor私服地址 def harbor_url = "192.168.66.102:85" //Harbor的項目名稱 def harbor_project_name = "tensquare" //Harbor的憑證 def harbor_auth = "ef499f29-f138-44dd-975e-ff1ca1d8c933" node { //把選擇的項目信息轉為數組 def selectedProjects = "${project_name}".split(',') stage('拉取代碼') { checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '${git_auth}', url: 'git@192.168.66.100:itheima_group/tensquare_back_cluster.git']]]) } stage('代碼審查') { def scannerHome = tool 'sonarqube-scanner' withSonarQubeEnv('sonarqube6.7.4') { for(int i=0;i<selectedProjects.size();i++){ //取出每個項目的名稱和端口 def currentProject = selectedProjects[i]; //項目名稱 def currentProjectName = currentProject.split('@')[0] //項目啟動端口 def currentProjectPort = currentProject.split('@')[1] sh """ cd ${currentProjectName} ${scannerHome}/bin/sonar-scanner """ echo "${currentProjectName}完成代碼審查" } } } stage('編譯,構建鏡像,部署服務') { //編譯并安裝公共工程 sh "mvn -f tensquare_common clean install" for(int i=0;i<selectedProjects.size();i++){ //取出每個項目的名稱和端口 def currentProject = selectedProjects[i]; //項目名稱 def currentProjectName = currentProject.split('@')[0] //項目啟動端口 def currentProjectPort = currentProject.split('@')[1] //定義鏡像名稱 def imageName = "${currentProjectName}:${tag}" //編譯,構建本地鏡像 sh "mvn -f ${currentProjectName} clean package dockerfile:build" //給鏡像打標簽 sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}" //登錄Harbor,并上傳鏡像 withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) { //登錄 sh "docker login -u ${username} -p ${password} ${harbor_url}" //上傳鏡像 sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" } //刪除本地鏡像 sh "docker rmi -f ${imageName}" sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}" //=====以下為遠程調用進行項目部署======== //sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deployCluster.sh $harbor_url $harbor_project_name $currentProjectName $tag $currentProjectPort", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) echo "${currentProjectName}完成編譯,構建鏡像" } } }完成微服務多服務器遠程發布
1)配置遠程部署服務器
拷貝公鑰到遠程服務器
系統配置->添加遠程服務器
2)修改Docker配置信任Harbor私服地址
重啟Docker
3)添加參數
多選框:部署服務器
最終效果:
4)修改Jenkinsfile構建腳本
5)編寫deployCluster.sh部署腳本
#! /bin/sh #接收外部參數 harbor_url=$1 harbor_project_name=$2 project_name=$3 tag=$4 port=$5 profile=$6 imageName=$harbor_url/$harbor_project_name/$project_name:$tag echo "$imageName" #查詢容器是否存在,存在則刪除 containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'` if [ "$containerId" != "" ] ; then #停掉容器 docker stop $containerId #刪除容器 docker rm $containerId echo "成功刪除容器" fi #查詢鏡像是否存在,存在則刪除 imageId=`docker images | grep -w $project_name | awk '{print $3}'` if [ "$imageId" != "" ] ; then #刪除鏡像 docker rmi -f $imageId echo "成功刪除鏡像" fi # 登錄Harbor私服 docker login -u itcast -p Itcast123 $harbor_url # 下載鏡像 docker pull $imageName # 啟動容器 docker run -di -p $port:$port $imageName $profile echo "容器啟動成功"6)集群效果
Nginx+Zuul集群實現高可用網關
1)安裝Nginx(已完成)
2)修改Nginx配置
內容如下:
upstream zuulServer{ server 192.168.66.103:10020 weight=1; server 192.168.66.104:10020 weight=1; } server { listen 85 default_server; listen [::]:85 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { ### 指定服務器負載均衡服務器 proxy_pass http://zuulServer/; }3)重啟Nginx: systemctl restart nginx
4)修改前端Nginx的訪問地址
6、基于Kubernetes/K8S構建Jenkins持續集成平臺(上)
Jenkins的Master-Slave分布式構建
什么是Master-Slave分布式構建
Jenkins的Master-Slave分布式構建,就是通過將構建過程分配到從屬Slave節點上,從而減輕Master節
點的壓力,而且可以同時構建多個,有點類似負載均衡的概念。
如何實現Master-Slave分布式構建
1)開啟代理程序的TCP端口
Manage Jenkins -> Configure Global Security
2)新建節點
Manage Jenkins—Manage Nodes—新建節點
有兩種在Slave節點連接Master節點的方法
我們選擇第二種:
2)安裝和配置節點
下載agent.jar,并上傳到Slave節點,然后執行頁面提示的命令:
刷新頁面
3)測試節點是否可用
自由風格和Maven風格的項目:
流水線風格的項目:
Kubernetes實現Master-Slave分布式構建方案
傳統Jenkins的Master-Slave方案的缺陷
Master節點發生單點故障時,整個流程都不可用了
每個 Slave節點的配置環境不一樣,來完成不同語言的編譯打包等操作,但是這些差異化的配置導
致管理起來非常不方便,維護起來也是比較費勁
資源分配不均衡,有的 Slave節點要運行的job出現排隊等待,而有的Slave節點處于空閑狀態
資源浪費,每臺 Slave節點可能是實體機或者VM,當Slave節點處于空閑狀態時,也不會完全釋放
掉資源
以上種種問題,我們可以引入Kubernates來解決!
Kubernates簡介
Kubernetes(簡稱,K8S)是Google開源的容器集群管理系統,在Docker技術的基礎上,為容器化的
應用提供部署運行、資源調度、服務發現和動態伸縮等一系列完整功能,提高了大規模容器集群管理的
便捷性。 其主要功能如下:
使用Docker對應用程序包裝(package)、實例化(instantiate)、運行(run)。
以集群的方式運行、管理跨機器的容器。以集群的方式運行、管理跨機器的容器。
解決Docker跨機器容器之間的通訊問題。解決Docker跨機器容器之間的通訊問題。
Kubernetes的自我修復機制使得容器集群總是運行在用戶期望的狀態。
Kubernates+Docker+Jenkins持續集成架構圖
大致工作流程:手動/自動構建 -> Jenkins 調度 K8S API ->動態生成 Jenkins Slave pod -> Slave pod
拉取 Git 代碼/編譯/打包鏡像 ->推送到鏡像倉庫 Harbor -> Slave 工作完成,Pod 自動銷毀 ->部署
到測試或生產 Kubernetes平臺。(完全自動化,無需人工干預)
Kubernates+Docker+Jenkins持續集成方案好處
服務高可用:
當 Jenkins Master 出現故障時,Kubernetes 會自動創建一個新的 Jenkins Master容器,并且將 Volume 分配給新創建的容器,保證數據不丟失,從而達到集群服務高可用。
動態伸縮,合理使用資源:
每次運行 Job 時,會自動創建一個 Jenkins Slave,Job 完成后,Slave自動注銷并刪除容器,資源自動釋放,而且 Kubernetes 會根據每個資源的使用情況,動態分配Slave 到空閑的節點上創建,降低出現因某節點資源利用率高,還排隊等待在該節點的情況。
擴展性好:
當 Kubernetes 集群的資源嚴重不足而導致 Job 排隊等待時,可以很容易的添加一個Kubernetes Node 到集群中,從而實現擴展。
Kubeadm安裝Kubernetes
Kubernetes的架構
API Server:用于暴露Kubernetes API,任何資源的請求的調用操作都是通過kube-apiserver提供的接口進行的。
Etcd:是Kubernetes提供默認的存儲系統,保存所有集群數據,使用時需要為etcd數據提供備份計
劃。
Controller-Manager:作為集群內部的管理控制中心,負責集群內的Node、Pod副本、服務端點(Endpoint)、命名空間(Namespace)、服務賬號(ServiceAccount)、資源定額(ResourceQuota)的管理,當某個Node意外宕機時,Controller Manager會及時發現并執行自動化修復流程,確保集群始終處于預期的工作狀態。
Scheduler:監視新創建沒有分配到Node的Pod,為Pod選擇一個Node。
Kubelet:負責維護容器的生命周期,同時負責Volume和網絡的管理
Kube proxy:是Kubernetes的核心組件,部署在每個Node節點上,它是實現Kubernetes Service的通信與負載均衡機制的重要組件。
安裝環境說明
總結
以上是生活随笔為你收集整理的Jenkins-自动化构建、测试和部署-学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty-案例 WebSocket与n
- 下一篇: JVM学习笔记之-运行时数据区概述及线程