掘金 后端 ( ) • 2024-05-06 14:31

大早上10点,正在楼下咖啡店和小姐姐探讨什么比咖啡苦就接到了研发老哥的一通夺命连环Call。

image-20240506113354937.png

人在哪儿?

来了没?

快点的,测试环境的gitlab仓库无法push。上个月写的bug再不更新我就凉了!!!

见我没回消息,又发了一张图片

image-20240506110316279.png

饿……好吧。你赢了。

告别小姐姐,我拿着咖啡光速上楼。

甘!你钱早就该扣了,写的🌿🌿🌿代码坑死人。不过要是更不上去,这货估计又要分锅给我!

远程登录失败

整个gitlab网站点哪儿哪儿500错误,最麻爪的是我远程无法登录那台物理机。这画面似曾相识啊,可能是这几个月都没咋管这台机器现在又爆磁盘了

问题不大,反正机器在隔壁机房。直接物理登录呗!

果然物理机没问题,df -h

gb@gitlb:/home$ sudo df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.2G 1.3M 3.2G 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 98G 98G 0G 100% /

磁盘空间已经完全用尽。磁盘空间的满载不仅会导致新的数据无法写入,还会影响到大多数系统操作,这解释了为什么GitLab服务和远程登录都会失败。

丢掉个人素质,享受缺德人生

😂上个月摸鱼太严重,忘记清理日志和无用镜像导致的这个问题。这时应该勇于担当

image-20240506120408990.png

解决方案

清理Docker镜像

1. 删除悬空镜像

运行以下命令以清除那些未被任何容器引用的、没有标签的悬空镜像:

docker image prune

2. 删除所有未使用的镜像

要进一步释放空间,可以删除所有未被任何容器使用的镜像:

docker image prune -a

GitLab容器和镜像管理

gitlab-ctl registry-garbage-collect是一个命令行工具,用于在GitLab的容器注册表(Container Registry)中执行垃圾回收(garbage collection)。这个命令的主要目的是帮助你清理不再需要的或悬空的镜像层,释放存储空间。这在管理大量容器镜像的环境中特别有用,因为随着时间的推移,未使用的镜像层可能会占用大量的磁盘空间。

工作原理

GitLab Container Registry 是基于 Docker Distribution 项目构建的,它存储了所有的容器镜像。当你推送或更新镜像时,每个镜像层都会被存储在注册表中。如果某个镜像层不再被任何镜像标签引用,理论上这个镜像层就可以被删除,以节省空间。然而,这些未引用的镜像层并不会自动删除,这就是垃圾回收进程需要手动触发的原因。

使用gitlab-ctl registry-garbage-collect

在执行gitlab-ctl registry-garbage-collect命令时,GitLab会扫描容器注册表中所有的镜像层,识别出那些不再被任何现有镜像标签引用的层,并将其删除。这个过程可以显著减少GitLab容器注册表所占用的磁盘空间。

执行步骤

  1. 备份: 在执行垃圾回收之前,强烈建议进行备份,以防万一删除了重要数据。

  2. 停止写入操作: 为了避免在垃圾回收过程中出现数据不一致的情况,建议在执行过程中暂停新的镜像推送操作。这可以通过停止GitLab实例或通知团队在维护期间避免推送新镜像来实现。

  3. 执行命令: 在GitLab服务器上执行以下命令开始垃圾回收过程:

    gitlab-ctl registry-garbage-collect
    
  4. 监控日志: 垃圾回收过程可能需要一些时间,具体取决于容器注册表的大小。可以通过监控GitLab的日志来跟踪进度。

注意事项

  • 中断风险: 如果垃圾回收过程被中断,可能会导致部分数据处于不一致状态。如果发生这种情况,可能需要重新执行垃圾回收来清理未完成的部分。

  • 性能影响: 垃圾回收过程可能会占用大量的CPU和IO资源,对GitLab服务的性能产生影响。因此,建议在系统负载较低的时段执行此操作。

通过定期执行gitlab-ctl registry-garbage-collect命令,可以有效管理GitLab容器注册表的磁盘空间使用,避免无用的镜像层积累导致的空间浪费。

进一步的磁盘空间管理

如果上述步骤后磁盘空间仍然紧张,考虑以下额外措施:

1. 清理Docker资源

  • 容器: 使用docker container prune删除停止的容器。
  • : 使用docker volume prune删除未使用的卷。

2. 清理Docker构建缓存

docker builder prune命令用于清除Docker构建过程中产生的数据,主要包括不再被任何镜像引用的构建缓存。这些构建缓存可能包括临时或中间层镜像,这些镜像在构建过程中用于缓存,以便在后续构建中重用,从而加快构建速度。然而,随着时间的推移,这些缓存可能会占用大量的磁盘空间,尤其是在频繁构建镜像的环境中。

命令格式
docker builder prune [OPTIONS]
主要选项
  • -a, --all: 移除所有未使用的构建缓存,而不仅仅是悬挂的(没有标签或引用的)构建缓存。
  • -f, --force: 不提示确认直接删除。
  • --filter: 提供过滤器以选择删除的缓存。例如,可以根据缓存的创建时间(until=<timestamp>)来删除旧的构建缓存。
使用场景和好处
  1. 释放磁盘空间:最直接的好处是释放那些被旧的或不必要的构建缓存占用的磁盘空间。

  2. 维护和管理:定期清理构建缓存可以帮助维护Docker环境的健康,避免因磁盘空间不足而导致的构建或运行失败。

  3. 提高构建效率:虽然构建缓存的目的是加快构建速度,但过多的缓存条目可能会降低Docker的性能。定期清理可以确保缓存的有效利用。

示例
  • 清理悬挂的构建缓存(即,没有被任何镜像引用的缓存):

    docker builder prune
    
  • 强制删除所有未使用的构建缓存,不进行确认提示:

    docker builder prune -af
    
  • 删除一周前的所有构建缓存:

    docker builder prune -a --force --filter "until=168h"
    
注意事项
  • 在执行清理操作之前,确认不再需要这些构建缓存。虽然docker builder prune命令默认不会删除被标记或正在使用的镜像的缓存,但使用-a选项会删除所有未使用的缓存,可能包括一些最近未使用但将来可能会用到的缓存。

  • 对于生产环境,建议在执行此类清理操作前进行适当的评估和备份,以避免意外删除重要数据。

通过定期使用docker builder prune命令,你可以有效管理Docker环境的磁盘空间,保持系统的整洁和高效运行。

3. 清理GitLab日志和临时文件

直接服务器安装应该会在/var/log/gitlab目录中

docker安装的一般是自己挂载出来的,比如这种

    volumes:
      - './data:/var/opt/gitlab'
      - './logs:/var/log/gitlab' # 这一行是你挂载的目录
      - './config:/etc/gitlab'  

看看有什么能删除的,直接给清了吧

但是我不建议这样做,虽然有日志可能分锅给你。但是没了日志留存锅一定是你的

4. 检查其他大文件

利用du命令检查系统中其他可能占用大量空间的文件或目录。

流水线优化方案

优化GitLab CI/CD

通过精心设计.gitlab-ci.yml配置文件,可以有效地减少不必要的镜像构建,节省计算资源和存储空间。以下是一些优化策略:

1. 限制构建触发条件

.gitlab-ci.yml中,可以通过onlyexcept关键字来控制哪些分支或标签会触发构建过程。例如,你可能只希望在推送到mainrelease分支时才构建和部署镜像,而对于其他分支,则不进行这些操作。

build:
  script: echo "Building the project..."
  only:
    - main
    - /^release-.*$/

这个例子中,构建任务只会在推送到main分支或任何以release-开头的分支时触发。

2. 使用缓存来减少构建时间和资源消耗

GitLab CI/CD 允许你定义缓存,以便在多次构建间共享特定文件或目录。这在构建过程中需要下载依赖项或编译代码时特别有用。

build:
  script: make build
  cache:
    paths:
      - node_modules/

在这个例子中,node_modules目录被缓存起来,这意味着如果package.json文件没有变化,后续的构建将不需要重新下载所有的npm包,从而节省时间和带宽。

3. 利用工件(Artifacts)

工件是构建过程中产生的文件,可以在同一工作流的后续阶段或作业中使用。通过合理利用工件,可以避免重复的构建步骤。

build:
  script: make build
  artifacts:
    paths:
      - build/

在这个配置中,构建产生的文件会被保存为工件,这样在部署或测试阶段就可以直接使用这些文件,而不需要重新构建。

4. 使用Docker镜像作为缓存

如果你的CI/CD流程包括构建Docker镜像,可以利用Docker的层缓存机制来减少构建时间。这通常意味着在Dockerfile中尽可能地重用已有的层,并在.gitlab-ci.yml中使用适当的策略来推送和拉取这些镜像。

build:
  stage: build
  script:
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
  only:
    - main

这个例子中,docker build命令使用了--cache-from选项来指定一个已存在的镜像作为缓存源。这样,只有当Dockerfile的相应层发生变化时,Docker才会重新构建这些层。

敲重点啊,一定要@种老师看看

使用外部存储

将GitLab Container Registry配置为使用云存储服务,如Amazon S3或Google Cloud Storage,是一个有效的方法来减少对本地磁盘空间的需求。然而,在某些情况下,尤其是在中国大陆地区,由于网络连接、数据主权或成本考虑,你可能更倾向于使用国内的存储解决方案,如阿里云的OSS、腾讯云的COS,或者是传统的文件系统,如NFS。

使用NFS作为存储

NFS(网络文件系统)是一种分布式文件系统协议,允许你将一部分服务器的文件系统挂载到网络上的另一台计算机上,使得这部分文件系统对于这台计算机就像是本地存储一样。使用NFS作为GitLab Container Registry的存储后端,可以帮助你轻松扩展存储能力,同时减少本地磁盘空间的需求。

步骤概览:
  1. 设置NFS服务器:首先,你需要在一台服务器上配置NFS服务,并创建一个共享目录,用于存储容器镜像。

  2. 配置NFS客户端:在运行GitLab的服务器上,你需要安装NFS客户端,并将NFS服务器上的共享目录挂载到本地文件系统上。

  3. 配置GitLab:最后,你需要修改GitLab的配置文件(gitlab.rb),将Container Registry的存储路径指向挂载的NFS共享目录。

示例配置:
  • 在NFS服务器上

    创建共享目录并配置NFS导出。这通常涉及到编辑/etc/exports文件并添加类似以下的条目:

    /path/to/shared/directory <client-ip>(rw,sync,no_root_squash,no_subtree_check)
    

    然后,重新启动NFS服务以应用更改。

  • 在GitLab服务器上

    挂载NFS共享目录:

    mount -t nfs <nfs-server-ip>:/path/to/shared/directory /mnt/gitlab-registry
    

    配置gitlab.rb以使用挂载的目录作为容器注册表的存储路径:

    gitlab_rails['registry_storage_path'] = "/mnt/gitlab-registry"
    

    应用更改后,重新配置GitLab:

    gitlab-ctl reconfigure
    

注意事项

  • 性能和可用性:使用NFS或其他网络存储解决方案时,需要考虑网络延迟和带宽对性能的影响。此外,确保NFS服务的高可用性也非常重要,以避免成为系统的单点故障。

  • 备份和恢复:虽然使用NFS可以减少对本地磁盘空间的依赖,但仍然需要定期备份NFS服务器上的数据,以防数据丢失或损坏。

  • 安全性:确保你的NFS服务器配置得当,以防止未授权访问。使用网络安全组、防火墙规则和加密通信(如NFSv4 over Kerberos)来保护数据。

通过将GitLab Container Registry配置为使用NFS或其他国内文件系统,你可以有效地管理存储资源,同时保持良好的性能和可扩展性。

最终成果

gb@gitlb:/home$ sudo df -h
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              3.2G  1.3M  3.2G   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   98G   38G   56G  41% /

image.png

你看,他还得谢谢咱~👀