DevOps概述¶
一. DevOps介绍¶
1. 背景¶
软件开发最开始是由两个团队组成
- 开发计划由开发团队从头开始设计和整体系统的构建。需要系统不停的迭代更新
- 运维团队将开发团队的Code进行测试后部署上线,希望系统稳定安全的运行
在这过程中开发团队制定好计划并完成coding后,需要提供给运维团队。同样,运维团队将也会向开发团队反馈需要修复的bug以及一些需要返工的任务。如果这时候开发团队等待运维团队的反馈就会延长时间,导致推迟了整个软件开发的周期
为了保证更敏捷是的开发,就需要把开发和运维整合到同一个团队,这就是DevOps
DevOps,字面意思就是 Develoment&Operations 的缩写,也就是开发&运维。
核心就在于简化开发和运维团队之间的流程,使得整体的软件开发过程更快速
2. 整体的软件开发流程包括¶
- PLAN: 开发团队根据客户的需求制定开发计划
- CODE: 根据PLAN开始编码过程,需要将不同版本的代码存储在同一个库中
- BUILD: 编码完成后,需要将代码构建并运行
- TEST: 成功构建项目后,需要测试代码是否存在BUG或其他错误
- DEPLOY: 代码警告手动测试和自动化测试后,认定代码以及准备好部署并且交给运维团队
- OPERATE: 运维团队将代码部署到生产环境中
- MONITOR: 项目部署上线以后,需要持续监控的产品
- INTEGRATE: 最好将监控阶段收到的反馈发送回PLAN阶段,整体反复的留着就是DevOps的核心。即持续集成,持续部署。
3. DevOps的最终定义¶
DevOps强调的是高校组织团队之间如何通过自动化工具协作和沟通来完成软件的声明周期管理,从而更快更频繁的交付更稳定的软件
二. GitOps平台部署计划¶
| 主机名 | IP地址 | 安装服务名 | 对应阶段 |
|---|---|---|---|
| 1 | 192.168.100.99 | git,docker,gitlab | CODE |
| 2 | 192.168.100.100 | docker,maven,jenkins | BUILD/INTEGRATE |
| 3 | 192.168.100.101 | docker,sonarqube | OPERATE |
三. Code阶段工具¶
在code阶段,我们需要将不同版本的代码存储到一个仓库中,场景的版本控制工具就是SVN或者Git,这里我们采用Git作为版本控制工具,GitLab作为远程仓库。
一般开发人员和jenkins需要使用git作为版本控制工具,开发人员使用git作为客户端工具进行拉取码,jenkins可以通过安装git插件来实现从远处仓库拉取代码
我们在1上部署Code阶段工具
1. Git安装¶
直接使用命令 dnf -y install git 安装git
2. GitLab安装¶
单独准备服务器,采用docker容器部署GitLab
前提是先部署好docker环境和docker compose
1) 安装docker¶
这里我们可以参考 docker安装文档就不多说了。同时其他几台服务器也都需要安装docker,我们这里就一起安装了
[root@my-project dockerinstall]# ansible -m command -a "docker --version" "K8s*"
3 | CHANGED | rc=0 >>
Docker version 29.7.2, build a7dcaa6
2 | CHANGED | rc=0 >>
Docker version 29.7.2, build a7dcaa6
1 | CHANGED | rc=0 >>
Docker version 29.7.2, build a7dcaa6
2) 安装GitLab¶
a. 如果我们没有gitlab的镜像可以手动拉取
或者将已有的镜像导入
b. 创建目录
c. 准备docker-compose.yaml文件
在/usr/local/docker/gitlab-docker下创建docker-compose.yaml文件
version: '3.1'
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
container_name: gitlab
restart: always
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://192.168.100.99:8929'
gitlab _rails['gigtlab_shell_ssh_port'] = 2224
ports:
- '8929:8929'
- '2224:2224'
volumes:
- './config:/etc/gitlab'
- './logs:/var/log/gitlab'
- './data:/var/opt/gitlab'
这其中要挂载的目录中/etc/gitalbyongyucunchugitlab的配置文件,/var/log/gitlab用于存储日志,/var/opt/gitlab用于存储应用数据
# 启动容器
[root@K8s1 gitlab-docker]# docker compose up -d
WARN[0000] /usr/local/docker/gitlab-docker/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] up 2/2
✔ Network gitlab-docker_default Created 0.0s
✔ Container gitlab Started
# 查看gitlab
[root@K8s1 gitlab-docker]# docker compose logs -f
...
然后我们就可以访问gitlab了
3) 配置gitlab¶
a. 浏览器输入http://192.168.100.99:8929访问GitLab首页

b. 在终端中查看root用户初始密码
[root@K8s1 gitlab-docker]# docker exec -it gitlab cat /etc/gitlab/initial_root_password
...
Password: FRhgz3OTAy75mDKN+akgryhrJ25I/cpo5nqXOX4kiiw=
c. 首次以root身份登录进行配置

d. 然后修改登陆密码


都搞定后gitlab就可以像Gitee,GitHub一样使用了
四. build阶段工具¶
再单独准备一台服务器K8s2。我们此处使用Maven作为项目的编译工具,并安装Jenkins
具体的maven安装流程可以参考这里我们可以参考 Docker镜像仓库就不多说了。
a. 我本地有就直接解压了
ansible -m unarchive -a 'src=/root/DevOps/2026_08_24_GitOps/jdk-8u333-linux-x64.tar.gz dest=/usr/local/ remote_src=no' "2"
ansible -m unarchive -a 'src=/root/DevOps/2026_08_24_GitOps/apache-maven-3.8.5.tgz dest=/usr/local/ remote_src=no' "2"
因为不需要在宿主机做java的编译操作,这里就不再宿主机做jdk环境变量设置了,jenkins是需要jdk和maven环境。我们把jenkins放在容器里面运行,到时候直接通过数据卷映射到容器就可以了
b. 设置maven
settings.xml 是 Maven 的配置文件,这里主要改动两处:
改动一:添加阿里云镜像(<mirrors> 标签内)
Maven 默认从国外官网下载 jar 包很慢,加一个阿里云镜像来加速下载。
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
| 字段 | 含义 |
|---|---|
id |
镜像的唯一标识(自定义) |
mirrorOf |
* 表示所有仓库的下载请求都走这个镜像 |
name |
镜像显示名称 |
url |
阿里云仓库地址 |
改动二:设置 JDK 1.8 编译版本(<profiles> 标签内)
保证不管宿主机装了几个 JDK,编译时统一用 JDK 1.8。
<profile>
<id>jdk18</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
再在 <activeProfiles> 标签中启用(使上面的配置默认生效):
⚠️ 注意:
<mirrors>里原本有一个maven-default-http-blocker镜像,作用是屏蔽不安全的 HTTP 仓库,这个保留不用动,只新增aliyunmaven即可。<profiles>注释里的示例内容也不用动。
至此,JDK和maven就都就绪了。后面Jenkins容器会用到,我们直接把它挂载到Jenkins容器数据卷即可。
五. Operate阶段工具¶
部署过程会采用docker进行部署,暂时只安装docker即可,后续会用到K8s。我们之前已经在所有主机上都一起部署了docker,这里就先跳过
六. Integrate工具¶
1. Jenkins介绍¶
Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具
Jenkins应用广泛,大多数互联网公司都会采用Jenkins配合GitLab、Docker、K8s作为实现DevOps的核心工具。
Jenkins的强大在于其插件,这些插件保证了自动化CI/CD过程中的繁杂功能
Jenkins最主要的工作就是将GitLab上可以构建的工程代码拉取并进行构建,再根据流程可以选择发布到测试环境或者是生产环境
一般是GitLab上进行的代码进行大量测试后确定发行版本,再发布到生产环境。
CI/CD可以理解为:
- CI过程即使通过Jenkins将代码拉取、构建、制作镜像交给测试人员测试
-
- 持续集成: 让软件代码可以持续集成到主干上,并自动构建测试
- CD过程即是通过Jenkins将打好标签的发行版本代码拉取、构建、制作镜像交给运维人员部署
-
- 持续交付: 让经过持续集成的代码可以进行手动部署
-
- 持续部署: 让可以持续交付的代码随时随地的自动化部署
2. Jenkins安装¶
1) 拉取镜像¶
此处我们在2上直接拉取Jenkins的镜像使用命令docker pull jenkins/jenkins
或者如果本地有镜像直接导入
2) 创建目录,并编写docker-compose.yaml文件¶
version: "3.1"
services:
jenkins:
image: jenkins/jenkins
container_name: jenkins
ports:
- 8080:8080
- 50000:50000
volumes:
- ./data/:/var/jenkins_home/
3) 启动容器¶
注意: 首次启动我们可能会因为数据卷data目录没有权限二导致启动失败,这时候我们就需要设置data目录写入权限
# 赋权
chmod -R a+w /usr/local/docker/jenkins_docker/data
# 重启
docker compose -f /usr/local/docker/jenkins_docker/docker-compose.yaml restart
4) 配置加速¶
由于Jenkins需要下载大量内容,但是默认下载地址的下载速度较慢,这里可以设置为国内镜像站。
步骤一:修改更新源配置文件,如下:
进入 Jenkins 容器数据卷中的 hudson.model.UpdateCenter.xml 文件:
原来的默认地址(国外,下载慢):
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://updates.jenkins.io/update-center.json</url>
</site>
</sites>
将其中的 <url> 改为官方可用的更新源地址(国内镜像站不提供 update-center.json 索引文件,实测会返回 404):
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://updates.jenkins.io/update-center.json</url>
</site>
</sites>
步骤二:重启 Jenkins 使配置生效,如下:
然后浏览器访问 Jenkins,就能正常下载插件了。
⚠️ 重要提示(实测验证):
国内镜像站(清华
mirrors.tuna.tsinghua.edu.cn、华为云mirrors.huaweicloud.com)只提供插件二进制文件(plugins/、war/等目录),不提供updates/update-center.json这个更新索引文件,访问会返回 404。配置成清华源
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json会导致 Jenkins 连不上更新中心,页面上显示"离线"。
update-center.json这个索引文件只有官方源https://updates.jenkins.io/update-center.json提供,它是通的(会 301 跳转到最新路径,属正常)。
3. 浏览器中配置Jenkins¶
浏览器中输入http://192.168.100.100:8080进入Jenkins界面进行配置

这时候就要回到终端,查看密码
[root@K8s2 jenkins_docker]# docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
ef6c4e0a965b45d4a952e5d727b95777
重启返回浏览器,将得到的密码输入到对应位置


我这里本地有插件就先跳过了,一会初始化完成后再一次性导入插件。
然后创建用户如图


4. 下载插件¶
a. 就直接从本地导入了
b. 查看确认插件内容出来了
[root@K8s2 data]# ls /usr/local/docker/jenkins_docker/data/plugins
ant github-api.jpi localization-support resource-disposer.jpi
antisamy-markup-formatter github-branch-source localization-support.jpi scm-api
antisamy-markup-formatter.jpi github-branch-source.jpi localization-zh-cn scm-api.jpi
ant.jpi github.jpi localization-zh-cn.jpi script-security
apache-httpcomponents-client-4-api git.jpi mailer script-security.jpi
apache-httpcomponents-client-4-api.jpi git-parameter mailer.jpi snakeyaml-api
asm-api git-parameter.jpi matrix-auth snakeyaml-api.jpi
asm-api.jpi gradle matrix-auth.jpi snakeyaml-engine-api
bootstrap5-api gradle.jpi matrix-project snakeyaml-engine-api.jpi
bootstrap5-api.jpi gson-api matrix-project.jpi ssh-credentials
bouncycastle-api gson-api.jpi mina-sshd-api-common ssh-credentials.jpi
bouncycastle-api.jpi instance-identity mina-sshd-api-common.jpi ssh-slaves
branch-api instance-identity.jpi mina-sshd-api-core ssh-slaves.jpi
branch-api.jpi ionicons-api mina-sshd-api-core.jpi structs
build-timeout ionicons-api.jpi okhttp-api structs.jpi
build-timeout.jpi jackson2-api okhttp-api.jpi theme-manager
caffeine-api jackson2-api.jpi pipeline-build-step theme-manager.jpi
caffeine-api.jpi jackson3-api pipeline-build-step.jpi timestamper
checks-api jackson3-api.jpi pipeline-github-lib timestamper.jpi
checks-api.jpi jackson-annotations2-api pipeline-github-lib.jpi token-macro
cloudbees-folder jackson-annotations2-api.jpi pipeline-graph-view token-macro.jpi
cloudbees-folder.jpi jakarta-activation-api pipeline-graph-view.jpi trilead-api
commons-lang3-api jakarta-activation-api.jpi pipeline-groovy-lib trilead-api.jpi
commons-lang3-api.jpi jakarta-mail-api pipeline-groovy-lib.jpi variant
commons-text-api jakarta-mail-api.jpi pipeline-input-step variant.jpi
commons-text-api.jpi jakarta-xml-bind-api pipeline-input-step.jpi woodstox-core-api
credentials jakarta-xml-bind-api.jpi pipeline-milestone-step woodstox-core-api.jpi
credentials-binding javax-activation-api pipeline-milestone-step.jpi workflow-aggregator
credentials-binding.jpi javax-activation-api.jpi pipeline-model-api workflow-aggregator.jpi
credentials.jpi jaxb pipeline-model-api.jpi workflow-api
dark-theme jaxb.jpi pipeline-model-definition workflow-api.jpi
dark-theme.jpi jjwt-api pipeline-model-definition.jpi workflow-basic-steps
display-url-api jjwt-api.jpi pipeline-model-extensions workflow-basic-steps.jpi
display-url-api.jpi joda-time-api pipeline-model-extensions.jpi workflow-cps
durable-task joda-time-api.jpi pipeline-stage-step workflow-cps.jpi
durable-task.jpi jquery3-api pipeline-stage-step.jpi workflow-durable-task-step
echarts-api jquery3-api.jpi pipeline-stage-tags-metadata workflow-durable-task-step.jpi
echarts-api.jpi jsch pipeline-stage-tags-metadata.jpi workflow-job
eddsa-api jsch.jpi plain-credentials workflow-job.jpi
eddsa-api.jpi json-api plain-credentials.jpi workflow-multibranch
email-ext json-api.jpi plugin-util-api workflow-multibranch.jpi
email-ext.jpi json-path-api plugin-util-api.jpi workflow-scm-step
font-awesome-api json-path-api.jpi prism-api workflow-scm-step.jpi
font-awesome-api.jpi jsoup prism-api.jpi workflow-step-api
git jsoup.jpi publish-over workflow-step-api.jpi
git-client junit publish-over.jpi workflow-support
git-client.jpi junit.jpi publish-over-ssh workflow-support.jpi
github ldap publish-over-ssh.jpi ws-cleanup
github-api ldap.jpi resource-disposer ws-cleanup.jpi
c. 导入后重启Jenkins
5. Jenkins入门配置¶
由于Jenkins需要从Git拉取代码(需要安装git parameter插件)、需要本地构建(需要maaven、jdk,可以将之前部署在宿主机的maven、jdk放到jenkins容器的数据卷中)、甚至需要直接发布自定义镜像到Docker仓库(需要安装publish over ssh插件),所以jenkins需要做一些配置
准备好GitLab仓库的项目,并且通过Kenkins配置项实现当前项目DevOps的基本流程
1) 构建Maven工程发布到GitLab¶
a. 先创建仓库



b. 登录
c. 初始化仓库,后将提前准备好的代码提交
d. 关联远程仓库,后推送
⚠️ 注意(重要):GitLab 创建项目时,即使没勾选 README,也会默认生成一个 main 分支(初始提交)。而本地 git init 生成的是 master 分支。两者历史不相关,直接推 main 会报 fetch first 或 --force 被拒(main 是 GitLab 的保护分支,禁止强推)。
因此正确的做法是:先 pull 合并两条历史,再推送。
第一步:关联远程仓库,并设置好 pull 合并策略
git remote add origin http://192.168.100.99:8929/root/test.git
git config --global pull.rebase false # 让 git pull 默认用 merge 合并
第二步:拉取远程 main,允许两条不相关历史合并
git pull origin main --allow-unrelated-histories
# 如果提示"需要指定如何调和偏离的分支",是 pull.rebase 未设置为 false,执行上面那条配置后重试
# 输出类似: Merge made by the 'ort' strategy. README.md | 93 +++ 表示合并成功
第三步:推送到远程 main
成功输出类似:
[root@K8s1 mytest-hello]# git remote add origin http://192.168.100.99:8929/root/test.git
[root@K8s1 mytest-hello]# git push -u origin main
Username for 'http://192.168.100.99:8929': root
Password for 'http://root@192.168.100.99:8929':
枚举对象中: 20, 完成.
对象计数中: 100% (20/20), 完成.
使用 2 个线程进行压缩
压缩对象中: 100% (14/14), 完成.
写入对象中: 100% (19/19), 3.02 KiB | 619.00 KiB/s, 完成.
总共 19(差异 1),复用 0(差异 0),包复用 0(来自 0 个包)
To http://192.168.100.99:8929/root/test.git
e57ff74..99507cb main -> main
分支 'main' 设置为跟踪 'origin/main'。
e. 到gitlab上查看验证

## 💡 避坑复盘(重要经验)
本次推送踩到的坑,核心原因和解决办法如下:
| 现象 | 根本原因 | 正确做法 |
|---|---|---|
| 代码在 Branches 里能看到,但主页看不到 | GitLab 主页显示默认分支 main(空),你的代码在 master |
统一分支名,让代码推到默认分支 |
git push --force 被拒 |
GitLab 把默认分支设为保护分支,禁止强推覆盖 | 不要用 --force,改用合并历史的方式 |
删了 master 还是推不上 |
删 master 与 main 是否被保护无关 |
处理 main 本体,不是删别的分支 |
| 最后还是推上去了 | git pull --allow-unrelated-histories 把两条历史合并成一个提价,push 变成正常快进,保护分支放行 |
远程已有初始提交时,先 pull 合并再 push |
一句话总结:远程 main 是保护分支,禁强推;解决"历史不相关"问题用 pull --allow-unrelated-histories 合并,而不是用 --force 对抗保护机制。
至此,一个maven工程就成功推送到gitlab上了
2) Jenkins新建任务¶
点击左侧导航




3) Jenkins立即构建¶



可以看到源码已经拉渠到了Jenkins本地,可以根据第三行日志信息,查看Jenkins本地拉渠道的源码
4) 查看Jenkins容器的源码¶
5) 配置Maven构建代码¶
代码拉取到Jenkins本地后,需要在Jenkins中对代码进行构建这里maven的环境。而Maven需要java的环境。所以接下来需要在Jenkins中安装JDK和maven,并且配置到Jenkins服务
# 将宿主机的JDK、MAVEN目录移动到Jenkins容器的数据卷中
cd /usr/local/docker/jenkins_docker/data/
mv /usr/local/jdk1.8.0_333/ ./
mv /usr/local/apache-maven-3.8.5/ ./
然后进入jenkins容器查看
[root@K8s2 data]# docker exec -it jenkins ls /var/jenkins_home/
apache-maven-3.8.5 identity.key.enc nodeMonitors.xml userContent
config.xml jdk1.8.0_333 plugins users
copy_reference_file.log jenkins.install.InstallUtil.lastExecVersion queue.xml war
credentials.xml jenkins.install.UpgradeWizard.state queue.xml.bak workspace
fingerprints jenkins.model.JenkinsLocationConfiguration.xml secret.key
hudson.model.UpdateCenter.xml jenkins.telemetry.Correlator.xml secret.key.not-so-secret
hudson.plugins.git.GitTool.xml jobs secrets
可以看到jdk和maven已经移动到Jenkins的容器卷了。
6) Jenkins配置JDK&Maven并保存¶



7) 配置Jenkins任务的构建代码¶




重新测试构建并查看


可以看到已经构建成功了
8) 配置Publish发布&远程操作¶
jar包构建好以后就可以根据情况发布到测试或生产环境,这里需要用到之前下载好的插件Publish Over SSH。
a. 配置Publish Over SSH连接 测试、生产环境
系统管理 ---> 系统配置 ---> Publish over SSH ---> SSH Servers。点击新增。

我们使用192.168.100.101作为测试生产环境的服务器,所以hostname填写其的IP地址,username写用户比如管理员root,remote directory填写将构建好的jar包部署到对应主机的哪个目录下,如/usr/local/test确保指定目录存在。最后点击保存。
如果目标机器不存在该目录,可以先使用命令mkidr /usr/local/test创建
b. 配置好任务构建后操作,发布jar包到目录服务



c. 重新构建任务,然后去目标服务器查看

回到K8s3上,查看文件
[root@K8s3 ~]# cd /usr/local/test
[root@K8s3 test]# tree target/
target/
└── mytest-1.0-SNAPSHOT.jar
0 directories, 1 file
9) 更新java项目的内容¶
vi /root/mytest-hello程序代码/mytest-hello/src/main/java/com/bdqn/controller/HelloController.java
vi /root/mytest-hello程序代码/mytest-hello/docker/docker-compose.yaml
package com.bdqn.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Administrator
* @version 1.0
* @description TODO
* @date 2023/11/17 11:27
*/
@RestController
public class HelloController {
@RequestMapping("/hello")
public String sayHello(){
return "hello jenkins --v2.0.0";
/* 把hello jenkins改成hello jenkins --v2.0.0 */
}