Devops概念
**本人博客網站 **IT小神 www.itxiaoshen.com
引用百度原話
DevOps(Development和Operations的組合詞)是一組過程、方法與系統的統稱,用於促進開發(應用程序/軟件工程)、技術運營和質量保障(QA)部門之間的溝通、協作與整合。
它是一種重視“軟件開發人員(Dev)”和“IT運維技術人員(Ops)”之間溝通合作的文化、運動或慣例。透過自動化“軟件交付”和“架構變更”的流程,來使得構建、測試、發布軟件能夠更加地快捷、頻繁和可靠。
從字面上來看,“DevOps”一詞是由英文 Development(開發)和 Operations (運維)組合而成,但它所代表的理念和實踐要比這廣闊的多。DevOps 涵蓋了安全、協作方式、數據分析等許多方面。
DevOps 強調通過一系列手段來實現既快又穩的工作流程,使每個想法(比如一個新的軟件功能,一個功能增強請求或者一個 bug 修復)在從開發到生產環境部署的整個流程中,都能不斷地為用戶帶來價值。這種方式需要開發團隊和運維團隊密切交流、高效協作並且彼此體諒。此外,DevOps 還要能夠方便擴展,靈活部署。有了 DevOps,需求最迫切的工作就能通過自助服務和自動化得到解決;通常在標准開發環境編寫代碼的開發人員也可與 IT 運維人員緊密合作,加速軟件的構建、測試和發布,同時保障開發成果的穩定可靠。
下面我們先從幾張圖大概了解Devops及常用工具集
主體流程

常用CICD工具集

核心生態圈

CICD示例
需求
構建一個基於容器化的CICD,提交源碼則后自動觸發構建、打包、測試、部署到單個應用服務器docker宿主機容器中運行,目前是單個docker運行環境,后續可改為docker swarm或者K8S集群容器環境
運維架構

部署規划
三台主機或虛擬機 CentOS 7.8以上版本
- 192.168.50.94(用途:倉庫服務器;)
- GitLab:Git Server 內網私有部署,和GitHub、Gitee都屬於Git Server,作為代碼倉庫
- Nexus:本地倉庫服務器,maven私有倉庫,可做內網私服和倉庫代理服務器
- Harbor: docker私有倉庫,存放和管理docker鏡像
- docker: 應用安裝基於docker環境組件,如GitLab
- 192.168.50.95 (用途:Jenkins中心服務器)
- Jenkins:CICD核心組件
- docker:用於本地編譯Dockerfile生成docker鏡像文件
- maven: 用於在本地構建、編譯和打包
- 192.168.3.117 (應用服務器:運行docker鏡像)
- docker: 用於本地運行docker容器
部署步驟
安裝docker環境
[docker安裝官網地址](https://docs.docker.com/engine/install/centos/)
詳細請參考官網,官網有非常詳細安裝說明,此外還需要安裝docker-compose,docker-compose安裝非常簡單,直接拷貝到系統的/usr/local/bin並sudo chmod +x /usr/local/bin/docker-compose賦予執行文件權限即可,docker-compose可執行文件存在GitHub中;后續我們再組織專門學習討論docker和k8s,這里只是需要使用到docker

兩台主機都安裝完畢后檢查下版本,如有如下顯示就可以使用docker了

安裝Harbor
選擇下載離線包最新版本安裝

直接解壓進入根目錄,官網已經提供docker-compose方式,直接docker-compose up -d運行即可

查看docker容器狀態,Harbor暴露提供端口是80,所以直接訪問http://192.168.50.94即可

默認賬號:admin 密碼:Harbor12345
我們新建一個jenkins項目


進入后可以新建賬號,我這里新建一個harbor賬號,密碼為Harbor123,用於后續CICD示例測試
安裝Nexus
Nexus官網 https://www.sonatype.com
需要注冊賬號下載,Nexus主要存儲maven 倉庫,可以將我們企業內部開發jar公用模塊在Nexus中管理,也可以將其作為代理方式統一管理
下載nexus-3.32.0-03-unix.tar.gz,直接解壓到/usr/local目錄下,然后進入到bin目錄下直接用 ./nexus start啟動即可


默認端口為8081,訪問http://192.168.50.94:8081 默認系統用戶名:admin,密碼:admin123,不過后面的CICD示例暫且還沒有使用到Nexus

安裝Jenkins
Jenkins官網下載地址 https://www.jenkins.io/download/
我們這里選擇generic java package .war包下載,最新版本2.306的jenkins.war,以war形式安裝
下載Tomcat8的安裝包,將jenkins.war包放在Tomcat的webapps目錄,我這里主要為了訪問是不加目錄,所以解壓完后我先關閉Tomcat,刪除jenkins.war 和重命名ROOT目錄為ROOTBAK,最后將解壓后的jenkins目錄重命名為ROOT,重新./startup.sh 啟動Tomcat ,使用默認端口8080

jenkins訪問地址:http://192.168.50.95:8080
查看tomcat logs目錄下的catalina.out 運行日志,jenkins初始化一個管理員密碼用於初始化系統驗證,驗證完畢后可以進入安裝插件頁面



如果無法使用或者需要重置密碼先找到工作目錄,一般都在/root/.jenkins,如果指定過jenkins的目錄的話,使用命令行查找JENKINS_HOME環境變量
進入jenkins工作目錄,找到config.xml配置文件
jenkins初始配置
進入首頁后通過左側的系統管理-插件管理,切換到高級設置tab框
將URL升級站點修改為國內地址:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
檢查並安裝必要插件,包括git、maven、jdk等,這次示例還用到pipe line流水線插件,jenkins強大的地方就是有很多第三方插件簡單安裝就可直接使用。so easy ;jenkins比較重要使用是參數化構建和pipeline流水線功能,但本篇文章不對jenkins使用做過多的描述,僅是示例入門
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DCYprSJx-1628783084242)(http://www.itxiaoshen.com:3001/assets/1628765111753GkteHEtc.png)]
jenkins依賴其他配置
安裝jenkins的服務器,我們也在其本地安裝好Jdk和Maven,由於我們需要與Harbor服務器進行交互,還需增加如下的配置,配置insecure-registries為192.168.50.94為Harbor服務器地址,我們這里由於簡單演示則采用http協議和IP地址,在所有安裝docker且需要和Harbor服務器做通訊都加上下面的配置,包括192.168.3.117和192.168.50.95都要配置
[root@k8s-master-2 bin]# vi /etc/docker/daemon.json
{
"insecure-registries":["192.168.50.94"]
}

安裝GitLab
GitLaba安裝官方地址 https://about.gitlab.com/install/
官方提供很多部署方式,這里我們選擇docker部署,進入docker安裝說明頁面
https://docs.gitlab.com/ee/install/docker.html

我們直接采用docker-compose部署方式,建立一個docker-compose.yml文件,內容如下,這里我們先設置好GITLAB_HOME環境變量路徑,
export GITLAB_HOME=/home/docker_resource/gitlabdata
web:
image: 'gitlab/gitlab-ce:latest'
restart: always
hostname: 'k8s-master-2'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://192.168.50.94'
# Add any other gitlab.rb configuration here, each on its own line
ports:
- '3380:80'
- '33443:443'
- '3322:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'

配置完后直接在docker-compose.yml所在目錄下使用docker-compose up -d后台啟動,查看docker 運行容器

訪問端口為3380,訪問地址為http://192.168.50.94:3380,初次訪問后直接輸入初始化root用戶密碼並登錄
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-RI5Ee3ud-1628783084249)(http://www.itxiaoshen.com:3001/assets/1628753333325S2tRkTKc.png)]
創建一個空的項git-test
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YWtKWT1Q-1628783084251)(http://www.itxiaoshen.com:3001/assets/16287571527517EtnSZb6.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wMywcGpT-1628783084253)(http://www.itxiaoshen.com:3001/assets/1628763846454TcBha64n.png)]
我們這里選擇Intellij IDEA作為開發工具,在windows安裝git客戶端(Git-2.32.0.2-64-bit.exe,如果直接使用git客戶端還需要熟悉幾個簡單常用的git命令),IDEA Setting中安裝GitLab集成插件,在Idea配置git項目地址就可以操作git了

在IDEA的File-Settings-Version Control Git中配置上面已安裝windows git客戶端可執行文件地址

示例構建
上面我們已經基本環境准備完畢,接下來我們開始構建一個hello world 的SpringBoot Web工程測試
流程簡單說明
- Jenkins 建立流水線任務,配置web hook觸發器、編寫流水線腳本
- GitLab建立項目和提供訪問、操作權限,配置項目的jenkins web hook回調地址
- Harbor建立用戶、項目和提供訪問、操作權限
- 在Windows個人電腦開發環境建立Java語言的Maven項目,配置GitLab項目地址,完成代碼編寫和Dockerfile,通過IDEA提交本地git后push遠程GitLab
- Gitlab收到提交操作完成后觸發jenkin web hook觸發jenkins 流水線任務構建;
- jenkins所在服務器通過先從GitLab 獲取項目源碼,拿到源碼進行maven編譯、測試、構建和打包;
- jenkins所在服務器打包完成后再執行docker編譯制作成docker鏡像並登錄和推送鏡像到Harbor遠程倉庫;
- jenkins所在服務器登錄應用服務器,登錄Harbor遠程倉庫並拉取指定鏡像到本地docker並運行容器提供暴露端口服務
准備源碼
IDEA 新建git-test的maven工程項目,設置gitlab項目地址,這個git項目地址我們在上一章節已創建好


pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.aotain</groupId>
<artifactId>git-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>git-test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<slf4j-springboot.version>1.4.6</slf4j-springboot.version>
<lombok.version>1.18.20</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>wiki.xsx</groupId>
<artifactId>slf4j-spring-boot-starter</artifactId>
<version>${slf4j-springboot.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
啟動類
package cn.aotain;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GitTestApplication {
public static void main(String[] args) {
SpringApplication.run(GitTestApplication.class, args);
}
}
controller測試類
package cn.aotain.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import wiki.xsx.core.log.Log;
import wiki.xsx.core.log.ResultLog;
import java.util.HashMap;
import java.util.Map;
@RestController
public class HelloController {
@RequestMapping("/hello")
@Log(value = "gettaskbydev", paramFilter = {"request"})
@ResultLog(value = "ResultLog-test2")
public Map<String, Object> Hello(){
Map<String, Object> result = new HashMap<>(3);
result.put("code", 200);
result.put("msg", "success");
return result;
}
}
編寫DockerFile文件
FROM java:8
MAINTAINER itxiaoshen
COPY target/*.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
GitLab更新測試
修改result對象中msg值,先執行commit提交到本地git操作 然后再執行push操作提交到遠程GitLab項目倉庫

查看GitLab項目上內容確認已提交

Jenkins 流水線任務配置
新建一個流水線的任務,輸入名稱、選擇流水線、點擊確定按鈕,我們這里暫時只演示流水線,暫時不使用參數化構建功能
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-C9s2DucC-1628783084262)(http://www.itxiaoshen.com:3001/assets/1628767700284apa76HRS.png)]
點擊進入剛剛創建的git-test任務的管理頁面,左邊菜單欄有流水線語法幫助,比如git check out操作可以輸入自動生成,逐漸熟悉一些常用語法,點擊配置功能
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-f47QDuCu-1628783084263)(http://www.itxiaoshen.com:3001/assets/16287657297564CsTWzck.png)]
配置觸發器為web hook(構建時機可以有很多種比如像定時觸發),這里有一個說明提示http://JENKINS_URL/generic-webhook-trigger/invoke ,將JENKINS_URL替換為我們jenkins服務器web地址,我們這里也即是 http://192.168.50.95:8080/generic-webhook-trigger/invoke

在GitLab的git-test項目管理頁面Settings-Webhooks中將上面url地址加上配置Token參數 http://192.168.50.95:8080/generic-webhook-trigger/invoke?token=gittest123456 添加進去,至此GitLab的git-test如果發生提交操作就會調用jenkins webhook鈎子接口實現自動觸發構建機制

接下來到了最關鍵的環節,CICD核心也即是編寫流水線腳本,編寫完腳本放置到高級項目選項的流水線中

下面是一段簡單pipeline流水線腳本,核心部署是git源碼拉取-編譯-打包推送docker鏡像到docker倉庫-登錄應用服務器並從docker倉庫獲取鏡像部署到本地docker環境並運行容器,容器應用暴露外部訪問端口18080
pipeline {
agent any
stages {
// 拉取代碼 git從git倉庫中拉取代碼,采用的是免交互方式 checkout如何產生?參考 Docker:pipeline編寫基本技巧- jenkins配置通過密鑰拉取git源碼管理倉庫的代碼
stage('Git Checkout') {
steps {
checkout([$class: 'GitSCM', branches: [[name: 'master']], extensions: [], userRemoteConfigs: [[url: 'http://192.168.50.94:3380/root/git-test.git']]])
}
}
// 代碼編譯
stage('Maven Build') {
steps {
sh '''
export JAVA_HOME=/home/commons/jdk8
cd git-test
/home/commons/apache-maven-3.6.3/bin/mvn clean package -Dmaven.test.skip=true
'''
}
}
// 項目打包到鏡像並推送到鏡像倉庫
stage('Build and Push Image') {
steps {
sh '''
cd git-test
REPOSITORY=192.168.50.94/jenkins/git-test-demo
docker build -t $REPOSITORY .
docker login 192.168.50.94 -u harbor -p Harbor123
docker push $REPOSITORY
'''
}
}
// 部署到Docker主機
stage ('Docker run') {
agent none
steps {
script {
def remote = [:]
remote.name = 'application-server'
remote.host ='192.168.3.117'
remote.user = '******'
remote.password ='*********'
remote.allowAnyHosts= true
sshCommand remote: remote, command:
'''
REPOSITORY=192.168.50.94/jenkins/git-test-demo
docker rm -f git-test-demo |true
docker pull $REPOSITORY
docker container run -d --name git-test-demo -p 18080:8080 $REPOSITORY
'''
}
}
}
}
}
先手工點擊立即構建進行手工構建測試,構建分階段執行運行完畢后如下

訪問Spring Boot的HelloWorld應用服務器部署地址:http://192.168.3.117:18080/hello,成功顯示頁面

接下來我們直接修改源碼將result對象中msg值修改為后綴222222,push提交GitLab執行自動觸發構建測試

從jenkins構建歷史數據看已出現一個新的成功構建記錄#4

重新訪問測試頁面顯示為修改的數據

查看應用服務器上docker容器也有我們git-test-demo

