从零搭建CICD流水线:GitLab与Jenkins实战指南

张开发
2026/4/12 11:11:50 15 分钟阅读

分享文章

从零搭建CICD流水线:GitLab与Jenkins实战指南
1. 为什么你需要一条自己的CICD流水线如果你和我一样是个经常写代码、然后手动打包、再登录服务器去部署的程序员那你一定经历过这种痛苦深夜加班改完一个紧急Bug小心翼翼地执行一系列重复的打包、上传、重启命令生怕手滑敲错一个字母。更别提团队协作时张三的代码在本地跑得好好的一合并到主分支就出问题大家互相“甩锅”排查起来费时费力。这就是为什么我们需要CICD。简单来说它就像给你的软件开发流程装上了一套全自动的“智能流水线”。你只需要把代码推送到仓库比如GitLab剩下的构建、测试、部署等一系列繁琐工作全部交给像Jenkins这样的“机器人”去自动完成。它能带来的好处我亲身经历过可以总结为三点第一解放双手告别重复劳动。以前发布一次版本可能要执行十几条命令现在一次git push就全搞定了。省下来的时间喝杯咖啡、研究下新技术不香吗第二快速反馈问题早发现早解决。每次代码提交流水线都会自动运行测试。如果测试失败你和你的团队会立刻收到通知马上就能知道是这次提交引入了问题而不是等到一周后集成时才发现那时候早就忘了改过什么了。第三部署过程标准化、可追溯。人工操作难免有疏忽而自动化脚本每次执行都一样。谁、在什么时候、通过哪次构建部署的在Jenkins里都记录得清清楚楚出问题回滚也特别方便。所以今天我就带你从零开始亲手搭建一条属于你自己的CICD流水线。我们用最经典的组合GitLab作为代码仓库和管理中心Jenkins作为自动化执行引擎。不用担心我会把每一步都掰开揉碎即便你之前没接触过跟着做也能搞定。我们的目标很简单实现一个“Hello World”项目从你写下代码到自动部署上线的完整闭环。2. 搭建舞台准备你的实验环境工欲善其事必先利其器。在开始连接GitLab和Jenkins之前我们需要先把这两个“主角”请到我们的服务器上。为了模拟真实场景我建议你准备两台Linux服务器虚拟机即可一台装GitLab一台装Jenkins。如果资源有限装在同一台机器上也可以但要注意端口冲突比如两者默认的Web端口都是80/8080需要修改。2.1 安装与配置GitLabGitLab是一个功能强大的DevOps平台我们这里主要用它来托管代码。它的安装方式很多用Docker最简单但为了更贴近生产环境我们采用官方RPM包安装。首先登录到你准备用作GitLab的服务器。确保内存至少4GB官方建议我这里用的是CentOS 9 Stream其他发行版命令可能略有不同。# 1. 安装必要的依赖 sudo yum install -y curl policycoreutils openssh-server perl # 2. 添加GitLab仓库并安装这里以极狐GitLab中国镜像为例速度更快 curl -fsSL https://packages.gitlab.cn/repository/raw/scripts/setup.sh | sudo bash sudo yum install -y gitlab-jh安装完成后我们需要进行一个关键配置告诉GitLab它可以通过什么网址被访问。编辑GitLab的主配置文件sudo vim /etc/gitlab/gitlab.rb找到external_url这一行可以用/external_url搜索把它改成你服务器的IP地址或域名。比如我的服务器IP是192.168.1.100就修改为external_url http://192.168.1.100保存退出后运行重配置命令这个过程会初始化数据库、生成各种密钥时间稍长请耐心等待。sudo gitlab-ctl reconfigure看到绿色的“gitlab Reconfigured!”就成功了。现在打开浏览器访问http://你的服务器IP。第一次访问会要求你为root用户设置一个新密码。设置完成后用root和你刚设置的密码登录。注意安装后24小时内初始随机密码存放在/etc/gitlab/initial_root_password中如果你忘了自己设的密码可以在这个文件失效前从这里查看。登录进去后我建议你先在“Admin Area” - “Settings” - “General”里把默认语言改成中文这样后续操作会更顺手。好了你的私有代码仓库GitLab已经就绪2.2 安装与启动Jenkins接下来在另一台服务器上部署Jenkins。Jenkins是一个用Java写的自动化服务器安装也很简单。# 1. 安装Java环境 (Jenkins 2.4xx 需要Java 11或17) sudo yum install -y fontconfig java-17-openjdk git # 2. 导入Jenkins仓库并安装 sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key sudo yum install -y jenkins # 3. 启动并设置开机自启 sudo systemctl enable --now jenkins sudo systemctl status jenkins # 检查状态应该是active (running)安装完成后Jenkins默认会在8080端口启动。打开浏览器访问http://你的Jenkins服务器IP:8080。你会看到一个“解锁Jenkins”的页面它要求你输入初始管理员密码。这个密码在哪里呢Jenkins把它放在了服务器的一个文件里sudo cat /var/lib/jenkins/secrets/initialAdminPassword把输出的一串字符复制粘贴到网页里点击“继续”。接下来会让你选择安装插件对于新手我强烈建议选择“安装推荐的插件”。这会安装最常用的一套插件包括我们后面需要的Git、Pipeline等。插件安装需要一些时间泡杯茶等等。插件装完后会提示你创建第一个管理员用户。这里一定要认真填写并记住不要再用初始密码了创建一个你自己的管理员账号比如用户名admin邮箱填你自己的。完成后Jenkins会提示你设置实例URL保持默认的http://你的IP:8080就行。点击“保存并完成”然后“开始使用Jenkins”。恭喜你的自动化引擎Jenkins也启动成功了3. 打通任督二脉连接GitLab与Jenkins现在我们有了GitLab代码库和Jenkins自动化引擎但它们俩现在还互不认识。我们的目标是一旦GitLab有代码推送就自动通知Jenkins开始工作。这需要两步第一让Jenkins能“伸手”到GitLab拉取代码配置SSH密钥第二让GitLab“踢”Jenkins一脚配置Webhook。3.1 配置SSH密钥认证为什么需要这个因为Jenkins服务器需要从GitLab仓库克隆代码而最安全方便的方式就是使用SSH密钥对无需密码。我们在Jenkins服务器上生成一对密钥ssh-keygen -t rsa -b 4096 -C jenkinsyourcompany.com一路回车采用默认路径/home/jenkins/.ssh/id_rsa和不设密码。然后查看公钥cat ~/.ssh/id_rsa.pub你会看到一串以ssh-rsa AAAAB3...开头的文本复制它。接下来登录到GitLab网页。点击右上角头像 - “Settings” - 左侧菜单“SSH Keys”。把刚才复制的公钥内容粘贴到“Key”文本框中“Title”可以起个名字比如“Jenkins Server Key”。点击“Add key”。现在我们需要让Jenkins进程知道并使用刚才生成的私钥。回到Jenkins网页点击“Manage Jenkins” - “Credentials”凭据 - “System” - “Global credentials (unrestricted)” - “Add Credentials”。Kind: 选择 “SSH Username with private key”Scope: 保持 GlobalID: 可以留空Jenkins会自动生成但建议你填一个有意义的名字如gitlab_ssh_keyUsername: 填写你在GitLab上的用户名比如rootPrivate Key: 选择 “Enter directly”然后点击“Add”。我们需要把私钥内容贴进去。回到Jenkins服务器的命令行查看私钥cat ~/.ssh/id_rsa将输出的全部内容包括-----BEGIN OPENSSH PRIVATE KEY-----和-----END OPENSSH PRIVATE KEY-----复制粘贴到Jenkins网页的Key区域。最后点击“Create”。3.2 在GitLab创建项目并配置Webhook现在我们在GitLab上创建一个项目作为流水线的源头。在GitLab首页点击绿色的“New project”选择“Create blank project”。给项目起个名字比如my-cicd-demo可见性设为“Private”私有。点击“Create project”。项目创建好后我们需要告诉GitLab“以后这个项目有代码推送Push或者合并请求Merge Request时去通知一下Jenkins”。这个通知机制就是Webhook。首先我们需要知道Jenkins接收Webhook的地址。Jenkins需要一个插件来提供这个接口。在Jenkins中点击“Manage Jenkins” - “Plugins”插件管理 - “Available plugins”可选插件。搜索并安装“GitLab”和“GitLab API”插件。安装后重启Jenkins。插件装好后我们在Jenkins里创建一个新的“任务”其实就是流水线项目。点击“New Item”输入任务名称例如My-CICD-Pipeline选择“Pipeline”然后点击“OK”。在项目配置页面我们先找到“Build Triggers”构建触发器区域勾选上“Build when a change is pushed to GitLab”。下面会显示一个形如http://你的Jenkins IP:8080/project/My-CICD-Pipeline的URL这个就是GitLab Webhook要回调的地址。把它复制下来。然后进入“Pipeline”区域在“Definition”处选择“Pipeline script from SCM”SCM选择“Git”。在“Repository URL”中填入你GitLab项目的SSH地址在GitLab项目页面上点击“Clone”按钮选择“Clone with SSH”看到的地址如gityour-gitlab-ip:root/my-cicd-demo.git。在“Credentials”下拉框中选择我们刚才创建的gitlab_ssh_key凭据。其他保持默认点击“Save”保存Jenkins任务。现在回到GitLab项目页面进入 “Settings” - “Webhooks”。在“URL”栏粘贴刚才复制的Jenkins项目URL。在“Secret token”部分你可以点击“Generate”生成一个令牌并把这个令牌也填到Jenkins项目配置的“Build Triggers”区域对应的“Secret token”栏里增加安全性可选但推荐。在“Trigger”触发事件里至少勾选“Push events”和“Merge request events”。取消勾选“Enable SSL verification”因为我们用的是HTTP如果是HTTPS生产环境则应开启。最后点击“Add webhook”。为了测试连接点击“Test”下拉框选择“Push events”。如果配置正确GitLab会显示“Hook executed successfully: HTTP 200”。同时你回到Jenkins会发现你的My-CICD-Pipeline任务自动触发了一次构建这说明从GitLab到Jenkins的“单向通信”已经打通了。4. 编写流水线的“剧本”深入理解Jenkinsfile流水线自动化的核心逻辑写在了一个叫做Jenkinsfile的文件里。这个文件通常放在你的Git项目根目录它用一套声明式或脚本化的语法告诉Jenkins每一步该做什么。我们这次用更直观、更主流的声明式Pipeline。4.1 你的第一个Pipeline脚本在你的本地电脑上克隆刚才在GitLab创建的空项目然后创建一个Jenkinsfile文件。git clone gityour-gitlab-ip:root/my-cicd-demo.git cd my-cicd-demo touch Jenkinsfile用你喜欢的编辑器打开Jenkinsfile写入以下内容pipeline { agent any // 告诉Jenkins在任何可用的代理机器上执行此Pipeline stages { stage(拉取代码) { steps { echo 开始从GitLab拉取代码... checkout scm // 这是一个特殊指令会自动拉取触发本次构建的代码版本 } } stage(代码编译) { steps { echo 开始编译代码... // 这里假设是一个简单的Java Maven项目 sh mvn clean compile } } stage(运行测试) { steps { echo 开始运行单元测试... sh mvn test // 生成测试报告如果有 junit target/surefire-reports/*.xml } } stage(构建打包) { steps { echo 开始构建应用包... sh mvn package -DskipTests // 跳过测试因为上一步已经跑过了 archiveArtifacts artifacts: target/*.jar, fingerprint: true // 存档构建产物 } } stage(部署到测试环境) { steps { echo 正在部署到测试服务器... // 这里只是一个示例实际可能是 scp/ssh 或调用容器平台API sh scp target/*.jar usertest-server:/opt/app/ ssh usertest-server systemctl restart myapp } } } post { always { echo 当前流水线运行结束。 // 清理工作空间避免磁盘空间占用过大 cleanWs() } success { echo 恭喜流水线执行成功 // 可以在这里添加成功通知如发送邮件、钉钉消息等 } failure { echo 糟糕流水线执行失败了 // 可以在这里添加失败告警 } } }这个脚本定义了一个完整的五阶段流水线。我来解释几个关键点agent any: 指定执行环境。stages和stage: 定义了流水线的不同阶段逻辑清晰。steps: 每个阶段内的具体步骤。checkout scm: 这是一个Jenkins内置步骤用于检出代码它会自动匹配触发构建的仓库和分支非常方便。sh: 执行Shell命令。post: 构建后处理无论成功失败都会执行always里的步骤根据结果执行success或failure。4.2 为“Hello World”项目定制简易流水线上面是一个通用模板但我们的第一个demo项目可能很简单甚至不是Maven项目。没关系我们来个更简单的。假设我们只有一个index.html文件流水线只需要把它打包并推送到一个静态服务器。我们先在项目里创建一个简单的index.html!DOCTYPE html html head title我的CICD演示/title /head body h1Hello, CICD Pipeline!/h1 p这个页面由GitLab Jenkins自动部署。/p /body /html然后修改Jenkinsfile让它适配这个静态项目pipeline { agent any stages { stage(拉取代码) { steps { checkout scm } } stage(质量检查) { steps { echo 检查HTML文件语法... // 这里可以加入简单的检查例如用tidy检查语法这里仅作演示 sh find . -name *.html -type f | head -5 } } stage(打包归档) { steps { echo 将网站文件打包... sh tar -czf website.tar.gz *.html archiveArtifacts artifacts: website.tar.gz, fingerprint: true } } stage(部署) { steps { echo 模拟部署到Web服务器... // 实际场景中这里会是 scp/rsync 到Nginx目录或上传到云存储 sh echo 部署步骤解压website.tar.gz到/var/www/html/ // 模拟一个部署命令 sh mkdir -p /tmp/cicd-demo-deploy/ tar -xzf website.tar.gz -C /tmp/cicd-demo-deploy/ echo 部署完成可通过 http://localhost 访问模拟 } } } post { always { echo 流水线执行完毕。 cleanWs() } } }把这个Jenkinsfile和index.html一起提交到GitLabgit add . git commit -m 添加初始文件和Jenkinsfile git push origin main神奇的事情发生了由于我们配置了Webhook这次git push操作会立刻触发GitLab通知Jenkins。你马上打开Jenkins的页面就能看到My-CICD-Pipeline任务开始自动运行并且按照Jenkinsfile里定义的阶段一步步执行下去。在Jenkins的“Stage View”中你能清晰地看到每个阶段的执行状态蓝色进行中绿色成功红色失败。5. 进阶与避坑让流水线更健壮实用基础流水线跑通后你可能会遇到一些实际问题。别担心这都是我踩过的坑分享给你如何解决和优化。5.1 处理依赖与私有仓库认证你的项目很可能依赖内部Maven仓库或私有NPM包。在流水线中如何认证最佳实践是使用Jenkins的凭据管理和凭证绑定。例如你的Mavensettings.xml需要私服密码。不要在Jenkinsfile里写明文密码而是在Jenkins的“Credentials”里添加一个“Secret file”或“Username with password”类型的凭据。然后在Pipeline中这样使用stage(编译构建) { environment { // 从Jenkins凭据库读取ID为maven-private-repo-creds的用户名密码并赋值给环境变量 NEXUS_CREDS credentials(maven-private-repo-creds) } steps { sh // 将密码写入一个临时的settings.xml cat /tmp/settings.xml EOF settings servers server idmy-nexus/id username${NEXUS_CREDS_USR}/username password${NEXUS_CREDS_PSW}/password /server /servers /settings EOF mvn clean package -s /tmp/settings.xml } }credentials()函数会自动注入两个环境变量NEXUS_CREDS_USR和NEXUS_CREDS_PSW分别对应凭据的用户名和密码安全又方便。5.2 优化构建速度与资源管理流水线跑得慢可以从以下几点优化使用Docker Agent在Jenkinsfile顶部指定agent { docker { image maven:3.8.4-openjdk-11 } }。这样每次构建都会在一个全新的、包含所有依赖的Maven容器中运行无需在Jenkins代理机上安装Maven且环境绝对干净。缓存依赖对于Maven、Gradle、NPM等项目下载依赖很耗时。可以使用Jenkins的stash/unstash功能在阶段间缓存~/.m2/repository目录或者更优雅地使用Docker Volume持久化缓存。并行执行如果某些阶段互不依赖可以用parallel指令让它们同时跑。比如单元测试和代码静态分析可以并行。stage(测试与分析) { parallel { stage(单元测试) { steps { sh mvn test } } stage(代码检查) { steps { sh mvn sonar:sonar } } } }5.3 关键的调试与日志查看技巧流水线失败了怎么办别慌Jenkins提供了详细的日志。蓝色小球点击构建编号进入构建详情页。Console Output这是最重要的调试信息会打印出流水线每一步执行的具体命令和输出。错误信息通常在这里。Stage View直观看到哪个阶段失败了点击该阶段可以只看这个阶段的日志。脚本调试对于复杂的Scripted Pipeline或Shell脚本可以在关键步骤前后加echo ‘当前变量值是${MY_VAR}’来打印变量值。一个常见错误是权限问题比如Jenkins用户没有执行某个命令或访问某个目录的权限。可以在Jenkins管理页面“Manage Jenkins” - “Configure Global Security” 里检查执行Shell命令的用户身份或者在Shell命令前加上sudo需要配置密码免密。最后记得给你的流水线加上通知。在post块里可以使用emailext插件发送邮件或者使用钉钉、企业微信等插件发送消息到群组这样无论成功失败团队都能第一时间知晓。走到这里你已经拥有了一条完全由自己搭建、可以自动运行的基础CICD流水线。从代码推送到自动部署整个过程无需人工干预。这只是一个起点你可以在此基础上加入代码扫描、安全检测、多环境部署开发、测试、生产、自动化回滚等更多高级功能。记住CICD的核心价值在于“快速反馈”和“减少人工错误”根据你的项目需求不断迭代和优化这条流水线让它真正成为你研发团队的效率引擎。

更多文章