Gitlab + Jenkins 实现 CICD

news2025/6/10 7:16:56

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

一 、前期准备

1、部署 Gitlab

点击查看安装教程

2、部署 Jenkins

点击查看安装教程

3、部署 Docker Harbor

点击查看安装教程

4、部署 Kubernetes

点击查看安装教程

5、服务器配置

服务IP角色
master192.168.31.110集群管理节点
node1192.168.31.111集群工作节点
node2192.168.31.112集群工作节点
harbor192.168.31.113镜像仓库
gitlab192.168.31.114代码托管
jenkins192.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}
                """
            }
        }
        
        // 部署到Kubernetes
        stage('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} --record
                                kubectl 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: 2
  selector:
    matchLabels:
      app: helloworld
  template:
    metadata:
      labels:
        app: helloworld
    spec:
      containers:
        - name: helloworld
          image: cicd.ddzhixu.com:443/helloworld/helloworld:{{TIMESTAMP}}
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: "200m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          imagePullPolicy: IfNotPresent
          env:
            - name: ENVIRONMENT
              value: "production"
      imagePullSecrets:
        - name: cicd  // Docker Harbor 镜像仓库认证的 Secret 名称

---
# Service
apiVersion: v1
kind: Service
metadata:
  name: helloworld-service
spec:
  type: NodePort
  selector:
    app: helloworld
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30001
      
---
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: helloworld-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: helloworld-deployment
  minReplicas: 1
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 70

2、测试

将 web 项目上传到 Gitlab 仓库之后,会触发 Jenkins 执行 web 项目下 Jenkinsfile 中定义的一系列任务 ,然后浏览器访问 http://192.168.31.111:30001 或 http://192.168.31.112:30001

Jenkins 执行成功或者失败,可以在 Jenkins 中查看日志
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2406343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无头浏览器技术:Python爬虫如何精准模拟搜索点击

1. 无头浏览器技术概述 1.1 什么是无头浏览器&#xff1f; 无头浏览器是一种没有图形用户界面&#xff08;GUI&#xff09;的浏览器&#xff0c;它通过程序控制浏览器内核&#xff08;如Chromium、Firefox&#xff09;执行页面加载、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、需求 我们知道大型语言模型 &#xff08;LLM&#xff09; 是无状态的&#xff0c;这就意味着他们不会保…

Qt 按钮类控件(Push Button 与 Radio Button)(1)

文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button&#xff08;鼠标点击不放连续移动快捷键&#xff09; Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…

生成对抗网络(GAN)损失函数解读

GAN损失函数的形式&#xff1a; 以下是对每个部分的解读&#xff1a; 1. ⁡, ​ &#xff1a;这个部分表示生成器&#xff08;Generator&#xff09;G的目标是最小化损失函数。 &#xff1a;判别器&#xff08;Discriminator&#xff09;D的目标是最大化损失函数。 GAN的训…

汇编语言学习(三)——DoxBox中debug的使用

目录 一、安装DoxBox&#xff0c;并下载汇编工具&#xff08;MASM文件&#xff09; 二、debug是什么 三、debug中的命令 一、安装DoxBox&#xff0c;并下载汇编工具&#xff08;MASM文件&#xff09; 链接&#xff1a; https://pan.baidu.com/s/1IbyJj-JIkl_oMOJmkKiaGQ?pw…

数据可视化交互

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

安宝特方案丨从依赖经验到数据驱动:AR套件重构特种装备装配与质检全流程

在高压电气装备、军工装备、石油测井仪器装备、计算存储服务器和机柜、核磁医疗装备、大型发动机组等特种装备生产型企业&#xff0c;其产品具有“小批量、多品种、人工装配、价值高”的特点。 生产管理中存在传统SOP文件内容缺失、SOP更新不及、装配严重依赖个人经验、产品装…

【JavaEE】万字详解HTTP协议

HTTP是什么&#xff1f;-----互联网的“快递小哥” 想象我们正在网上购物&#xff1a;打开淘宝APP&#xff0c;搜索“蓝牙耳机”&#xff0c;点击商品图片&#xff0c;然后下单付款。这一系列操作背后&#xff0c;其实有一个看不见的“快递小哥”在帮我们传递信息&#xff0c;…

华为云Flexus+DeepSeek征文 | MaaS平台避坑指南:DeepSeek商用服务开通与成本控制

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 前言 一、技术架构概览 1.1 整体架构设…

【动态规划】B4336 [中山市赛 2023] 永别|普及+

B4336 [中山市赛 2023] 永别 题目描述 你做了一个梦&#xff0c;梦里有一个字符串&#xff0c;这个字符串无论正着读还是倒着读都是一样的&#xff0c;例如&#xff1a; a b c b a \tt abcba abcba 就符合这个条件。 但是你醒来时不记得梦中的字符串是什么&#xff0c;只记得…

可下载旧版app屏蔽更新的app市场

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

claude3.7高阶玩法,生成系统架构图,国内直接使用

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

河北对口计算机高考MySQL笔记(完结版)(2026高考)持续更新~~~~

MySQL 基础概念 数据&#xff08;Data&#xff09;&#xff1a;文本&#xff0c;数字&#xff0c;图片&#xff0c;视频&#xff0c;音频等多种表现形式&#xff0c;能够被计算机存储和处理。 **数据库&#xff08;Data Base—简称DB&#xff09;&#xff1a;**存储数据的仓库…

2025-06-01-Hive 技术及应用介绍

Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具&#xff0c;它为海量结构化数据提供类 SQL 的查询能力&#xf…

AI书签管理工具开发全记录(十八):书签导入导出

文章目录 AI书签管理工具开发全记录&#xff08;十八&#xff09;&#xff1a;书签导入导出1.前言 &#x1f4dd;2.书签结构分析 &#x1f4d6;3.书签示例 &#x1f4d1;4.书签文件结构定义描述 &#x1f523;4.1. ​整体文档结构​​4.2. ​核心元素类型​​4.3. ​层级关系4.…

docker容器互联

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

安宝特案例丨寻医不再长途跋涉?Vuzix再次以AR技术智能驱动远程医疗

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

Modbus转Ethernet IP深度解析:磨粉设备效率跃升的底层技术密码

在建材矿粉磨系统中&#xff0c;开疆智能Modbus转Ethernet IP网关KJ-EIP-101的应用案例是一个重要的技术革新。这个转换过程涉及到两种主要的通信协议&#xff1a;Modbus和Ethernet IP。Modbus是一种串行通信协议&#xff0c;广泛应用于工业控制系统中。它简单、易于部署和维护…

在MobaXterm 打开图形工具firefox

目录 1.安装 X 服务器软件 2.服务器端配置 3.客户端配置 4.安装并打开 Firefox 1.安装 X 服务器软件 Centos系统 # CentOS/RHEL 7 及之前&#xff08;YUM&#xff09; sudo yum install xorg-x11-server-Xorg xorg-x11-xinit xorg-x11-utils mesa-libEGL mesa-libGL mesa-…