在 GitLab 中使用 NFS
- Tier: Free, Premium, Ultimate
- Offering: GitLab Self-Managed
NFS 可用作对象存储的替代方案,但通常不推荐,因为性能原因。
对于 LFS、Uploads 和 Artifacts 等数据对象,由于性能更好,建议尽可能使用 Object Storage service 而不是 NFS。当不再使用 NFS 时,除了迁移到 Object Storage 外,还需要执行 其他步骤。
NFS 不能用于仓库存储。
有关测试文件系统性能的步骤,请参阅 File System Performance Benchmarking。
快速查找授权的 SSH 密钥
fast SSH key lookup 功能可以提升 GitLab 实例的性能,即使它们在使用块存储。
Fast SSH key lookup 是使用 GitLab 数据库替代 authorized_keys(位于 /var/opt/gitlab/.ssh)的功能。
NFS 会增加延迟,因此如果将 /var/opt/gitlab 移动到 NFS,建议使用快速查找。
我们正在研究将 fast lookup 作为默认设置。
NFS 服务器
安装 nfs-kernel-server 包允许您与运行 GitLab 应用的客户端共享目录:
sudo apt-get update
sudo apt-get install nfs-kernel-server必需功能
文件锁定:GitLab 需要建议性文件锁定,这仅在 NFS 版本 4 中原生支持。NFSv3 也支持锁定,只要使用 Linux Kernel 2.6.5+ 即可。我们建议使用版本 4,并且没有专门测试 NFSv3。
推荐选项
当您定义 NFS 导出时,建议添加以下选项:
no_root_squash- NFS 通常会将root用户更改为nobody。当 NFS 共享被许多不同用户访问时,这是一个很好的安全措施。但是,在这种情况下,只有 GitLab 使用 NFS 共享,所以是安全的。GitLab 推荐no_root_squash设置,因为我们需要自动管理文件权限。没有此设置,当 Linux 包尝试更改权限时,您可能会收到错误。GitLab 和其他捆绑组件 不 以root身份运行,而是以非特权用户身份运行。推荐no_root_squash是为了允许 Linux 包根据需要设置文件的所有权和权限。在某些情况下,如果no_root_squash选项不可用,可以使用root标志达到相同效果。sync- 强制同步行为。默认是异步的,在某些情况下,如果在数据同步之前发生故障,可能会导致数据丢失。
由于使用 LDAP 运行 Linux 包的复杂性以及在没有 LDAP 的情况下维护 ID 映射的复杂性,在大多数情况下,您应该启用数字 UID 和 GID(在某些情况下默认关闭),以简化系统之间的权限管理:
- NetApp 说明
- 对于非 NetApp 设备,通过执行与 启用 NFSv4 idmapper 相反的操作来禁用 NFSv4
idmapping
禁用 NFS 服务器委派
我们建议所有 NFS 用户禁用 NFS 服务器委派功能。这是为了避免一个 Linux 内核漏洞,该漏洞会导致 NFS 客户端因大量 TEST_STATEID NFS 消息产生的 excessive network traffic 而急剧变慢。
要禁用 NFS 服务器委派,请执行以下操作:
-
在 NFS 服务器上运行:
echo 0 > /proc/sys/fs/leases-enable sysctl -w fs.leases-enable=0 -
重启 NFS 服务器进程。例如,在 CentOS 上运行
service nfs restart。
内核漏洞可能已在 此提交的较新内核中修复。Red Hat Enterprise 7 在 2019 年 8 月 6 日 发布了一个内核更新,也可能解决了此问题。如果您知道自己使用的是已修复的 Linux 内核版本,则可能不需要禁用 NFS 服务器委派。也就是说,GitLab 仍然建议实例管理员保持 NFS 服务器委派禁用状态。
NFS 客户端
nfs-common 提供 NFS 功能,而无需安装我们不需要在应用节点上运行的服务器组件。
apt-get update
apt-get install nfs-common挂载选项
以下是添加到 /etc/fstab 的示例片段:
10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2
10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,_netdev,lookupcache=positive 0 2您可以通过运行 nfsstat -m 和 cat /etc/fstab 来查看每个已挂载 NFS 文件系统的信息和设置选项。
请注意,有几个选项您应该考虑使用:
| Setting | Description |
|---|---|
vers=4.1 |
NFS v4.1 应该用于替代 v4.0,因为 v4.0 中存在一个 Linux NFS 客户端漏洞,可能导致因数据陈旧而出现严重问题。 |
nofail |
不要为了等待此挂载可用而停止启动过程。 |
lookupcache=positive |
告诉 NFS 客户端遵守 positive 缓存结果,但使任何 negative 缓存结果失效。Negative 缓存结果会导致 Git 出现问题。具体来说,git push 可能无法在所有 NFS 客户端上统一注册。Negative 缓存会导致客户端"记住"这些文件以前不存在。 |
hard |
而不是 soft。进一步详情。 |
cto |
cto 是默认选项,您应该使用。不要使用 nocto。进一步详情。 |
_netdev |
等待网络在线后再挂载文件系统。另请参阅 high_availability['mountpoint'] 选项。 |
soft 挂载选项
建议您在挂载选项中使用 hard,除非您有特定原因需要使用 soft。
当 GitLab.com 使用 NFS 时,我们使用 soft,因为有时我们需要重启 NFS 服务器,而 soft 提高了可用性,但每个人的基础设施都不同。例如,如果您的 NFS 由具有冗余控制器的本地存储阵列提供,您就不需要担心 NFS 服务器的可用性。
NFS 手册页说明:
“soft” 超时在某些情况下可能导致静默数据损坏
阅读 Linux 手册页 了解区别,如果您确实使用 soft,请确保已采取措施降低风险。
如果您遇到可能由 NFS 服务器上未发生磁盘写入导致的行为,例如提交丢失,请使用 hard 选项,因为(来自手册页):
仅当客户端响应速度比数据完整性更重要时才使用 soft 选项
其他供应商也提出了类似的建议,包括 读写目录的推荐挂载选项 和 NetApp 的 知识库,他们强调如果 NFS 客户端驱动程序缓存数据,soft 意味着无法确定 GitLab 的写入是否实际在磁盘上。
使用 hard 选项设置的挂载点性能可能不佳,如果 NFS 服务器宕机,hard 会导致进程在与挂载点交互时挂起。使用 SIGKILL (kill -9) 处理挂起的进程。intr 选项 在 2.6 内核中停止工作。
nocto 挂载选项
不要使用 nocto。相反,使用默认的 cto。
使用 nocto 时,dentry 缓存始终会被使用,最多从创建时间起 acdirmax 秒(属性缓存时间)。
这会导致多个客户端出现陈旧的 dentry 缓存问题,每个客户端可能看到目录的不同(缓存)版本。
来自 Linux 手册页 的重要部分:
如果指定了
nocto选项,客户端会使用非标准启发式方法来确定服务器上的文件何时已更改。
使用
nocto选项可能会提高只读挂载的性能,但应仅在服务器数据偶尔更改时使用。
我们在关于 推送后找不到 refs 的问题中注意到了这种行为,其中新添加的松散 refs 在具有本地 dentry 缓存的不同客户端上可能被视为缺失,如 此问题中所述。
单个 NFS 挂载
建议将所有 GitLab 数据目录嵌套在一个挂载点内,这样可以在不手动移动现有数据的情况下自动恢复备份。
mountpoint
└── gitlab-data
├── builds
├── shared
└── uploads为此,请配置 Linux 包,将每个目录的路径嵌套在挂载点内,如下所示:
挂载 /gitlab-nfs,然后使用以下 Linux 包配置将每个数据位置移动到子目录:
gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads'
gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared'
gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds'运行 sudo gitlab-ctl reconfigure 开始使用中央位置。请注意,如果您有现有数据,需要手动复制或 rsync 到这些新位置,然后重启 GitLab。
绑定挂载
除了更改 Linux 包中的配置外,还可以使用绑定挂载将数据存储在 NFS 挂载上。
绑定挂载提供了一种方法,只需指定一个 NFS 挂载,然后将默认的 GitLab 数据位置绑定到 NFS 挂载。首先像往常一样在 /etc/fstab 中定义您的单个 NFS 挂载点。假设您的 NFS 挂载点是 /gitlab-nfs。然后在 /etc/fstab 中添加以下绑定挂载:
/gitlab-nfs/gitlab-data/.ssh /var/opt/gitlab/.ssh none bind 0 0
/gitlab-nfs/gitlab-data/uploads /var/opt/gitlab/gitlab-rails/uploads none bind 0 0
/gitlab-nfs/gitlab-data/shared /var/opt/gitlab/gitlab-rails/shared none bind 0 0
/gitlab-nfs/gitlab-data/builds /var/opt/gitlab/gitlab-ci/builds none bind 0 0使用绑定挂载要求您在尝试恢复之前手动确保数据目录为空。有关 恢复先决条件 的更多信息,请阅读。
多个 NFS 挂载
使用默认的 Linux 包配置时,您需要在所有 GitLab 集群节点之间共享 3 个数据位置。不应共享其他位置。以下是需要共享的 3 个位置:
| Location | Description | Default configuration |
|---|---|---|
/var/opt/gitlab/gitlab-rails/uploads |
用户上传的附件 | gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads' |
/var/opt/gitlab/gitlab-rails/shared |
构建工件、GitLab Pages、LFS 对象和临时文件等对象。如果您使用 LFS,这也可能占您数据的很大一部分 | gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared' |
/var/opt/gitlab/gitlab-ci/builds |
GitLab CI/CD 构建跟踪 | gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds' |
其他 GitLab 目录不应在节点之间共享。它们包含节点特定的文件和不需要共享的 GitLab 代码。要将日志发送到中央位置,请考虑使用远程 syslog。Linux 包提供了 UDP 日志传输 的配置。
拥有多个 NFS 挂载要求您在尝试恢复之前手动确保数据目录为空。有关 恢复先决条件 的更多信息,请阅读。
测试 NFS
当您设置好 NFS 服务器和客户端后,可以通过测试以下命令来验证 NFS 是否配置正确:
sudo mkdir /gitlab-nfs/test-dir
sudo chown git /gitlab-nfs/test-dir
sudo chgrp root /gitlab-nfs/test-dir
sudo chmod 0700 /gitlab-nfs/test-dir
sudo chgrp gitlab-www /gitlab-nfs/test-dir
sudo chmod 0751 /gitlab-nfs/test-dir
sudo chgrp git /gitlab-nfs/test-dir
sudo chmod 2770 /gitlab-nfs/test-dir
sudo chmod 2755 /gitlab-nfs/test-dir
sudo -u git mkdir /gitlab-nfs/test-dir/test2
sudo -u git chmod 2755 /gitlab-nfs/test-dir/test2
sudo ls -lah /gitlab-nfs/test-dir/test2
sudo -u git rm -r /gitlab-nfs/test-dir任何 Operation not permitted 错误都意味着您应该检查 NFS 服务器导出选项。
防火墙环境中的 NFS
如果您的 NFS 服务器和 NFS 客户端之间的流量受到防火墙的端口过滤,那么您需要重新配置该防火墙以允许 NFS 通信。
来自 Linux 文档项目 (TDLP) 的本指南 介绍了在防火墙环境中使用 NFS 的基础知识。此外,我们鼓励您搜索并查看您的操作系统或发行版以及防火墙软件的具体文档。
Ubuntu 示例:
通过运行命令 sudo ufw status 检查来自客户端的 NFS 流量是否被主机上的防火墙允许。如果被阻止,则可以使用以下命令允许来自特定客户端的流量。
sudo ufw allow from <client_ip_address> to any port nfs已知问题
避免使用基于云的文件系统
GitLab 强烈建议不要使用基于云的文件系统,例如:
- AWS Elastic File System (EFS).
- Google Cloud Filestore.
- Azure Files.
我们的支持团队无法协助解决与基于云的文件系统访问相关的性能问题。
客户和用户报告称,这些文件系统对于 GitLab 所需的文件系统访问性能不佳。像 git 这样以串行方式写入许多小文件的工作负载不太适合基于云的文件系统。
如果您确实选择使用这些,请避免将 GitLab 日志文件(例如 /var/log/gitlab 中的文件)存储在那里,因为这也会影响性能。我们建议将日志文件存储在本地卷上。
有关使用基于云的文件系统与 GitLab 的经验详情,请参阅此 Commit Brooklyn 2019 视频。
避免使用 CephFS 和 GlusterFS
GitLab 强烈建议不要使用 CephFS 和 GlusterFS。这些分布式文件系统不太适合 GitLab 的输入/输出访问模式,因为 Git 使用许多小文件,并且访问时间和文件锁定时间的传播使得 Git 活动非常缓慢。
避免使用 PostgreSQL 与 NFS
GitLab 强烈建议不要跨 NFS 运行您的 PostgreSQL 数据库。GitLab 支持团队无法协助解决与此配置相关的性能问题。
此外,此配置在 PostgreSQL 文档 中被特别警告:
PostgreSQL 对 NFS 文件系统没有做任何特殊处理,这意味着它假设 NFS 的行为与本地连接的驱动器完全相同。如果客户端或服务器 NFS 实现不提供标准的文件系统语义,这可能会导致可靠性问题。具体来说,延迟(异步)写入 NFS 服务器可能会导致数据损坏问题。
有关支持的数据库架构,请参阅我们关于 配置用于复制和故障转移的数据库 的文档。
故障排除
查找发送到 NFS 的请求
在 NFS 相关问题的情况下,使用 perf 跟踪正在进行的文件系统请求可能会有所帮助:
sudo perf trace -e 'nfs4:*' -p $(pgrep -fd ',' puma)在 Ubuntu 16.04 上,使用:
sudo perf trace --no-syscalls --event 'nfs4:*' -p $(pgrep -fd ',' puma)