ConoHaのVPSに入れたCoreOSのcloud-config.yamlが(部分的に)無視される件

解決済。

概要

私は、GMOから提供されているConoHaというVPSサービスを利用している。 (このブログのサーバもConoHaのサーバだ。) ここではサーバを起動する際、様々なOS(プレーンなものからアプリケーション導入済のものまで)を初期イメージとして選択できる。 複数のサービスをコンテナで提供しようというとき便利なCoreOSはその選択肢にない(現在)ため自力でインストールすることになる[0]が、CoreOSのインストールや設定更新は、設定ファイルひとつとコマンドひとつで実行できるので、そこには特に大きな問題はない。

問題はないはずだったのだが、実際にはインストールすると以下のような状況になる。

ConoHaのVPSにインストールしたCoreOSで発生する予期せぬ挙動
期待された挙動 実際の挙動
hostnameが設定ファイルで設定した通りに変更される 設定ファイルを正しく設定したにも関わらず、ホスト名がIPアドレス由来のもののままになる
設定ファイルで設定した公開鍵と対になる秘密鍵でSSHログインできるようになる 設定ファイルを正しく設定したにも関わらず、SSHの公開鍵によるログインができず、パスワードログインに移行してしまう

これは私の気付いたことだけなので、他にも上書きされてしまう設定があるかもしれない。

原因と解決策

この現象の原因は、ConoHa側で用意された光学ドライブ/dev/sr1[1]にある。 これがCoreOSの設定が格納されているものとして認識されてしまい、中のファイルがロードされることで、ユーザの設定(/var/lib/coreos-install/user_data)を上書きしてしまうためである。

これを阻止するためには、光学ドライブを除去するか自動ロードを防ぐかの2通りの方法があるが、前者は無理そうなので今回は後者の方法をとった。

/usr/lib/udev/rules.d/90-configdrive.rulesの内容が、以下のようになっている。

# Automatically trigger configdrive mounting.

ACTION!="add|change", GOTO="coreos_configdrive_end"

# A normal config drive. Block device formatted with iso9660 or fat
SUBSYSTEM=="block", ENV{ID_FS_TYPE}=="iso9660|udf|vfat", ENV{ID_FS_LABEL}=="config-2", TAG+="systemd", ENV{SYSTEMD_WANTS}+="media-configdrive.mount"

# Addtionally support virtfs from QEMU
SUBSYSTEM=="virtio", DRIVER=="9pnet_virtio", ATTR{mount_tag}=="config-2", TAG+="systemd", ENV{SYSTEMD_WANTS}+="media-configvirtfs.mount"

LABEL="coreos_configdrive_end"
CoreOS 1122.2.0 における/usr/lib/udev/rules.d/90-configdrive.rulesの内容

config-2というラベルのついたFAT32のドライブか光学メディアがあった場合、マウントして設定をロードさせるというものである。 これが余計なことをしているため、udevにこのファイルを無視させればよい。 udevのルールを無効化する方法については、man udev(7)に記載がある。

Files in /etc have the highest priority, files in /run take precedence over files with the same name in /lib. This can be used to override a system-supplied rules file with a local file if needed; a symlink in /etc with the same name as a rules file in /lib, pointing to /dev/null, disables the rules file entirely.

man udev(7), "Rules files" セクションより

/etc以下にあるファイルは優先度が最も高く、システムによって提供されたルールをオーバーライドできるということなので、この仕組みを使う。 cloud-config.yamlwrite_filesで、/etc/udev/rules.d/90-configdrive.rulesを空ファイルとして作らせる設定をすれば良い。

        write_files:
  # override /usr/lib64/udev/rules.d/90-configdrive.rules (which reads configdrive and overrides user config).
  - path: /etc/udev/rules.d/90-configdrive.rules
    content: ""
      
cloud-config.yamlwrite_filesに追加するべき項目

これで設定を反映し、再起動すれば完璧だ。