Mallux - 宁静致远

GitLab

Gitlab 概述

Gitlab 架构

[Doc] https://github.com/gitlabhq/gitlabhq/blob/master/doc/development/architecture.md

  • nginx:静态 Web 服务器
  • gitlab-shell:用于处理 Git 命令和修改 authorized keys 列表
  • gitlab-workhorse:轻量级的反向代理服务器,它会处理一些大的 HTTP 请求,比如文件上传、文件下载、Git push/pull 和 归档下载。其它请求会反向代理到 GitLab Rails 应用,即反向代理给后端的 unicorn。
  • Unicorn:Ruby Web Server,托管 GitLab Rails 服务。增加 unicorn 的 workers 数量,可以减少应用的响应时间并提高处理并发请求的能力。对于大部分实例,我们建议使用这样的配置:CPU 核心数 + 1 = unicorn workers 数
  • Gitaly:执行 gitlab-shell 和 gitloab-workhorse 的 git 操作,并向 GitLab web 应用程序提供一个 API,以从 git(例如 title, branches, tags, other meta data)获取属性,并获取 blob(例如 diffs,commits,files)
  • postgresql:使用 PostgreSQL 必须确认 GitLab 使用的数据库安装了 pg_trgm 扩展。 这个扩展需要 PostgreSQL 使用 root 用户在 GitLab 每个数据库里面执行 CREATE EXTENSION pg_trgm; 命令
  • redis:Redis 存储每个客户端的 sessions 和后台任务队列。Redis 需求的存储空间很小, 大约每个用户 25kB
  • sidekiq:Sidekiq 使用多线程处理后台任务(异步)。 这个进程启动的时候会使用整个 Rails 堆栈(200MB+),但是它会在内存泄漏的情况下增加。 一个用户非常活跃的服务器上(10,000个活跃用户),Sidekiq 进程会占用 1GB+ 的内存。
  • logrotate:日志文件管理

gitlab-shell 组件

[Doc] (https://gitlab.com/gitlab-org/gitlab-shell/blob/master/README.md)

GitLab Shell 的作用:处理 Git 命令修改 authorized keys 列表。GitLab Shell 不是 Unix shell,也不是 Bash 或 Zsh 的替代品。早期的 gitlab-shell 是实现方式为 gitolite。

当通过 SSH 访问 GitLab Server 时,GitLab Shell 会:

  • 限制执行预定义好的Git命令(git push, git pull, git annex)
  • 调用 GitLab Rails API,检查用户权限
  • 执行 pre-receive 钩子(在 GitLab 企业版中叫做 Git 钩子)
  • 执行你请求的动作
  • 处理 GitLab 的 post-receive 动作
  • 处理自定义的 post-receive 动作

当通过 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

Gitlab 硬件需求

[Doc] https://doc.gitlab.cc/ce/install/requirements.html

  • CPU:2 核心 500 用户,4 核心 2000 用户,8 核心 5000 用户 …
  • Memory:4G 100 用户,8G 1000 用户,32G 4000 用户 …
  • Swap:即使你服务器有足够多的 RAM, 也要给服务器至少分配 2GB 的交换分区。 因为使用交换分区可以在你的可用内存波动的时候降低 GitLab 出错的几率

Gitlab 高可用

  • Active/Acitve(双主架构)
  • Active/Passive(主从架构)

Acitve/Acitve

Active/Passive

解决方案:Corosync + Pacemaker + DRBD,参见 “Cluster 集群序列” 学习笔记。

安装 Gitlab CE

Omnibus

Omnibus GitLab 是集成了 GitLab 及 GitLab 所需的服务、依赖的一键安装包。Omnibus GitLab 源已经针对国内网络环境进行优化,镜像源由 TUNA 提供。

安装依赖包:

1
# apt-get install curl openssh-server ca-certificates postfix

添加 GitLab 仓库,并安装到服务器上:

1
2
3
# curl -sS http://packages.gitlab.cc/install/gitlab-ce/script.deb.sh | sudo bash
# apt-get install gitlab-ce

启动 gitlab:

1
# gitlab-ctl reconfigure

若执行 reconfigure 长时间卡在一个地方,可先执行:

1
# systemctl restart gitlab-runsvdir

开机自启动:

1
# systemctl enable gitlab-runsvdir

Docker

[Doc]

Gitlab Environment Variable

[Doc] https://docs.gitlab.com/ce/administration/environment_variables.html

1
2
# docker pull gitlab/gitlab-ce
# mkdir /data/gitlab/{config,logs,data}

docker run

1
2
3
4
5
6
7
# docker run -d --name gitlab --hostname gitlab \
--privileged --restart always \
-p 22:22 80:80 443:443 \
-v /data/gitlab/config:/etc/gitlab \
-v /data/gitlab/logs:/var/log/gitlab \
-v /data/gitlab/data:/var/opt/gitlab
gitlab/gitlab-ce:latest

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
### gitlob - Service define start
gitlab:
image: gitlab/gitlab-ce:latest
volumes:
- /data/gitlab/config:/etc/gitlab
- /data/gitlab/logs:/var/log/gitlab
- /data/gitlab/data:/var/opt/gitlab
ports:
- "22:22"
- "80:80"
- "443:443"
hostname: gitlab
mem_limit: 4096M
restart: always
### gitlab - Service define end

提示:将 config、data 等数据文件,使用 -v 映射卷以后,即使删除容器再新建一个容器,数据依然存在。

Upgrade GitLab

[Official] https://docs.gitlab.com/omnibus/update/README.html#updating-from-gitlab-66-and-higher-to-the-latest-version

安装指定版本的 GitLab:

1
# apt-get install gitlab-ce=9.0.0-ce.0

Gitlab 配置

[Doc] https://doc.gitlab.cc/omnibus/settings/configuration.html#storing-git-data-in-an-alternative-directory

自 GitLab 7.6 开始的新安装包,Gitlab 已经默认将所有的参数写入到 /etc/gitlab/gitlab.rb 文件中。

gitlab-ctl 命令

Gitlab 使用 gitlab-ctl 命令来重新应用 gitlab.rb 的配置。

  • deploy-page:Put up the deploy page
  • diff-config:Compare the user configuration with package available configuration
  • remove-accounts:Delete all users and groups used by this package
  • upgrade:Run migrations after a package upgrade

General Commands:

  • cleanse:Delete all gitlab data, and start from scratch.
  • help:Print this help message.
  • reconfigure:Reconfigure the application.
  • show-config:Show the configuration that would be generated by reconfigure.
  • uninstall:Kill all processes and uninstall the process supervisor (data will be preserved).

Service Management Commands:

  • graceful-kill:Attempt a graceful stop, then SIGKILL the entire process group.
  • hup:Send the services a HUP.
  • int:Send the services an INT.
  • kill:Send the services a KILL.
  • once:Start the services if they are down. Do not restart them if they stop.
  • restart:Stop the services if they are running, then start them again.
  • service-list:List all the services (enabled services appear with a *.)
  • start:Start services if they are down, and restart them if they stop.
  • status:Show the status of all the services.
  • stop:Stop the services, and do not restart them.
  • tail:Watch the service logs of all enabled services.
  • term:Send the services a TERM.

Container Registry Commands:

  • registry-garbage-collect:Run Container Registry garbage collection.

Database Commands:

  • pg-upgrade:Upgrade the PostgreSQL DB to the latest supported version
  • revert-pg-upgrade:Run this to revert to the previous version of the database

使用外部的 Postgresql 和 Redis

Gitlab 使用 CE v8.17,目前 CE 版本只支持外部的 Postgresql,MySQL 只在 EE 版本中被支持。

修改 gitlab.rb 配置部分,修改完毕后使用 gitlab-ctl reconfigure 命令重新配置 gitlab 即可。

Postgresql

1
2
3
4
5
6
7
8
9
10
# Disable the built-in Postgres
postgresql['enable'] = false
gitlab_rails['db_adapter'] = "postgresql"
gitlab_rails['db_encoding'] = "utf8"
gitlab_rails['db_database'] = "dbgitlab"
gitlab_rails['db_username'] = "gitsrv"
gitlab_rails['db_password'] = "gitsrv"
gitlab_rails['db_host'] = "192.168.104.9"
gitlab_rails['db_port'] = 5432

Redis

1
2
3
4
5
6
7
8
# Disable the built-in Redis
redis['enable'] = false
#### Redis TCP connection
gitlab_rails['redis_host'] = "192.168.112.6"
gitlab_rails['redis_port'] = 6379
gitlab_rails['redis_password'] = "redispass"
gitlab_rails['redis_database'] = 0

重配置 Gitlab

1
2
3
4
5
6
7
8
9
# gitlab-ctl reconfigure
### 查看 gitlab 各组件运行状态
# gitlab-ctl status
run: gitlab-workhorse: (pid 32492) 56640s; run: log: (pid 29667) 57100s
run: logrotate: (pid 7138) 3093s; run: log: (pid 29712) 57094s
run: nginx: (pid 32504) 56639s; run: log: (pid 29669) 57100s
run: sidekiq: (pid 12938) 14355s; run: log: (pid 29650) 57102s
run: unicorn: (pid 13049) 14338s; run: log: (pid 29608) 57108s

配置 SMTP 服务

[Doc] https://doc.gitlab.cc/omnibus/settings/smtp.html

测试邮件:

1
2
3
4
5
6
7
# gitlab-rails console
Loading production environment (Rails 4.2.7.1)
irb(main):001:0>
### 在控制台上,输入以下命令发送一封测试邮件
Notify.test_email('收件人邮箱', '邮件标题', '邮件正文').deliver_now

OmniAuth 认证

GitLab 利用 OmniAuth 允许用户使用 Twitter、GitHub 和其他流行服务来登录 GitLab。

OAUTH 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 OAUTH 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 OAUTH 是安全的。oAuth 是 Open Authorization 的简写。

允许从第三方平台,登陆 GitLab 的 providers 有:

配置 OmniAuth

配置 OmniAuth(默认禁用) 不会阻止标准的 GitLab 身份验证或 LDAP(如果已配置)继续工作。 用户可以选择使用任何已配置的机制来登录 GitLab。

在配置 OmniAuth providers 之前,有几个全局设置是需要考虑的:

  • OmniAuth 默认禁用
  • allow_single_sign_on 允许您指定要允许自动创建帐户的 providers,默认为 false。 如果为 false 的话,用户必须手动创建用户,否则他们将无法通过 OmniAuth 登录
  • 如果已启用 LDAP/ActiveDirectory,则可以使用 auto_link_ldap_user,默认为 false。 启用后,通过 OmniAuth 自动创建的用户也将链接到其 LDAP 条目。
  • block_auto_created_users 默认为 true。 如果为 true,那么自动创建的用户将被默认阻止,并且必须由管理员解除阻止才能登录。

注意

  • 如果将 block_auto_created_users 设置为 false,请确保只定义您能够控制的 allow_single_sign_on 下的 providers (如 SAML,Shibboleth,Crowd 或 Google),或将其设置为false,否则互联网上的任何用户都可以成功登录你的 GitLab。
  • auto_link_ldap_user 要求 LDAP 和 OmniAuth provider 中用户的 uid 相同。

修改默认的运行用户和组

默认情况下 omnibus-gitLab 使用 git 用户登陆 Git gitlab-shell,Git data 是属主也是 git,网页上生成的 SSH URL 也是 git 用户。 同样的,git 用户组也是 Git data 的属组。

不建议在已经安装好的 gitlab 上修改默认的 user/group,因为这会产生无法预知的副作用。 如果你固执的想要修改默认的 user/group,你可以在 /etc/gitlab/gitlab.rb 文件中添加下面加行配置:

1
2
user['username'] = "git"
user['group'] = "git"

注意:如果你在已经安装好的 GitLab 中修改了 user/group,reconfigure 不会修改子目录的属主和属组,你需要手动修改, 并确认新用户可以读写 repositories 和 uploads 目录。

设置使用数字表示的用户和组

omnibus-gitlab 为 GitLab, PostgreSQL, Redis 和 NGINX 创建了运行用户。 你可以在 /etc/gitlab/gitlab.rb 文件中指定这些用户的 uid 和 gid。

1
2
3
4
5
6
7
8
user['uid'] = 1234
user['gid'] = 1234
postgresql['uid'] = 1235
postgresql['gid'] = 1235
redis['uid'] = 1236
redis['gid'] = 1236
web_server['uid'] = 1237
web_server['gid'] = 1237

禁用管理用户和组账户的功能

默认情况下,omnibus-gitlab 负责创建用户和组账户,以及更新账户信息。该做法对大多数用户是有意义的, 但在某些环境和需求中,我们需要用其他的软件来管理用户和组账号,比如 LDAP 环境。Omnibus-gitlab 建议在系统上保留 omnibus-gitlab 安装包创建的默认用户和组。

配置项:

1
manage_accounts['enable'] = false

默认用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
### GitLab user(必需)
git
### Web server user(必需)
gitlab-www
### Redis user for GitLab(使用内置的 redis,该账号必需)
gitlab-redis
### Postgresql user(如使用内置的 Postgresql,该账号必需)
gitlab-psql
### GitLab Mattermost user(如使用内置的 Mattermost,该账号必需)
mattermost

默认组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
### GitLab group(必需)
git
### Web server group(必需)
gitlab-www
### Redis group for GitLab(如使用内置的Redis,该用户组必需)
gitlab-redis
### Postgresql group(如使用内置的Postgres,该用户组必需)
gitlab-psql
### GitLab Mattermost group(如使用内置的Mattermost,该用户组必需)
mattermost

自定义用户和组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
### 禁用管理 user/group 的功能
manage_accounts['enable'] = false
### GitLab
user['username'] = "custom-gitlab"
user['group'] = "custom-gitlab"
user['shell'] = "/bin/sh"
user['home'] = "/var/opt/custom-gitlab"
### Web server
web_server['username'] = 'webserver-gitlab'
web_server['group'] = 'webserver-gitlab'
web_server['shell'] = '/bin/false'
web_server['home'] = '/var/opt/gitlab/webserver'
### Postgresql(如使用外部 Postgresql,可忽略该配置)
postgresql['username'] = "postgres-gitlab"
postgresql['shell'] = "/bin/sh"
postgresql['home'] = "/var/opt/postgres-gitlab"
### Redis(如使用外部 Redis,可忽略该配置)
redis['username'] = "redis-gitlab"
redis['shell'] = "/bin/false"
redis['home'] = "/var/opt/redis-gitlab"
### 以此类推,GitLab CI 和 GitLab Mattermost 也需要指定详细的 user/group

禁用管理存储目录的功能

默认情况下,omnibus-gitlab 负责创建所有必需的文件夹并赋予目录正确的所有权和权限, 并根据配置文件保持更新。

在某些大型组织架构中,随着项目代码和数量的增加,一些目录会存储大量的数据, 为扩展存储能力这些目录可能就需要挂载到NFS(或者其他共享存储)上。

挂载某些文件系统会拒绝 root 用户自动创建目录, 比如 NFS 需要启用 root_squash(压缩 root 用户权限为普通账号,例如 git) 。 要解决这个问题,omnibus-gitlab 会尝试使用该目录的属主用户来自动创建子目录。

如果你挂载了 /etc/gitlab 目录,你可以禁用 omnibus-gitlab 对该目录的管理功能。修改 /etc/gitlab/gitlab.rb :

1
manage_storage_directories['manage_etc'] = false

如果计划重新挂载 GitLab 所有存储目录到每个独立的挂载点上, 应该完全禁用 omnibus-gitlab 对各个存储目录的管理功能。

为禁止对所有存储目录的管理功能, 修改 /etc/gitlab/gitlab.rb :

1
manage_storage_directories['enable'] = false

omnibus-gitlab 建议保留默认的目录。 如该选项已设置, 将有管理员创建目录并设置正确的权限。启用此设置会阻止 omnibus-gitlab 创建如下目录:

更改默认仓库路径

默认情况下 omnibus-gitlab 将仓库数据存储在 /var/opt/gitlab/git-data 目录下,仓库存放在子目录 repositories 里面。 以可以通过修改 /etc/gitlab/gitlab.rb 的这一行来自定义 git-data 的父目录。

1
git_data_dirs({"default" => "/data/git-data"})

NFS 配置

Step 1:NFS 服务端,安装 NFS

1
# apt-get install nfs-kernel-server

Step 2:NFS 服务端,配置 NFS

1
2
3
4
5
6
7
8
9
10
11
### NFS 有个比较恼人的权限问题,这种权限问题会出现在服务端和用户端 UID 不一致的情况。
### 因此为了保证 NFS 权限正常,不错乱(UID 一致,但账号不同),需要保证服务器环境一致。
### Linux 文件、目录权限是以 UID/GID 来做判断的。
### 为了解决,账号错乱(UID 一致,但账号不同),权限不匹配(同服务器设置不一致等等问题)
### 可以通过结合 NIS、LDAP 等集中认证授权的方式,来保证账户始终可用。
### 同时在 NFS 共享的资源,不管是 root 用户,还是普通的用户,全部压缩为服务器上的某一账户(例 git)
### 对于或使用集中认证授权的 NFS 而言
### 为了保证 Mount NFS 资源时,服务端和客户端的权限一致
### 那么需要在服务端和客户端上,创建 uid 和 git 相同的 Gitlab repositories 用户账号(git)
1
2
3
4
# useradd -u 998 -g 997 git
# tail -n1 /etc/exports
/data/git-data 192.168.104.2(rw,sync,all_squash,subtree_check,anonuid=998,anongid=997)

Step 2:NFS 客户端(Gitlab),挂载 NFS

如果 /var/opt/gitlab/git-data 目录已经存在 Git 仓库数据, 你可以用下面的命令把数据迁移到新的位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
### 创建 git-data 目录
# apt-get install nfs-common
# mkdir /data/git-data
# chwon git.git /data/gitdata
### 挂载 NFS
# mount -t nfs 192.168.104.2:/data/git-datta \
/data/git-data
### 准备迁移之前要停止 GitLab 服务,防止用户写入数据。
# gitlab-ctl stop
### 注意 'repositories' 后面不带斜杠,而 'git-data' 后面是有斜杠的。
# rsync -vrlptoD /var/opt/gitlab/git-data/repositories /data/git-data/
### 如果需要修复权限设置,可运行下面的命令进行修复。
# gitlab-ctl reconfigure
### 再次检查下 /mnt/nas/git-data 的目录,正常情况应该有下面这个子目录: repositories
# ls /data/git-data/
### 启动 GitLab,验证下是否能通过 web 访问 Git 仓库
# gitlab-ctl start

设置延迟启动

为保证服务质量,我们可以设置让 omnibus-gitlab 的服务(Nginx, Redis, Unicorn 等)在指定的文件系统挂载成功后再启动,在 /etc/gitlab/gitlab.rb 文件中添加如下内容:

1
2
# wait for /var/opt/gitlab to be mounted
high_availability['mountpoint'] = '/var/opt/gitlab'

启用禁用账户验证防护

1
2
3
4
5
6
7
gitlab_rails['rack_attack_git_basic_auth'] = {
'enabled' => true, # 启用/禁用 Rack Attack
'ip_whitelist' => ["127.0.0.1"], # 白名单地址,多个 IP 用","隔开
'maxretry' => 10, # 限制每个 IP 尝试登陆的次数为 10 次。
'findtime' => 60, # 60 秒后重置每 IP 的授权计数器
'bantime' => 3600 # 对多次错误登陆的 IP 封禁 1 小时(3600 秒)
}

禁用用户开放注册

OpenLDAP 集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
gitlab_rails['ldap_enabled'] = true
###! **remember to close this block with 'EOS' below**
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
main: # 'main' is the GitLab 'provider ID' of this LDAP server
label: 'LDAP'
host: '192.168.112.5'
port: 389
uid: 'uid'
method: 'tls' # "tls" or "ssl" or "plain"
bind_dn: ''
password: ''
active_directory: true
allow_username_or_email_login: false
block_auto_created_users: false
base: 'dc=mallux,dc=org'
user_filter: ''
attributes:
username: ['uid', 'userid', 'sAMAccountName']
email: ['mail', 'email', 'userPrincipalName']
name: 'cn'
first_name: 'givenName'
last_name: 'sn'
# ## EE only
# group_base: ''
# admin_group: ''
# sync_ssh_keys: false
#
# secondary: # 'secondary' is the GitLab 'provider ID' of second LDAP server
# label: 'LDAP'
# host: '_your_ldap_server'
# port: 389
# uid: 'sAMAccountName'
# method: 'plain' # "tls" or "ssl" or "plain"
# bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
# password: '_the_password_of_the_bind_user'
# active_directory: true
# allow_username_or_email_login: false
# block_auto_created_users: false
# base: ''
# user_filter: ''
# attributes:
# username: ['uid', 'userid', 'sAMAccountName']
# email: ['mail', 'email', 'userPrincipalName']
# name: 'cn'
# first_name: 'givenName'
# last_name: 'sn'
# ## EE only
# group_base: ''
# admin_group: ''
# sync_ssh_keys: false
EOS

重新加载 gitlab 服务:

1
# gitlab-ctl reconfigure

Gitlab 登陆:

Gitlab 验证:

启动、停止 GitLab 服务

禁止自启

1
# systemctl disable gitlab-runsvdir.service

开机自启

1
# systemctl enable gitlab-runvdir.service

启停 Gitlab 服务

1
2
# gitlab-ctl stop
# gitlab-ctl start

Reply by email

允许用户通过回复预设的邮件来评论 issue 和合并请求

Reply by email 需要一个 IMAP 的电子邮件帐户。 GitLab允许您为此功能使用三种策略:

  • using email sub-addressing
  • using a dedicated email address
  • using a catch-all mailbox

IMAP

POP3 协议允许电子邮件客户端下载服务器上的邮件,但是在客户端的操作(如移动邮件、标记已读等),不会反馈到服务器上,比如通过客户端收取了邮箱中的 3 封邮件并移动到其他文件夹,邮箱服务器上的这些邮件是没有同时被移动的 。

而 IMAP 提供 webmail 与电子邮件客户端之间的双向通信,客户端的操作都会反馈到服务器上,对邮件进行的操作,服务器上的邮件也会做相应的动作。

同时,IMAP 像 POP3 那样提供了方便的邮件下载服务,让用户能进行离线阅读。IMAP 提供的摘要浏览功能可以让你在阅读完所有的邮件到达时间、主题、发件人、大小等信息后才作出是否下载的决定。此外,IMAP 更好地支持了从多个不同设备中随时访问新邮件。

Email sub-addressing

sub-addressing 是一个允行向 user+some_arbitrary_tag@example.com 发送的任何电子邮件发送的电子邮件都将会发送到 user@example.com 的邮箱中,被 Gmail,Google Apps,Yahoo! Mail,Outlook.com 和 iCloud,以及本地运行的 Postfix 邮件服务器等支持。

反向代理后的 Gitlab HTTPS 设置

  • 前端 LB:启用 HTTPS
  • 后端 Gitlab:配置 gitlab.rb

默认情况下,如果 external_url 包含 https://,则 NGINX 将自动检测是否使用 SSL。 如果您在反向代理之后运行 GitLab,则需要将下面的设置应用于 gitlab.rb

1
2
3
4
5
6
7
8
9
10
11
external_url 'https://gitlab.mallux.org'
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
"X-Forwarded-Proto" => "https",
"X-Forwarded-Ssl" => "on"
}
nginx['real_ip_header'] = 'X-Real-IP'
nginx['real_ip_recursive'] = 'on

重新应用配置:

1
# gitlab-ctl reconfigure

Gitlab 管理

导入用户 Key

Step 1:用户端,生成用户 key(不设置密码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[mallux@i-v5dik2p2 ~]$ ssh-keygen -t rsa -C 'mallux@gitlab-test'
Generating public/private rsa key pair.
Enter file in which to save the key (/home/mallux/.ssh/id_rsa):
Created directory '/home/mallux/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/mallux/.ssh/id_rsa.
Your public key has been saved in /home/mallux/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:1ypJ1o/V3TRJK9U3AvOUBbP/ph5L9OQIO7en+Nwu1wE mallux@gitlab-test
The key's randomart image is:
+---[RSA 2048]----+
| o.+++.|
| +o=.=|
| +.++|
| . . Eooo|
| S o + +.+|
| o o = + *.|
| o o + = B|
| . *.B+|
| .oO*o|
+----[SHA256]-----+

Step 2:Gitlab 服务端导入用户 key

右上角 “个人头像” -> “settings” -> “SSH Keys”,添加用户公钥(默认 id_rsa.pub)

Step3:用户端,验证 SSH 连接方式

1
2
3
4
5
6
7
8
[mallux@i-v5dik2p2 ~]$ ssh git@192.168.104.2
The authenticity of host '192.168.104.2 (192.168.104.2)' can't be established.
ECDSA key fingerprint is SHA256:7PC/o+BHPeh0gWSRo/ADiELxzWZINqyg3ei1rY2PkU0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.104.2' (ECDSA) to the list of known hosts.
PTY allocation request failed on channel 0
Welcome to GitLab, HJ.Mallux!
Connection to 192.168.104.2 closed.

导入 GitHub 项目

Gitlab 目前支持如下几种方式的代码导入

导入 GitHub 项目

  • 步骤一:GitHub 生成 Token

如下图所示,菜单位置个人 “settings” -> “Persiona access token” 子项。

  • 步骤二:Gitlab 导入项目

选择“List You GitHub Repositories”后,将列出你的账号所允许被访问的 GitHub 的项目,选择“Import”导入项目。

Deploy Key

Deploy keys allow read-only access to multiple projects with a single SSH key.

This is really useful for cloning repositories to your Continuous Integration (CI) server. By using deploy keys, you don’t have to setup a dummy user account.

If you are a project master or owner, you can add a deploy key in the project settings under the section 'Deploy Keys'. Press the ‘New Deploy Key’ button and upload a public SSH key. After this, the machine that uses the corresponding private key has read-only access to the project.

You can’t add the same deploy key twice with the ‘New Deploy Key’ option. If you want to add the same key to another project, please enable it in the list that says ‘Deploy keys from projects available to you’. All the deploy keys of all the projects you have access to are available. This project access can happen through being a direct member of the project, or through a group. See def accessible_deploy_keys in app/models/user.rb for more information.

Deploy keys can be shared between projects, you just need to add them to each project.

4.4 安装 gitlab-runner

添加源:

1
2
3
4
5
### For Debian/Ubuntu
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash
### For RHEL/CentOS
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash

安装 runner

1
2
3
4
5
### For Debian/Ubuntu
sudo apt-get install gitlab-ci-multi-runner
### For RHEL/CentOS
sudo yum install gitlab-ci-multi-runner

Git workflow

[Doc] https://doc.gitlab.cc/ce/workflow/authorization_for_merge_requests.html

  • Protected branch flow

    • With the protected branch flow everybody works within the same GitLab project.
    • The project maintainers get Master access and the regular developers get Developer access.
    • The maintainers mark the authoritative branches as ‘Protected’.
    • The developers push feature branches to the project and create merge requests to have their feature branches reviewed and merged into one of the protected branches.
    • Only users with Master access can merge changes into a protected branch.
  • Forking workflow

    • With the forking workflow the maintainers get Master access and the regular developers get Reporter access to the authoritative repository, which prohibits them from pushing any changes to it.

    • Developers create forks of the authoritative project and push their feature branches to their own forks.

    • To get their changes into master they need to create a merge request across forks.

Gitlab 高可用

NFS 配置

  • no_root_squash:NFS 通常 将 root 用户更改为 nobody。 这是一个很好的安全措施,当 NFS 共享将被许多不同的用户访问。 但是,在这种情况下,只有 GitLab 才能使用 NFS 共享,所以它是安全的。 GitLab 需要 no_root_squash 设置,因为我们需要自动管理文件权限。 没有设置,当 Omnibus 软件包尝试更改权限时,您将收到错误。 请注意,GitLab 和其他捆绑组件不以 root 身份运行,而不作为非特权用户运行。 no_root_squash 的要求是允许 Omnibus 包根据需要设置文件的所有权和权限
  • sync:强制同步行为。 默认是异步的,在某些情况下,如果在数据同步之前发生故障,可能会导致数据丢失。
1
10.1.1.1:/data/git-data /var/opt/gitlab/git-data nfs4 defaults,soft,rsize=262144,wsize=262144,noatime,nobootwait,lookupcache=positive 0 2
  • nobootwait:不要停止启动进程等待此挂载成为可用
  • lookupcache=positive:告诉 NFS 客户端遵循 positive(积极)的缓存结果,但会使任何 negative( 消极)缓存结果无效。 Negative 缓存结果会导致 Git 出现问题。 具体来说,git push 可能无法在所有 NFS 客户端上统一注册。 Negative 缓存导致客户端 “记住” 之前文件不存在的情况。
  • rsize、wsize:通过设置更大的数据块大小(以字节为单位)来一次传输,从而加速读取(rsize)和写入(wsize)的 NFS 通信。默认 4096
  • sec=mode:指定在验证 NFS 连接时要使用的安全性类型,类型有 sys、krb5、krb5i 和 krb5p
  • proto=tcp or udp:指定 NFS 挂载使用 TCP or UDP 协议
  • hard or softhard 使用硬挂载的方式挂载系统,该值是默认值,重复请求直到 NFS 服务器回应;soft 使用软挂载的方式挂载系统,若 Client 的请求得不到回应,则重新请求并传回错误信息
  • intr:当你使用 hard 方式挂载时,若加上 intr 这个参数, 则当 RPC 持结连接时,该次的呼叫是可以被中断的(interrupted)
  • retrans:重传次数
  • noatime:访问文件时不修改相关文件的 Access Time
  • nodiratime:不修改目录的 Access Time
  • noexec:不允许直接运行文件,即使该文件有 x 权限
  • nodev:屏蔽字符设备或块设备的属性
  • nosuid:屏蔽 suid

共享挂载点

使用默认的 Omnibus 配置时,您需要在所有 GitLab 群集节点之间共享 5 个数据位置(如下表所示),不应共享其他位置。

Location Description Default configuration
/var/opt/gitlab/git-data Git repository data. This will account for a large portion of your data git_data_dirs({"default" => "/var/opt/gitlab/git-data"})
/var/opt/gitlab/.ssh SSH authorized_keys file and keys used to import repositories from some other Git services user['home'] = '/var/opt/gitlab/'
/var/opt/gitlab/gitlab-rails/uploads User uploaded attachments gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'
/var/opt/gitlab/gitlab-rails/shared Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you’re using LFS this may also account for a large portion of your data gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'
/var/opt/gitlab/gitlab-ci/builds GitLab CI build traces gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'

节点之间不应该共享其他 GitLab 目录,包含不需要共享的节点特定文件和 GitLab 代码。 要将日志发送到中央位置,请考虑使用远程 syslog。 GitLab Omnibus 软件包 为 UDP 日志传送提供配置。

示例

1
2
3
4
5
git_data_dirs({"default" => "/data/gitlab_data"})
user['home'] = "/data/gitlab_data/"
gitlab_rails['uploads_directory'] = "/data/gitlab_data/gitlab-rails/uploads"
gitlab_rails['shared_path'] = '/data/gitlab_data/gitlab-rails/shared'
gitlab_ci['builds_directory'] = '/data/gitlab_data/gitlab-ci/builds'

要移动 git 主目录,必须停止所有 GitLab 服务。 运行 gitlab-ctl stop && systemctl stop gitlab-runsvdir。 然后继续重新配置。

运行 sudo gitlab-ctl reconfigure 以开始使用中央位置。 请注意,如果您有现有数据,则需要手动 copy/rsync 复制数据到这些新位置,然后重新启动 GitLab。

1
2
3
# gitlab-ctl stop
# systemctl stop gitlab-runsvdir
# gitlab-ctl reconfigure

日志目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# gitlab_rails['incoming_email_log_directory'] = "/var/log/gitlab/mailroom"
# gitlab_rails['log_directory'] = "/var/log/gitlab/gitlab-rails"
# registry['log_directory'] = "/var/log/gitlab/registry"
# gitlab_workhorse['log_directory'] = "/var/log/gitlab/gitlab-workhorse"
# unicorn['log_directory'] = "/var/log/gitlab/unicorn"
# sidekiq['log_directory'] = "/var/log/gitlab/sidekiq"
# gitlab_shell['log_directory'] = "/var/log/gitlab/gitlab-shell/"
# gitlab_shell['git_trace_log_file'] = "/var/log/gitlab/gitlab-shell/gitlab-shell-git-trace.log"
# postgresql['log_directory'] = "/var/log/gitlab/postgresql"
# nginx['log_directory'] = "/var/log/gitlab/nginx"
# gitlab_pages['log_directory'] = "/var/log/gitlab/gitlab-pages"
# pages_nginx['log_directory'] = "/var/log/gitlab/nginx"
# mattermost['log_file_directory'] = '/var/log/gitlab/mattermost'
# mattermost_nginx['log_directory'] = "/var/log/gitlab/nginx"
# registry_nginx['log_directory'] = "/var/log/gitlab/nginx"
# prometheus['log_directory'] = '/var/log/gitlab/prometheus'
# node_exporter['log_directory'] = '/var/log/gitlab/node-exporter'
# redis_exporter['log_directory'] = "/var/log/gitlab/redis-exporter"
# postgres_exporter['log_directory'] = "/var/log/gitlab/postgres-exporter"
# gitlab_monitor['log_directory'] = "/var/log/gitlab/gitlab-monitor"
# sidekiq_cluster['log_directory'] = "/var/log/gitlab/sidekiq-cluster"

迁移日志:

1
2
3
4
5
6
7
8
9
# gitlab-ctl stop
# systemctl stop gitlab-runsvdir.service
# rsync -av /var/log/gitlab/ /data/gitlab_logs/
# rm -rf gitlab
# ln -s /data/gitlab_logs /var/log/gitlab
# systemctl start gitlab-runsvdir.service
# gitlab-ctl start

Gerrit + Gitlab 整合

Gitlab CE 的代码 Code Review(代码审核) 功能太弱,总结起来,有以下几个方面:

  • 没有很严格的权限控制机制,也无法控制到具体的分支权限,基本权限控制可以说只针对版本库而言
  • 用户组概念模糊,所有代码库的权限授权动作,都是针对项目组(Group )而言
  • 对于有权限的 git push 操作,会直接修改远程托管代码的仓库的 refs/heads/<branch> 分支。另外,其 Code Review 机制也不够健全

在 Gitlab 中,可以设置 Master 为保护分支,那么普通用户可以自己创建分支并提交代码到自己的分支上,没有权限直接 push 到 Master 分支。用户若需要提交自己的代码到 Master 分支,需要发起一个 Merge Request,项目指定的管理人员收到 Merge Request 后, Review 代码后选择是否合并代码。

Gerrit

Gerrit 是 Googel 开发的,托管 Android 代码的开源项目代码审查工具,也是广泛采用的 Code Review 系统。Gerrit 本身不需要依赖任何其它代码管理工具,就可作为一个独立的代码管理平台。

Gerrit 的优势

  • 非常健全的代码审核及权限控制机制
  • 对于任何 git push 的操作,可以控制用户提交的代码,不直接 merge 到 refs/heads/<branch> 分支(即直接进入主代码库,包括 master 和其它分支),而是提交到 refs/for/<branch> 分支上进入代码审核流程
  • 可以设置 多人员 进行代码审核,分为 Verified(核查,-1/+1 权限,普通开发人员协同审核) 和 Code Review(-2/+2 权限,核心开发/项目管理人员,是否允许 Merge 代码)
  • 代码审核通过后,项目管理人员可以无需自己合并代码,Gerrit 会主动邮件通知代码提交人员,做最后的 merge 代码到主代码库的动作
  • 内置实时复制插件:Merge 代码主动触发复制功能,可以做到具体某一分支或整个代码库的镜像

通过将 Gitlab 和 Gerrit 的集成,除了让 Gerrit 作为 Gitlab 的备份外,借助于 Gerrit 的复制功能,也可以使 Gitlab 作为 Gerrit 的备份,且代码完全是实时同步的。

Gerrit 代码审核工作流:

Gerrit 具体部署,请参见 Git 权威指南 - 学习笔记

GitLab runner

Runner 类型

GitLab-Runner 可以分类两种类型:Shared Runner(共享型)和Specific Runner(指定型)

  • Shared Runner:这种Runner(工人)是所有工程都能够用的。只有系统管理员能够创建Shared Runner。

  • Specific Runner:这种Runner(工人)只能为指定的工程服务。拥有该工程访问权限的人都能够为该工程创建Shared Runner。

运行 Runner

添加源

Debian / Ubuntu:

1
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash

RHEL / CentOS:

1
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash

安装 Gitlab Runner

1
2
3
4
5
### For Debian/Ubuntu
sudo apt-get install gitlab-ci-multi-runner
### For RHEL/CentOS
sudo yum install gitlab-ci-multi-runner

注册 Gitlab Runner

1
# gitlab-ci-multi-runner register

END