- Geo 要求使用快速查找
- 通过极狐GitLab Shell 设置快速查找
- 如何返回使用
authorized_keys
文件 - 使用
gitlab-sshd
而不是 OpenSSH - SELinux 支持和限制
- 故障排查
在数据库中快速查找授权的 SSH 密钥
authorized_keys
文件的直接替换。对于普通(非部署密钥)用户,请考虑使用 SSH 证书。它们甚至更快,但不是直接替代品。随着用户数量的增长,常规 SSH 操作变得缓慢,因为 OpenSSH 通过线性搜索搜索密钥来授权用户。在最坏的情况下,例如当用户无权访问极狐GitLab 时,OpenSSH 会扫描整个文件连搜索密钥。这可能会花费大量时间和磁盘 I/O,从而延迟用户尝试推送或拉取仓库的时间。更糟糕的是,如果用户频繁添加或删除密钥,操作系统可能无法缓存 authorized_keys
文件,从而导致磁盘被重复访问。
极狐GitLab Shell 通过提供一种在数据库中快速索引查找来授权 SSH 用户的方法,来解决这个问题。本页介绍如何启用快速查找授权的 SSH 密钥。
AuthorizedKeysCommand
必须能够接受指纹。使用 sshd -V
检查服务器上 OpenSSH 的版本。Geo 要求使用快速查找
与云原生极狐GitLab 不同,Omnibus GitLab 默认管理位于 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 的用户的所有公共 SSH 密钥。但是,为了维护单一事实来源,必须将 Geo 配置为通过数据库查找执行 SSH 指纹查找。
作为设置 Geo 的一部分,您需要针对主要节点和次要节点执行以下概述的步骤,但必须仅在主要节点上取消选中**写入“授权密钥”文件 **,因为如果数据库复制正在工作,它会自动反映在次要节点上。
通过极狐GitLab Shell 设置快速查找
极狐GitLab Shell 提供了一种通过对极狐GitLab 数据库进行快速索引查找来授权 SSH 用户的方法。极狐GitLab Shell 使用 SSH 密钥的指纹来检查用户是否有权访问极狐GitLab。
将以下内容添加到您的 sshd_config
文件中。该文件通常位于 /etc/ssh/sshd_config
,但如果您使用的是 Omnibus Docker,它位于 /assets/sshd_config
:
Match User git # Apply the AuthorizedKeysCommands to the git user only
AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k
AuthorizedKeysCommandUser git
Match all # End match, settings apply to all users again
重新加载 OpenSSH:
# Debian or Ubuntu installations
sudo service ssh reload
# CentOS installations
sudo service sshd reload
通过在 authorized_keys
文件中注释掉您的用户密钥来确认 SSH 正在工作(以 #
开始注释它的行),然后从您的本地计算机尝试提取仓库或运行:
ssh -T git@gitlab.example.com
成功的拉取或欢迎消息意味着极狐GitLab 能够在数据库中找到密钥,因为它不存在于文件中。
/home/git/gitlab-shell/bin/gitlab-shell-authorized-keys-check
。您可能需要考虑在其他地方创建一个包装脚本,因为此命令必须由 root
拥有,并且不能由组或其他人写入。您还可以考虑根据需要更改此命令的所有权,但可能需要在 gitlab-shell
升级期间临时更改所有权。在查找失败(很常见)的情况下,仍会扫描 authorized_keys
文件。因此,只要存在大文件,Git SSH 的性能对于许多用户来说仍然会很慢。
要禁用对 authorized_keys
文件的写入:
- 在顶部栏上,选择 主菜单 > 管理员。
- 在左侧边栏中,选择 设置 > 网络。
- 展开 性能优化。
- 清除 使用 authorized_keys 文件来验证 SSH 密钥 复选框。
- 选择 保存更改。
再次,通过在 UI 中删除用户的 SSH 密钥、添加新密钥并尝试提取仓库来确认 SSH 是否正常工作。
然后您可以备份和删除您的 authorized_keys
文件以获得最佳性能。
当前用户的密钥已经存在于数据库中,因此无需迁移,无需用户重新添加其密钥。
如何返回使用 authorized_keys
文件
这个概述很简短。有关更多上下文,请参阅上述说明。
-
重建
authorized_keys
文件。 - 允许写入
authorized_keys
文件。- 在顶部栏上,选择 主菜单 > 管理员。
- 在左侧边栏中,选择 设置 > 网络。
- 展开 性能优化。
- 选中 使用 authorized_keys 文件来验证 SSH 密钥 复选框。
- 如果您使用的是 Omnibus Docker,请从
/etc/ssh/sshd_config
或/assets/sshd_config
中删除AuthorizedKeysCommand
行。 - 重新加载
sshd
:sudo service sshd reload
。
使用 gitlab-sshd
而不是 OpenSSH
引入于 14.5 版本作为 Alpha 发布功能,适用于私有化部署版用户。
gitlab-sshd
处于 Alpha 状态。还没有准备好用于生产。gitlab-sshd
是用 Go 编写的一个独立的 SSH 服务器。它作为 gitlab-shell
包的一部分提供。作为 OpenSSH 的替代方案,它的内存使用量较低,并且支持 IP 地址的群组访问限制,用于在代理后面运行的应用程序。
gitlab-sshd
是 OpenSSH 的轻量级替代方案,用于提供 SSH 操作。
虽然 OpenSSH 使用受限的 shell 方法,但 gitlab-sshd
更像是一个现代多线程服务器应用程序,响应传入的请求。主要区别在于 OpenSSH 使用 SSH 作为传输协议,而 gitlab-sshd
使用远程过程调用 (RPC)。
极狐GitLab Shell 的功能不仅限于 Git 操作。
如果您正在考虑从 OpenSSH 切换到 gitlab-sshd
,请考虑以下问题:
-
gitlab-sshd
组件仅适用于云原生 Helm Charts 部署。 -
gitlab-sshd
支持 PROXY 协议。它可以在依赖它的代理服务器后面运行,例如 HAProxy。PROXY 协议默认不启用,但可以通过 Helm chart 设置启用。 - 默认情况下,
gitlab-sshd
绑定到端口 22,但您可以在 Helm chart 中配置不同的端口。 -
gitlab-sshd
不支持 SSH 证书。
从 OpenSSH 切换到 gitlab-sshd
:
-
将
gitlab-shell
chartsshDaemon
选项设置为gitlab-sshd
。例如:gitlab: gitlab-shell: sshDaemon: gitlab-sshd
-
执行 Helm 升级。
SELinux 支持和限制
极狐GitLab 支持使用 SELinux 进行 authorized_keys
数据库查找。
由于 SELinux 策略是静态的,系统目前不支持更改内部网络服务器端口的功能。管理员必须为环境创建一个特殊的 .te
文件,因为它不是动态生成的。
更多文档
gitlab-sshd
的其他技术文档可以在极狐GitLab Shell 文档页面上找到。
故障排查
如果您的 SSH 传输速度慢或导致高 CPU 负载,请务必检查 /var/log/btmp
的大小,并确保它定期轮换或在达到一定大小后轮换。
如果这个文件非常大,极狐GitLab SSH 快速查找会导致更频繁地遇到瓶颈,从而进一步降低性能。
如果可以的话,您可以考虑在 sshd_config
中禁用 UsePAM
以避免完全读取 /var/log/btmp
。
在正在运行的 sshd: git
进程上运行 strace
和 lsof
会返回调试信息。
要通过 IP x.x.x.x
的 SSH 连接在正在进行的 Git 上获取 strace
,请运行:
sudo strace -s 10000 -p $(sudo netstat -tp | grep x.x.x.x | egrep 'ssh.*: git' | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')
或者为通过 SSH 进程运行的 Git 获取一个 lsof
:
sudo lsof -p $(sudo netstat -tp | egrep 'ssh.*: git' | head -1 | sed -e 's/.*ESTABLISHED *//' -e 's#/.*##')