Help us learn about your current experience with the documentation. Take the survey.

SSH 密钥的快速查找

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab Self-Managed

当用户数量增长时,SSH 操作会变慢,因为 OpenSSH 会线性搜索 authorized_keys 文件来认证用户。 这个过程需要大量的时间和磁盘 I/O,从而延迟了用户尝试推送或拉取代码仓库的操作。 如果用户频繁添加或删除密钥,操作系统可能不会缓存 authorized_keys 文件,这会导致重复的磁盘读取。

您可以配置 GitLab Shell 来查找 SSH 密钥,而不是使用 authorized_keys 文件。这种方式更快,因为查找操作在 GitLab 数据库中建立了索引。

对于标准(非部署密钥)用户,建议使用 SSH 证书。 它们比数据库查找更快,但并非 authorized_keys 文件的直接替代品。

Geo 需要启用快速查找

  • Tier: Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

Cloud Native GitLab 不同,Linux 包安装默认会管理一个位于 git 用户主目录下的 authorized_keys 文件。在大多数安装中,该文件位于 /var/opt/gitlab/.ssh/authorized_keys。使用以下命令定位您系统上的 authorized_keys 文件:

getent passwd git | cut -d: -f6 | awk '{print $1"/.ssh/authorized_keys"}'

authorized_keys 文件包含所有被授权访问 GitLab 的用户的公钥。然而,为了维护单一可信源,Geo 必须配置为使用数据库查找来执行 SSH 指纹查找。

当您设置 Geo 时,必须为主节点和辅助节点都执行以下步骤。不要在主节点上选择 写入 authorized_keys 文件,因为如果数据库复制正常工作,该操作会自动反映到辅助节点上。

设置快速查找

GitLab Shell 提供了一种通过对 GitLab 数据库进行快速、索引化的查找来授权 SSH 用户的方法。GitLab Shell 使用 SSH 密钥的指纹来检查用户是否有权访问 GitLab。

可以通过以下 SSH 服务器启用快速查找:

您可以通过为每个服务使用不同的端口来同时运行这两个服务。

使用 gitlab-sshd

要设置 gitlab-sshd,请参阅 gitlab-sshd 文档。 启用 gitlab-sshd 后,GitLab Shell 和 gitlab-sshd 将自动配置为使用快速查找。

使用 OpenSSH

前提条件:

  • 需要 OpenSSH 6.9 或更高版本,因为 AuthorizedKeysCommand 必须接受指纹。要检查您的版本,请运行 sshd -V

要使用 OpenSSH 设置快速查找:

  1. 将以下内容添加到您的 sshd_config 文件中:

    Match User git    # 仅对 git 用户应用 AuthorizedKeysCommands
      AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k
      AuthorizedKeysCommandUser git
    Match all    # 结束匹配,设置再次应用于所有用户

    该文件通常位于:

    • Linux 包安装:/etc/ssh/sshd_config
    • Docker 安装:/assets/sshd_config
    • 自行编译安装:如果您遵循了从源码安装 GitLab Shell的说明,该命令应位于 /home/git/gitlab-shell/bin/gitlab-shell-authorized-keys-check。建议在其他位置创建一个包装脚本,因为此命令必须由 root 用户拥有,并且不能被组或其他用户写入。同时,根据需要考虑更改此命令的所有权,但这在 gitlab-shell 升级期间可能需要临时更改所有权。
  2. 重新加载 OpenSSH:

    # Debian 或 Ubuntu 安装
    sudo service ssh reload
    
    # CentOS 安装
    sudo service sshd reload
  3. 确认 SSH 是否正常工作:

    1. authorized_keys 文件中注释掉您的用户密钥。为此,请在行首添加 #

    2. 在您的本地计算机上,尝试拉取一个仓库或运行:

      ssh -T git@gitlab.example.com

      成功的拉取操作或欢迎消息意味着 GitLab 在数据库中找到了密钥,因为该密钥不在文件中。

如果查找失败,系统仍会扫描 authorized_keys 文件。 只要这个大文件存在,对于大量用户而言,Git SSH 性能可能仍然很慢。

要解决此问题,您可以禁用对 authorized_keys 文件的写入:

  1. 确认 SSH 可以正常工作。此步骤很重要,否则文件会很快过时。

  2. 禁用对 authorized_keys 文件的写入:

    1. 在左侧边栏的底部,选择 管理员
    2. 选择 设置 > 网络
    3. 展开 性能优化
    4. 清除 使用 authorized_keys 文件认证 SSH 密钥 复选框。
    5. 选择 保存更改
  3. 验证更改:

    1. 在 UI 中移除您的 SSH 密钥。
    2. 添加一个新密钥。
    3. 尝试拉取一个仓库。
  4. 备份并删除您的 authorized_keys 文件。 当前用户的密钥已存在于数据库中,因此无需迁移,也无需用户重新添加他们的密钥。

如何恢复使用 authorized_keys 文件

此概述较为简略。更多上下文信息请参考前面的说明。

  1. 启用对 authorized_keys 文件的写入。
    1. 在左侧边栏的底部,选择 管理员
    2. 在左侧边栏,选择 设置 > 网络
    3. 展开 性能优化
    4. 选中 使用 authorized_keys 文件认证 SSH 密钥 复选框。
  2. 重建 authorized_keys 文件
  3. /etc/ssh/sshd_config/assets/sshd_config(如果您使用的是 Linux 包安装的 Docker)中移除 AuthorizedKeysCommand 行。
  4. 重新加载 sshdsudo service sshd reload

SELinux 支持

GitLab 支持通过 SELinux 进行 authorized_keys 数据库查找。

由于 SELinux 策略是静态的,GitLab 不支持更改内部 Web 服务器端口。管理员必须为环境创建一个特殊的 .te 文件,因为它不是动态生成的。

其他文档

关于 gitlab-sshd 的更多技术文档,请参阅 GitLab Shell 文档。

故障排查

SSH 流量缓慢或 CPU 负载过高

如果您的 SSH 流量缓慢或导致 CPU 负载过高:

  • 检查 /var/log/btmp 文件的大小。
  • 确保它被定期轮转,或在达到一定大小时进行轮转。

如果此文件非常大,GitLab SSH 快速查找可能会导致瓶颈更频繁地出现,从而进一步降低性能。考虑在您的 sshd_config禁用 UsePAM,以完全避免读取 /var/log/btmp

在正在运行的 sshd: git 进程上运行 stracelsof 可以返回调试信息。要获取 IP 为 x.x.x.x 的正在进行中的 Git over SSH 连接的 strace,请运行:

sudo strace -s 10000 -p $(sudo netstat -tp | grep x.x.x.x | egrep 'ssh.*: git' | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')

或者获取正在运行的 Git over SSH 进程的 lsof

sudo lsof -p $(sudo netstat -tp | egrep 'ssh.*: git' | head -1 | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')