尧图精选

GitLab部署与CI/CD实践:从Docker安装到自动化流水线

🕒 发布时间:2026/9/15 8:03:13 📁 来源:尧图网络
1. 部署与安装先把GitLab跑起来1.1 部署方式选型先想清楚再动手聊GitLab之前我猜你大概率是这两种情况之一要么公司想搭一套内网的代码托管平台把代码从第三方平台迁回来自建要么你自己想搞一台服务器把GitLab跑起来当个人代码仓库和CI/CD调度中心。我接触GitLab的时间不算短从最早公司自建到后来自己用Docker部署踩过的坑能写满一个备忘录。老实说GitLab不像某些开箱即用的小工具它本质上是一套重量级研发协作平台部署前如果不把方案想清楚后面改起来会相当痛苦。部署方式其实就三条路直接用GitLab官方的SaaS服务、在自己的服务器上用Omnibus包安装、用Docker容器跑。官方SaaS解决的是“不想运维”的问题适合个人或小团队注册即用不需要关心升级、备份、安全问题但代码托管在别人那里对于很多公司来说合规上过不去。自己搭服务器则是完全不同的思路。大多数企业选它是因为要代码资产100%掌握在自己手里同时利用GitLab自带的CI/CD、仓库管理、代码评审流程来统一研发流程。我见过很多团队一开始图省事用第三方平台等到要接内网权限系统、自定义CI构建流程的时候才意识到自由度的价值最后还是要折腾一套自建的。Docker部署是我个人使用频率最高的方式它有几个明显优势升级方便、环境隔离干净、迁移简单。你只需要维护一份docker-compose配置换服务器的时候几行命令就能把整个平台恢复起来。不过Docker方式也要注意GitLab是一个多进程应用如果宿主机配置不够大团队使用会明显卡顿。我自己的经验是5人以下小团队用2核4G的机器勉强能跑10人以上至少4核8G起步磁盘建议单独挂一块SSDGit仓库的读写性能对磁盘IO非常敏感。1.2 Docker方式安装GitLab十分钟跑通第一步Docker安装GitLab我先给出一个我长期在用的最小化部署方案。这里用的镜像是gitlab/gitlab-ceCE就是社区版功能上对绝大多数团队完全够用。你不需要单独拉取数据库、Redis之类的容器GitLab镜像内部已经集成了这些组件开箱即用。# 创建数据目录目录结构建议固定下来方便后续备份 mkdir -p /srv/gitlab/config mkdir -p /srv/gitlab/logs mkdir -p /srv/gitlab/data # 启动容器 docker run --detach \ --hostname gitlab.example.com \ --publish 8443:443 --publish 8080:80 --publish 2222:22 \ --name gitlab \ --restart always \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest这里有几个参数我展开说一下因为它们直接影响你后续的使用体验。--hostname决定了GitLab生成的仓库URL地址。如果你不设置域名建议直接填服务器的IP比如--hostname 192.168.1.100这样clone仓库的时候地址就是http://192.168.1.100/group/project.git访问起来最省事。端口方面我这里做了自定义映射宿主机8080映射容器80HTTP8443映射443HTTPS2222映射22SSH。注意SSH端口宿主机22端口经常被系统自带的sshd占用所以映射到2222但这就意味着你后面配置SSH克隆地址时需要写成ssh://gitgitlab.example.com:2222/group/project.git这也是很多人第一次配置SSH时死活连不上的原因之一。启动之后容器第一次启动会有一个初始化的过程通常需要两三分钟。GitLab社区版默认会为管理员账号root生成一个随机密码存放在容器内的/etc/gitlab/initial_root_password文件中。你需要执行下面这条命令来查看docker exec -it gitlab cat /etc/gitlab/initial_root_password拿到的密码用于首次登录登录后记得马上在用户设置里改成自己的密码。这个随机密码文件在首次登录后24小时会被GitLab自动删除如果你忘了查看就得另外走重置流程挺麻烦的。另外我特别建议部署完之后立刻去Admin Area - Settings - Network里把“限制创建项目、限制注册”这些选项打开。GitLab默认是允许任何人注册账号的如果部署在内网还好一旦暴露到公网扫描机器人分分钟给你注册一堆垃圾账号这是我踩过最痛的坑之一。1.3 离线环境部署GitLab没网也能装前面说过很多企业内网和生产环境是物理隔离的没法直接在线拉取镜像或安装包。这种情况下就需要走离线安装路线我工作中也处理过不少这类需求这里分享一下Linux环境下的离线部署思路。第一步是在一台能上网的同系统环境下去GitLab官方或清华镜像站下载对应系统版本的RPM包。GitLab官方下载页面提供了版本选择注意要匹配你的系统发行版比如CentOS 7对应的就是el7版本Ubuntu 20.04对应的是focal版本。我用得比较多的是清华镜像源速度比官方快很多地址是https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/版本号和企业版名要对应好。下载好RPM包之后拷贝到内网服务器上执行安装# 先安装依赖离线环境如果有本地yum源直接装没有的话要提前把依赖包下载好 sudo yum install -y curl policycoreutils openssh-server openssh-clients postfix # 安装GitLab sudo rpm -i gitlab-ce-16.10.2-ce.0.el7.x86_64.rpm # 配置external_url这一步很关键不配置后面访问会有一堆奇怪问题 sudo vim /etc/gitlab/gitlab.rb # 找到 external_url http://gitlab.example.com改成实际IP或域名 # 重新配置并启动 sudo gitlab-ctl reconfigure sudo gitlab-ctl status离线安装最常见的坑是依赖缺失。GitLab依赖的组件不少比如policycoreutilsSELinux相关、openssh-server、postfix邮件通知这些在最小化安装的Linux系统上经常没有。更麻烦的是有些依赖本身还有依赖纯离线情况下要把整棵依赖树都准备好。我的习惯是先准备一台和离线服务器同样系统版本、同样架构的机器用yum downloadext --resolve把需要的RPM全部拉下来再转移到内网批量安装这样最保险。external_url这个配置项特别值得多说一句。很多人在离线部署时图省事不配置结果启动后页面上生成的仓库地址全是默认的gitlab.example.com导致代码clone地址全部无法访问。我一般是部署完第一时间检查这个配置要么改成服务器的实际IP要么改成内网DNS能解析的域名。如果改完发现页面地址还是不对需要执行gitlab-ctl reconfigure并重启服务因为Omnibus包很多配置是启动时一次性写入的不是动态生效。2. 日常使用入门注册、SSH与代码仓库操作2.1 账号注册真的不需要Visa卡“GitLab注册需要Visa卡吗”这个问题我居然在高频搜索里看到过那就在这里顺便辟个谣。无论你用的是GitLab官方SaaS还是自建的社区版普通账号注册都只需要一个邮箱跟信用卡没有任何关系。需要绑卡的情况只存在于企业版某些计费功能或高级服务中日常使用完全用不上。如果是自建的GitLab管理员默认开启了注册功能你直接去登录页点“Register now”填邮箱、用户名、密码就行。注册完之后你还需要让管理员把你拉进对应的Group或项目里并分配角色权限。GitLab的权限体系分五个级别Guest访客、Reporter报告者、Developer开发者、Maintainer维护者、Owner所有者。实际使用中普通研发给Developer就够了可以push代码、创建分支、发起合并请求Maintainer以上才有权限修改项目设置和管理成员。2.2 配置SSH密钥一次配置长期使用SSH密钥是GitLab日常使用中最基础也最影响体验的一环。很多新手第一次clone代码时提示权限失败八成就是SSH密钥配置出了问题。我先把最标准的操作流程贴出来。# 生成SSH密钥对-t指定算法-C填你的邮箱-b指定长度 ssh-keygen -t ed25519 -C your_emailexample.com -f ~/.ssh/id_ed25519 # 查看公钥内容把这段内容复制到GitLab的SSH Keys页面 cat ~/.ssh/id_ed25519.pub登录GitLab之后点击右上角头像 - Preferences - SSH Keys把刚才复制的公钥粘贴进去起个容易辨识的标题保存就完成了。GitLab支持同时添加多个公钥比如一台办公电脑一台家用电脑你可以分别生成各自的密钥对并添加这样不管在哪台机器上都能正常访问仓库。配置完成后建议先做一次连接测试来验证是否真的通了ssh -T gitgitlab.example.com如果看到Welcome to GitLab, yourname!这段输出说明SSH密钥配置成功可以正常clone代码了。密钥算法我建议直接用ed25519安全性比传统的RSA 2048更高密钥长度更短GitLab新版本完全支持。如果你用的还是老旧的RSA格式建议尽快升级。SSH还有个好处是无需频繁输入账号密码在命令行操作时体验比HTTPS方式好很多。但如果你用的是局域网GitLab且经常换电脑HTTPS方式配合Git的credential store也能做到类似效果只是每次新增机器都要重新验证我个人还是推荐SSH一条路走到底。2.3 代码上传与拉取从页面操作到命令行代码上传这块我见过两种完全不同的场景。一种是已经用Git很多年的老手上来直接命令行初始化另一种是偏测试或文档的同学习惯在GitLab页面上传文件。两种方式我都说下。命令行方式以把一个已有的本地项目推送到新建的GitLab仓库为例# 在GitLab上新建空项目后会得到一个仓库地址比如 # http://gitlab.example.com/myteam/myproject.git cd myproject git init git add . git commit -m init project git remote add origin http://gitlab.example.com/myteam/myproject.git git branch -M main git push -u origin main这里注意git branch -M main是让默认分支名统一为main。GitLab默认分支名是main如果你本地默认是master不重命名直接push会出现远端有两个分支的情况虽然不影响功能但团队协作时分支不够规范容易混乱。页面方式更简单进入项目页面后点击号选择Upload file或者直接进入某个目录点Upload files把本地文件拖拽进去即可。不过这种方式有大小限制且每次只能操作少量文件适合偶尔传个文档或配置文件。如果是批量代码千万别用页面传老老实实走命令行。拉取代码这件事本质上就是一个命令git clone 仓库地址。但实际工作中我更建议用git clone之前先想好你要克隆的分支。比如你要拉取某个功能分支的代码可以直接git clone -b feature/login http://gitlab.example.com/group/project.git避免克隆完默认分支还要切换。另外如果公司仓库特别大历史提交很多可以考虑--depth 1做浅克隆只拉取最新一次提交能节省大量时间和磁盘空间。不过浅克隆后续如果要看历史记录或切换分支需要再git fetch --unshallow把历史补回来各有利弊。3. 分支管理与协作模型别让Git变成“混乱之源”3.1 分支策略一套适合团队的Git Flow代码托管只是GitLab的基本功能真正让团队协作顺畅的是分支管理策略。我见过太多团队所有人都在一个main分支上直接提交发布的时候手忙脚乱出了问题甚至不知道回滚到哪个提交。这种情况不是Git的问题而是缺少一套明确的分支管理约定。我个人比较推荐的是简化的Git Flow模型它不需要像完整版那样重但对于中小团队足够清晰。核心分支就两个main主干始终保持可发布状态和dev日常集成开发分支。功能开发时从dev拉出feature/xxx分支开发完通过Merge Request合并回dev。准备发布时从dev拉出release/x.x.x分支只做修复不开发新功能测试通过后合并到main并打上tag。这个模型最大的好处是main永远是干净的、可发布的任何人任何时候拉取最新代码都不会拉到半成品。分支命名也建议规范化比如feature/订单模块、bugfix/登录异常、hotfix/紧急修复通过前缀一眼就能看出分支的用途。GitLab里我们还可以在项目设置里为受保护分支设置规则比如main分支禁止直接push只能通过Merge Request合入这样从工具层面强制了代码评审流程。3.2 如何查看某个分支是从哪个分支拉出来的“GitLab如何查看某个分支是从哪个分支拉取的”这个热搜词出现的频率挺高我一开始有点意外后来想想确实是个很实际的痛点。你接手一个老项目看到几十个分支根本分不清谁是谁的爹。查分支来源我常用的命令有这几条。# 查看分支的最近共同祖先与合并基础 git merge-base --fork-point feature/login dev # 查看包含关系dev分支是否已经包含feature分支的提交 git branch --merged dev # 最直观的方式查看分支图 git log --graph --oneline --decorate --all其中git merge-base --fork-point是我用得最多的它可以直接找出两个分支是在哪个提交开始分叉的。举例来说你执行git merge-base --fork-point feature/login dev如果输出一个commit hash再用git log -1 hash查看这个提交的信息就能大致判断feature/login是从dev的哪个位置拉出来的。但说实话Git本身并不会记录“某个分支是从哪个分支拉出来的”这个元信息它只记录提交的父子关系和图结构。所以如果你真想做到可追溯更靠谱的方式是在分支命名上就携带信息或者在创建分支时用git push的--set-upstream选项让远端明确知道上游关系。还有一个小技巧适合查看分支生命周期中的分叉点# 显示两个分支从共同祖先以来的提交差异 git log --oneline --graph --left-right --cherry-pick --boundary main...feature/login这个命令在评审Merge Request之前使用非常方便能清晰看到feature分支相对于main做了哪些改动哪些是cherry-pick过来的哪些是冲突的。3.3 合并请求与代码评审把好质量关口GitLab把Pull Request叫Merge Request简称MR。MR机制不只是代码合并的工具更是团队做代码评审的抓手。我强烈建议所有团队不管人多人少都养成“改动必须走MR”的习惯哪怕只有你自己一个开发MR也能让你在合并前重新审视一遍diff很多低级错误就是在这一关被拦住。创建MR的入口很简单推送分支之后GitLab会在项目页面提示你创建MR或者点击Merge Requests - New Merge Request选择源分支和目标分支。创建时建议把模板写好背景说明、改动范围、测试情况、关联Issue。这些信息看起来繁琐但三个月后你回看历史MR时就会感谢自己写清楚了。GitLab内置的评审功能其实很全面。你可以在diff的每一行发起评论作者可以回复或标记为已解决评审人还可以在最后通过Approval功能正式批准合并。在项目设置中可以配置最少需要几个Approval才能合并这对核心主干分支特别有用。我曾经的团队就设置成main分支必须至少2人Approval才能合并虽然执行初期大家不太适应但后面代码质量肉眼可见地提升了。4. CI/CD流水线从代码提交到自动部署4.1 先理解CI/CD的整体结构GitLab CI/CD是我认为它相对其他代码托管平台最有竞争力的功能。你只需要在仓库根目录放一个.gitlab-ci.yml文件GitLab就会自动识别并调度构建任务完全不需要额外的配置服务。先理清几个基础概念。Runner是执行任务的代理程序它可以是独立的服务器、虚拟机、容器甚至你的笔记本GitLab将job任务分发给Runner执行再把结果上报回GitLab。Pipeline是一整条流水线由多个stage组成比如常见的build - test - deploystage下面有具体的job一个job就是一组命令。.gitlab-ci.yml的核心就是定义这些stage和job的关系。Runner需要在每个项目中注册注册时需要GitLab实例提供的注册token。你可以在Admin Area - CI/CD - Runners里看到这个token和注册命令。安装Runner也很简单Linux下通常是一个RPM包加两行命令# 安装GitLab Runner sudo rpm -i gitlab-runner_16.10.2-1_amd64.rpm # 注册Runner交互式问答模式 sudo gitlab-runner register注册时长按你的环境选。shell执行器最简单直接在Runner所在机器上执行命令docker执行器更弹性和隔离每个job都在独立的容器中运行这也为后面Docker镜像构建提供了便利环境。我个人推荐团队用docker执行器因为构建环境可以完全由Dockerfile定义一次配置到处运行。4.2 Docker镜像构建与自动化部署的完整实践在GitLab CI/CD中构建Docker镜像并部署是我觉得最有实际价值的一块内容也是很多团队还没打通的关键环节。先讲构建。我们知道在CI里执行docker build需要Docker环境如果你的Runner用的是shell执行器直接装Docker就行。但更标准的方式是用docker执行器然后在job中挂载Docker的socket实现“DinD”Docker in Docker这样job内部就有独立的Docker环境了。下面是一套我实际使用的.gitlab-ci.yml模板实现了“代码推送后自动构建镜像并推送到镜像仓库然后通过SSH登录服务器拉取镜像并重启容器”的完整链路stages: - build - deploy variables: IMAGE_NAME: registry.example.com/myteam/myapp IMAGE_TAG: $CI_COMMIT_SHORT_SHA build_image: stage: build image: docker:24.0.7 services: - docker:24.0.7-dind before_script: - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin registry.example.com script: - docker build -t $IMAGE_NAME:$IMAGE_TAG . - docker push $IMAGE_NAME:$IMAGE_TAG only: - main deploy: stage: deploy image: alpine:3.19 before_script: - apk add --no-cache openssh-client - eval $(ssh-agent -s) - echo $DEPLOY_SERVER_PRIVATE_KEY | ssh-add - script: - ssh -o StrictHostKeyCheckingno root$DEPLOY_SERVER_HOST docker pull $IMAGE_NAME:$IMAGE_TAG docker stop myapp || true docker rm myapp || true docker run -d --name myapp -p 8080:80 $IMAGE_NAME:$IMAGE_TAG only: - main when: manual这套流程里几个细节我认为值得单独说明。$CI_COMMIT_SHORT_SHA是GitLab预定义变量代表当前提交的短哈希用它做镜像tag可以保证每个提交对应的镜像都是唯一的部署之后也能精确定位是哪个代码版本在运行。when: manual让部署这一步需要人工点击执行而不是自动触发这个策略适合生产环境避免代码一推就自动上线导致来不及检查。如果你对自动化有信心可以把when: manual去掉改成自动执行但部署前一定要有完善的回滚方案。这个过程中最容易出问题的地方是Docker in Docker的共享资源冲突。多名开发者同时推送代码触发多个pipeline并行时如果它们共享同一个dind服务偶尔会有镜像层缓存冲突。解决办法是给每个job配置独立的service或者为每个pipeline使用独立的命名空间GitLab在较新版本中对dind的支持已经好了很多不再需要格外担心。4.3 GitLab与Jenkins集成经典组合不踩坑虽然GitLab自带CI/CD已经很强但很多公司旧的CI系统是Jenkins短时间内不会完全迁移。于是“GitLab加Jenkins”就成了一个非常常见的过渡组合大家在搜索引擎里频繁搜“jenkins配置gitlab connection”也印证了这一点。Jenkins与GitLab集成核心是两件事一是Jenkins能拉取GitLab仓库的代码二是GitLab能触发Jenkins任务。拉取代码很简单在Jenkins源码管理里填GitLab的仓库地址再配置好凭据Credentials即可。复杂的是触发联动通常我们通过GitLab的Webhook实现在GitLab项目里创建Webhook把Jenkins的地址如http://jenkins.example.com/project/myjob填进去配置触发事件为Push或Merge Request代码变化时GitLab就会通知Jenkins执行构建。实际集成时我踩过一个非常普遍的坑报错信息是gitlab login failed. check api token or gitlab version. log in via git if the version is too old这个报错基本集中在Jenkins的GitLab Plugin配置API Token那一环节。它翻译一下就是说Jenkins尝试用API Token调用GitLab API时认证失败。常见原因有三个Token配置错误、GitLab账号被禁用、GitLab版本过老导致API端点不兼容。解决办法是在GitLab里创建一个专门的账号或者用管理员账号在用户设置中生成Personal Access Token权限至少需要api和read_repository把token完整复制到Jenkins的GitLab Connection配置里。如果GitLab版本确实很老比如10.x之前建议先升级GitLab因为老版本的API接口已经不再被新版Jenkins插件兼容。4.4 Runner异动与Pipeline卡住几个急救手段CI/CD用久了总会有各种意外最常见的是Pipeline卡在pending状态迟迟不执行这通常意味着没有可用的Runner或者Runner的tag和job的tag不匹配。你可以在项目页面的CI/CD - Runners里检查是哪些Runner处于在线状态。如果Runner是离线的去Runner所在机器执行sudo gitlab-runner status查看服务是否正常再查看/var/log/gitlab-runner日志定位原因。另一个常见问题是构建环境缺依赖导致每次跑都报同样的错。我的建议是尽量把所有环境准备都写进Dockerfile或runner镜像里而不是在job里临时装。比如我经常让前端项目的job基于一个预装了node和pnpm的镜像这样构建时间能大幅压缩同时避免了公网软件源不稳定带来的概率性失败。5. 周边工具联动IDE、K8s与日常开发效率5.1 设置kubectl配置文件访问Kubernetes集群GitLab和Kubernetes的组合已经成为现代云原生部署的标准姿势。很多团队已经把GitLab CI/CD与K8s打通实现代码提交后自动构建镜像并滚动更新集群内应用。而要在本地或CI环境中访问Kubernetes集群第一步就是配置kubectl。kubectl访问集群依赖一个config文件默认路径是~/.kube/config。如果你用的是云厂商的托管K8s服务一般可以在控制台直接下载kubeconfig。自建集群则通常由管理员生成并分发文件。这个文件里包含了集群API Server的地址、证书和用户凭据本质上就是一把打开集群的钥匙所以文件权限非常敏感GitLab CI里使用它时要格外小心。在GitLab的CI/CD流水线中使用kubectl的典型做法是把kubeconfig内容设置为项目的CI/CD变量然后在job中动态生成配置文件deploy_to_k8s: stage: deploy image: bitnami/kubectl:latest script: - mkdir -p $HOME/.kube - echo $KUBE_CONFIG | base64 -d $HOME/.kube/config - kubectl apply -f k8s/deployment.yaml - kubectl rollout status deployment/myapp -n production这里把kubeconfig用base64编码后存到GitLab的变量中job执行时再解码回文件。注意变量的类型要选File或Variable且不要在日志中打印base64内容否则等于把集群钥匙公开了。我见过不止一次有人把kubeconfig直接提交到仓库里这种做法如果是个人的临时集群还好团队集群的话基本等于直接送管理员权限非常危险。5.2 IDEA、VS Code与SourceTree的日常集成日常开发工具上的GitLab集成直接影响开发效率。现在主流的IDE都原生支持GitLab的仓库操作包括clone项目、创建分支、提交代码、查看MR、甚至浏览CI流水线。IDEA的配置很简单Settings - Version Control - Git里配置好Git可执行文件路径然后在Settings - Version Control - GitHub或直接通过File - New - Project from Version Control粘贴GitLab仓库地址完成clone。IDEA可以从GitLab拉取项目列表需要安装GitLab插件并配置访问token。插件安装后在Settings - Tools - GitLab填入你的GitLab地址和Personal Access Token就能直接在IDEA里浏览和clone你可见的仓库了。VS Code同样支持GitLab扩展配置方式类似在扩展市场搜索GitLab Workflow安装后在设置中填写GitLab实例地址和token就可以在侧边栏浏览合并请求、GitLab CI流水线状态。SourceTree是很多Windows用户的图形化Git客户端。用SSH方式连接局域网Git服务器时重点在于SSH密钥的配置。SourceTree内置的SSH客户端可能和系统ssh-agent冲突我建议在SourceTree设置里改为使用系统Git自带的OpenSSH这样你的密钥配置一次命令行和SourceTree都能共用。如果连接时提示SSH认证失败多半是密钥格式不被识别或者没有正确添加到PageantPuTTY的认证代理。具体办法把id_ed25519私钥导入PageantSourceTree的认证选择PuTTY然后重新测试连接。这里还要说一个实操细节很多人在本地配置了多套SSH密钥比如一个用于GitLab一个用于个人仓库。SSH默认读取~/.ssh/id_rsa或id_ed25519如果密钥文件名不是默认的需要通过~/.ssh/config文件显式指定Host gitlab.example.com HostName gitlab.example.com User git IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yes这样ssh在连接特定Host时会使用指定密钥不用来回切换或反复覆盖默认密钥文件。这个问题看似简单但困扰过不少同事我还专门写了个小工具把常用Host的配置自动生成。6. 安全加固与常见问题排查维护一个稳定的GitLab6.1 高危漏洞修复升级是第一优先级GitLab这类DevOps平台一旦有高危漏洞影响面往往不只是代码托管本身CI/CD的权限扩大、多项目项目管理等特性都方便了攻击者横向移动。近年来GitLab多次公开过高危漏洞包括SSRF、任意文件读取、RCE等。修复方案里最重要的一条永远是保持GitLab版本更新。升级本身不需要过于担心。Omnibus包和Docker镜像都支持直接升级但在升级前务必查看官方升级路径图大版本跨版本升级时可能需要先升级到中间版本再继续直接跨大版本跳着升级会报错甚至导致数据损坏。这是不少人踩过的坑。我自己的习惯是每两个月看一次官方release notes有小版本就顺手升避免年久失修需要大跨度升级的尴尬。除了升级版本安全加固还应该包括关闭开放注册开启需要管理员审批或限定企业域名注册强制开启2FA至少对管理员账号强制为Runner设置专用的受限账号不推荐用root跑job对公网暴露的GitLab配置HTTPS并定期更新证书设置备份策略备份文件加密并异地存储备份这块值得单独提醒一下。GitLab的备份命令是gitlab-backup createDocker安装对应的命令是docker exec -t gitlab gitlab-backup create。备份只会备份数据库和Git仓库文件配置文件/etc/gitlab/gitlab.rb和密钥/etc/gitlab/trusted-certs需要额外手动备份。也就是说你只做备份命令是远远不够的必须连配置文件一起打包保存否则机器挂了之后恢复会非常痛苦。我一般会写一个定时任务同时备份数据、配置和环境变量文件放到远程存储上。6.2 常见报错排查速查表踩过的坑都在这里日常使用GitLab报错不算少而很多报错网上搜索出来的都是老版本的解决方案不一定适配这里把我自己实际踩过的常见问题整理成一个速查表方便你对照处理报错或现象可能原因排查和解决方法Host key verification failedSSH首次连接远程主机时没有确认指纹手动执行ssh-keyscan gitlab.example.com ~/.ssh/known_hosts或临时加-o StrictHostKeyCheckingnoPermission denied (publickey)SSH私钥没被正确识别或公钥未添加到GitLab检查密钥文件名是否被ssh-agent加载ssh-add -l用ssh -T gitgitlab.example.com -v调试详细原因fatal: repository not found项目地址不对或无权限确认仓库URL大小写完全一致检查当前SSH key是否有该项目的访问权限Email has already been taken注册时邮箱被占用先用该邮箱尝试登录不记得密码就走找回密码流程自建系统可联系管理员处理GitLab is taking too much time to respond服务器负载过高或数据库异常查看gitlab-ctl status检查各组件状态查看/var/log/gitlab/gitlab-rails/production.log和gitlab-ctl tailPipeline一直pendingRunner离线或没有匹配tag去项目的Runners页面检查Runner在线状态确认job的tag与Runner的tag匹配docker: command not found执行器环境没有Docker如果用的docker执行器确认job里写了image: docker:latest并启用了dind service如果shell执行器确认Runner主机的Docker已安装且当前用户有权限我在实际操作中还有一个经验连接GitLab报错时不要只看报错的第一行。比如fatal: unable to access http://...: The requested URL returned error: 502这个报错背后可能是GitLab反向代理配置错误、unicorn/nginx崩溃、甚至是磁盘满了导致的写操作异常。所以排查务必朝两个方向铺开一看GitLab自身的health check访问服务器的/-/health路径二看磁盘空间和内存占用许多GitLab异常最终都跟资源不够有关。6.3 记录一次真实的故障恢复磁盘写满引发的连锁问题想分享一次我印象很深的故障处理经历。有一次公司GitLab突然大面积报错所有人都无法访问项目首页转圈很久才打开打开后提示500错误。我第一反应是看服务状态gitlab-ctl status显示各组件均正常但gitlab-rails所在的端口迟迟没有响应。又继续看日志结果发现/var/log/gitlab日志目录里有一堆磁盘写入失败的记录。再执行df -h才反应过来根分区已经100%占满。排查下去发现罪魁祸首是CI流水线产生的构建缓存和日志文件日积月累把磁盘吃满了。这次故障持续了大概40分钟处理方式也很暴力清理无用的容器镜像和构建缓存删除旧的备份文件再给日志目录配置了logrotate。之后我在CI中加入了定期清理任务同时对磁盘监控加了告警只要使用率超过85%就自动通知从那之后再也没有出现过这类“突然挂了但不知道为什么”的情况。这里也想提醒一下GitLab跑久了占空间的不只有Git仓库本身还有CI缓存、构建产物、容器镜像、系统日志。很多人只关注仓库大小忽视这些“隐藏胖子”结果磁盘告警来得猝不及防。建议每隔一段时间用du -sh /srv/gitlab/*这类命令扫描一下各个目录的空间占用把不需要的旧镜像和过期构建产物及时清掉。写在最后一点个人体会经过这么多年的使用和部署维护我认为GitLab最被低估的功能其实是它的“全流程集成能力”。很多人把它当成一个存代码的地方但实际上它把代码托管、分支管理、代码评审、CI/CD、制品库、Kubernetes部署串联成了一个闭环。只要你愿意花时间去理解它的设计逻辑工作效率的提升会非常明显。如果你是从零开始接触GitLab我的建议是分三步走第一步先不管CI/CD把代码托管、SSH、分支管理这些基础功能用熟练保证团队日常协作流畅第二步部署Runner把最简单的构建任务跑起来慢慢理解流水线的概念第三步再逐步尝试镜像构建、自动部署、K8s联动这些进阶玩法。不要想着一步到位GitLab功能太多一次装完反而容易迷失。还有一点如果你用的是Docker部署并长期使用一定要尽早配置好监控。GitLab不像普通Web应用那样挂了重启就好它的内部状态牵扯到数据库、Redis、Gitaly等组件出问题以后排查成本不低。提前做好磁盘告警、探活检查和备份演练是对自己负责也是对整个团队负责。如果你能把上面这些内容消化掉再跟着操作走一遍我相信你已经能从“听说GitLab”进化到“能独立维护一套GitLab平台”的程度了。后面如果再遇到具体问题欢迎带着报错信息来找我交流GitLab的坑确实多但一个个踩过去也就慢慢熟了。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →