ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Jenkins与GitLab集成:认证配置与自动化部署实战指南

Jenkins与GitLab集成:认证配置与自动化部署实战指南 很多做交付的兄弟来找我第一句话就是“我手动部署一次要40分钟天天重复怎么把 Jenkins 和 GitLab 打通”说实话Jenkins 与 GitLab 的集成本身不难难的是把认证这件事想清楚是让 Jenkins 用哪个身份去访问 GitLab是只读代码还是也要回写是拿 Token 还是用 SSH Key这些看似选 A 选 B 的小决定直接决定你后面要不要半夜爬起来排障。这篇文章我基于自己的项目经验把“Jenkins 配置 GitLab 认证并实现自动化部署”的完整链路拆开来讲适合正在搭 CI/CD、或者已经搭了但经常 Job 报错的同学读完你至少能搞明白三件事认证怎么配最稳Pipeline 怎么写能直接落地以及报错后从哪儿开始查。1. 项目脉络为什么我把认证和部署绑在一起聊1.1 先分清三个“登录”很多新手第一次搭 Jenkins 就懵了明明登录 Jenkins 是正常的为什么 Job 里连 GitLab 拉代码总失败因为这里至少有三种“登录”登录 Jenkins 控制台这是 Jenkins 自己的用户体系跟你访问 GitLab 没关系。Jenkins 作为一个客户端去访问 GitLab这是机器身份常见形式是 Token、Deploy Key、SSH Key。GitLab 网页登录这是人用的身份有 2FA、SSO 之类。自动化部署里真正要解决的是第二种。Jenkins 不是代替你登录网页而是以某个“机器人身份”去 GitLab 拉代码、触发构建甚至回写构建状态。这个区分想清楚之后后面所有配置就顺了。你不需要把 GitLab 的管理员账号密码塞给 Jenkins更不应该把个人密码暴露在 Jenkins 的配置里因为一旦有人看到你的 Job 配置就等于拿到了你 GitLab 账号的操作权限风险非常大。正确做法是单独创建一个低权限的机器人账号或者直接用我后面要讲的 Personal Access Token / Deploy Key。1.2 自动化部署的整体链路长什么样我习惯把这个链路画成四段虽然这里不方便画图但你可以在脑子里勾勒一下开发 push 代码到 GitLab 仓库 → GitLab 通过 Webhook 通知 Jenkins → Jenkins 根据分支匹配对应的 Pipeline Job → Pipeline 依次执行拉代码、构建、测试、推送镜像/制品、SSH 到服务器执行部署命令。整条链路的“大脑”是 Jenkins 的 Pipeline 脚本但“神经”就是认证配置。如果某一环认证断了比如 Jenkins 拉不到代码或者 Webhook 通知被 Jenkins 拒绝后面所有环节都会停。所以我的建议是不要一上来就写一堆流水线先把“认证 手动构建 手动部署”跑通再加 Webhook 自动化。这样排障范围小出了问题一眼就能定位是在认证阶段还是构建阶段。下面我按 GitLab 侧、Jenkins 侧、Pipeline 实战这个顺序展开最后把高频报错集中整理一遍方便你直接对照。2. GitLab 侧准备不管选哪种认证先把这几个开关备好2.1 用 Personal Access Token 认账最省事也最通用Personal Access Token简称 PAT是我最常用的方式。GitLab 里创建路径是右上角头像 → Preferences偏好设置→ Access Tokens访问令牌老版本可能叫 User Settings Access Tokens。创建时最需要注意的是 Scope权限范围Scope作用要不要勾api可以调用 GitLab 全部 API包括创建 Webhook、改仓库设置等绝大多数 Jenkins 集成场景需要勾read_repository只读仓库内容能拉代码如果只是拉代码勾这个就够write_repository写入仓库内容一般配合 API 使用如果需要 Jenkins 回写构建状态、打 Tag 之类建议勾read_user读取用户信息个别插件需要按需勾read_api只读 API 权限如果不想给完整 api可折中勾这个填完 Name设置过期时间点击 CreateGitLab 只会给你展示一次 Token 值一定要当场复制保存。Token 的格式是一长串随机字符形如glpat-xxxxxxxxxx。然后回到 Jenkins 侧保存时我建议用户名处填一个便于识别的名字比如jenkins-bot密码处填 Token 值。有人会问“用户名填什么是不是填 GitLab 账号名”在 GitLab 的 HTTP Basic 认证逻辑里用户名其实可以随便填真正有效的是 Token 这一串但为了维护清晰我习惯填gitlab-token或者专门的机器人名。这里有一个实操细节如果 GitLab 账号开了双因素认证2FA用真实密码直接拉代码是会被拒的此时 Token 几乎是唯一的选择。所以哪怕你只是个小团队我也建议上手就直接用 PAT别费劲去折腾真实密码的兼容性。2.2 什么时候改用 Deploy Key / SSH KeyPAT 适合“一个 Jenkins 要访问多个项目”的场景因为它作用域是整个账号。但如果你公司安全要求比较严格希望 Jenkins 只能访问某一个仓库甚至只允许拉代码、不允许写其他东西那就用 Deploy Key。Deploy Key 是 SSH Key 的一种。你在服务器上执行ssh-keygen -t rsa -b 4096 -C jenkins-deploy -f /root/.ssh/jenkins_deploy_key生成一对公钥私钥。然后把公钥内容贴到 GitLab 项目里的 Settings → Repository → Deploy Keys勾选可写权限后保存。私钥则放到 Jenkins 的凭据里。这样做的好处是权限边界非常小一把 Key 只对一个仓库有效而且可以随时在 GitLab 里删掉不影响其他项目。坏处是如果你有 30 个项目就要维护 30 把 Key管理成本上来了。我的经验是测试环境、临时项目用 Deploy Key正式核心项目用 PAT 项目级权限控制各取所长。另外如果是 Jenkins 需要 clone 私有依赖库比如 Maven 依赖放在某个私有 GitLab用 SSH 方式比 HTTP Token 方式稳定得多。因为 Maven/Gradle 在解析 SSH URL 时不需要额外的凭据配置只要 Jenkins 构建节点上有这把 Key 就行。2.3 版本兼容性预检清单GitLab 版本这块很多人吃过暗亏。你可能会在 IDEA、VS Code 或 Jenkins 插件里看到类似提示“GitLab versions older than 14.0 are not supported”或者login failed. check api token or gitlab version。这不是你操作错了而是新版插件/工具默认走新的 API 协议老版本 GitLab 不支持。GitLab 14.0 前后API 对 Token 的校验方式有一些变化新版插件会先调一个请求来探测版本探测失败就直接拒绝登录。所以配置之前先确认你的 GitLab 到底是多少版。如果低于 14.0有两个方向升级 GitLab这是最彻底的方案但升级有风险需要提前备份。换旧版本的 Jenkins 插件或 IDE 插件让插件逻辑适配旧 API或者改用 SSH Key 拉取代码绕开 API 探测这块。我建议矩阵里保持简单GitLab 14 以下强制团队统一用 SSH Key 认证GitLab 14 及以上随便你选 Token/SSH。另外GitLab API 的 Base URL 一定不要填错多数情况就是http://gitlab.example.com/api/v4/少一个/api/v4都会导致接口 404插件报错但不会提示得很明显。还有一个小按钮GitLab 14 以上有些版本默认停用了“不推荐认证方式”比如明文密码登录。如果你用浏览器登录正常但 Jenkins 用密码方式连不上去 GitLab 管理员后台看看有没有类似的登录限制开关这属于最容易忽略的一环。3. Jenkins 侧配置从全局工具到凭据的完整动作3.1 插件清单与版本建议Jenkins 的插件生态很杂不要全装按我下面的清单来基本够用插件作用说明GitLab Plugin让 Jenkins 识别 GitLab Webhook并支持 GitLab 相关步骤必装比如触发构建、回写构建状态Git Parameter Plugin构建时动态选择分支/Tag我习惯装手动构建时不用改配置PipelineJenkinsfile 运行环境装 Pipeline 相关全套即可Credentials Binding在 Pipeline 里安全引用凭据必装SSH Agent Plugin把 SSH 私钥临时加载到构建环境如果走 SSH 部署必装Docker Pipeline构建镜像、登录仓库用到容器化才装插件版本建议不要长期停留在“能跑就不升”的状态。GitLab 和 Jenkins 都在频繁迭代老插件很可能遇到 API 不兼容。我一般是每月抽空升级一次插件升级前看 Change Log升级完先在一个废弃 Job 上跑一遍。装好插件后去 Manage Jenkins → Plugins → Available plugins搜索安装即可。国内网络下如果插件下载慢可以先在 Advanced Settings 里换镜像源或者直接离线安装 .hpi 文件这个属于常见基础操作不过多展开。3.2 凭据填写的关键表格在 Jenkins 里配置 GitLab 认证路径是Dashboard → Manage Jenkins → Credentials → System → Global credentials → Add Credentials。常见类型和填法如下凭据类型适用场景关键字段怎么填Username with passwordHTTP 方式拉取 GitLab 代码或用 PAT 调 APIUsername 填机器人名Password 填 TokenSSH Username with private key走 SSH 协议拉代码/部署Username 填任意名字Key 里粘贴私钥内容GitLab API Token新版 GitLab 插件专用的 Token 类型直接填 Token插件自己会处理 Base URLSecret text存 Webhook Secret Token用于校验 GitLab 发来的请求很多人在“Username with password”里把密码填成自己的 GitLab 登录密码结果怎么都连不上。这里再说一遍如果你开了 2FA密码是假的就算没开真实密码权限也太大。正确的做法就是密码处填 PAT 那一串。还有一个小细节SSH 私钥的格式必须是标准的 OpenSSH 私钥块以-----BEGIN OPENSSH PRIVATE KEY-----或-----BEGIN RSA PRIVATE KEY-----开头。如果用的是 PuTTY 生成的.ppk格式Jenkins 认不了需要先在 PuTTYgen 里转换成 OpenSSH 格式。3.3 全局设置与构建环境准备创建完凭据后别急着写 Job先把 Jenkins 的全局工具链配好。Manage Jenkins → Tools 里配置 JDK、Maven、Node.js 等。版本号要和 GitLab CI 里用的大致对齐不然本地构建通过、Jenkins 构建失败的情况会反复出现。如果你是用 Docker 部署应用构建节点上必须能执行 docker 命令。这里最常见的坑是两种Jenkins 和 Docker 不在同一台机器需要远程 Docker Host比如tcp://docker-host:2375。只填 URI 还不够一般要配 TLS 证书否则 docker 客户端默认不信任不安全端口。Jenkins 跑在容器里构建时要用宿主机的 Docker启动 Jenkins 容器时加参数-v /var/run/docker.sock:/var/run/docker.sock把宿主机的 Docker 套接字挂进去。这样 Jenkins 容器内执行 docker 命令实际是请求宿主机 Docker。挂载 socket 之后宿主机上执行 docker 的是 root 还是某个用户会影响 Jenkins 容器内是否有权限。如果报permission denied while trying to connect to the Docker daemon socket多半是 socket 文件的权限组问题可以把 Jenkins 用户加进 docker 组或者在容器启动时以合适用户运行。4. 实战流水线写一个能真正部署的 Jenkins Pipeline4.1 设定一个典型部署目标为了不悬空我拿一个非常常见的场景来讲Spring Boot 项目代码推到 GitLab 的 master 分支Jenkins 拉代码后用 Maven 打包再把 jar 包通过 scp 传到应用服务器/data/app然后 ssh 上去执行systemctl restart app或者直接用nohup java -jar重启。目标很朴素但这段链路覆盖了认证拉代码、构建Maven、部署SSH三个核心环节跑通之后你再横向改成前端、Python、Docker 都很顺。4.2 完整 Jenkinsfile 参考我把 Pipeline 写在 Jenkinsfile 里这样就存在 GitLab 仓库里维护方便分支策略也清晰。这里给一份简化但可运行的参考pipeline { agent any environment { // 引用 Jenkins 里配置好的 GitLab 令牌 GITLAB_CRED credentials(gitlab-token) // 应用服务器信息 DEPLOY_SERVER root192.168.1.10 APP_PATH /data/app/demo.jar } stages { stage(拉取代码) { steps { checkout scm } } stage(Maven 构建) { steps { sh mvn clean package -DskipTests } } stage(上传并部署) { steps { sshagent([deploy-ssh-key]) { sh scp target/*.jar ${DEPLOY_SERVER}:${APP_PATH} sh ssh ${DEPLOY_SERVER} systemctl restart demo-app } } } } post { failure { // 失败时把状态回写给 GitLab updateGitlabCommitStatus(name: build, state: failed) } } }这里有几个点要特别说明。checkout scm会自动使用 Job 里配置的 Git 仓库地址和凭据不需要手动写 git clone。如果要手动拉某个分支也可以写成git branch: master, credentialsId: gitlab-token, url: http://gitlab.example.com/group/repo.git。sshagent([deploy-ssh-key])会把 Jenkins 凭据里的 SSH 私钥临时注入环境然后 scp/ssh 就能免密访问服务器。注意这个凭据不是 GitLab 用的 Deploy Key而是你用来登录应用服务器的私钥。我见过有人混用把 GitLab 的 Deploy Key 拿去 ssh 应用服务器结果被拒绝因为两个系统的授权完全独立。updateGitlabCommitStatus是 GitLab Plugin 提供的方法能把构建结果同步到 GitLab 的提交记录上释放手去 GitLab 页面刷新看状态的洁癖。4.3 Webhook 触发配置与分支策略Pipeline 跑通之后再加自动触发。GitLab 仓库里 Settings → Webhooks → Add WebhookURL 填http://你的Jenkins地址/project/你的Job名Secret Token 填一个自定义字符串并在 Jenkins 对应 Job 的配置里也填上同样的 Token这样 GitLab 请求 Jenkins 时会做校验防止陌生人拿着 URL 乱触发构建。Trigger 里建议不要勾所有事件只要 Push events 和 Tag push events。分支过滤可以选main/master避免开发分支一推就触发一堆没意义的构建。这里有个 Webhook 很常见的 403 问题Jenkins 默认开启 CSRF 保护GitLab 发来的请求没带正确的 crumb就会报 HTTP 403。老版本 GitLab Plugin 能自动处理但如果你用的是新版可能需要在 Jenkins 系统配置里把 GitLab 的 API Token 配好或者在“GitLab 连接”里启用“忽略 SSL/TLS 证书”和“允许钩子”相关配置。遇到 403 时第一反应不是关掉 CSRF而是去查 Jenkins 里 GitLab 连接是否配置完整。分支策略上我强烈建议核心分支开启 GitLab 分支保护。这个在 GitLab 项目仓库 Settings → Repository → Protected branches 里配置。很多团队有一个误解Developer 角色能不能直接推 master答案很直接如果 master 是默认的受保护分支Developer 是推不上去的只能提 Merge Request由 Maintainer 批准后合并。这个设计是对的不要为了省事而关掉保护。如果实在需要某个 Developer 直推可以在保护分支设置里把 Allowed to push 改成“Maintainers 指定角色”但请务必在代码评审流程上把补偿措施补上否则就是自己给自己挖坑。5. 排坑速查这几个报错我基本每周都见5.1 login failed 系列模拟场景你在 Jenkins 里配好 GitLab 凭据跑构建日志里弹出login failed. check api token or gitlab version或者 IDE 里登录提示 GitLab 版本太低。这个在 2.3 里已经讲了思路这里给出具体排查顺序确认 GitLab 版本号左下角 Help 里能看到或者访问/help页面。检查 Token 是否带glpat-前缀有没有多粘贴空格。检查 API Base URL最常见错误是把http://gitlab.example.com/api/v4/写成了http://gitlab.example.com/。检查账号状态是否被锁、是否过期、是否需要强制 2FA。如果是老版本 GitLab直接放弃 Token 方式改 SSH。有的同学问为什么 IDE 提示 “versions older than 14.0 are not supported” 但 Web 页面登录正常因为 IDE 插件调用的接口路径变了老版本 GitLab 没有实现新接口自然返回不支持。这个只能升级 GitLab 或降级插件没有第三条真正干净的出路。5.2 权限不足系列典型报错You are not allowed to push code to protected branches。这也是热词里“gitlab developer 可以提交代码到 master 吗”的答案来源。处理办法是去 GitLab 的 Protected Branches 页面看当前分支是否被保护。如果确实需要直推就把该分支的 Allowed to push 放开一些如果不想放开就全流程走 Merge Request。还有一个权限问题容易被忽视Jenkins 用的 Token 只勾了read_repository但 Pipeline 里想调用 GitLab API 创建 Tag就会报 403。解决办法是给 Token 补api或write_repository权限不要一上来就怀疑插件坏了。5.3 容器内 Docker 与网络问题场景Jenkins 的节点是容器构建时执行 docker build报Cannot connect to the Docker daemon。按我 3.3 里的解法把/var/run/docker.sock挂进去一顿操作之后可能还会遇到镜像拉取很慢的问题。国内网络环境下Docker Hub 的镜像拉取经常超时这个可以配置 Docker daemon 的 registry mirror比如在/etc/docker/daemon.json里写 registry-mirrors 或 daocloud 等公共镜像加速地址然后重启 docker。配置完成后再执行docker pull速度会明显改善。如果 Jenkins 配置的是远程 Docker Hosttcp://...比如网上搜到docker host uri root那你要确认是否是带 TLS 的。裸 2375 端口很容易被攻击正式环境一定配 TLS 或走 Dind 容器。这个不用图省事我被裸 2375 坑过一次第二天发现服务器上多了个挖矿容器教训很深刻。5.4 Jenkins 挂起与队列问题构建一直显示“等待”或“已排队”第一反应是看 Executor 数量。Jenkins 默认只有 2 个 Executor如果同时跑几个 Job 就把队列挤满了。可以到 Manage Jenkins → Nodes 里调大 Number of executors或者在流水线里给不同阶段分配不同 agent label。还有一种情况是 Webhook 触发了新构建但老构建还在跑导致后续阶段都卡住。Pipeline 里用options { disableConcurrentBuilds() }禁止并发即可。如果希望新构建取消旧构建用options { disableConcurrentBuilds(abortPrevious: true) }。这条对自动化部署很重要推两次代码前一次还在跑就把它停掉保证最终部署的是最新代码。6. 我的一点实操体会与后续扩展方向6.1 把部署动作抽象出来跑通这套基础方案后我建议你把部署动作从 Pipeline 脚本里抽出来独立成一个 shell 脚本放到服务器上Pipeline 里只留一行sh ssh ${DEPLOY_SERVER} bash /data/scripts/deploy.sh demo.jar这样做的好处是部署逻辑变更不需要重新跑整个流水线也不用重启 Jenkins直接在服务器上改脚本就行。而且后续蓝绿发布、回滚版本脚本里都能写逻辑比在 Jenkins 里手写一堆 Groovy 好维护得多。另一个抽象点是凭据统一管理。不要每个 Job 各自建凭据而是建一个全局凭据所有项目 Job 通过credentials(gitlab-token)引用。换 Token、换服务器密钥时只改一处谁都不会漏。6.2 进一步自动化Webhook 质量门禁 部署告警基础自动化跑起来之后可以继续加三样东西Webhook 里勾上 Merge Request events让 Jenkins 在 MR 创建时就跑静态检查和单测提前把问题暴露在合并之前。Pipeline 里按 SonarQube 质量门禁结果决定是否继续发布比如单元测试覆盖率低了就直接失败而不是等人工看报告。部署完成后通过企业微信/钉钉机器人发通知内容带上构建人、分支、版本号、部署时间和结果。这个实现也不难Pipeline 的post块加一个sh curl调用机器人 Webhook 就行。我也建议团队尽早用上glabGitLab CLI来辅助日常操作比如命令行创建 Merge Request、查流水线状态。虽然不是 Jenkins 侧必需但能把 GitLab 操作自动化水平拉上一层配合 Jenkins 使用时效率更高。最后再分享一个小技巧但凡是认证相关的报错我一般先手工验证一次“这个 Token/Key 能不能拉代码”。随便找个目录执行git clone http://用户名:Tokengitlab地址/组/仓库.git能拉通再回去查 Jenkins拉不通问题就在 GitLab 侧压根不用碰 Jenkins。这个习惯帮我避开了无数次无效排障。做 CI/CD 这件事急躁是大忌把认证当成一个明确的“先决条件”处理后面的部署链路才会顺。
返回列表