Gitlab + Jenkins 实现 CICD
CICD 是持续集成(Continuous Integration, CI)和持续交付/部署(Continuous Delivery/Deployment, CD)的缩写,是现代软件开发中的一种自动化流程实践。下面介绍 Web 项目如何在代码提交到 Gitlab 后,自动发布到 Kubernetes 集群中。
一 、前期准备
1、部署 Gitlab
点击查看安装教程
2、部署 Jenkins
点击查看安装教程
3、部署 Docker Harbor
点击查看安装教程
4、部署 Kubernetes
点击查看安装教程
5、服务器配置
服务 | IP | 角色 |
---|---|---|
master | 192.168.31.110 | 集群管理节点 |
node1 | 192.168.31.111 | 集群工作节点 |
node2 | 192.168.31.112 | 集群工作节点 |
harbor | 192.168.31.113 | 镜像仓库 |
gitlab | 192.168.31.114 | 代码托管 |
jenkins | 192.168.31.115 | 自动化构建与部署 |
二、配置 Gitlab
Gitlab 中主要是配置 webhooks,作用是接收到代码推送后触发 Jenkins 任务。有两种方式,下面是配置过程截图:
(一)方式一:使用 Webhooks 触发 Jenkins(传统方式)
1、新建项目 HelloWorld
,地址:http://192.168.31.114/root/helloworld.git
2、点击 管理员 - 设置 - 网络
3、勾选 允许来自 webhooks 和集成对本地网络的请求
,然后保存更改
作用:代码推送后可以触发自动化通知
4、选择项目,点击设置,点击 Webhooks
5、配置 Webhooks
URL 和 Secret 令牌从 Jenkins 获取,如何获取下面配置 Jenkins 有截图
(二)方式二:使用 GitLab 的 Jenkins 集成(推荐方式)
1、新建项目,在项目设置中点击集成
,然后添加 Jenkins 集成模块
2、Jenkins 集成模块配置
URL 从 Jenkins 获取,如何获取下面配置 Jenkins 有截图
(三)两种方式比较
特性 | Webhooks 手动配置 | GitLab Jenkins 插件 |
---|---|---|
配置难度 | 较高 | 简单 |
灵活性 | 高 | 中等 |
维护成本 | 高 | 低 |
支持的功能 | 完全自定义 | 包括 MR、PR、状态反馈等 |
是否需要插件 | 是(如 Generic Webhook Trigger) | 是(GitLab Plugin) |
安全性 | 需手动配置 Secret | 支持 Token 验证 |
多项目支持 | 需手动逐一配置 | 可集中管理 |
GitLab 回调支持 | 需要自己开发 | 内置支持 |
GitLab 提供的 Jenkins 集成模块本质上也是基于 Webhook 实现的,但封装更易用和安全。但使用 Webhooks 触发 Jenkins 的传统方式依然会经常使用,尤其适用于:自建的服务,第三方不支持 GitLab 内置集成的系统,需要高度定制化的场景。只是 GitLab 建议你在“有内置集成可用”的情况下,优先使用集成,因为它们更可靠、更易于维护。
三、配置 Jenkins
1、添加全局凭据
2、新建任务
3、Triggers(触发器)配置
需要安装插件 Gitlab,在系统管理 - 插件管理 - Available plugins 中搜索并安装
(1)勾选 “Build when a change is pushed to GitLab” 配置项,目的是实现 GitLab 与 Jenkins 之间的自动化触发关联
(2)点开高级 - 选择 Filter branches by name
,作用是让你能精确控制哪些 Git 分支的代码变更可以触发当前 Jenkins 任务(这里是 “helloworld” 任务 )的构建 。
4、流水线配置
(1)关联 GitLab 代码仓库
需要在 Jenkins 服务器(192.168.31.115)上安装 Git
dnf install git -y
(2)设置 Jenkins 从 Git 仓库的 main 分支拉取代码,并用仓库里的 Jenkinsfile 定义的流程来跑自动化构建 。
四、DockerHarbor,新建项目 helloworld
五、部署 web 项目
1、web 项目内容
(1)index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebView Test</title>
</head>
<body><h1>Hello World!</h1>
</body>
</html>
(2)Dockerfile 文件
# 使用官方的 Nginx 镜像作为基础镜像
FROM nginx:latest# 将当前目录下的所有文件复制到 Nginx 容器的默认网页根目录(/usr/share/nginx/html)
COPY . /usr/share/nginx/html# 暴露 Nginx 服务的默认端口 80
EXPOSE 80
(3)Jenkinsfile 文件
pipeline {agent any // 在任何可用代理上运行此流水线environment {// Docker 镜像配置DOCKER_REGISTRY = "harbor.yiyang.com:443" // 私有Docker仓库地址IMAGE_NAME = "helloworld/helloworld" // 镜像名称TIMESTAMP = "${new Date().format('yyyyMMdd_HHmmss', TimeZone.getTimeZone('Asia/Shanghai'))}" // 带时区的时间戳IMAGE_TAG_LATEST = "latest" // 最新标签// Kubernetes 配置K8S_DEPLOYMENT_NAME = "helloworld-deployment" // 必须与 helloworld.yaml 中的 Deployment 名称一致K8S_CONFIG_FILE = "helloworld.yaml" // Kubernetes部署文件}stages {// 代码检出stage('Checkout') {steps {git credentialsId: '9ba151c2-08ec-4e25-a38c-4b322c40e2bf', url: 'http://192.168.31.114/root/helloworld.git', branch: 'main'}}// 构建Docker镜像stage('Build Docker Image') {steps {sh """docker build --pull --no-cache --network none \-t ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP} .docker tag ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP} \${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG_LATEST}"""}}// 登录Docker仓库stage('Login to Docker Harbor') {steps {withCredentials([usernamePassword(credentialsId: '61e24bcf-39b1-42b3-8815-080502c30a53',usernameVariable: 'DOCKER_USER',passwordVariable: 'DOCKER_PASSWORD')]) {sh '''echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USER}" --password-stdin ${DOCKER_REGISTRY}'''}}}// 推送Docker镜像stage('Push Docker Image') {steps {sh """docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP}docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG_LATEST}"""}}// 部署到Kubernetesstage('Deploy to Kubernetes') {steps {script {withCredentials([file(credentialsId: '34fffd5d-e5f4-465d-b3ff-205929444c95', variable: 'KUBECONFIG')]) {try {// 1. 预检查sh "kubectl apply --dry-run=client -f ${K8S_CONFIG_FILE}"// 2. 执行部署sh """kubectl set image deployment/${K8S_DEPLOYMENT_NAME} *=${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP} --recordkubectl rollout status deployment/${K8S_DEPLOYMENT_NAME} --timeout=5m"""echo "Deployment succeeded for image: ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP}"} catch (err) {// 3. 失败时自动回滚echo "Deployment failed! Error: ${err}"echo "Initiating rollback..."sh """kubectl rollout undo deployment/${K8S_DEPLOYMENT_NAME}kubectl rollout status deployment/${K8S_DEPLOYMENT_NAME} --timeout=3m"""error "Deployment failed and was rolled back. Original error: ${err}"}}}}}}// 后置处理post {// 无论成功失败都执行的步骤always {// 镜像清理sh "docker rmi -f ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP} || true"// 可选:清理悬空镜像sh "docker image prune -f || true"}// 仅当流水线成功时执行的步骤success {echo "Pipeline succeeded! Image: ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP}"}// 仅当流水线失败时执行的步骤failure {echo "Pipeline failed. Check logs for details."}}
}
(4)helloworld.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:name: helloworld-deployment
spec:replicas: 2selector:matchLabels:app: helloworldtemplate:metadata:labels:app: helloworldspec:containers:- name: helloworldimage: cicd.ddzhixu.com:443/helloworld/helloworld:{{TIMESTAMP}}ports:- containerPort: 80resources:requests:cpu: "200m"memory: "256Mi"limits:cpu: "500m"memory: "512Mi"imagePullPolicy: IfNotPresentenv:- name: ENVIRONMENTvalue: "production"imagePullSecrets:- name: cicd // Docker Harbor 镜像仓库认证的 Secret 名称---
# Service
apiVersion: v1
kind: Service
metadata:name: helloworld-service
spec:type: NodePortselector:app: helloworldports:- name: httpprotocol: TCPport: 80targetPort: 80nodePort: 30001---
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:name: helloworld-hpa
spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: helloworld-deploymentminReplicas: 1maxReplicas: 10metrics:- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 70- type: Resourceresource:name: memorytarget:type: UtilizationaverageUtilization: 70
2、测试
将 web 项目上传到 Gitlab 仓库之后,会触发 Jenkins 执行 web 项目下 Jenkinsfile 中定义的一系列任务 ,然后浏览器访问 http://192.168.31.111:30001 或 http://192.168.31.112:30001
Jenkins 执行成功或者失败,可以在 Jenkins 中查看日志
相关文章:

Gitlab + Jenkins 实现 CICD
CICD 是持续集成(Continuous Integration, CI)和持续交付/部署(Continuous Delivery/Deployment, CD)的缩写,是现代软件开发中的一种自动化流程实践。下面介绍 Web 项目如何在代码提交到 Gitlab 后,自动发布…...

无头浏览器技术:Python爬虫如何精准模拟搜索点击
1. 无头浏览器技术概述 1.1 什么是无头浏览器? 无头浏览器是一种没有图形用户界面(GUI)的浏览器,它通过程序控制浏览器内核(如Chromium、Firefox)执行页面加载、JavaScript渲染、表单提交等操作。由于不渲…...

SDU棋界精灵——硬件程序ESP32实现opus编码
一、 音频处理框架 该项目基于Espressif的音频处理框架构建,核心组件包括 ESP-ADF 和 ESP-SR,以下是完整的音频处理框架实现细节: 1.核心组件 (1) 音频前端处理 (AFE - Audio Front-End) main/components/audio_pipeline/afe_processor.c功能: 声学回声…...

Spring AI中使用ChatMemory实现会话记忆功能
文章目录 1、需求2、ChatMemory中消息的存储位置3、实现步骤1、引入依赖2、配置Spring AI3、配置chatmemory4、java层传递conversaionId 4、验证5、完整代码6、参考文档 1、需求 我们知道大型语言模型 (LLM) 是无状态的,这就意味着他们不会保…...

Qt 按钮类控件(Push Button 与 Radio Button)(1)
文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button(鼠标点击不放连续移动快捷键) Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…...
生成对抗网络(GAN)损失函数解读
GAN损失函数的形式: 以下是对每个部分的解读: 1. , :这个部分表示生成器(Generator)G的目标是最小化损失函数。 :判别器(Discriminator)D的目标是最大化损失函数。 GAN的训…...

汇编语言学习(三)——DoxBox中debug的使用
目录 一、安装DoxBox,并下载汇编工具(MASM文件) 二、debug是什么 三、debug中的命令 一、安装DoxBox,并下载汇编工具(MASM文件) 链接: https://pan.baidu.com/s/1IbyJj-JIkl_oMOJmkKiaGQ?pw…...
【Java基础】向上转型(Upcasting)和向下转型(Downcasting)
在面向对象编程中,转型(Casting) 是指改变对象的引用类型,主要涉及 继承关系 和 多态。 向上转型(Upcasting) ⬆️ 定义 将 子类对象 赋值给 父类引用(自动完成,无需强制转换&…...
GitHub 常见高频问题与解决方案(实用手册)
1.Push 提示权限错误(Permission denied) 问题: Bash Permission denied (publickey) fatal: Could not read from remote repository. 原因: 没有配置 SSH key 或使用了 HTTPS 而没有权限…...

数据可视化交互
目录 【实验目的】 【实验原理】 【实验环境】 【实验步骤】 一、安装 pyecharts 二、下载数据 三、实验任务 实验 1:AQI 横向对比条形图 代码说明: 运行结果: 实验 2:AQI 等级分布饼图 实验 3:多城市 AQI…...

安宝特方案丨从依赖经验到数据驱动:AR套件重构特种装备装配与质检全流程
在高压电气装备、军工装备、石油测井仪器装备、计算存储服务器和机柜、核磁医疗装备、大型发动机组等特种装备生产型企业,其产品具有“小批量、多品种、人工装配、价值高”的特点。 生产管理中存在传统SOP文件内容缺失、SOP更新不及、装配严重依赖个人经验、产品装…...

【JavaEE】万字详解HTTP协议
HTTP是什么?-----互联网的“快递小哥” 想象我们正在网上购物:打开淘宝APP,搜索“蓝牙耳机”,点击商品图片,然后下单付款。这一系列操作背后,其实有一个看不见的“快递小哥”在帮我们传递信息,…...
Vue3学习(接口,泛型,自定义类型,v-for,props)
一,前言 继续学习 二,TS接口泛型自定义类型 1.接口 TypeScript 接口(Interface)是一种定义对象形状的强大工具,它可以描述对象必须包含的属性、方法和它们的类型。接口不会被编译成 JavaScript 代码,仅…...

华为云Flexus+DeepSeek征文 | MaaS平台避坑指南:DeepSeek商用服务开通与成本控制
作者简介 我是摘星,一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型,将实际使用经验分享给大家,希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 前言 一、技术架构概览 1.1 整体架构设…...
WEB3全栈开发——面试专业技能点P8DevOps / 区块链部署
一、Hardhat / Foundry 进行合约部署 概念介绍 Hardhat 和 Foundry 都是以太坊智能合约开发的工具套件,支持合约的编译、测试和部署。 它们允许开发者在本地或测试网络快速开发智能合约,并部署到链上(测试网或主网)。 部署过程…...

【动态规划】B4336 [中山市赛 2023] 永别|普及+
B4336 [中山市赛 2023] 永别 题目描述 你做了一个梦,梦里有一个字符串,这个字符串无论正着读还是倒着读都是一样的,例如: a b c b a \tt abcba abcba 就符合这个条件。 但是你醒来时不记得梦中的字符串是什么,只记得…...

可下载旧版app屏蔽更新的app市场
软件介绍 手机用久了,app越来越臃肿,老手机卡顿成常态。这里给大家推荐个改善老手机使用体验的方法,还能帮我们卸载不需要的app。 手机现状 如今的app不断更新,看似在优化,实则内存占用越来越大,对手机性…...

claude3.7高阶玩法,生成系统架构图,国内直接使用
文章目录 零、前言一、操作指南操作指导 二、提示词模板三、实战图书管理系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 在线考试系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 四、感受 零、前言 现在很多AI大模型可以…...

河北对口计算机高考MySQL笔记(完结版)(2026高考)持续更新~~~~
MySQL 基础概念 数据(Data):文本,数字,图片,视频,音频等多种表现形式,能够被计算机存储和处理。 **数据库(Data Base—简称DB):**存储数据的仓库…...

2025-06-01-Hive 技术及应用介绍
Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具,它为海量结构化数据提供类 SQL 的查询能力…...
DriveGPT4: Interpretable End-to-end Autonomous Driving via Large Language Model
一、研究背景与创新点 (一)现有方法的局限性 当前智驾系统面临两大核心挑战:一是长尾问题,即系统在遇到新场景时可能失效,例如突发交通状况或非常规道路环境;二是可解释性问题,传统方法无法解释智驾系统的决策过程,用户难以理解车辆行为的依据。传统语言模型(如 BERT…...

AI书签管理工具开发全记录(十八):书签导入导出
文章目录 AI书签管理工具开发全记录(十八):书签导入导出1.前言 📝2.书签结构分析 📖3.书签示例 📑4.书签文件结构定义描述 🔣4.1. 整体文档结构4.2. 核心元素类型4.3. 层级关系4.…...
codeforces C. Cool Partition
目录 题目简述: 思路: 总代码: https://codeforces.com/contest/2117/problem/C 题目简述: 给定一个整数数组,现要求你对数组进行分割,但需满足条件:前一个子数组中的值必须在后一个子数组中…...
TMC2226超静音步进电机驱动控制模块
目前已经使用TMC2226量产超过20K,发现在静音方面做的还是很不错。 一、TMC2226管脚定义说明 二、原理图及下载地址 一、TMC2226管脚定义说明 引脚编号类型功能OB11电机线圈 B 输出 1BRB2线圈 B 的检测电阻连接端。将检测电阻靠近该引脚连接到地。使用内部检测电阻时,将此引…...

docker容器互联
1.docker可以通过网路访问 2.docker允许映射容器内应用的服务端口到本地宿主主机 3.互联机制实现多个容器间通过容器名来快速访问 一 、端口映射实现容器访问 1.从外部访问容器应用 我们先把之前的删掉吧(如果不删的话,容器就提不起来,因…...

安宝特案例丨寻医不再长途跋涉?Vuzix再次以AR技术智能驱动远程医疗
加拿大领先科技公司TeleVU基于Vuzix智能眼镜打造远程医疗生态系统,彻底革新患者护理模式。 安宝特合作伙伴TeleVU成立30余年,沉淀医疗技术、计算机科学与人工智能经验,聚焦医疗保健领域,提供AR、AI、IoT解决方案。 该方案使医疗…...

Modbus转Ethernet IP深度解析:磨粉设备效率跃升的底层技术密码
在建材矿粉磨系统中,开疆智能Modbus转Ethernet IP网关KJ-EIP-101的应用案例是一个重要的技术革新。这个转换过程涉及到两种主要的通信协议:Modbus和Ethernet IP。Modbus是一种串行通信协议,广泛应用于工业控制系统中。它简单、易于部署和维护…...
Python打卡训练营学习记录Day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
八、【ESP32开发全栈指南:UDP客户端】
1. 环境准备 安装ESP-IDF v4.4 (官方指南)确保Python 3.7 和Git已安装 2. 创建项目 idf.py create-project udp_client cd udp_client3. 完整优化代码 (main/main.c) #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h&…...

在MobaXterm 打开图形工具firefox
目录 1.安装 X 服务器软件 2.服务器端配置 3.客户端配置 4.安装并打开 Firefox 1.安装 X 服务器软件 Centos系统 # CentOS/RHEL 7 及之前(YUM) sudo yum install xorg-x11-server-Xorg xorg-x11-xinit xorg-x11-utils mesa-libEGL mesa-libGL mesa-…...