gitlab-ci を Google Compute Engine(GCE) で月額100円以内で回す

GCEのf1-microが1台無料になった ので、 アップデートです。

オフピーク(定時時間外みたいな)といった概念があって、定時内だけ アイドルマシンの数を増やしたりと、各種お財布に優しい機能がテンコ 盛りで最強という印象です。

こういう構成になります。

  • gitlab.com

    • Runner(マネージャー常時起動のf1-micro)

      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • 実行マシン(docker-machine n1-standard-1とか、速い奴)
      • ...

お値段

さきにお金の話をしておくと、

2017年3月9日 f1-micro / us-central / 24hours*1month + 30GBのPersistent Disk が常時無料 になりました。 そして n1-standard-1 / Preemptible / us-central / SSD / 10min が 1回$0.01(1円ぐらい) です。

GCEは最低10分開始の1分単位での課金なのですが、私の用途だと1ジョブ10分かからないので、 1回1円です。100回やって100円です。月に600円以内で必要十分なCI環境が手に入りました。 安い。Azureだと最初から1分単位でしたっけ?同じこと出来るのかな?

※2017年03月時点

Runner(マネージャー)を準備

f1-microでインスタンスを上げておきます。必要なものは

  • gitlab-ci-multi-runner
  • docker-machine
  • gcloudコマンド

だけインストールが必要です。 気が向いたら手順書くけど公式の説明で十分なのでいったん割愛。 私はAnsibleを使ってUbuntu16.04で作りました。

手順

全部Runner(マネージャー)上での作業です。

  1. GCPにログイン
  2. runnerの設定ファイルを編集
  3. runner再起動

だけです。

1. Runner(f1-micro)からGCPにログイン

sudo -H gcloud auth login --no-launch-browser

2. runnerの設定ファイルを編集

#/etc/gitlab-runner/config.toml
concurrent = 50  # ジョブの最大同時実行数

[[runners]]
  name = "gitlab-ci-master"   # GitLabで見えるRunner名
  url = "https://gitlab.com"  # GitLabがセルフホスティングの場合はそのURLを
  token = ""           # GitlabのRunnerページに記載のトークン
  executor = "docker+machine" # 今回の構成はdocker-machineを使うのでこの指定
  limit = 5                   # 最大インスタンス数
  [runners.docker]
    tls_verify = false
    image = "ubuntu:16.04"
    privileged = false
    disable_cache = false
    volumes = ["/cache"]
  [runners.cache]
  [runners.machine]
    IdleCount = 4
    IdleTime = 300
    OffPeakPeriods = [
      "* * 0-9,18-23 * * mon-fri *",
      "* * * * * sat,sun *"
    ]
    OffPeakIdleCount = 1
    OffPeakIdleTime = 300     # オフピーク
    MaxBuilds = 100           # 何ビルド動かしたらインスタンスを停止させるか
    MachineDriver = "google"
    MachineName = "gitlab-ci-%s"
    MachineOptions = [
        "google-machine-type=n1-standard-1",
        "google-project=my-project-123456",
        "google-zone=us-central1-a",
        "google-machine-image=coreos-cloud/global/images/coreos-stable-1298-6-0-v20170315",
        "google-preemptible",
        "google-disk-type=pd-ssd",
        "google-scopes=https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/devstorage.read_write"
    ]

この[runners.machine] で出来ることが秀逸ですね、

IdleCountは常時起動させておくインスタンスの数です。 IdleTimeは何もジョブを実行していない場合にインスタンスを削除する までの時間です。

OffPeakPeriods で業務時間外を指定出来ます。 (Runnerのタイムゾーンは設定必須ですね。) OffPeakIdleCount は業務時間外の待機マシンの数を指定できます。 OffPeakIdleTime は業務時間外のアイドルタイムですね。 今回はGCEを使用するので、MachineDriver"google"を指定しました。 MachineNameはGCEのインスタンス名のrunner-abcd1234-HOGEHOGE-1234...の HOGEHOGE以降が指定できます。 MachineOptionsdocker-machine のオプションです。 google-preemptible を入れておくのと、google-machine-imageに CoreOSを指定するのがポイントです。docker-machine createは対象に dockerが入っていなければインストールするので、最初からdockerが入っている CoreOSなら起動もその分早くなります。(Ubuntuだとジョブの実行時間が 3分ぐらいかかったのに対してCoreOSは1分半ぐらいで終わりました)

(私は安くしたいのでIdleCountは0にしています。)

動きの流れですが、(公式にも似たような事書いていますが) まずgitlab-runnerサービスが起動すると、docker-machine createにより インスタンスがIdleCountの数だけ起動します。その後ジョブが実行 されなければ、IdleTimeの秒数たったら消えて、また作成されて、、、 が繰り返されます。(preemptibleでも安心!)ジョブの実行完了後 IdleTimeが経過しても削除されます。 また、同時実行されるジョブの数がIdleCountを超えると新しく docker-machine createによってインスタンスが立ち上げられてその上で ジョブが実行されます。

3. runner再起動

sudo systemctl restart gitlab-runner

これでGitlab側のrunnerの設定画面に現れていたら準備OKです。

あとがき

gitlab.comの共有Runnerは海外勢が活発な時間帯になるとpendingが長くなってきて イラっとすることがあるのですが、この構成だとスっと通ってとても快適です。