日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Jenkins-自动化构建、测试和部署-学习笔记

發布時間:2024/4/15 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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官方的插件列表下載到本地,接著修改地址文件,替換為國內插件地址

cd /var/lib/jenkins/updates sed -i 's/http:\/\/updates.jenkinsci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json && sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json

最后,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用戶生成公鑰和私鑰

ssh-keygen -t rsa

在/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/
添加阿里云私服地址:

alimaven aliyun maven http://maven.aliyun.com/nexus/content/groups/public/ central

測試Maven是否配置成功

使用之前的gitlab密碼測試項目,修改配置

構建->增加構建步驟->Execute Shell

輸入

mvn clean package


再次構建,如果可以把項目打成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以下配置,
添加用戶及權限

vi /opt/tomcat/conf/tomcat-users.xml <tomcat-users> <role rolename="tomcat"/> <role rolename="role1"/> <role rolename="manager-script"/> <role rolename="manager-gui"/> <role rolename="manager-status"/> <role rolename="admin-gui"/> <role rolename="admin-script"/> <user username="tomcat" password="tomcat" roles="manager-gui,managerscript,tomcat,admin-gui,admin-script"/> </tomcat-users>

用戶和密碼都是:tomcat
注意:為了能夠剛才配置的用戶登錄到Tomcat,還需要修改以下配置

vi /opt/tomcat/webapps/manager/META-INF/context.xml <!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->

把上面這行注釋掉即可!

重啟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模板

生成內容如下:

pipeline {agent anystages {stage('Hello') {steps {echo 'Hello World'}}} }

stages:代表整個流水線的所有執行階段。通常stages只有1個,里面包含多個stage
stage:代表流水線中的某個階段,可能出現n個。一般分為拉取代碼,編譯構建,部署等階段。
steps:代表一個階段內需要執行的邏輯。steps里面是shell腳本,git拉取代碼,ssh遠程發布等任意內
容。
編寫一個簡單聲明式Pipeline:

pipeline {agent anystages {stage('拉取代碼') {steps {echo '拉取代碼'}}stage('編譯構建') {steps {echo '編譯構建'}}stage('項目部署') {steps {echo '項目部署'}}} }

點擊構建,可以看到整個構建過程

2)Scripted Pipeline腳本式-Pipeline

創建項目

這次選擇"Scripted Pipeline"

node {def mvnHomestage('Preparation') { // for display purposes}stage('Build') {}stage('Results') {} }

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

node {def mvnHomestage('拉取代碼') { // for display purposesecho '拉取代碼'}stage('編譯構建') {echo '編譯構建'}stage('項目部署') {echo '項目部署'} }

構建結果和聲明式一樣!

腳本式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)配置需要觸發的工程

定時構建


定時字符串從左往右分別為: 分 時 日 月 周

一些定時表達式的例子: 每30分鐘構建一次:H代表形參 H/30 * * * * 10:02 10:32 每2個小時構建一次: H H/2 * * * 每天的8點,12點,22點,一天構建3次: (多個時間點中間用逗號隔開) 0 8,12,22 * * * 每天中午12點定時構建一次 H 12 * * * 每天下午18點定時構建一次 H 18 * * * 在每個小時的前半個小時內的每10分鐘 H(0-29)/10 * * * * 每兩小時一次,每個工作日上午9點到下午5點(也許是上午10:38,下午12:38,下午2:38,下午 4:38) H H(9-16)/2 * * 1-5

輪詢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,并設置權限

yum install unzip unzip sonarqube-6.7.4.zip 解壓 mkdir /opt/sonar 創建目錄 mv sonarqube-6.7.4/* /opt/sonar 移動文件 useradd sonar 創建sonar用戶,必須sonar用于啟動,否則報錯 chown -R sonar. /opt/sonar 更改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

cd /opt/sonarqube-6.7.4 su sonar ./bin/linux-x86-64/sonar.sh start 啟動 su sonar ./bin/linux-x86-64/sonar.sh status 查看狀態 su sonar ./bin/linux-x86-64/sonar.sh stop 停止 tail -f logs/sonar.logs 查看日志

訪問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代碼審查(非流水線項目)
添加構建步驟:

# must be unique in a given SonarQube instance sonar.projectKey=web_demo # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=web_demo sonar.projectVersion=1.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # This property is optional if sonar.modules is set. sonar.sources=. sonar.exclusions=**/test/**,**/target/** sonar.java.source=1.8 sonar.java.target=1.8 # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8

在項目添加SonaQube代碼審查(流水線項目)

1)項目根目錄下,創建sonar-project.properties文件

# must be unique in a given SonarQube instance sonar.projectKey=web_demo # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=web_demo sonar.projectVersion=1.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # This property is optional if sonar.modules is set. sonar.sources=. sonar.exclusions=**/test/**,**/target/** sonar.java.source=1.8 sonar.java.target=1.8 # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8

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微服務項目打包
必須導入該插件

<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>

打包后在target下產生jar包
2)本地運行微服務的jar包

java -jar xxx.jar

3)查看效果

本地部署(2)-前端靜態web網站

前端技術棧:NodeJS+VueJS+ElementUI
使用Visual Studio Code打開源碼
1)本地運行

npm run dev

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

FROM openjdk:8-jdk-alpine ARG JAR_FILE COPY ${JAR_FILE} app.jar EXPOSE 10086 ENTRYPOINT ["java","-jar","/app.jar"]

3)構建鏡像

docker build --build-arg JAR_FILE=tensquare_eureka_server-1.0-SNAPSHOT.jar -t eureka:v1 .

4)查看鏡像是否創建成功

docker images

5)創建容器

docker run -i --name=eureka -p 10086:10086 eureka:v1

6)訪問容器

環境準備(3)-Harbor鏡像倉庫安裝及使用

Harbor簡介


Harbor(港口,港灣)是一個用于存儲和分發Docker鏡像的企業級Registry服務器。
除了Harbor這個私有鏡像倉庫之外,還有Docker官方提供的Registry。相對Registry,Harbor具有很
多優勢:

  • 提供分層傳輸機制,優化網絡傳輸 Docker鏡像是是分層的,而如果每次傳輸都使用全量文件(所以
    用FTP的方式并不適合),顯然不經濟。必須提供識別分層傳輸的機制,以層的UUID為標識,確定
    傳輸的對象。
  • 提供WEB界面,優化用戶體驗 只用鏡像的名字來進行上傳下載顯然很不方便,需要有一個用戶界
    面可以支持登陸、搜索功能,包括區分公有、私有鏡像。
  • 支持水平擴展集群 當有用戶對鏡像的上傳下載操作集中在某服務器,需要對相應的訪問壓力作分
    解。
  • 良好的安全機制 企業中的開發團隊有很多不同的職位,對于不同的職位人員,分配不同的權限,
    具有更好的安全性。
  • Harbor安裝

    Harbor需要安裝在192.168.66.102上面
    1)先安裝Docker并啟動Docker(已完成)
    參考之前的安裝過程
    2)先安裝docker-compose

    sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/dockercompose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose

    3)給docker-compose添加執行權限

    sudo chmod +x /usr/local/bin/docker-compose

    4)查看docker-compose是否安裝成功

    docker-compose -version

    5)下載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/harbor

    7)修改Harbor的配置

    vi harbor.yml

    修改hostname和port

    hostname: 192.168.66.102 port: 85

    8)安裝Harbor

    ./prepare ./install.sh

    9)啟動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:v1

    2)推送鏡像

    docker push 192.168.66.102:85/tensquare/eureka:v1


    3)把Harbor地址加入到Docker信任列表

    vi /etc/docker/daemon.json { "registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"], "insecure-registries": ["192.168.66.102:85"] }

    需要重啟Docker
    4)再次執行推送命令,會提示權限不足

    denied: requested access to the resource is denied

    需要先登錄Harbor,再推送鏡像
    5)登錄Harbor

    docker login -u 用戶名 -p 密碼 192.168.66.102:85

    從Harbor下載鏡像

    微服務持續集成(1)-項目代碼上傳到Gitlab

    在IDEA操作即可,參考之前的步驟。包括后臺微服務和前端web網站代碼

    微服務持續集成(2)-從Gitlab拉取項目源碼

    1)創建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_back.git']]]) } }

    2)拉取Jenkinsfile文件

    微服務持續集成(3)-提交到SonarQube代碼審查

    1)創建項目,并設置參數
    創建tensquare_back項目,添加兩個參數

    2)每個項目的根目錄下添加sonar-project.properties

    # must be unique in a given SonarQube instance sonar.projectKey=tensquare_zuul # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=tensquare_zuul sonar.projectVersion=1.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # This property is optional if sonar.modules is set. sonar.sources=. sonar.exclusions=**/test/**,**/target/** sonar.java.binaries=. sonar.java.source=1.8 sonar.java.target=1.8 sonar.java.libraries=**/target/classes/** # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8

    注意:修改sonar.projectKey和sonar.projectName
    3)修改Jenkinsfile構建腳本

    //gitlab的憑證 def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8" //構建版本的名稱 def tag = "latest" 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 """ } } }

    微服務持續集成(4)-使用Dockerfile編譯、生成鏡像

    利用dockerfile-maven-plugin插件構建Docker鏡像
    1)在每個微服務項目的pom.xml加入dockerfile-maven-plugin插件

    <plugin> <groupId>com.spotify</groupId> <artifactId>dockerfile-maven-plugin</artifactId> <version>1.3.6</version> <configuration> <repository>${project.artifactId}</repository> <buildArgs> <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE> </buildArgs> </configuration> </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構建腳本

    //gitlab的憑證 def git_auth = "68f2087f-a034-4d39-a9ff-1f776dd3dfa8" //構建版本的名稱 def tag = "latest" //Harbor私服地址 def harbor_url = "192.168.66.102:85/tensquare/" 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" } }

    注意:如果出現找不到父工程依賴,需要手動把父工程的依賴上傳到倉庫中

    微服務持續集成(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.103

    2)系統配置->添加遠程服務器

    修改Jenkinsfile構建腳本

    生成遠程調用模板代碼

    添加一個port參數

    //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}" //=====以下為遠程調用進行項目部署======== sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) } }

    編寫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服務器

    yum install epel-release yum -y install 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: application: name: EUREKA-HA --- server: port: 10086 spring: # 指定profile=eureka-server1 profiles: eureka-server1 eureka: instance: # 指定當profile=eureka-server1時,主機名是eureka-server1 hostname: 192.168.66.103 client service-url: # 將自己注冊到eureka-server1、eureka-server2這個Eureka上面去 defaultZone: http://192.168.66.103:10086/eureka/,http://192.168.66.104:10086/eureka/ --- server: port: 10086 spring: profiles: eureka-server2 eureka: instance: hostname: 192.168.66.104 client: service-url: defaultZone: http://192.168.66.103:10086/eureka/,http://192.168.66.104:10086/eureka/

    在啟動微服務的時候,加入參數: 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)添加參數
    字符串參數:分支名稱

    多選框:項目名稱

    tensquare_eureka_server@10086,tensquare_zuul@10020,tensquare_admin_service@9001, tensquare_gathering@9002


    最后效果:

    完成微服務構建鏡像,上傳私服

    //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)配置遠程部署服務器
    拷貝公鑰到遠程服務器

    ssh-copy-id 192.168.66.104

    系統配置->添加遠程服務器

    2)修改Docker配置信任Harbor私服地址

    { "registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"], "insecure-registries": ["192.168.66.102:85"] }

    重啟Docker
    3)添加參數
    多選框:部署服務器


    最終效果:

    4)修改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 { //把選擇的項目信息轉為數組 def selectedProjects = "${project_name}".split(',') //把選擇的服務區信息轉為數組 def selectedServers = "${publish_server}".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}" //=====以下為遠程調用進行項目部署======== for(int j=0;j<selectedServers.size();j++){ //每個服務名稱 def currentServer = selectedServers[j] //添加微服務運行時的參數:spring.profiles.active def activeProfile = "--spring.profiles.active=" if(currentServer=="master_server"){ activeProfile = activeProfile+"eureka-server1" }else if(currentServer=="slave_server1"){ activeProfile = activeProfile+"eureka-server2" } sshPublisher(publishers: [sshPublisherDesc(configName: "${currentServer}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deployCluster.sh $harbor_url $harbor_project_name $currentProjectName $tag $currentProjectPort $activeProfile", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) } echo "${currentProjectName}完成編譯,構建鏡像" } } }

    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配置

    vi /etc/nginx/nginx.conf

    內容如下:

    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節點,然后執行頁面提示的命令:

    java -jar agent.jar -jnlpUrl http://192.168.66.101:8888/computer/slave1/slaveagent.jnlp -secret f2ecbb99e0c81331e8b7a7917a94d478f39cb9763fc6c66d9a9741c61f9ae6d6 -workDir "/root/jenkins"

    刷新頁面

    3)測試節點是否可用
    自由風格和Maven風格的項目:

    流水線風格的項目:

    node('slave1') { stage('check out') { 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/tensquare_back_cluster.git']]]) } }

    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-自动化构建、测试和部署-学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    香蕉久久久久久av成人 | 亚洲国产欧美一区二区三区丁香婷 | 免费在线日韩 | 97精品国产97久久久久久免费 | 精品在线观看一区二区三区 | 亚洲专区欧美 | 99久久精品免费看国产 | 国产香蕉97碰碰久久人人 | 国产女教师精品久久av | 日韩高清精品一区二区 | 国产精品完整版 | 视频一区久久 | 国产麻豆视频 | 成人黄色短片 | 天天射天天 | 国产精品123| 婷婷午夜 | 五月天综合网站 | 亚洲一级久久 | 欧美一级在线 | 天天操天天色天天 | 中文字幕av电影下载 | 中文字幕资源网在线观看 | 国产精久久久久久妇女av | 丁五月婷婷 | 色吊丝在线永久观看最新版本 | 99操视频| 免费91在线 | 中文字幕观看在线 | 久久国产午夜精品理论片最新版本 | 中文字幕综合在线 | 天天躁日日躁狠狠 | 亚洲国产手机在线 | 狠狠干夜夜爽 | 欧产日产国产69 | 亚洲黄色免费在线看 | 爱爱一区| 久久精品毛片基地 | 久久久污 | 国产高清不卡 | 日韩免费中文 | 97视频免费在线 | 欧美与欧洲交xxxx免费观看 | 在线免费观看国产视频 | 六月色丁 | 天天爽夜夜爽人人爽曰av | 亚洲精品视频在线观看视频 | 97国产情侣爱久久免费观看 | 日韩肉感妇bbwbbwbbw | 国产精品av免费在线观看 | 又黄又爽又刺激视频 | 国产成人综合在线观看 | 国产高清视频色在线www | 亚洲欧洲一区二区在线观看 | 日韩美一区二区三区 | 亚洲乱码中文字幕综合 | 欧美乱码精品一区 | 亚洲黄色av一区 | 日本精品视频免费 | 国产99免费 | 日韩精品一区二区三区在线播放 | 国产一级二级三级在线观看 | av免费电影网站 | 91精品在线免费视频 | 成年人视频免费在线播放 | 国产情侣一区 | 日韩av资源站 | 在线国产精品一区 | 婷婷在线免费视频 | 国产成人精品在线播放 | 免费在线观看日韩欧美 | 91av亚洲 | 亚洲欧美日韩精品久久奇米一区 | 天天做天天看 | 欧美日韩伦理在线 | 免费在线观看毛片网站 | www夜夜操com| 天天天综合 | 91色欧美| 丁香狠狠 | 午夜精品一区二区三区视频免费看 | 美女久久久久 | 国产精品99久久久久人中文网介绍 | 色婷婷激情四射 | 九九热只有精品 | 国产小视频在线观看 | 九七视频在线观看 | 尤物一区二区三区 | 黄色免费网 | 丁香婷婷成人 | 精品一二三区 | 国产精品久久久久久久久久久免费看 | 国产精品久久久久久久久久不蜜月 | 国产区精品 | 亚洲综合在线五月 | 久久久亚洲麻豆日韩精品一区三区 | 国产日韩三级 | 五月综合激情网 | 婷婷六月天综合 | 欧美日韩精品网站 | 成人一区二区三区在线 | 免费高清看电视网站 | 国产精品网红直播 | 丝袜足交在线 | 很黄很污的视频网站 | 日韩三级一区 | 天天色中文 | 久久久精品电影 | 久久久香蕉视频 | 欧洲av不卡 | 人人干人人艹 | 成人午夜性影院 | 一区二区三区国产精品 | www,黄视频| 亚洲91中文字幕无线码三区 | 婷婷激情在线观看 | 911国产在线观看 | 人人爽人人爽人人爽 | 欧美一级爽 | 狠狠操狠狠操 | 亚洲综合色婷婷 | 欧美日韩精品在线 | 亚洲精品久久在线 | 青草视频在线看 | 黄色网址中文字幕 | 欧美午夜精品久久久久 | 午夜资源站 | 免费av在 | 久久手机在线视频 | 精品国产成人av | www.狠狠干 | 日本久久成人中文字幕电影 | 在线黄色国产电影 | 精品国产亚洲日本 | 国产99久久久国产精品成人免费 | 成人免费在线观看av | 亚洲人成人天堂h久久 | 五月婷婷伊人网 | 国产精品免费一区二区 | 亚洲不卡在线 | 婷婷久久久| 午夜精品福利一区二区三区蜜桃 | 中文字幕免费观看全部电影 | 黄色三级网站 | 五月婷在线视频 | 亚洲专区在线播放 | 午夜精品一区二区三区在线视频 | 97超碰色| 丁香午夜 | 免费三级大片 | 国产成人久久av977小说 | 日韩中文字幕免费 | 国产精品正在播放 | 日韩免费一级电影 | 西西444www大胆高清视频 | 久久久久亚洲精品中文字幕 | 亚洲国产偷| www.在线观看视频 | 亚洲综合导航 | 日韩欧美在线观看一区二区 | 国产中文在线播放 | 六月丁香激情综合色啪小说 | 久久久久免费观看 | 一区二区三区在线观看中文字幕 | 色爽网站| 国产午夜影院 | 国产精品高清在线观看 | 久久系列| 久久久久久蜜桃一区二区 | 国际精品久久久久 | 波多野结衣精品 | 中文字幕在线观看av | 欧美激情va永久在线播放 | 三级黄色在线观看 | 久久躁日日躁aaaaxxxx | 婷婷综合视频 | 九九免费在线看完整版 | 欧美日韩高清一区二区 国产亚洲免费看 | 久久久免费 | 一区二区三区在线观看 | 久草视频免费观 | 99免费在线视频 | 久久男人中文字幕资源站 | 亚洲最大在线视频 | 久久久精品一区二区 | 亚洲精品一区中文字幕乱码 | 国产999精品久久久 免费a网站 | 国产欧美日韩精品一区二区免费 | 精品亚洲视频在线 | 亚洲男人天堂a | 波多野结衣在线观看视频 | 永久免费毛片在线观看 | 日本狠狠色 | 精品999| 在线 国产一区 | 国产精品国产三级国产 | 香蕉视频导航 | 国产精品视频99 | 狠狠色伊人亚洲综合网站色 | 久草青青在线观看 | 久久综合狠狠综合久久激情 | 国产在线精品播放 | 亚洲国产精品va在线看黑人动漫 | 亚洲欧美国产精品va在线观看 | 日韩a级免费视频 | 国产在线观看av | 亚洲欧洲久久久 | 成片免费观看视频 | 久久不见久久见免费影院 | 最近日韩免费视频 | 色综合久久五月 | 亚洲国产成人精品久久 | 欧美成年人在线视频 | 欧美午夜激情网 | 国产五十路毛片 | 91精品一区二区三区蜜臀 | 91在线免费播放视频 | 国产亚洲欧美在线视频 | 日韩午夜精品福利 | 99视频精品视频高清免费 | 国产成a人亚洲精v品在线观看 | 最近中文国产在线视频 | 中文在线a√在线 | 国产最新精品视频 | 韩国av免费观看 | 成人黄色在线视频 | 日韩美一区二区三区 | 精品久久久一区二区 | www.福利| 四虎国产精品成人免费影视 | 久久久精品午夜 | 色资源中文字幕 | 午夜骚影 | 久久久久9999亚洲精品 | 精品国偷自产在线 | 欧美日韩高清一区二区三区 | 欧美人人 | 久久免费精彩视频 | 日韩av图片| 亚洲第一区在线观看 | 狠狠色丁香久久综合网 | 成人不用播放器 | 久久你懂得 | 久久免费av电影 | 五月婷婷影院 | 天天草天天插 | 日韩二区在线 | 一级免费看视频 | 国产一区二区三区高清播放 | 91色吧 | 激情五月婷婷综合 | 91精品国产自产91精品 | 久久亚洲综合色 | 免费碰碰 | free,性欧美 九九交易行官网 | 91视频国产免费 | av大片网址 | 国产精品午夜免费福利视频 | 久久精品79国产精品 | 国产免费久久精品 | 免费成人黄色av | 国产麻豆果冻传媒在线观看 | 西西大胆免费视频 | japanesexxxxfreehd乱熟 | 免费一级特黄录像 | 日本女人的性生活视频 | 日韩中文字 | 亚洲欧洲中文日韩久久av乱码 | 热久久国产精品 | 婷婷深爱 | 黄色片毛片 | 97视频免费 | 香蕉免费在线 | 成人欧美一区二区三区在线观看 | 日本福利视频在线 | 99色人| 九九九九九九精品任你躁 | 国产成人久久精品亚洲 | 亚洲午夜精品一区二区三区电影院 | 91自拍91| 欧美国产91| 麻豆视频免费 | 97精品国产97久久久久久 | 精品国产诱惑 | 国产精品毛片一区 | 狠狠色综合欧美激情 | 婷婷丁香在线视频 | 国产视频精品免费播放 | www.伊人网| 精品久久久免费视频 | 天天操天天爱天天爽 | 六月丁香色婷婷 | 在线观看国产高清视频 | 国产精品第三页 | 久久精品国产免费看久久精品 | 婷婷av综合| 久久影院亚洲 | 中文字幕乱视频 | 久久高清国产 | 久草免费福利在线观看 | 欧美日韩不卡在线观看 | 亚洲va欧洲va国产va不卡 | 国产精品久久久av | 五月激情姐姐 | 国产精品一区二区免费 | 午夜电影中文字幕 | 午夜在线免费观看 | www.久久久| 一区二区在线电影 | 成人久久18免费网站图片 | 狠狠干狠狠插 | 丁香视频在线观看 | 国产尤物在线视频 | 国产成人61精品免费看片 | 国产黄色片一级 | 国产三级香港三韩国三级 | 日韩美女久久 | 色综合天天 | 一级黄色片在线观看 | 91九色蝌蚪视频 | 99久久久免费视频 | 二区三区av | 99久久精品费精品 | av色一区| 奇米7777狠狠狠琪琪视频 | 波多野结衣在线中文字幕 | 亚洲传媒在线 | 日韩xxxxxxxxx| 天天操操操操操操 | 成人av网站在线观看 | 97超碰成人 | 在线观看久久久久久 | 亚洲精品免费观看 | 色视频国产直接看 | 欧美在线a视频 | 激情欧美日韩一区二区 | 天天综合日 | 日韩欧美一区二区三区黑寡妇 | 久草网在线 | 国产成人av网 | 中文字幕在线视频国产 | 久久久黄色| 激情小说久久 | 六月丁香久久 | 国产四虎在线 | 在线午夜 | 日韩高清国产精品 | 久久黄色网页 | 婷婷在线看 | 久久精品99国产精品日本 | 97人人视频| 久久视频国产精品免费视频在线 | 成人av一二三区 | 国产一区麻豆 | 激情欧美国产 | 深爱激情亚洲 | 欧美精品一区二区在线观看 | 亚洲福利精品 | 久热久草 | 福利精品在线 | 91精品对白一区国产伦 | 在线黄色av| 中文字幕在线观看视频一区 | 国产成人在线一区 | www日韩视频| 韩国一区二区三区在线观看 | 夜夜操夜夜干 | 激情伊人五月天久久综合 | 国产视频18 | 亚洲精品国精品久久99热 | 成人app在线播放 | 国产精品久久久久国产精品日日 | 999超碰| 久久三级毛片 | 久久tv | av在线a | 国产精品一区二区久久国产 | 国产黄色大全 | 国产精品久久久久久久免费 | 91麻豆国产福利在线观看 | 国产成人亚洲在线观看 | 在线 欧美 日韩 | 色www精品视频在线观看 | 中文字幕日韩精品有码视频 | 国产中的精品av小宝探花 | 黄色午夜网站 | www色网站| 久久精品国产精品亚洲精品 | 久久精品波多野结衣 | 精产嫩模国品一二三区 | 91高清视频免费 | 91麻豆国产 | 日韩伦理一区二区三区av在线 | 亚洲国产精品视频在线观看 | 久久久久久激情 | 国产成人三级三级三级97 | 9999精品视频 | 亚洲永久国产精品 | 国产一区二区视频在线 | 天天色影院 | 中文字幕精 | 国产aa精品 | 亚洲欧美国产精品18p | 久久96国产精品久久99漫画 | 2018好看的中文在线观看 | 婷婷色综合网 | 久久精品毛片 | 免费网站在线观看人 | 国产精品免费观看国产网曝瓜 | 日韩在线观看 | 天天色天天射天天操 | 狠狠色免费 | av在线电影播放 | 久久综合五月天 | 中文字幕在线看视频国产中文版 | 日韩一区二区在线免费观看 | 欧美91av| 亚洲www天堂com | 玖玖在线看 | 99久久久久久 | 91探花在线视频 | 亚洲欧美国产日韩在线观看 | 免费进去里的视频 | 久久99国产综合精品免费 | 国产精品入口a级 | 成人国产一区 | 久久艹免费 | 在线观看亚洲成人 | 97天天综合网 | 欧美日韩国产精品一区二区三区 | 亚洲 欧美 日韩 综合 | 国产午夜精品av一区二区 | 成人久久视频 | 永久免费精品视频 | 国产精品黄网站在线观看 | 黄色精品在线看 | 成人性生交视频 | 中文字幕乱码在线播放 | 人人天天夜夜 | 国产一级大片在线观看 | 久久久久欧美精品999 | 国产精品理论在线观看 | 日韩高清 一区 | 国产破处在线视频 | 日韩系列在线 | 婷婷丁香视频 | 亚洲欧美怡红院 | 久久9精品 | 五月综合激情网 | 久久久久久久久久久福利 | 欧美精品一二 | 亚洲劲爆av| 毛片网站免费 | 黄色成人在线观看 | 久久理论电影网 | 免费观看不卡av | 又污又黄的网站 | 久久国产精品免费观看 | 天天操福利视频 | 中文字幕视频 | 在线视频欧美精品 | 97麻豆视频 | 蜜桃视频精品 | 六月丁香激情网 | 国产视频欧美视频 | 精品国产自 | 国语久久 | 久草在线视频首页 | 色的网站在线观看 | 五月综合激情婷婷 | 天天草天天操 | 国产又黄又爽又猛视频日本 | 丁香视频全集免费观看 | 国产亚洲精品久久久久久电影 | 国产精品久久久久久久午夜 | 亚洲 欧美日韩 国产 中文 | 射射色 | 国产麻豆精品久久 | 天天操综合 | 久久久久免费精品国产 | 免费av片在线 | 久久久久国产精品免费 | 91精品视频免费看 | 狠狠色丁香婷婷综合最新地址 | 午夜美女网站 | 99热最新在线 | 亚洲区视频在线观看 | 国产不卡精品视频 | 欧美激情xxxx性bbbb | 午夜精品久久久久久久99婷婷 | 国产精品久久久视频 | 五月婷色 | 国产一级特黄电影 | 国产精品福利在线观看 | 综合网伊人 | 美女禁18| 亚洲自拍偷拍色图 | 特级西西人体444是什么意思 | 美女视频a美女大全免费下载蜜臀 | 国产精品伦一区二区三区视频 | 婷婷色站 | 2019中文字幕第一页 | 99久久精品免费看国产一区二区三区 | 99精品国产兔费观看久久99 | 91精品夜夜| 97色在线| 免费男女网站 | 国产 一区二区三区 在线 | 91视频久久久久 | 欧美日韩在线免费观看 | 啪啪小视频网站 | 中文字幕视频一区二区 | 中文字幕亚洲情99在线 | 99精品欧美一区二区三区 | 久久久久亚洲精品中文字幕 | 国产高清视频在线播放 | 亚洲精品国偷拍自产在线观看蜜桃 | 色综合在 | 国产一区二区高清不卡 | 中文字幕一区二区三区精华液 | 日日干日日操 | 国产精品系列在线观看 | 欧美日韩后 | 日韩免费一区 | 911av视频 | 天天天天天天天天操 | 欧亚日韩精品一区二区在线 | 国产一级片视频 | 高清日韩一区二区 | 99色国产 | 麻豆国产视频 | www.黄色片网站| 久久av中文字幕片 | 在线视频日韩欧美 | 激情校园亚洲 | 一区二区三区中文字幕在线 | 色婷婷久久 | 日韩有码中文字幕在线 | 91大神dom调教在线观看 | 九九视频免费观看视频精品 | 国产精品白丝jk白祙 | 91视频久久久久 | 又粗又长又大又爽又黄少妇毛片 | 色.www | 精品福利网站 | 又长又大又黑又粗欧美 | 久久久精品国产一区二区电影四季 | 亚洲日本va午夜在线影院 | 婷婷伊人综合亚洲综合网 | 在线播放av网址 | 五月婷综合网 | 操碰av| 日韩免费视频观看 | 成人v| 欧美日韩视频网站 | 一区二区不卡视频在线观看 | 欧美日韩中文字幕视频 | www99久久 | 成人免费看电影 | 青青草视频精品 | av在线收看| 欧美一区二区精品在线 | 免费看的视频 | 婷婷综合国产 | 99久高清在线观看视频99精品热在线观看视频 | 免费毛片一区二区三区久久久 | 超碰在线公开免费 | 中文字幕在线日亚洲9 | 久久尤物电影视频在线观看 | 日韩av在线网站 | 97超视频 | 少妇精品久久久一区二区免费 | 波多野结衣精品视频 | 欧美成人a在线 | 欧美天天干| 国产打女人屁股调教97 | 免费观看视频黄 | 91激情视频在线观看 | 911国产在线观看 | 亚洲视频分类 | 国产精品久久久久久久久蜜臀 | 欧美日韩在线精品一区二区 | 日本 在线 视频 中文 有码 | 91精品国产高清自在线观看 | 婷婷中文字幕在线观看 | 久久国产精品免费视频 | 亚州人成在线播放 | 国产精品高清在线 | 久久免费看 | 国产黄色片一级三级 | 深爱婷婷激情 | 日韩免费av网址 | 91精品国产一区二区在线观看 | 国内精品久久影院 | 人人舔人人射 | 精品一区二区三区久久久 | 三级av在线 | 91午夜精品 | 亚洲国产偷 | 三级视频片 | 麻豆传媒视频在线免费观看 | 日本精品视频在线播放 | 国产精品久久在线观看 | 一级免费观看 | 草久电影 | 美女免费电影 | 婷婷av网站| 中文字幕文字幕一区二区 | 国产粉嫩在线观看 | 午夜电影久久 | 国产美女永久免费 | 特级西西444www大胆高清无视频 | 麻豆综合网| 精品一二三四五区 | 深爱激情久久 | 天天色草 | 草久久久久久 | 国内精品久久久久久中文字幕 | 91精品啪在线观看国产81旧版 | 人人干网站 | 久久视频在线观看 | 国产精品中文字幕av | 欧美一级黄色视屏 | www.午夜视频 | 在线观看视频日韩 | 日日干av| 国产91在线观看 | 91亚洲国产成人久久精品网站 | 色的网站在线观看 | 天天干夜夜爱 | 国产亚洲婷婷免费 | 日韩精品在线观看视频 | 成人免费xyz网站 | 久草资源在线 | 国产精品久久久 | 国产精品一区二区三区视频免费 | 亚洲丝袜一区二区 | 黄色一级大片在线免费看产 | 成人理论电影 | 国产又粗又长又硬免费视频 | 91社区国产高清 | 丁香狠狠 | 日韩欧美视频 | 久草在线这里只有精品 | 成人在线观看影院 | 成人一级片免费看 | 久草 | 国产视频18| 国产一区二区三区 在线 | 成人精品999 | av在线最新 | 国产精品久久久久久久久久三级 | 午夜美女wwww| 久久久精品国产免费观看同学 | 国产精品久久久久久久久婷婷 | 国产精品国内免费一区二区三区 | 一区二区久久 | 一区二区视频在线播放 | av色图天堂网 | 欧美日韩亚洲在线观看 | 午夜免费久久看 | 亚洲乱亚洲乱亚洲 | 欧美久久九九 | 91精品国产成人 | 日韩在线观看三区 | 婷婷新五月 | 夜夜躁日日躁狠狠久久88av | 麻豆一二 | 午夜精品一区二区三区可下载 | 久久不卡免费视频 | av专区在线 | 黄色一级影院 | 国产精品视频999 | 天天操天天射天天舔 | 日韩一区二区三区视频在线 | 91福利专区 | 日本不卡视频 | 麻豆成人精品视频 | 一级性视频 | 天天夜夜亚洲 | 91在线观看黄 | 国产69精品久久app免费版 | 国产一区国产二区在线观看 | 97**国产露脸精品国产 | 免费在线观看视频一区 | 人人爽人人爽 | 有码中文字幕在线观看 | 精品国产1区二区 | 四虎在线观看网址 | 精品亚洲免费 | 特级aaa毛片 | 九九热在线免费观看 | 久久久久久久久久久黄色 | 韩日三级在线 | 欧美精品资源 | 伊人亚洲精品 | 日韩网站一区二区 | 午夜在线免费观看视频 | 国产精品久久久久免费观看 | 久久一及片| 欧美久久综合 | 最新av在线播放 | 天天色天天骑天天射 | 69国产盗摄一区二区三区五区 | 国产精品久久久久高潮 | 欧美少妇xxx| 成人精品久久久 | 亚洲在线视频免费观看 | 911国产精品 | 又湿又紧又大又爽a视频国产 | 女人18毛片a级毛片一区二区 | 亚州国产精品 | 三三级黄色片之日韩 | 国产精品毛片一区二区 | 91视频91蝌蚪 | 亚洲视频第一页 | 91在线中字| 婷婷久操| 午夜精品一区二区三区在线观看 | 国产日韩欧美精品在线观看 | 国产综合婷婷 | 久久9999久久免费精品国产 | 999久久久精品视频 日韩高清www | 国产高清不卡 | 欧美特一级 | 91污污 | 精品国产aⅴ麻豆 | 亚洲一级免费电影 | 天天操天天干天天 | 免费在线中文字幕 | 丁香六月激情 | 午夜久久久久久久久久久 | 日本中出在线观看 | 91久久久久久国产精品 | 91精品国自产在线观看 | 色婷婷电影| 久热av| 狠狠色香婷婷久久亚洲精品 | 天天玩天天干天天操 | 国产精品视频区 | 国产成人99久久亚洲综合精品 | 国产一区欧美二区 | 波多野结衣亚洲一区二区 | 摸bbb搡bbb搡bbbb| 久久精品视频中文字幕 | 欧美精品在线一区二区 | 欧洲视频一区 | 国产色拍拍拍拍在线精品 | 最新在线你懂的 | 久久人人爽 | 亚洲三级在线 | 久久精品国产精品 | 欧美一级片免费在线观看 | 国内精品久久久久久久影视简单 | 精品国产乱码一区二区三区在线 | 国产又粗又长的视频 | 精品九九久久 | 国产精品理论在线观看 | 久久精品韩国 | 国产999精品久久久 免费a网站 | 国产精品自产拍在线观看网站 | 黄色1级大片 | 国产日韩精品久久 | 久精品视频在线观看 | 国产精品久久久久国产精品日日 | 播五月综合| 91污污视频在线观看 | 在线观看av小说 | 中文伊人 | 国产精品久久久久久久久免费看 | 99精品国产福利在线观看免费 | 日韩专区视频 | 亚洲综合五月 | 天天干中文字幕 | 成人毛片一区二区三区 | 亚洲精品美女久久17c | 五月婷婷在线视频观看 | 91看片淫黄大片在线播放 | 少妇bbb| 亚洲综合精品视频 | 国产96在线观看 | 91激情视频在线播放 | 麻豆国产视频下载 | 最近高清中文字幕在线国语5 | 成人在线播放网站 | 国产不卡在线播放 | 精品久久福利 | 四虎影视成人永久免费观看视频 | 天天操综 | 九色免费视频 | 免费aa大片 | 97成人精品区在线播放 | 欧美日韩精品综合 | 中文字幕4 | 欧美精品小视频 | 国产91精品在线观看 | www.人人草 | 中文字幕亚洲综合久久五月天色无吗'' | 一区二区三区在线看 | 久久dvd| 亚洲电影院 | 麻豆成人精品 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 国产91精品高清一区二区三区 | 国产精品美女999 | 国产男女免费完整视频 | 在线精品亚洲一区二区 | 狠狠操导航 | 色妞色视频一区二区三区四区 | 97人人澡人人添人人爽超碰 | 日韩av免费观看网站 | 国产精品中文字幕av | 欧美精品亚洲二区 | 午夜久久视频 | 91视频在线免费下载 | 午夜精品婷婷 | 久久免费高清 | 久久久国产精品久久久 | 国产亚洲精品v | 一区二区三区动漫 | 国产伦理久久精品久久久久_ | 久久午夜免费视频 | 91毛片在线观看 | 91高清不卡 | 三级av在线免费观看 | 精品成人久久 | 欧美激情综合色综合啪啪五月 | 国产高清免费观看 | 国产精品久久久久免费 | 亚洲视频 在线观看 | 五月丁色| 国产精品69久久久久 | 黄a在线看 | 午夜影院先| av三级在线免费观看 | 久久综合九色综合97_ 久久久 | 九色porny真实丨国产18 | 日韩在线视频免费播放 | 亚洲欧洲中文日韩久久av乱码 | 国产人成精品一区二区三 | 免费日韩 精品中文字幕视频在线 | 婷婷免费在线视频 | 国产视频导航 | 伊人天天狠天天添日日拍 | 天天做天天射 | 免费视频在线观看网站 | 五月天婷亚洲天综合网鲁鲁鲁 | 国产美女永久免费 | 国产视频1区2区 | 国产破处视频在线播放 | 婷婷久月 | 人人搞人人爽 | 国产成人精品免高潮在线观看 | 天天射天天操天天 | 国产黄色大全 | 中文视频在线播放 | 99人久久精品视频最新地址 | 五月天狠狠操 | 五月婷婷六月丁香激情 | 精品久久久久免费极品大片 | 日本精品久久久一区二区三区 | 亚州性色 | 一级国产视频 | 色婷婷综合视频在线观看 | 超碰免费成人 | 久久天堂影院 | 色噜噜在线观看视频 | 国产韩国日本高清视频 | 国产精品久久久久久妇 | 99久久激情视频 | 国产 亚洲 欧美 在线 | 在线观看91av | 中文字幕国产精品一区二区 | 国产精品久久久久永久免费 | 久久精品波多野结衣 | 久久天天躁夜夜躁狠狠85麻豆 | 麻豆传媒视频在线播放 | 五月亚洲综合 | 黄色免费电影网站 | 国产精品成人一区二区 | 久久免费公开视频 | 国产视频日韩视频欧美视频 | 成人久久亚洲 | 黄色国产区 | 美女久久 | 午夜视频在线网站 | 91亚洲国产 | 免费手机黄色网址 | 亚洲午夜久久久久久久久 | 蜜桃视频成人在线观看 | 日韩午夜高清 | 国产乱码精品一区二区蜜臀 | 久久99电影| 国产专区精品 | 欧美成人亚洲 | 91精品国产91 | 一区二区久久 | 韩国av一区二区三区在线观看 | 在线视频 区 | 啪啪小视频网站 | 91黄在线看 | 国产美女网站在线观看 | 99久久久国产精品免费99 | 99久久久国产精品免费99 | 中文字幕在线视频第一页 | 欧美日韩伦理在线 | 国产手机视频在线 | 手机版av在线| 99r精品视频在线观看 | 又黄又爽又刺激的视频 | 国内精品久久久久影院一蜜桃 | 欧美日韩精品在线观看 | 国产 亚洲 欧美 在线 | 国产精品福利av | 四虎影视国产精品免费久久 | 国偷自产中文字幕亚洲手机在线 | 综合色伊人 | 国产黄色一级大片 | 婷婷中文字幕在线观看 | 国产a高清 | 久久一线 | 精品视频国产 | 激情小说网站亚洲综合网 | 99 色 | 天天草天天干天天射 | 亚洲jizzjizz日本少妇 | 在线免费观看视频 | 又色又爽又激情的59视频 | 国产福利91精品一区 | 久久久久久激情 | 日韩一区二区三区高清在线观看 | 国产中文字幕亚洲 | av一级在线| 手机成人免费视频 | 在线免费观看一区二区三区 | 少妇精品久久久一区二区免费 | 91精品国产三级a在线观看 | 在线三级播放 | 91视频午夜 | 国产天天爽 | 日韩欧美国产视频 | 91在线porny国产在线看 | 欧美日本高清视频 | 欧美视频99 | av久久在线 | 国产精品一区二区久久精品 | 久久久久日本精品一区二区三区 | 韩国av一区二区三区在线观看 | 国产一级淫片在线观看 | 婷婷激情欧美 | 久久九九国产精品 | 日本电影黄色 | 99免费看片 | 欧美性生交大片免网 | 久久久久 | 久久久精品在线观看 | 国产精品 中文字幕 亚洲 欧美 | 五月天久久综合网 | 99精品免费观看 | 97精产国品一二三产区在线 | 偷拍福利视频一区二区三区 | 欧美一级久久久久 | 一级片黄色片网站 | 亚洲精品在线观看网站 | 91在线你懂的 | 国产精久久久 | 波多野结衣日韩 | 一区二区三区免费在线观看视频 | 黄色成人av网址 | 麻豆传媒在线免费看 | www.色的| 久久99久久99免费视频 | 十八岁以下禁止观看的1000个网站 | 精品国精品自拍自在线 | 欧美一级免费高清 | 亚洲国产成人精品久久 | 一级α片 | 亚洲美女精品视频 | 夜夜操夜夜干 | 日韩中文字幕视频在线观看 | 成人免费共享视频 | 亚洲国产伊人 | 国产精品福利在线观看 | 精品久久1 | 国产成人61精品免费看片 | 在线观看亚洲视频 | 精品国产观看 | 麻豆精品在线视频 | 亚洲综合色丁香婷婷六月图片 | 久久精品视频播放 | 久久久久久电影 | 欧美另类69 | 成人av亚洲 | 亚洲黄色区 | 精品视频免费久久久看 | 天天操天天干天天摸 | 在线看黄色的网站 | 色婷婷免费|