PreseedからChef-clientを実行させようと思った話


PXEとPreseed(Kickstart)でOSの自動インストールができるので、そのままそのサーバの設定とかも自動でできたら便利だなと思い。PreseedでOSのインストール、Chefでサーバの設定やらソフトのインストールをしようと思った。


##1.まず、何も考えずにlate_commandでchef-clientを呼んでみた。

とすると Packageリソースの評価あたりでこんなエラーがでた

```
397 STDERR: Extracting templates from packages: 50%^MExtracting templates from packages: 100%
398 /usr/share/debconf/confmodule: line 44: 3: Bad file descriptor
```

これに関しては、インストール時の環境変数が邪魔をしていて下記をunsetするとうまくいきます

```邪魔する環境変数をunset
unset UDPKG_QUIET
unset DEBIAN_FRONTEND
unset DEBCONF_REDIR
unset DEBIAN_HAS_FRONTEND
unset DEBCONF_OLD_FD_BASE
```


##2.邪魔する環境変数をunsetして、chef-clientを呼んでみた

とすると、またまた、Packageリソースの評価あたりでこんなのが出た。

```
421 initctl: Unable to connect to Upstart: Failed to connect to socket /com/ubuntu/upstart: Connection refused
422 invoke-rc.d: unknown initscript, /etc/init.d/hogehoge not found.
```

*/com/ubuntu/upstart: Connection refused* だと、そんなことあるのか？ちゃんとドメインソケットがあるのか試してみた。(late_command実行時を確認するので毎回OSインストールからやり直しつらい。。。)

```netstat_lnx
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     7628     /var/run/dbus/system_bus_socket
```

あれ？それらしきものないじゃん。
インストールしてReboot後に確認してみる

```
root@installedMachine:/home/ukinau# netstat -lnx
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     7003     @/com/ubuntu/upstart
unix  2      [ ACC ]     SEQPACKET  LISTENING     7324     /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     7628     /var/run/dbus/system_bus_socket
```

あっある、@/com/ubuntu/upstartの持ち主を調べてみる

```
root@ installedMachine:/home/ukinau# lsof | grep /com/ubuntu/upstart
init          1                root    7u     unix 0xffff880036c02700      0t0       7003 @/com/ubuntu/upstart
init          1                root   10u     unix 0xffff88003d08d500      0t0       7316 @/com/ubuntu/upstart
init          1                root   14u     unix 0xffff88003c4e2e00      0t0       7985 @/com/ubuntu/upstart
init          1                root   16u     unix 0xffff88003bc62000      0t0       8511 @/com/ubuntu/upstart
```

「init」がお世話してるドメインソケットだということが分かる

う〜ん、なんでPreseedのlate_command実行時は、作られてないんだろう。。。。
initが呼ばれていないなんてこと考えられないしなぁ。。。。

あっ！？

##ここで重要なことに気づく（なぜもっと早く気がつかなかった）

**Preseedのlate_commandは、インストール用のカーネルが動いているところで実行されるので、インストール後のカーネルとは別ものな環境で動く**

今回の例でいうと、late_command実行時に動いているinitとインストール後に動いてるinitはまったく別物！！

どういうことかは、OSインストールのプロセスを考えると分かりやすい

インストールはだいたい下記のようなイメージで進む

1. サーバは、OSインストール用のカーネル、カーネル初期イメージを読み込む
2. diskをルートディスクとして、/targetにマウントする
3. /targetにファイルシステムを構築
4. 必要なパッケージなどを/target配下にぶっ込む
5. /target/bootにカーネルとカーネル初期イメージを配置
6. diskにgrubブートローダをインストール
7. preseedのlate_commandを実行
8. リブート
9. 先ほどインストールしたgrubブートローダの呼び出し
10. 先ほどインストールしたカーネル、カーネル初期イメージを呼び出し
11. init実行


ここで注目してもらいたいのが、1~7はインストール用カーネルで動く、だからインストール後のOS(e.g Ubuntu14.04)で実行されることを想定されているスクリプトなどは動かないこともある(当然)

「2.邪魔する環境変数をunsetして、chef-clientを呼んでみた」で出たエラー

```
421 initctl: Unable to connect to Upstart: Failed to connect to socket /com/ubuntu/upstart: Connection refused
```

はupstartのdomainソケットがないことが原因だった。
これは、インストール用カーネルが最初に叩く、initがインストール後のinitとは別物で、Upstartに対応していないから起きている。

試しに、late_commandの中でps axを実行すると

```ps_ax
  1   PID TTY      STAT   TIME COMMAND
  2     1 ?        Ss     0:00 /bin/busybox init
  3     2 ?        S      0:00 [kthreadd]
  4     3 ?        S      0:00 [ksoftirqd/0]
  5     4 ?        S      0:00 [kworker/0:0]
```

なんか/bin/busybox initというのが呼ばれていることが分かる。

こいつがUpstartに対応していないせいで、chefでUpstartで動くデーモンをインストールしようとすると、エラーが起きてしまう。

しかも、apt-get install とやるとUbuntuはインストールしたdamonを即座にスタートしようとするのでUpstart/Sysvinitを呼びにいくのである。そこでエラーが出るとapt-get自体がエラーコード吐いて終了してしまう（やっかいだ）

こう考えると、Preseedのlate_commandでchefでいろいろするのは危険かも知れない。
Fileの配置、設定ファイルの編集程度なら大丈夫だとは思うが。

##結論

Preseedのlate_commandで、Chef-clientを実行する際、

**Upstartで動くserviceをインストールしようとすると失敗する(sysvinitで動くやつはイケました)**

もし、Preseedからchef-clientを実行して全部自動化したいと思った場合は、上の制約だけ覚えといてほしい。Upstartで動くserviceがレシピ内になければうまくいくはずです。

もし、Upstartで動くServiceのレシピを適用したい場合は、やっぱりCronに仕込んだりして回避するしかなさそう。

PS.
busyboxのinitをupstartに対応させてほしい。。。。（切実）