ComputeEngine で CoreOS を選ぶとスタートアップスクリプトから docker が見えない


概要

Google Compute EngineCoreOS イメージ(coreos-stable-1298-7-0-v20170401) を使ってインスタンスを作成すると,スタートアップスクリプトから docker コマンドが使えないような気がする.

Apr 21 12:20:59 xxx.internal rkt[1110]: + /usr/bin/google_metadata_script_runner --script-type startup
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO Starting startup scripts.
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO Found startup-script in metadata.
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO startup-script: /tmp/startup-qconLt/tmpI9QQlX: line 29: /usr/bin/docker: No such file or directory
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO startup-script: /tmp/startup-qconLt/tmpI9QQlX: line 33: /usr/bin/docker: No such file or directory
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO startup-script: Return code 1.
Apr 21 12:20:59 xxx.internal startup-script[1361]: INFO Finished running startup scripts.

仕方ないので, Ignition 経由で docker.service に依存するサービスとしてスタートアップスクリプトを送り込むことにした.(そもそもこっちが本来の使い方なのかもしれないが・・・)

Ignition

Ignition は cloud-init のように起動設定を簡略化してくれるツールで,cloud-init とは異なり設定を JSON フォーマットで渡す.Compute Engine の場合, この設定を user-data という名前のメタデータ経由で渡すことができる(参考: Ignition Config

設定例はこの辺 にあるのだが,今回はスタートアップスクリプト用の Systemd サービス Unit が定義できれば良いので,

user-data
{
  "ignition": { "version": "2.0.0" },
  "systemd": {
    "units": [{
      "name": "example.service",
      "enable": true,
      "contents": "[Service]\nType=oneshot\nExecStart=/usr/bin/echo Hello World\n\n[Install]\nWantedBy=multi-user.target"
    }]
  }
}

この設定を編集して利用する.

units には,登録したい Systemd サービスの Unit を配列で指定する.各 Unit の設定は,name, enable, contents の三つの属性を持つオブジェクトとなっていて,各属性はそれぞれサービス名,enable にするか,そして unit ファイルの中身を表している.

スタートアップスクリプト用サービス Unit

Docker が起動した後に実行されるようにしておく.

startup.service
[Unit]
Description=Startup Script
Requires=docker.service
After=docker.service

[Service]
ExecStartPre=-/usr/bin/docker stop myservice
ExecStartPre=-/usr/bin/docker rm myservice
ExecStart=/usr/bin/docker run --name myservice jkawamoto/myservice
ExecStop=/usr/bin/docker stop myservice
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target

(参考: dockerコンテナをsystemdで管理させる

この unit ファイルを登録するための Ignition config ファイルは次の通り.

user-data
{
  "ignition": { "version": "2.0.0" },
  "systemd": {
    "units": [{
      "name": "startup.service",
      "enable": true,
      "contents": "[Unit]\nDescription=Startup Script\nRequires=docker.service\nAfter=docker.service\n[Service]\nExecStartPre=-/usr/bin/docker stop myservice\nExecStartPre=-/usr/bin/docker rm myservice\nExecStart=/usr/bin/docker run --name myservice jkawamoto/myservice\nExecStop=/usr/bin/docker stop myservice\nRestart=always\nType=simple\n[Install]\nWantedBy=multi-user.target"
    }]
  }
}

あとは,このテキストデータを user-data という名前のメタデータとして渡せば良い.