GitLab CI/CD について使い方を把握してみます。
簡単のため docker イメージを利用します。マウントしたディレクトリは、Docker エントリーポイントから実行される Chef によってプロビジョニングされます。
docker run \
--hostname localhost \
--publish 10443:443 --publish 10080:80 --publish 10022:22 \
--name gitlab \
--volume /tmp/gitlab/config:/etc/gitlab \
--volume /tmp/gitlab/logs:/var/log/gitlab \
--volume /tmp/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
初回起動時は管理ユーザ root
のパスワードを設定します。
ユーザに SSH 鍵をします。
22 番以外のポートで clone するためには以下のようにします。
git clone ssh://git@localhost:10022/mygroup/myproject.git
レポジトリ内の Settings → Repository → Protected Branches によって、指定したブランチに push できないように設定できます。ワークフローとしてマージリクエストを強制したい場合などに有用です。
API 認証の方法の一つにアクセストークンの利用があります。アクセストークンは個人設定ページから発行できます。API リソース一覧のうち Issues リソースを取得する例は以下のようになります。
curl -sS --header 'PRIVATE-TOKEN: xxxx_NUQoNZWhQw1xnjQ' http://localhost:10080/api/v4/issues
こちらのページを参照して Job の内容を設定します。.gitlab-ci.yml
ファイルはレポジトリのルートディレクトリに設置します。動作確認のために以下のように設定してみます。Job 実行時にコミット内容を git clone せずに ok を echo します。
variables:
GIT_STRATEGY: none
run-test:
script:
- echo ok
/-/ci/lint
を追加した http://localhost:10080/mygroup/myproject/-/ci/lint
で設定ファイルを検証できます。
GitLab Runner は .gitlab-ci.yml
設定によって生成された Job を処理するワーカです。Go で開発されたバイナリとして配布されています。GitLab Runner の実行方法は複数存在しますが、ここではホストの Docker コンテナとして実行する方法と、kubernetes Pod として実行する方法を試してみます。
Docker コンテナ内で Go バイナリ gitlab-runner
を実行します。
docker run --rm --name gitlab-runner gitlab/gitlab-runner
docker exec で gitlab-runner
の register を実行して GitLab に runner として登録します。--url
には runner から GitLab にアクセスするための URL を指定します。
docker exec gitlab-runner gitlab-runner register \
--non-interactive \
--description my-runner \
--url http://172.17.0.1:10080/ \
--registration-token aJBwbSXygCPsEsFZw2s9 \
--executor shell
トークンは事前に GitLab から取得しておきます。GitLab のグループ内のすべてのプロジェクトで利用する場合は、グループの Settings → CI/CD → Runners → Set up a specific Runner manually でトークンを取得できます。プロジェクトの Settings からプロジェクト専用の Runner を登録することもできます。
gitlab runner は Job を処理する際に executor を実行します。executor の一つに shell があります。shell を利用すると、gitlab runner が実行されているホスト上で、runner から shell コマンドとして Job が実行されます。
登録に成功すると以下のような表示になります。
Git コミットを push するなどをトリガーとして Job が実行されます。
kubernetes クラスタ内に deployment/pod として GitLab runner docker container を起動します。Job の実行方法として選択できる executor は複数ありますが、毎回クリーンな環境で実行するためには SSH executor や Shell executor は不適です。Docker executor で Pod 内に docker コンテナを起動することもできそうですが、ここでは kubernetes executor を executor として利用します。そのために、以下のように runner の deployment には他の pod を create する権限を付与しておきます。
GitLab および GitLab Runner を k8s クラスタ内で起動して、GitLab Runner に他の Pod を起動する権限を role binding しておき、Kubernetes executor で Job を処理する設定はこちらです。
k8s には Role-based access control (RBAC) という仕組みがあります。default namespace における pod と deployment リソースの操作が可能な role を作成してみます。pod 内プロセスが k8s リソースを利用する際には ServiceAccount を利用します。新規に ServiceAccount を作成して、role を binding できます。
deployment と pods の操作が可能な role を作成して deployment から利用する例は以下のようになります。こちらのページに設定のサンプルがあります。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: gitlab-runner
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: default
name: gitlab-runner
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: gitlab-runner
subjects:
- kind: ServiceAccount
name: gitlab-runner
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab-runner
簡単のため nginx image を利用してみます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
serviceAccountName: gitlab-runner
kubectl コマンドで API リソースが利用できることを確認します。
kubectl exec -it nginx-55c8bc94b4-27zm9 -- /bin/bash
apt update && apt install -y curl
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x kubectl
mv kubectl /usr/local/bin/
kubectl get pods
kubectl get deployments
例えば services は role に設定していないため利用できません。
root@nginx-55c8bc94b4-27zm9:/# kubectl get service
Error from server (Forbidden): services is forbidden: User "system:serviceaccount:default:gitlab-runner" cannot list resource "services" in API group "" in the namespace "default"
.gitlab-ci.yml
設定GitLab が組込みでサポートする環境変数、Web UI から設定した環境変数、.gitlab-ci.yml
内で設定した環境変数が利用できます。
script:
- echo $GITLAB_USER_LOGIN
- echo $AAA
出力例
$ echo $GITLAB_USER_LOGIN
root
$ echo $AAA
123
Job 実行後に、指定した paths
にマッチするファイルを runner から GitLab にアップロードして保存できます。Web UI からダウンロードしたり、別の Job から利用することができます。
myjob:
image: python:3.8-alpine
script:
- python --version
artifacts:
paths:
- README.md
expire_in: 1 week
出力例
$ python --version
Python 3.8.0
Uploading artifacts...
README.md: found 1 matching files
Uploading artifacts to coordinator... ok id=11 responseStatus=201 Created token=nAHRxd3i
Job succeeded
パイプラインは、git push をトリガーとした実行の他に、cron のようにスケジュールを設定して実行することもできます。設定したスケジュールは Web UI から手動で任意のタイミングで実行することもできます。
スケジュールによるトリガー時のみ実行したい場合は only
で schedules
を指定します。
myjob-only-schedules:
image: python:3.8-alpine
only:
- schedules
script:
- echo myjob-only-schedules
myjob:
image: python:3.8-alpine
script:
- echo myjob
git submodule を利用するレポジトリの場合は GIT_SUBMODULE_STRATEGY
環境変数を設定する必要があることに注意します。
variables:
GIT_SUBMODULE_STRATEGY: recursive