GitLab Runner構築:パイプラインに命を吹き込もう

「指示書はアップしたのに、なぜ反応がないんだ?」

前回、私は意気込んで .gitlab-ci.yml ファイルを書いて push した。「これで自動的にデプロイされるはず!」と期待を込めてGitLabの「CI/CD > Pipelines」メニューをクリックした。

しかし画面に表示されたのは緑色の成功マークではなく、ひたすら回り続けるローディングバーと「Pending(保留中)」というステータスメッセージだけだった。メッセージをクリックしてみると、こんな警告が出ていた。

This job is stuck because the project doesn't have any runners online assigned to it.

意訳すると「仕事は入ってきたのに、これを処理する作業者(Runner)が出勤していません」という意味だ。しまった、私は工場長(GitLabサーバー)に作業指示書を渡しただけで、肝心の工場で働く従業員(Runner)を雇っていなかったのだ。

設計図がいくら完璧でも、それを組み立てる「作業員」がいなければ工場は動かない。

GitLab Runner:パイプラインの手足

GitLabは大きく2つの要素に分かれている。

  1. GitLab Server(本社/工場長):コードを保存し、パイプラインの状態を管理し、指示を出す。
  2. GitLab Runner(支社/現場作業員):実際のサーバーにインストールされ、本社の指示を受けてコードを取得し、ビルドし、デプロイコマンドを実行する。

「GitLabが自分で勝手にうちのサーバーに接続してデプロイしてくれればいいのに?」と考えてみると、これは非常に危険な話だ。もしインターネット上のWebサイト(GitLab)が、ボタン一つ押されただけで私の部屋にあるコンピューター(サーバー)に入って好き勝手にコマンドを実行できるとしたら?それはほぼ「ハッキング」と同じだ。誰かが私のGitLabアカウントを乗っ取ったら、私のサーバーをビットコインのマイニングマシンに変えてしまうこともできる。

だからGitLabは直接私のサーバーには接続しない。代わりに、私のサーバー内でだけ動作する「身元のしっかりした代理人(Runner)」を仕込んでおき、その代理人を通じてのみ仕事を依頼する。これから行う複雑なインストールと登録の手順は、まさにこの代理人を認証する「セキュリティ手続き」なのだ。

ステップ1:求人票を確認する(トークン発行)

Runnerをインストールする前に、まず本社(GitLab)で「うちのプロジェクトに作業員が必要です」という「求人票」を出して「登録証(トークン)」を受け取る必要がある。

最新のGitLabバージョンでは、セキュリティ強化のためにトークンの確認方法が少し隠されている。

  1. GitLabプロジェクトにアクセス
  2. 左メニュー:Settings > CI/CD
  3. RunnersセクションのExpandをクリック
  4. Project runnersセクション右上にある3点ボタン(⋮)をクリック

このボタンを押すとポップアップメニューが表示され、そこに探していた情報がある。URLとRegistration tokenを確認してコピーしておこう。

(参考:「Support for registration tokens is deprecated」という恐ろしい警告が出ることがある。これは「やがて廃止される方式」という意味だが、まだ互換性のためにサポートされているので、慌てずトークンをコピーすればOKだ。)

[Tip] プロジェクトが複数ある場合は?(Group Runner) もし私のようにフロントエンド、バックエンドなど複数のプロジェクトを1つのグループにまとめて管理しているなら、プロジェクトごとに一つひとつRunnerを登録するのは非効率だ。このときはプロジェクト設定ではなく、グループ設定(Group Settings)> CI/CDメニューからRunnerを登録すればよい。こうして作った「Group Runner」は、そのグループに属するすべてのプロジェクトの仕事を一人で全部こなすことができる。(私はプロジェクトが多いので、この方式を選んだ。)

隠しメニュー(⋮)を開かないとトークンは見られない。このトークンはRunnerとサーバーをつなぐ「秘密の鍵」なので、絶対に漏らしてはいけない。

ステップ2:作業員を雇う(Runnerインストール)

では、Linuxサーバー(または自分のPC)に実際にRunnerをインストールしてみよう。一番きれいな方法はやはり、私たちが愛する「Docker」を使うことだ。

# 1. GitLab Runner コンテナを起動
docker run -d --name gitlab-runner --restart always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v gitlab-runner-config:/etc/gitlab-runner \
  gitlab/gitlab-runner:latest

  • -v /var/run/docker.sock:/var/run/docker.sock:これが重要だ。Runnerは別のDockerコンテナ(ビルド用)を立ち上げる必要があるので、ホストのDockerソケットを共有してあげるのだ。(Docker in Docker方式)

ステップ3:労働契約書を書く(Runner登録)

Runnerをインストールしたら終わり、というわけではない。このRunnerが「私はAプロジェクトの作業員です」とGitLabサーバーに登録(Register)する手続きが必要だ。

先ほど立ち上げたRunnerコンテナの中に入って、登録コマンドを実行しよう。

# Runner コンテナ内で登録コマンドを実行
docker exec -it gitlab-runner gitlab-runner register

するとターミナルで二十の質問のような問答が始まる。先ほどステップ1で見た情報を入力していけばよい。

  1. Enter the GitLab instance URL:
    • https://gitlab.com/(またはセルフホストしているGitLabのアドレス)
  2. Enter the registration token:
    • (先ほどコピーしたトークンを貼り付ける)
  3. Enter a description for the runner:
    • my-runner-01(何でもいいので、見分けやすい名前)
  4. Enter tags for the runner:
    • (Enterを押せば省略できる。特定のタグが付いたジョブだけを任せたいときに使う。)
  5. Enter an executor:
    • docker(私たちはDockerの上でビルドするので、dockerと入力する。)
  6. Enter the default Docker image:
    • docker:latest(デフォルトで使うイメージ)

「Runner registered successfully.」このメッセージが出たら採用完了だ!GitLab画面を更新してみると、緑色のランプが点いたRunnerが「準備できました(Online)」と叫んでいるはずだ。

連携が成功すると、GitLab画面のRunnerステータスランプが緑色に変わる。

ステップ4:パイプライン稼働!

Runnerが登録された瞬間、止まっていた(Pending)パイプラインが自動的に動き始める。Running… そして少し後に Passed!

私は何もしていないのに、機械が勝手にテストを回し、ビルドし、イメージを作ってリポジトリにアップした。ターミナルを開いてログを確認してみると、私が手動でやるよりずっと速く正確に、すべての工程が完了していた。

「うわ……マジで動くじゃん!」

10分かかっていた手動デプロイが、これからは git push 一発で終わる。私はこれで、デプロイをかけてからコーヒーを飲みに行けるようになった。

実務アドバイス:Docker権限問題(Permission Denied)

初めてRunnerをセットアップするとき、99%の確率で出会うエラーがある。dial unix /var/run/docker.sock: connect: permission denied

Runnerがdockerコマンドを使おうとしているのに権限がなくて発生する問題だ。こういうときは gitlab-runner の設定ファイル(config.toml)を開いて privileged = true オプションを有効にしてあげればいい。

# /etc/gitlab-runner/config.toml(Runner 設定ファイル)
[[runners]]
  name = "my-runner-01"
  executor = "docker"

[runners.docker]

privileged = true # この部分をtrueに変えるとDocker-in-Dockerがうまく動く。# …

おわりに:これでもう退勤できる

ついに自分専用の「デプロイロボット」ができた。これで私はコードを書くことだけに集中すればいい。退屈で繰り返しの多い検証とデプロイ作業は、忠実なロボット(Runner)が代わりにやってくれるのだから。

でもまだ2%足りない。今のところパイプラインは master ブランチにプッシュされるたびに無条件で実行される。「開発用サーバー(dev)には自動でデプロイしたいけど、本番サーバー(prod)は『承認ボタン』を押したときだけデプロイしたいなら?」

次回はパイプラインをもっと賢く制御する「ブランチ別デプロイ戦略」と「手動承認(Manual)手順」について見ていこう。

コメントする