我尝试将Gitlab部署到Kubernetes环境中
首先 / 首先
以前我们在k8s环境中部署了Gitbucket并使用过,现在我们将尝试运行更专业的Gitlab(sameersbn/docker-gitlab)容器。
GitLab的默认状态下,未登录账户无法自由浏览仓库。可以直接通过公开仓库、探索页面或用户页面的URL来浏览,但如果没有线索,就无法从首页跳转。
就这一点而言,我认为Gitbucket在中小规模使用和公开代码方面,即使不做任何修改,已经具备足够简便和功能齐全。
可供参考的资料
-
- Gitbucketをkubernetesにデプロイしてみた
- https://github.com/sameersbn/docker-gitlab
环境
-
- Kubernetes – v1.25.6 (Kubespray v2.21.0)
-
- Rook/Ceph v1.9.13 (ceph version 16.2.10)
-
- Ingress (Webアクセス用。Serviceでtype: LoadBalancerはSSHでのみ利用)
- OpenLDAP (ユーザー認証用)
Gitlab的CE版本只需连接LDAP即可,但是有点可惜的是不能有效地使用过滤器。
参考文献
- https://github.com/sameersbn/docker-gitlab
政策
sameersbn/docker-gitlabは、docker-compose.yamlファイルだけでなく、kuberentesで稼動させるためのYAMLファイルが含まれています。
$ git clone https://github.com/sameersbn/docker-gitlab.git
$ cd docker-gitlab
$ git checkout refs/tags/15.2.2 -b t_15.2.2
kubernetes/ディレクトリにあるファイルは、PVCの定義が抜けている点と、gitlab-svc.yamlでtype: LoadBalancerが指定されていますが、これは使わずにIngress経由でcontext-rootを変更し、/gitlab/に来たリクエストを振ります。
考慮点
負荷分散させるためのgitalyのクラスター化や、Object Storageの利用などは行なっていません。
そのため、redis/postgresqlはクラスター化させることは比較的容易だと思いますが、全てのインスタンス(Pod)は1つずつ動かしています。
请注意这些可能会成为SPoF(单点故障)的事项。
YAML文件
我将在介绍中包含已更改的部分,以展示整个YAML文件。
PVC文件
我们将准备一个用于使用Rook/Ceph的PVC。
在事先准备好的redis-rc.yml文件中,已经保护了/var/lib/redis目录,但是由于使用的镜像是以/data为持久化目标,因此我们需要更改该路径。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-data-pvc
namespace: gitlab
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 10Gi
storageClassName: rook-ceph-block
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pg-data-pvc
namespace: gitlab
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 200Gi
storageClassName: rook-ceph-block
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitlab-data-pvc
namespace: gitlab
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 100Gi
storageClassName: rook-ceph-block
SVC文件
只有在Service的YAML文件中进行了更改,即gitlab-svc.yml。
apiVersion: v1
kind: Service
metadata:
name: gitlab
namespace: gitlab
labels:
name: gitlab
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: ssh
port: 10022
targetPort: 22
selector:
name: gitlab
由于无法通过22号端口进行外部访问,所以SSH访问将在10022号端口上等待。
在前端Web服务器上,将10022号端口的访问连接到此LoadBalancer分配的EXTERNAL-IP。
如前文所述,不使用EXTERNAL-IP来访问80端口,而是通过Ingress将请求代理到svc/gitlab服务(gitlab.gitlab.svc.cluster.local)。
RC文件
最近的Kubernetes中已經不再使用Deployment物件,而是使用ReplicationController物件。儘管寫這段文字的內容相對繁瑣,但還是維持原樣不作修改。
主要的变化是将volumeMounts/volumes更改为使用定义的PVC,并将加入DB连接密码、GitLab各种设置(特别是LDAP设置)。
apiVersion: v1
kind: ReplicationController
metadata:
name: redis
namespace: gitlab
spec:
replicas: 1
selector:
name: redis
template:
metadata:
name: redis
labels:
name: redis
spec:
containers:
- name: redis
image: redis:6.2.7
ports:
- name: redis
containerPort: 6379
volumeMounts:
- mountPath: /data
name: redis-data
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
timeoutSeconds: 1
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-data-pvc
apiVersion: v1
kind: ReplicationController
metadata:
name: postgresql
namespace: gitlab
spec:
replicas: 1
selector:
name: postgresql
template:
metadata:
name: postgresql
labels:
name: postgresql
spec:
containers:
- name: postgresql
image: sameersbn/postgresql:12-20200524
env:
- name: DB_USER
value: gitlab
- name: DB_PASS
value: e6cb3ac870c56287
- name: DB_NAME
value: gitlab_production
- name: DB_EXTENSION
value: pg_trgm,btree_gist
ports:
- name: postgres
containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql
name: data
livenessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- postgres
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- postgres
initialDelaySeconds: 5
timeoutSeconds: 1
volumes:
- name: data
persistentVolumeClaim:
claimName: pg-data-pvc
postgresql-rc.yml文件的修改包括在PVC之外,还添加了DB_EXTENSION的btree_gist插件,并设置了用于DB连接的密码。
---
apiVersion: v1
kind: ReplicationController
metadata:
name: gitlab
namespace: gitlab
spec:
replicas: 1
selector:
name: gitlab
template:
metadata:
name: gitlab
labels:
name: gitlab
spec:
containers:
- name: gitlab
image: sameersbn/gitlab:15.2.2
env:
- name: DEBUG
value: "false"
- name: TZ
value: "Asia/Tokyo"
- name: GITLAB_TIMEZONE
value: "Tokyo"
- name: GITLAB_UNICORN_MEMORY_MAX
value: "629145600"
- name: GITLAB_HTTPS
value: "false"
- name: SSL_SELF_SIGNED
value: "false"
- name: OAUTH_ENABLED
value: "false"
- name: GITLAB_SECRETS_DB_KEY_BASE
value: 1c10d46a57abd38c2c7957d87980fecb
- name: GITLAB_SECRETS_SECRET_KEY_BASE
value: e927734a7fdb0363e078ede99e4d7180
- name: GITLAB_SECRETS_OTP_KEY_BASE
value: 4f69440296aa7db3be56c5ea2d8f3876
- name: GITLAB_ROOT_PASSWORD
value: ""
- name: GITLAB_ROOT_EMAIL
value: "gitlab-admin@example.com"
- name: GITLAB_EMAIL_REPLY_TO
value: "gitlab-admin@example.com"
- name: GITLAB_EMAIL_SUBJECT_SUFFIX
value: "[Gitlab]"
- name: GITLAB_RELATIVE_URL_ROOT
value: "/gitlab"
- name: GITLAB_HOST
value: "external.example.com"
- name: GITLAB_PORT
value: "80"
- name: GITLAB_SSH_PORT
value: "10022"
- name: GITLAB_NOTIFY_ON_BROKEN_BUILDS
value: "false"
- name: GITLAB_NOTIFY_PUSHER
value: "false"
- name: GITLAB_BACKUP_SCHEDULE
value: daily
- name: GITLAB_BACKUP_TIME
value: 01:00
- name: DB_ADAPTER
value: "postgresql"
- name: DB_TYPE
value: postgres
- name: DB_HOST
value: postgresql
- name: DB_PORT
value: "5432"
- name: DB_USER
value: gitlab
- name: DB_PASS
value: e6cb3ac870c56287
- name: DB_NAME
value: gitlab_production
- name: REDIS_HOST
value: redis
- name: REDIS_PORT
value: "6379"
- name: SMTP_ENABLED
value: "true"
- name: SMTP_DOMAIN
value: "example.com"
- name: SMTP_HOST
value: "smtp.example.com"
- name: SMTP_PORT
value: "25"
- name: SMTP_USER
value: ""
- name: SMTP_PASS
value: ""
- name: SMTP_STARTTLS
value: "false"
- name: SMTP_AUTHENTICATION
value: "plain"
- name: IMAP_ENABLED
value: "false"
- name: LDAP_ENABLED
value: "true"
- name: LDAP_LABEL
value: "AINS LDAP"
- name: LDAP_HOST
value: "ldap.example.com"
- name: LDAP_PORT
value: "636"
- name: LDAP_UID
value: "uid"
- name: LDAP_METHOD
value: "simple_tls"
- name: LDAP_VERIFY_SSL
value: "true"
- name: LDAP_ACTIVE_DIRECTORY
value: "false"
- name: LDAP_ALLOW_USERNAME_OR_EMAIL_LOGIN
value: "true"
- name: LDAP_BLOCK_AUTO_CREATED_USERS
value: "true"
- name: LDAP_BASE
value: "ou=People,ou=Proxy,dc=example,dc=com"
- name: LDAP_USER_ATTRIBUTE_NAME
value: "gecos"
- name: LDAP_USER_ATTRIBUTE_FIRSTNAME
value: "gecos"
- name: LDAP_USER_ATTRIBUTE_LASTNAME
value: "uid"
- name: LDAP_PREVENT_LDAP_SIGN_IN
value: "false"
ports:
- name: http
containerPort: 80
- name: ssh
containerPort: 22
volumeMounts:
- mountPath: /home/git/data
name: data
#livenessProbe:
# httpGet:
# path: /gitlab/
# port: 80
# initialDelaySeconds: 180
# timeoutSeconds: 5
#readinessProbe:
# httpGet:
# path: /gitlab/
# port: 80
# initialDelaySeconds: 5
# timeoutSeconds: 1
volumes:
- name: data
persistentVolumeClaim:
claimName: gitlab-data-pvc
关于Ingress等其他设置
通过设置环境变量(GITLAB_RELATIVE_URL_ROOT、GITLAB_HOST),使外部访问时的顶级地址为”https://external.example.com/gitlab/”。
我們將使用透過這個主機的10022端口通過ssh進行clone/push等操作。
为了这个原因,我们会进行Ingress和边界服务器(external.example.com/)的端口转发设置。不涉及在边界内部配置的Web服务器(https://external.example.com/)的设置方法等。
来自external.example.com的连接通过Ingress连接
在 ingress-nginx 命名空间中定义了以下的 Service(svc) 对象。
这个 externalName 是指向在 gitlab 命名空间中通过 gitlab-svc.yml 创建的 svc/gitlab 对象。
---
apiVersion: v1
kind: Service
metadata:
name: gitlab-svc
labels:
group: ingress-nginx
namespace: ingress-nginx
spec:
type: ExternalName
externalName: gitlab.gitlab.svc.cluster.local
在Ingress自身的设置中,添加以下定义。请注意不要覆盖已经使用的其他定义。
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: default
labels:
group: ingress-nginx
namespace: ingress-nginx
spec:
rules:
- http:
paths:
- backend:
service:
name: gitlab-svc
port:
number: 80
path: /gitlab
pathType: Prefix
... ## 他の backend: 定義が続く
在 ingress.yaml 中定义的 .spec.rules.http.paths.backend.service.name 指的是 ingress-svc-gitlab.yaml 中定义的 namespace: ingress-nginx 的 svc/gitlab-svc 对象。
将10022端口进行端口转发。
这台服务器的特点在于它是基于CentOS 8 Stream操作系统,并且使用了Ansible工具。
- name: firewalld enablse the masquerade service for external
firewalld:
zone: external
masquerade: yes
permanent: true
state: enabled
- name: firewalld external config for the gitlab ssh port
firewalld:
zone: external
rich_rule: rule family=ipv4 forward-port port=10022 protocol=tcp to-port=10022 to-addr=192.168.1.22
permanent: yes
immediate: yes
state: enabled
如果使用Ubuntu
我在使用Ubuntu时,如果要使用ufw会变得有点复杂。
但是我使用socat而不是ufw,因为它更加稳定,所以我选择使用socat。
#!/bin/bash
TARGET="10022"
ps auxww|grep "${TARGET}" | grep -v grep > /dev/null
rc="$?"
if test "${rc}" != "0" ; then
nohup socat tcp4-listen:10022,reuseaddr,fork TCP:192.168.1.22:10022 &
fi
为了在重新启动或异常关闭时自动启动,我们使用cron进行调度。
#Ansible: check-gitlab
2 * * * * /usr/local/sbin/check-gitlab
关于升级
目前我们正在使用15.3.1和15.3.3版本。为了更新到15系列的最新版本(15.11.13),首先需要升级到15.4.6,包括15.2.2在内。
在GitLab中,提供了升级路径,所以必须查看官方网站的信息确认。
目前推荐更新版本依次为 15.0.5 > 15.1.6(适用于具备多个网络节点的GitLab实例)> 15.4.6 > 15.11.13。从版本15.11.13起,可以按照16.1.5→16.3.6→16.6.1的顺序进行最新版的更新。
我害怕更新到最新版本会遇到bug,所以我想在15.11.13之前先观察一段时间。
建议将备份文件复制到本地,以免遗失,备份文件位于Pod上的/home/git/data/backups/目录下。
由于存在测试环境,所以我将尝试将gitlab-rc.yaml中的gitlab版本更改为15.4.6并应用。
diff --git a/gitlab/yaml/gitlab-rc.yml b/gitlab/yaml/gitlab-rc.yml
index f489a43..7b42ad1 100644
--- a/gitlab/yaml/gitlab-rc.yml
+++ b/gitlab/yaml/gitlab-rc.yml
@@ -16,7 +16,7 @@ spec:
spec:
containers:
- name: gitlab
- image: sameersbn/gitlab:15.3.1
+ image: sameersbn/gitlab:15.4.6
env:
- name: DEBUG
value: "false"
由于应用这个设置后,Pod不会自动重启,因此需要手动删除Pod。
在新版本中,gitlab的Pod启动后,当检查日志时,会在重新编译资源(使用相对URL)这部分暂停一段时间。
success Packages successfully patched.
Done in 41.60s.
yarn add v1.22.19
[1/5] Validating package.json...
[2/5] Resolving packages...
[3/5] Fetching packages...
[4/5] Linking dependencies...
warning "@gitlab/eslint-plugin > eslint-plugin-jest > @typescript-eslint/experimental-utils > @typescript-eslint/typescript-estree > tsutils@3.17.1" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
warning "@graphql-eslint/eslint-plugin > graphql-config > @endemolshinegroup/cosmiconfig-typescript-loader > ts-node@9.1.1" has unmet peer dependency "typescript@>=2.7".
warning Workspaces can only be enabled in private projects.
[5/5] Building fresh packages...
warning "ajv" is already in "devDependencies". Please remove existing entry first before adding it to "dependencies".
warning Workspaces can only be enabled in private projects.
success Saved 0 new dependencies.
$ node ./scripts/frontend/postinstall.js
success Dependency postinstall check passed.
success Packages successfully patched.
Done in 3.24s.
Recompiling assets (relative_url in use), this could take a while...
虽然需要花费相当长的时间,但是耐心等待,处理将会进行并且最终可以通过WebUI登录。
由于后台可能仍在进行更新处理,因此请不要急于进行下一个版本的更新。请通过管理界面确认更新处理已完成。
以 root 身份登入後,導航至管理員 → 監控 → 背景遷移,並確認所有處理達到「完成」狀態。
确认到此再继续进入下一次升级。
以上