はじめに
以前に Gitbucketをk8s環境にデプロイして利用してきましたが、より本格的なGitlab(sameersbn/docker-gitlab)のコンテナを稼動させてみます。
デフォルト状態のGitLabはログインしないとリポジトリを自由に閲覧することができません。
Publicなリポジトリ、あるいはExploreページやユーザーページのURLを直接指定すれば、閲覧することはできますが、手掛かりがないとトップページから遷移できません。
この点、Gitbucketは中小規模での利用やコードを公開する用途では、そのままでも手軽で十分な機能があると思います。
この記事はv15.11.13までの導入についてまとめています。
v15.11.13からv16.7.3へのバージョンアップについては別記事にまとめています。
参考資料
環境
- 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に接続するだけで、フィルターが有効に使えないのが少し残念なポイントです。
方針
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が永続化対象なので、このpathを含めて変更しています。
---
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に接続させます。
冒頭で説明したように、80番ポートへはEXTERNAL-IPは使わずにIngressからsvc/gitlabサービス(gitlab.gitlab.svc.cluster.local)にProxy接続させます。
RCファイル
Deploymentオブジェクトではなく、ReplicationControllerオブジェクトを使うことは最近のKubernetesではありませんが、書き換えるのも面倒なのでこのまま書き換えていきます。
主な変更点は、定義したPVCを利用するようにvolumeMounts/volumesを変更する点と、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/)の設定方法などは含めていません。
Ingressによるexternal.example.comからの接続
namespace: ingress-nginxに次のようなService(svc)オブジェクトを定義します。
このexternalName先がgitlab-svc.ymlで作成した namespace: gitlab に存在する、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を利用する場合には少し複雑になります。
ただ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.2.2を含めて15系列の最新版(15.11.13)にするためには、まず15.4.6にアップグレードする必要があります。
GitLabではアップグレードパスが提供されているので、公式サイトの情報確認が必須です。
いまのところ 15.0.5 > 15.1.6 (for GitLab instances with multiple web nodes) > 15.4.6 > 15.11.13.
とされていて、15.11.13 からは、16.1.5→16.3.6→16.6.1の順で最新版に更新できるようです。
ただ最新版への更新はバグが入り込むことが怖いので、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が起動し、ログを確認するとRecompiling assets (relative_url in use), this could take a while...
の部分からしばらく処理が止まります。
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からログインできるようになります。
まだバックグラウンドで更新処理が進んでいる可能性があるので、次のバージョンに更新する処理を急がずに、Admin画面から更新処理が終わっていることを確認します。
rootでログインしてから、Admin → Monitoring → Background Migrations と進み、全ての処理がFinish状態になっていることを確認します。
ここまで確認してから繰り返し次のアップグレードに進みます。
以上