Write and Run

it's a simple way, but the only way.

Amazonのコンテナホスト用OS「Bottlerocket」をなんとかして自宅サーバーで使う

id:koba789 です。

ここのところ B-Tree の話ばかり書いていたのでたまには別のネタを。

自宅サーバー管理めんどくさい問題

みなさん自宅にサーバーはありますか。
まぁ当然あると思うんですけど、管理めんどくさくないですか。私はめんどくさいなぁと思っています。

主に何がめんどくさいかといえば各種(たくさんの)パッケージの定期的なアップデートや構成管理だと思います。

Mutable な物体の管理はめんどくさい、Immutable なら毎度発破解体して作り直せばいいので気がラクでよい、というのがここ10年くらいのトレンドであり、ベアメタルにインストールする OS なんてのはコンテナが動けばそれで十分であって、コンテナの外のユーザーランドに余計なモノを置くのはジリープアー(徐々に不利)だということにみなさん薄々気づいているわけです。

私は10年くらい前からそのような事実に気づいていたので、当時から SmartOS というおもしろ OS を使っていたのですが、最近は開発元である Joyent の異常者CTO が辞めてしまって先行きが不安ということと、そもそもカーネルLinux ではないのでやはり互換性の面で不安というのがあり、使うのをやめていました。
というか Linux カーネルじゃないのに Linux の Docker イメージが動くってどういうことなんだマジで(こういうことらしいです)。

というわけで最近は RancherOS というやつを使っていたのですが、これがまたいまいち開発に元気がなくなってきてしまったので乗り換え先を探していました。
ちなみに、乗り換えるときも kube のマニフェストをスッとするだけでだいたい済むのはコンテナ OS のいいところですね。

乗り換え先 Bottlerocket

乗り換え先として Bottlerocket という OS に目をつけました。

aws.amazon.com

これは Amazon が開発しているコンテナホスト用 OS です。
いまのところは AWS 向けに開発が進んでいるため、EC2 以外の環境でそのまま動かすことはできません。
EC2 以外でも動かせるようにする計画はありそうなのですが、少なくとも現時点ではコードに手を入れるしかありません。 もっとも、ベアメタルで動かそうと思うと相応の苦しみがあります(後述)。

自宅で動くように改造する

SSH できるようにする

Bottlerocket では管理用のシェル環境すらもコンテナ内です。管理用コンテナには control と admin の2種類があります。

control は Bottlerocket の apiclient(ちょっと設定変更とかができる)を叩く用、admin はトラブル時にホストの ns に入ってトラブルシューティングをする用です。admin はデフォルトで無効化されており、control コンテナに入って有効化してはじめて起動します。

後者の admin コンテナのシェルへのアクセスは普通に SSH なのですが、前者の control コンテナのシェルへのアクセスは、セキュリティ上の理由から SSM(AWS Systems Manager Session Manager) を使うことになっています。
もちろんそんなもの(SSM)はおうちにないですし、apiclient は admin からでも叩けるので、自宅では control コンテナを使わないことにします。
常に admin コンテナを有効にしておくことになるのでセキュリティ的には弱くなりますが、自宅に SSH 以上のセキュリティを求めるのは難しいので諦めます。

で、この admin コンテナの ssh に使う公開鍵はオリジナルだと IMDS から取得することになっているのですが、これもまたおうちにはないので使わないこととし、代わりに公開鍵をコンテナイメージに焼き込みます。

これで SSH 可能になりました。

パッチはこんな感じ。

github.com github.com

ouchi(おうち)。アウチではない。

アップデートを配るリポジトリを用意する

さて、ここまでで自宅の VM で起動するようにはなっています。しかしアップデートは動きません。

Bottlerocket は TUF 準拠の仕組みでアップデートを行います。
オリジナルの Bottlerocket は S3 にある TUF Repository でアップデートを配っているのですが、私はカスタムビルドのアップデートを配らねばならないため、別途専用のリポジトリが必要です。

私は minio を使って自宅のネットワーク内に構築しました。

ベアメタルで動くようにする

ここからが本当の地獄です。

Bottlerocket のカーネルには、 EC2 の VM インスタンスまたはベアメタルインスタンスで動くのに十分なドライバしか含まれていません。

さらに悪いことに initrd や initramfs を使わないブートシーケンスを採用しているため、rootfs をマウントするまでに必要なドライバはモジュールにしてはいけません。

足らない場合、rootfs のマウント前にブートがコケて止まるわけなので調査は困難を極めます。ログをビデオカメラで撮影して追いかけるなどのテクが必要になります(シリアルコンソールを使え)。

最終的にうちのサーバーで起動させるのに必要な kernel config は以下のパッチのようになりました。

github.com

Bottlerocket は AmazonLinux 2 ベースなので、docker で amazonlinux:2 を起動してその中で make menuconfig するのが便利だと思います。

config を足してはビルドして、USB メモリに焼いてサーバーに刺して電源 ON、そしてブートが途中で止まる、というようなことを5億回くらいやりました。MegaRAID は許さん。

まとめ

とりあえず起動して SSH が通るところまではできました。
しかしまだ admin コンテナが起動するだけで、kubelet が不在の状態なので使い物になりません。

ここまで来ればあとは普通の Linux なのでなんとか常用するところまでもっていきたいですね。