那天凌晨2点15分,我被一阵急促的报警短信惊醒——公司GitLab服务器的磁盘使用率达到了100%。作为运维负责人,我深知这意味着什么:所有研发团队的代码提交、CI/CD流水线、甚至项目部署都将立即中断。这种紧急情况在版本发布前夕尤为致命,必须争分夺秒处理。
登录服务器后,我发现情况比预想的更糟:不仅GitLab网页端完全无法访问,连SSH连接都变得异常缓慢。这就是磁盘完全写满的典型症状——系统连最基本的日志都无法记录。下面是我在15分钟内完成故障排查和修复的全过程记录,这套方法后来成为我们团队的标准化应急方案。
当服务器响应迟缓时,首先要确认磁盘状态。我使用最基本的df -h命令(人类可读格式的磁盘空间检查)获取整体情况:
bash复制df -h
输出结果显示根分区已经100%占用:
code复制Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 40G 0 100% /
关键提示:如果
df -h执行后卡住,可以尝试df -i检查inode使用率。有时候inode耗尽也会导致类似问题,但解决方法完全不同。
知道磁盘满了只是第一步,更重要的是找出哪些文件在占用空间。我使用du命令配合排序快速定位:
bash复制du -h --max-depth=1 / | sort -hr
这个命令组合的妙处在于:
--max-depth=1只显示一级子目录大小sort -hr按人类可读格式(h)逆序(r)排序输出样例:
code复制36G /var
3.2G /home
1.1G /opt
...
锁定到/var目录后,进一步检查GitLab的专用存储路径:
bash复制du -h --max-depth=1 /var/opt/gitlab
典型的问题目录通常出现在:
/var/opt/gitlab/backups - 自动备份堆积/var/opt/gitlab/gitlab-rails/shared/artifacts - CI/CD产物/var/opt/gitlab/gitlab-rails/shared/lfs-objects - 大文件存储/var/log/gitlab - 日志文件GitLab默认备份路径通常占用最大空间。查看备份文件:
bash复制ls -lh /var/opt/gitlab/backups
删除所有备份(紧急情况下):
bash复制rm -rf /var/opt/gitlab/backups/*
或者选择性保留最近2个备份:
bash复制ls -t /var/opt/gitlab/backups | tail -n +3 | xargs rm --
血泪教训:曾经有团队误删了所有备份,结果当天就遭遇数据损坏。建议至少保留1-2个最新备份,除非你确认其他位置有副本。
GitLab日志通常位于两个位置:
/var/log/gitlab/var/opt/gitlab/gitlab-rails/log推荐使用GitLab内置命令安全清理:
bash复制gitlab-ctl truncate-logs
如果命令不可用,可以手动清理(有一定风险):
bash复制find /var/log/gitlab -type f -name "*.log" -exec truncate -s 0 {} \;
CI产物往往在不经意间堆积成山。检查artifacts目录:
bash复制du -sh /var/opt/gitlab/gitlab-rails/shared/artifacts
安全删除方式(保留最近版本):
bash复制gitlab-rake gitlab:artifacts:clean
紧急情况下强制清理:
bash复制rm -rf /var/opt/gitlab/gitlab-rails/shared/artifacts/*
很多团队会忽略Docker占用的空间。查看Docker磁盘使用:
bash复制docker system df
全面清理(包括未使用的镜像、容器、网络和缓存):
bash复制docker system prune -a -f
实测数据:在一次紧急处理中,仅Docker清理就释放了17GB空间,占当时总磁盘的40%以上。
如果项目使用Git LFS,可能需要专门清理:
bash复制du -sh /var/opt/gitlab/gitlab-rails/shared/lfs-objects
通过API查询LFS对象引用情况:
bash复制gitlab-rake gitlab:lfs:check
清理完成后必须重启服务:
bash复制gitlab-ctl restart
检查服务状态:
bash复制gitlab-ctl status
再次确认磁盘状态:
bash复制df -h
理想情况下,Use%应该显著下降。如果变化不大,可能需要检查:
lsof | grep deleted)编辑GitLab配置文件:
bash复制vim /etc/gitlab/gitlab.rb
添加或修改以下配置:
ruby复制# 保留7天备份
gitlab_rails['backup_keep_time'] = 604800
# 备份时跳过artifacts和LFS(可节省大量空间)
gitlab_rails['backup_archive_permissions'] = 0644
gitlab_rails['backup_pg_schema'] = 'public'
应用配置:
bash复制gitlab-ctl reconfigure
创建logrotate配置文件:
bash复制vim /etc/logrotate.d/gitlab
示例配置:
code复制/var/log/gitlab/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
dateext
}
推荐使用Prometheus监控磁盘使用率,配置类似告警规则:
yaml复制- alert: HighDiskUsage
expr: 100 - (node_filesystem_avail_bytes{mountpoint="/"} * 100 / node_filesystem_size_bytes{mountpoint="/"}) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "High disk usage on {{ $labels.instance }}"
description: "{{ $labels.instance }} has {{ $value }}% disk usage"
创建自动化清理脚本/usr/local/bin/gitlab_cleanup.sh:
bash复制#!/bin/bash
# 清理过期备份
find /var/opt/gitlab/backups -type f -mtime +7 -delete
# 清理Docker
docker system prune -af
# 清理CI artifacts
gitlab-rake gitlab:artifacts:clean
# 清理日志
find /var/log/gitlab -type f -name "*.log" -mtime +30 -delete
设置cron定时任务:
bash复制0 3 * * * /usr/local/bin/gitlab_cleanup.sh >/dev/null 2>&1
如果磁盘完全写满导致基本命令都无法执行,可以尝试:
有时候删除文件后空间并未释放,可能是因为仍有进程在占用:
bash复制lsof +L1
找到相关进程后,可以安全地重启它们。
对于特别庞大的仓库,可以考虑:
bash复制git gc --aggressive --prune=now
或者在GitLab中启用仓库压缩:
ruby复制gitlab_rails['git_gc_periodic_job_enabled'] = true
gitlab_rails['git_gc_interval'] = "12h"
这套方案在我们生产环境经历了多次实战检验,最近半年成功处理了4次磁盘爆满事件,平均恢复时间控制在8分钟以内。关键是要建立预防为主的运维理念,把问题消灭在发生之前。