1.Gitlab架构
GitLab有两个软件发行版:开源社区版(CE)和企业版(EE)。新版本的GitLab在稳定的分支机构中发布,主分支用于前沿开发。新版本通常与GitLab CE版本大致同时发布,除非有重要的安全更新。Gitlab生态现在主要由以下三大模块组成:
官方架构图:
Gitlab通常安装在GNU/Linux
上。使用Nignx
或Apache
作为Web前端将请求代理到Unicorn Web
服务器,默认情况下,Unicorn和前端通过Unix套接字来通信,也支持使用TCP来转发请求。Web前端访问 /home/git/gitlab/public
绕过Unicorn服务器以提供静态页面,上传(例如头像图片或附件)和预编译资源。 GitLab使用Unicorn Web服务器提供网页和 GitLab API。使用Sidekiq
作为作业队列,而后者又使用redis作为作业信息,元数据和传入作业的非持久数据库后端。
Gitlab 应用程序使用 MySQL
或 PostgreSQL
作为持久数据库,用来保存用户,权限,issue,其他元数据等 git repository 默认存储在 /home/git/repositories
中,保留默认分支和 hooks 信息。
当通过 HTTP/HTTPS 提供 repository 时,GitLab 使用 GitLab API 来解析授权和访问以及提供 git 对象。
gitlab-shell
通过 SSH 提供 repository。它管理 /home/git/.ssh/authorized_keys
内的 SSH 密钥,不应手动编辑。gitlab-shell 通过 Gitaly 访问 bare repository 以提供 git 对象并与 redis 进行通信以向 Sidekiq 提交作业以供 GitLab 处理。gitlab-shell 查询 GitLab API 以确定授权和访问。
Gitaly
从 gitlab-shell 和 GitLab web 应用中获取操作命令,执行 git 操作,并为 GitLab web 应用程序提供 API 以从 git 获取属性(例如 title,branches,tags,其他元数据)和 blob(例如 diffs,commits ,files)。
Gitlab的生产架构可以参考这里。
Gitlab组件:
repository
:代码库,可以是硬盘或 分布式文件系统Nginx
:Web 入口gitlab-workhorse
:轻量级反向代理服务器,可以处理一些大的HTTP请求(磁盘上的 CSS、JS 文件、文件上传下载等),处理 Git Push/Pull 请求,处理到Rails 的连接会反向代理给后端的unicorn(修改由 Rails 发送的响应或发送给 Rails 的请求,管理 Rails 的长期 WebSocket 连接等)。gitlab-shell
:用于 SSH 交互,而不是 HTTP。gitlab-shell 通过 Redis 与 Sidekiq 进行通信,并直接或通过 TCP 间接访问 Unicorn。用于处理Git命令和修改authorized keys列表Unicorn
:Gitlab 自身的 Web 服务器(Ruby Web Server),包含了 Gitlab 主进程,负责处理快速/一般任务,与 Redis 一起工作,配置参考:CPU核心数 + 1 = unicorn workers数量
。工作内容包括:通过检查存储在 Redis 中的用户会话来检查权限
为 Sidekiq 制作任务
从仓库(warehouse)取东西或在那里移动东西
Redis
:缓存每个客户端的sessions和后台队列,负责分发任务。Redis需求的存储空间很小,大约每个用户25KBGitaly
:后台服务,专门负责访问磁盘以高效处理 gitlab-shell 和 gitlab-workhorse 的git 操作,并缓存耗时操作。所有的 git 操作都通过 Gitaly 处理,并向 GitLab web 应用程序提供一个 API,以从 git(例如 title, branches, tags, other meta data)获取属性,并获取 blob(例如 diffs,commits,files)Sidekiq
:后台核心服务,可以从redis队列中提取作业并对其进行处理。后台作业允许GitLab通过将工作移至后台来提供更快的请求/响应周期。Sidekiq任务需要来自Redis数据库(PostgreSQL/MySQL)
:包含以下信息:repository 中的数据(元数据,issue,合并请求 merge request 等)
可以登录 Web 的用户(权限)
mail_room
:处理邮件请求。回复 GitLab 发出的邮件时,GitLab 会调用此服务处理Sidekiq、Unicorn 和 GitLab-shell 的任务logrotate
:日志文件管理,切割
Gitlab-shell组件:
GitLab Shell 的作用:处理 Git 命令
、修改 authorized keys 列表
。GitLab Shell 不是 Unix shell,也不是 Bash 或 Zsh 的替代品。早期的 gitlab-shell 的实现方式为 gitolite。
当通过 SSH
访问 GitLab Server 时,GitLab Shell 会:
限制执行预定义好的Git命令(git push, git pull)
调用 GitLab Rails API,检查用户权限
执行 pre-receive 钩子(在 GitLab 企业版中叫做 Git 钩子)
执行你请求的动作
处理 GitLab 的 post-receive 动作
处理自定义的 post-receive 动作
git pull over ssh - > gitlab-shell - > API调用gitlab-rails(授权) - >接受或拒绝 - >建立Gitaly会话
git push over ssh - > gitlab-shell(git命令尚未执行) - >建立Gitaly会话 - >(在Gitaly中)gitlab-shell pre-receive hook - > API调用gitlab-rails(授权) - >接受或拒绝push
当通过 http(s)
访问 GitLab Server 时,工作流程取决于你是从 Git 仓库拉取(pull)代码,还是向 git 仓库推送(push)代码。
如果你是从 Git 仓库 pull 代码,GitLab Rails 应用会全权负责处理用户鉴权和执行 Git 命令的工作
如果你是向 Git 仓库 push 代码,GitLab Rails 应用既不会进行用户鉴权也不会执行 Git 命令,它会把以下工作交由 GitLab Shell 进行处理:
调用GitLab Rails API 检查权限
执行pre-receive 钩子
执行你请求的动作
处理 GitLab 的 post-receive 动作
处理自定义的 post-receive 动作
也许你会奇怪在通过 http(s) push 代码的情况下,GitLab Rails应用为什么不在 GitLab Shell之前进行鉴权。这是因为 GitLab Rails 应用没有解析 git push 命令的逻辑。好的方法是将这些解析代码放在一个地方,这个地方就是 GitLab Shell,这样我们就可以在通过 SSH 进行访问时重用这段代码。实际上,GitLab Shell 在执行 git push 命令时根本不会进行权限检查,它是依赖于 pre-receive 钩子进行权限检查的。而当你执行 git pull 命令时,权限检查是在命令执行之前的。对 git pull 命令的权限检查要简单得多,因为你只需要检查一个用户是否可以访问这个仓库就可以了(不需要检查分支权限)。
Gitlab-workhorse组件:
Workhorse 可以处理一些请求,而不涉及 Rails:例如,Javascript 文件和 CSS 文件直接从磁盘载入
Workhorse 可以修改 Rails 发送的响应:例如,如果你在 Rails 中使用 send_file,那么 gitlab-workhorse 将打开磁盘上的文件,并将其内容作为响应体发送给客户端
Workhorse 可以在从 Rails 请求权限后接管请求。 例如:处理 git clone 动作
Workhorse 可以在将请求传递给 Rails 之前对其进行修改。 例如:处理 Git LFS 上传 Workhorse 首先向 Rails 请求权限,然后将请求主体存储在临时文件中,然后它将包含临时文件路径的修改后的请求发送到 Rails
Workhorse 可以管理 Rails 的长期 WebSocket 连接。 例如:处理环境的终端 websocket
Workhorse 不连接 Redis 或 Postgresql,只连接到 Rails
我们假设所有到达 Workhorse 的请求首先通过一个上游代理,如 NGINX 或 Apache
Workhorse 不接受 HTTPS 连接
Workhorse 不清除空闲客户端连接
我们假设所有对 Rails 的请求都通过 Workhorse
Gitaly组件:
Gitaly是一个Git RPC服务,使用gRPC协议与客户端通信,用于处理GitLab发出的所有git调用。详细介绍
Gitlab老版架构图(< 9.0):
2.Gitlab结构及配置
~/git
表示 git 用户的主目录,通常是 /home/git
。
GitLab 在安装时,会创建 git 用户,并安装在 /home/git
目录中。在主目录中是 gitlabhq 服务器软件以及 repository 所在的位置,repository 的位置可以单独配置。
repository 位于 /home/git/repositories
中。GitLab 是一款 Ruby on Rails 应用程序,因此可以通过研究 Ruby on Rails 应用程序的工作方式来了解内部工作的细节。
要通过 SSH 提供 repository,可以使用 gitlab-shell 这个附加应用程序,该应用程序安装在 /home/git/gitlab-shell
中。
Gitlab目录结构:
/home/git/.ssh
- 包含 openssh 设置。指定由 gitlab-shell 管理的 authorized_keys 文件。 /home/git/gitlab
- GitLab 核心软件。 /home/git/gitlab-shell
- GitLab 核心的附加组件。包括 SSH 复制和其他功能。 /home/git/data/repositories
- 由命名空间组织的所有项目的裸仓库(bare repository)。这是为所有项目维护推/拉的 git repository 的地方。这是项目的关键数据,最好备份。注意:repository 的默认位置可以在 GitLab 的 config/gitlab.yml
和 gitlab-shell 的 config.yml
中配置。
Gitlab配置文件:
Gitlab 的配置文件在 /home/git/gitlab/config/*
目录下, 常用的有:
gitlab.yml
- GitLab 配置.unicorn.rb
- Unicorn web server 配置.database.yml
- 数据库连接配置.
gitlab-shell 的配置文件在 /home/git/gitlab-shell/config.yml
.
Gitlab备份与恢复:
# 执行备份命令
bundle exec rake gitlab:backup:create RAILS_ENV=production
# 备份成功,你会找到一个类似 /home/git/data/backups/1531046569_2018_07_14_10.6.4_gitlab_backup.tar 的文件
# 执行恢复命令
bundle exec rake gitlab:backup:restore RAILS_ENV=production
详情请看官网。
Gitlab进程:
作为系统用户,它需要持久数据库(MySQL/PostreSQL)和 redis 数据库。它还使用 Nginx 来代理 Unicorn。作为 git 用户,它启动 Sidekiq 和 Unicorn(默认情况下运行在端口 8080 上的基于 ruby 的 HTTP 服务器)。在 GitLab 用户下,通常有 4 个进程:gitlab-workhorse
(1进程) , unicorn_rails master
(1进程),unicorn_rails worker
(2进程),sidekiq
(1进程),gitaly
(1进程),具体启动进程数以各组件配置文件为准。
Repository访问:
可以通过 HTTP 或 SSH 访问代码库。HTTP 中的 cloning/push/pull 使用 GitLab API,SSH 克隆由 gitlab-shell 处理。
Gitlab环境检查:
GitLab 还提供了 rake 任务,可以用来查看版本信息或检查配置是否正确。详情可以参考 maintenance rake tasks。简而言之:
sudo -i -u git
cd gitlab
bundle exec rake gitlab:env:info RAILS_ENV=production
bundle exec rake gitlab:check RAILS_ENV=production
注意:建议使用 sudo -i -u git
或 sudo su - git
登录 git 用户。虽然 gitlabhq 提供的 sudo 命令在 Ubuntu 中工作,但它们并不总是在 RHEL 中工作。
Gitlab服务日志:
gitlabhq (includes Unicorn and Sidekiq logs)
/home/git/gitlab/log/
containsapplication.log
,production.log
,sidekiq.log
,unicorn.stdout.log
,githost.log
andunicorn.stderr.log
normally.
gitlab-shell
/home/git/gitlab-shell/gitlab-shell.log
ssh
/var/log/auth.log
auth log (on Ubuntu)./var/log/secure
auth log (on RHEL).
nginx
/var/log/nginx/
contains error and access logs.
Apache httpd
/var/log/apache2/
contains error and output logs (on Ubuntu)./var/log/httpd/
contains error and output logs (on RHEL).
redis
/var/log/redis/redis.log
there are also log-rotated logs there.
PostgreSQL
/var/log/postgresql/*
MySQL
/var/log/mysql/*
/var/log/mysql.*