2022年09月26日 - Tomo Masakura    

GitLab Runner構築のススメ

GitLab CIを利用するために必要なGitLab Runnerをどういうときにどう構築すればいいかを解説します。

皆さん、GitLab CIを使ってますか? GitLab CIはビルドを自動化できるだけでなく、静的コード解析・テスト・セキュリティ検査・リリース・デプロイ・GitLab Pagesなどなどで活用されています。

このGitLab CIのジョブはRunnerと呼ばれるコンピューター上で実行されます。

このブログでは、このGitLab Runnerを構築しようとしている人向けに、GitLab Runnerとはどういうものか?どのように構築すればいいかを解説します。

GitLab Runnerとは?

GitLab CIジョブはRunnerと呼ばれるジョブ実行用のコンピューター上で実行されます。ジョブの起動はGitLabと連携しているGitLab Runnerというアプリケーションが担当します。

なお、GitLab Runnerはアプリケーションですが、単にRunnerと呼んだときはジョブ実行用のコンピューターそのものを指すことが多いようです。このドキュメントでも単にRunnerと書いたときは、GitLab Runnerがインストールされたジョブ実行用の環境のことを指します。

GitLab RunnerはLinuxだけでなく、WindowsやmacOS用も用意されていますので、WindowsやmacOSのジョブを実行できます。

GitLab.comではあらかじめSaaS版のRunnerが用意されていて、オンプレミスのGitLabと違って、すぐにGitLab CIを使い始められます。Freeプランでは月400分のGitLab CIの無料枠がありますし、1,000分ぶんの利用枠を$10で購入できます。詳しくはGitLab Pricingをご覧ください。

なお、GitLab.comでもRunnerを別途構築することができます。次のような場合に有用です。

  • ビルドジョブの実行時間を短縮したい。
    • SaaS版Runner (Linux)はシングルコアであまりビルドが速くありません
    • SaaS版Runner (Windows / macOS)はジョブの処理が開始されるまでに数分程度かかります。
  • Runnerから社内のサーバーへアクセスする必要がある。

とりあえずRunnerを構築してみる

実用になるRunnerの構築には考慮しなければいけないことがたくさんあります。幸いにして、とりあえず構築するだけならとても簡単です。細かいことはおいておいて、まずはとりあえずでRunnerを構築し、理解を深めた上で、いろんなことを覚えておきましょう。

本来ならRunner専用コンピューターを用意しなければなりませんが、それが難しい方も多いと思います。ここでは、Runner専用のコンピューターを用意せずに、あなたが今使っているコンピューターをRunner化します。

Runnerの構築の手順は次のようになります。

  1. GitLab RunnerをRunnerコンピューターにインストールする。
  2. RunnerをGitLabに登録する。

GitLab Runnerをインストールする

まずはInstall GitLab Runnerを参考にGitLab Runnerをインストールします。

インストールの方法はOSで異なります。おすすめのインストール方法は次のとおりです。

LinuxやmacOSをお使いの方は次のコマンドでインストールできたかを確認できます。

$ gitlab-runner --version

Windowsでは、C:\gitlab-runnerディレクトリに移動してからコマンドを実行してください。

> cd C:\gitlab-runner
> gitlab-runner --version

GitLabのプロジェクトにRunnerを登録する

GitLab Runnerのインストールは終わりました。次に、RunnerをGitLabに登録します。

Runnerを登録するためのGitLab.comにアクセスして、プロジェクトを新しく作成してください。

とりあえずのためにあまり安全ではない方法を利用しますので、次の点は必ず守ってください。

  • グループではなく、あなたのユーザーのプロジェクトとして作成します。
  • 必ず新しいプロジェクトを作成してください。
  • プロジェクトメンバーに誰も追加しないでください。

Runnerをプロジェクトに登録をするための情報を取得します。プロジェクトのサイドメニューから設定->CI/CD->Runnerを開いてください。Specific runnersに表示されているURL (GitLabのURLです)とregistration tokenの二つが必要です。

プロジェクトのRunner設定

Runnerの登録の際にSpecific runnersに表示されているURL (GitLabのURL)とregistration tokenを入力しますので、この画面はそのままにしておいてください。

次のコマンドでRunnerを登録します。(Windows の方はC:\gitlab-runnerディレクトリへの移動を忘れないでください)

$ gitlab-runner register

...

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):

...

登録するGitLabのURLなど、いくつか質問されますので、次の表を参考に入力してください。

質問 入力値
Please enter the gitlab-ci coordinator URL ... : 設定画面に表示されているURL (GitLabのURL)
Please enter the gitlab-ci token for this runner: 設定画面に表示されているregistration tokenの値
Please enter the gitlab-ci description for this runner: 規定値のまま
Please enter the gitlab-ci tags for this runner (comma separated): 空のまま
Enter optional maintenance note for the runner: 空のまま
Please enter the executor: ... : shell
...

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab.com/
Please enter the gitlab-ci token for this runner:
GR1348941zT9YmVhRfy-4-U8Qg2To
Please enter the gitlab-ci description for this runner:
[runner]: 
Please enter the gitlab-ci tags for this runner (comma separated):

Enter optional maintenance note for the runner:

Registering runner... succeeded                     runner=GR1348941zT9YmVhR
Please enter the executor: docker, docker-ssh, ssh, virtualbox, docker+machine, parallels, shell, docker-ssh+machine, kubernetes:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 

登録が完了したら、GitLab Runnerを起動します。

$ gitlab-runner run

プロジェクトのCI/CD設定画面をリロードして、Runnerが追加されているかを確認します。

登録されたRunner

Runnerの登録は以上ですが、GitLab.comではSaaS版Runnerがあらかじめ登録されており、どちらが動作するかわかりません。これを無効化します。共有 RunnerEnable shared runners for this projectをオフにします。

Shared Runnerの無効化

以上でRunnerを利用する準備が整いました。.gitlab-ci.ymlファイルを作成して、ジョブを実行しましょう。

プロジェクトのサイドメニューより、CI/CD->Editorを開きます。Configure pipelineをクリックして表示される.gitlab-ci.ymlの内容をすべて消して、次のように修正し、コミットします。しばらくするとジョブが始まります。

パイプラインエディターにジョブを設定

build:
  script:
    - echo hello

プロジェクトのサイドメニューより、CI/CD->パイプラインを開き、最新のパイプラインのジョブを確認できます。

ジョブの実行結果

ジョブはホームディレクトリのbuildsディレクトリの中で実行されます。ディレクトリを覗いてみてください。(Windowsの場合はC:\gitlab-runner\buildsディレクトリ)

あなたのパソコンにインストールされているツール類がそのまま利用できますので、.gitlab-ci.ymlを修正して、いろいろ試してみると良いでしょう。

後始末

GitLab Runnerが動いているシェルでCTRL+Cキーを押してGitLab Runnerを停止させます。

そして、次のコマンドで登録したRunnerをすべて削除します。

$ gitlab-runner unregister --unregister-all

この方法は安全ではありません

この方法で登録したRunnerのジョブはあなたのパソコンであなたのアカウントで動作します。プロジェクトの.gitlab-ci.ymlファイルを誰かが修正できると、その誰かはあなたのパソコンにいたずらをするかもしれません。(いたずらで済めばいいですが…)

ですので、この方法でのRunnerの構築は、必ずプライベートプロジェクトで、かつ誰もメンバーに加えていないプロジェクトで行ってください。

この方法はあまり行儀がよくありませんが、とりあえずRunnerを動かして、どういう感じなのかを知りたいときに重宝します。

Runnerの概要

スコープ

とりあえずで構築したRunnerはGitLabプロジェクトにRunnerを登録しました。このRunnerは登録されたGitLabプロジェクト専用で、他のGitLabプロジェクトでは利用できません。GitLabではそれ以外にも、特定のグループ専用RunnerやGitLabインスタンスのどのプロジェクトでも使えるようなRunnerも構築できます。

スコープ 利用できる範囲 登録に必要な権限
インスタンス GitLabインスタンスのすべてのプロジェクト GitLabの管理者
グループ グループのすべてのプロジェクト グループのMaintainer以上
プロジェクト 特定のプロジェクト プロジェクトのMaintainer以上

インスタンススコープのRunnerはShared Runnerと呼ばれていて、GitLabの管理者がみんなのために用意するものです。利便性の高いShared Runnerを用意できれば、開発チームはすぐにGitLab CIを使うことができます。GitLab.comで用意されているSaaS版RunnerもShared Runnerです。

それに対して、グループ・プロジェクトスコープのRunnerはSpecific Runnerと呼ばれ、開発チームが自分たちで使うために用意するものです。

Specific RunnerもShared Runnerも登録方法に変わりはありません。ですが、Shared Runnerはどのプロジェクトで誰が使うのかがわからないため、そのぶんだけ考慮しなければいけないことが多く、構築・運用が難しくなります。

Runnerへの要求

Runnerの様々な要求に対応すべく、GitLab Runnerの設定は複雑になっています。まずは要求を整理します。

  • ジョブが短時間で終わること
  • 利便性 - 簡単に使えること
  • 安定性 - ジョブを実行するタイミングによって、成功・失敗が不安定にならないこと。
  • 安全性 - プロジェクトリソースが漏洩しないこと

最初の一つの解決法の基本は、なるべく高性能なコンピューターと広帯域なネットワークを用意することです。GitLab Runnerの設定項目とは異なるので、このブログでは省略します。

利便性

Runnerは様々な開発で使われます。Javaかもしれませんし、Rubyかもしれません。Javaでもバージョンが7かもしれませんし、17かもしれません。ビルドツールはGradleでしょうか?Mavenでしょうか?これらの開発ツールを利用者が簡単に選べる利便性が必要となります。

ただし、グループやプロジェクトスコープのRunnerは利便性をそれほど必要としません。(もちろん、利便性が高いに越したことはありませんが)必要な開発ツールがわかっているいるため、あらかじめにRunnerに組み込むことができるからです。

安定性

失敗したジョブを再実行したら成功した。逆に成功したジョブを再実行したら失敗した。三回に一回くらいは成功する。などが不安定な状態です。

GitLabの利用者はRunnerにログインして調査することはできません。ジョブのデバッグは苦痛でしかありません。ジョブの結果が不安定ならなおさらです。

Runnerは安定してなければなりません。

安全性

Runner経由でプロジェクトのリソース(ソースコード・トークンなど)が第三者に漏洩することはあってはいけません。

グループやプロジェクトスコープのRunnerは、漏洩したとしてもプロジェクトメンバーに対してであり、大きな問題にはなりにくいです。ソースコードはもとよりアクセスできますので、漏洩ではありません。デプロイトークンのような一部のプロジェクトメンバーしか知らないような情報は注意が必要ですが、それでもプロジェクトの外に漏洩することはありません。

それに対して、Shared Runnerから漏洩するということは、プロジェクトとは関係ない第三者に対してとなります。

executor

GitLab Runnerはとりあえずで使ったローカルシェルだけでなく、Docker Engineを利用したコンテナーやVirtualBoxなどのCPU仮想化を利用することもできます。このCIジョブの実行環境の仕組みはexecutorと呼ばれています。

executor Linux Windows macOS 分離 利便性 安全性 安定性 構築
Shell × 簡単
Docker × 簡単 (1)
VirtualBox × 大変
Parallels 大変
  • (1) Linuxでは簡単ですが、Windowsでは難しいです。

他にもKubernetes executorなどのexecutorがあります。詳しくは公式ドキュメントのExecutorsをご覧ください。

ジョブ実行環境の分離

executorには非分離タイプと分離タイプがあります。

非分離タイプの代表例はshell executorです。Runner上で実行されるすべてのジョブは、作業用ディレクトリこそ個別に用意されますが、その他の実行ユーザーやファイルシステムやネットワークなどすべてを共有します。これは次の問題を生み出します。

  • 低い安全性 - ジョブは他の開発チームのジョブから丸見えです。ソースコードはもちろんのこと、各種トークン類も漏洩するかもしれません。
  • 不安定 - CIジョブが前回のジョブの結果や、他のCIジョブの影響を受けて不安定になりやすい。

これらの問題は開発チームで構築するグループ・プロジェクト用のRunnerではそれほど問題になりませんが、どの開発チームが使うかがわからないShared Runnerでは致命的になります。

それに対して、分離タイプのexecutorは、Docker EngineやVirtualBoxなどのコンテナー・仮想化技術を利用し、ジョブごとに実行環境を分離します。非分離タイプにあるこれらの問題が起きません。(もちろん、実行環境を共有する設定にすることもできますが、その場合は安全でなくなります)

Runnerは分離タイプのexecutorで構築すべきです。しかし、分離タイプのRunnerには構築・運用が難しいものもあります。欠点を認識した上で、非分離タイプを選択することもあります。

ただし、Shared Runnerでは必ず分離タイプのexecutorで、実行環境を共有しないようにします

docker executor

docker executorは、その名前の通りDocker Engineを利用してジョブの実行環境を分離します。また、構築や運用が簡単で、利便性・安全性・安定性全てに優れています。

docker executor(とその派生executor)は.gitlab-ci.ymlファイルのimage:キーワードで、Docker Imageを指定できます。GitLab CIの利用者が簡単に開発ツールを選択することができます。

build:
  image: ruby:3.1.1 # ビルドではruby@3.1.1を使う。
  before_script:
    - bundle install
  script:
    - rake build

VirtualBox/Parallels executor

VirtualBox及びParallels executorはジョブの実行環境にVirtualBoxやParallelsの仮想マシンを利用し、ジョブの実行環境を分離します。

WindowsやmacOS(Parallelsのみ)でも使え、分離されているので、安全性・安定性は高いのですが、欠点も多いです。

  • image:キーワードが使えないため、利便性に欠けます。開発ツールをあらかじめ組み込んでおくか、before_script:キーワードでジョブごとにインストールする必要があります。
  • ジョブで利用するOSイメージの作成やアップデートなど、構築・運用がかなり面倒です。

このため、WindowsやmacOSで安全性の高いRunnerがどうしても必要な場合以外はおすすめしません。

なお、使用するソフトウェアのライセンスに注意してください。

shell executor

shell executorは最も構築が簡単です。bashやpwshなどのローカルシェルを利用する非分離タイプのexecutorです。Linux・Windows・macOSいづれもサポートされています。

しかし欠点が多く、それほど使いやすくはありません。

  • image:キーワードが使えないため、開発ツールをあらかじめ組み込んでおく必要があります。また、これらの開発ツールのアップデートも必要となります。もしくは、利用者がbefore_script:キーワードなどでジョブごとにインストールする必要があります。
  • 実行環境が共有されるため、安全性・安定性に欠けます。

あまりおすすめはできませんが、WindowsやmacOSで分離されたRunnerを構築・運用するのは大変ですので、欠点を理解した上で利用することがあります。

タグを使ってRunnerを選択する

Runnerが一つしかなければ関係ありませんが、LinuxとWindowsのRunnerの両方を用意している場合などは、ジョブは動作するRunnerを選択しなければなりません。このRunnerの選択に利用するのがタグです。(ここでいうタグとGitのタグは無関係です)

例えば、次のようなタグが設定されたRunnerがあるとします。

Runner 設定されているタグ
Xcode12がインストールされたMac mac xcode xcode12
Xcode13がインストールされたMac mac xcode xcode13
Java8がインストールされたWindows windows java java8
Java17がインストールされたWindows windows java java17
Java8がインストールされたLinux linux java java8

開発でXcode 12を利用しているなら次のように指定します。

build:
  script:
    - echo run build
  tags:
    - xcode12

WindowsでJava8でビルドしたいときは次のように指定します。

build:
  script:
    - echo run build
  tags:
    - windows
    - java8

Runnerのタグはgitlab-runner register時にPlease enter the gitlab-ci tags for this runner (comma separated):の質問にカンマ区切りで設定できます。

登録時に指定を忘れても問題ありません。GitLabのRunner設定画面で変更できます。Runnerの設定画面から該当するRunnerの編集ボタンをクリックします。

Runnerのタグの設定

タグのないRunnerから適切なものを選ぶことはできません。Runnerには必ず適切なタグを設定してください。

タグのないジョブの実行

.gitlab-ci.ymlでタグを指定していない場合、タグのないジョブの実行が許可されているRunnerのどれかが選択されます。利用者にとって混乱の元になりやすく、気軽にタグのないジョブの実行を許可するのは避けたほうが無難です。

タグのないジョブの実行の設定

GitLab.comのSaaS版Runnerでは、一番よく利用されるLinuxのRunnerだけはタグのないジョブの実行が許可されています。利用者はタグという仕組みを知らなくてもよく使うLinuxのRunnerを使うことができます。WindowsやmacOSが必要になってからタグを指定することを覚えればいいわけです。これはタグのないジョブの実行をうまく利用した例です。

保護されたRunner

分離されておらず安全でないRunnerでは、本番環境用のデプロイトークンなどのプロジェクトメンバーに漏洩してしまいます。これを防ぐためには、保護されたRunnerを利用します。保護されたRunnerは保護されたブランチやタグ専用となりますので、これらのブランチやタグにプッシュできないメンバーから秘匿情報を守ります。

詳しくは公式ドキュメントのPrevent runners from revealing sensitive informationをご覧ください。

保護されたRunnerは、マージリクエストからのデプロイトークンの漏洩を防ぎます。しかし、メインブランチにマージされた悪意のあるジョブスクリプトからは防げません。

おすすめ構成

Runner自体のおすすめ構成は、あなたが開発チームのCI担当者なのかGitLabの管理者なのかで大きく変わります。それぞれ解説します。

開発チームのCI担当者

まずは用意されているShared Runnerを使ってみてください。特に問題がなければそのまま使い続けます。

Shared Runnerが用意されていなかったり、Shared Runnerでは問題がある場合は開発チーム専用のRunnerを用意します。

  • Linuxが必要 - docker executorを選択します。
  • WindowsやmacOSが必要 - shell executorを選択します。使用する開発ツールはあらかじめインストールしておきます。

後者のRunnerはCIジョブの実行環境が分離されておらず安全性・安定性に欠けます。しかし、他の開発チームがこのRunnerを使えるわけではありませんので、それほど心配する必要はないでしょう。

Runnerのスコープはプロジェクトかグループかを選べます。プロジェクトへの登録が基本ですが、グループ内の複数のプロジェクトで利用する場合はグループに登録します。 ただし、「全社」や「開発部」のような大きな関係のないメンバーが所属するグループへのRunnerの登録は避けてください。開発チーム以外でも使えてしまい、プロジェクトリソースの漏洩に繋がります。

分離されていないRunnerを利用していて、デプロイトークンなどのプロジェクトメンバーに隠したいリソースがある場合は、これらに加えて保護されたRunnerを別途用意します。

GitLabの管理者

あなたがCIを推進したいと考えているなら、Shared Runnerを用意したほうが良いでしょう。

Shared Runnerはどの開発チームで使われるかはわかりません。安全性・安定性と利便性が求められます。その分、構築や運用のコストが高くなります。構築・運用が簡単で、安全性と利便性の両方が高いdocker executorだけを提供します。また、このRunnerはタグのないジョブの実行を許可してください。

どうしてもWindowsやLinuxのRunnerが必要な場合は、VirtualBoxもしくはParallels executorで安全に分離されたRunnerを構築します。

GitLabの利用者はShared Runnerの使い方を知るすべはありません。Shared Runnerの仕様や簡単な使い方を公開してください。幸い、Shared Runnerの説明をGitLabに設定できます。Runnerの構築・運用・解説用のGitLabプロジェクトを作成し、Shared Runnerの説明にそのプロジェクトのリンクを貼ると良いでしょう。

Shared Runnerの利用者向け説明設定

Runnerの設定ページに表示されるShared Runnerの説明

Shared Runnerのドキュメントの例

Runnerを構築する(docker executor編)

docker executor (Linux)は構築・運用が簡単で、利便性・安定性・安全性が高く、最も有用なRunnerです。ここではその構築方法を紹介します。

とりあえずのときとは異なり、Runner専用のコンピューターや仮想環境を必ず用意してください。また、RunnerはCPUやメモリやストレージのスループットなどをかなり消費しますので、なるべく独立したコンピューターを用意します。

構築の手順はとりあえずのときと大きな差はありません。Docker Engineのセットアップと、GitLabへの登録の際にdocker executorを選ぶことくらいです。

  1. Linuxのコンピューター(もしくは仮想マシン)を用意する。
  2. GitLab Runnerのインストール。
  3. Docker Engineのセットアップ。
  4. GitLabにGitLab Runnerを登録する。

GitLab Runnerのインストール

Install GitLab Runner using the official GitLab repositoriesを参考にして、パッケージをインストールします。

Docker Engineのセットアップ

Install Docker Engineに従って、Dockerをインストールしてください。

GitLab Runnerサービスはgitlab-runnerローカルユーザーで動作しています。このユーザーからDocker Engineにアクセスできるように設定します。

$ sudo usermod -aG docker gitlab-runner
$ sudo systemctl restart gitlab-runner

念の為、gitlab-runnerローカルユーザーでDockerにアクセスできるかを確かめます。

$ sudo -u gitlab-runner docker version

...

Server: Docker Engine - Community
 Engine:
  Version:          20.10.12

...

GitLabにRunnerを登録する

登録したいスコープのRunner設定画面を呼び出します。

プロジェクトスコープの登録画面

グループスコープの登録画面

インスタンススコープの登録画面

sudo gitlab-runner registerでRunnerを登録します。Please enter the executor:にはdockerと入力してください。

$ sudo gitlab-runner register

...

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab.example.jp/
Please enter the gitlab-ci token for this runner:
GR1348941XiD4svcwKRMxVkexXTrt
Please enter the gitlab-ci description for this runner:
[runner]: 
Please enter the gitlab-ci tags for this runner (comma separated):

Registering runner... succeeded                     runner=GR134894
Please enter the executor: docker, docker-ssh, ssh, virtualbox, docker+machine, Parallels, shell, docker-ssh+machine, kubernetes:
docker
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 

以上でdocker executorなRunnerの構築は完了です。

GitLab Runnerはサービスとしてバックグラウンドで動作しています。gitlab-runner runは不要です。

GitLab Runnerの設定ファイル

GitLab Runnerの設定ファイルは/etc/gitlab-runner/config.tomlにあります。

concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "runner"
  url = "https://your.gitlab.example.jp/"
  token = "<runner token>"
  executor = "shell"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]

登録されたRunnerのぶんだけ[[runners]]セクションが追加されます。

グローバルセクションのconcurrent = 1は、このRunnerで同時に実行できるジョブが1に制限されていることを示しています。CPUコア数やストレージ負荷に余裕がある場合は少し増やしてもよいでしょう。

設定ファイルの詳細は公式ドキュメントのAdvanced configurationをご覧ください。

それ以外は公式ドキュメントで

これ以外のRunnerの構築が必要な方は、公式ドキュメントのInstall GitLab Runnerをご覧ください。

最後に

以前より継続的インテグレーション(CI)はビルドや自動テストに活用されてきました。近年では、継続的デリバリや継続的デプロイだけでなく、厳しくなるセキュリティ要件に対応するために脆弱性検査などにも活用されるようになりました。

もはやGitLab CIは開発に欠かせません。GitLab.comを使っていて、まだCIを使ったことがない開発チームはぜひGitLab CIを使ってみてください。オンプレミスのGitLabを使っている方は一度GitLab.comでGitLab CIがどういうものか触ってみてください。その後Runnerを構築し、あなたのGitLabで活用してください。

Gitlab x icon svg