DockerCon 2017でLiuxKitというツールが発表されました。
- https://github.com/linuxkit/linuxkit
- Announcing LinuxKit: A Toolkit for building Secure, Lean and Portable Linux Subsystems - Docker Blog
LinuxKitを使用するとDockerのイメージを組み合わせてLinuxのイメージを作成することができます。イメージはISOやqcow2等の形式で出力して、各種ハイパーバイザ、クラウド、ベアメタルサーバー上で実行することが可能です。
今回はLinuxKitで作成したイメージをベアメタルサーバー上で実行する例として、Packetのベアメタルサーバー上で実行してみます。
Packet
PacketはAWSやGCPと同じようなパブリッククラウドのプロバイダーですが、特徴として他の多くのクラウドと異なり仮想ではなくベアメタルでサーバーを提供しています。操作感的には他のクラウドとほぼ同様でAPIも提供されています。
とりあえず動かしてみる
とりあえず、LinuxKitのGetting Startedのlinuxkit.yml
で作成したイメージをPacketのベアメタルサーバーで動かしてみます。
linuxkit/README.md at master · linuxkit/linuxkit · GitHub
まずmoby buld
を実行してイメージを作成します。
$ moby build linuxkit.yml
$ ls linuxkit* | grep -v yml
linuxkit-bzImage
linuxkit-cmdline
linuxkit-efi.iso
linuxkit-initrd.img
linuxkit.iso
次にlinuxkit-bzImage
、linuxkit-initrd.img
をどこかにアップロードします。例ではGoogle Cloud Storageを使用していますが、Packetでサーバー作成する際にダウンロード可能であればどこでも良いです。
$ gsutil mb gs://<YourBucketName>
$ gsutil cp -a public-read linuxkit-bzImage gs://<YourBucketName>
$ gsutil cp -a public-read linuxkit-initrd.img gs://<YourBucketName>
PacketはLinuxKitでサポートされているためlinuxkit run packet
コマンドで簡単にサーバーを作成することができます。
$ linuxkit run packet --base-url http://storage.googleapis.com/<YourBucketName> --api-key <YourPacketAPIKey> --project-id <YourPacketProjectID> linuxkit
コマンドを実行したら、WebUI等でサーバーの作成状況とIPアドレスを確認します。Active状態になったらサーバーのIPアドレスをブラウザで開いてNignxの画面が表示されることを確認します1。
今のところlinuxkit run packet
コマンドではコンソールへの接続まではやってくれないですが以下のようにSSHするとコンソールに接続することも可能です。2
How to use our S.O.S. Rescue Mode | Packet Support
動作を確認したら必要以上に課金されないよう忘れず削除しておきましょう。今のところ削除のコマンドはないのでPacketのAPIやUIから削除します。
サーバーにSSHでログインする
Dockerイメージを組み合わせてOSのカスタマイズする例としてsshdのイメージを使ってSSHでログインできるようにしてみます。
次のようにlinuxkit.yml
のservices
とfiles
にSSHサーバーと鍵の情報を追記します。
services:
- name: rngd
image: "mobylinux/rngd:3dad6dd43270fa632ac031e99d1947f20b22eec9"
capabilities:
- CAP_SYS_ADMIN
oomScoreAdj: -800
readonly: true
- name: nginx
image: "nginx:alpine"
capabilities:
- CAP_NET_BIND_SERVICE
- CAP_CHOWN
- CAP_SETUID
- CAP_SETGID
- CAP_DAC_OVERRIDE
net: host
- name: sshd
image: "linuxkit/sshd:e108d208adf692c8a0954f602743e0eec445364e"
capabilities:
- all
net: host
pid: host
binds:
- /root/.ssh:/root/.ssh
- /etc/resolv.conf:/etc/resolv.conf
files:
- path: etc/docker/daemon.json
contents: '{"debug": true}'
- path: root/.ssh/authorized_keys
contents: '#your ssh key here'
再度イメージをビルド、アップロードしてlinuxkit run packet
コマンドでサーバーを作ります。
$ moby build linuxkit.yml
$ gsutil versioning set on gs://linuxkit
$ gsutil cp -a public-read linuxkit-bzImage gs://<YourBucketName>
$ gsutil cp -a public-read linuxkit-initrd.img gs://<YourBucketName>
$ linuxkit run packet --base-url http://storage.googleapis.com/<YourBucketName> --api-key <YourPacketAPIKey> --project-id <YourPacketProjectID> linuxkit
成功していればSSHでsshd
コンテナの中に入ることができます。binds
を変更することでホストのファイルをコンテナに見せることもできます。
ssh root@<サーバーのIP>
linuxkit run packetは何をしているか?
PacketではインストールするOSをCentOSやUbuntu、ESXi等から選択できますが、独自のOSがインストールできるようiPXEのスクリプトが使用できるようになっています。
linuxkit run packet
はこの仕組みを利用し、以下のようなiPXEスクリプトを生成、サーバー作成時の引数に渡すことによってアップロードしたイメージでサーバーを起動しています。
#!ipxe
dhcp
set base-url http://http://storage.googleapis.com/<YourBucketName>
set kernel-params ip=dhcp nomodeset ro serial console=ttyS1,115200
kernel ${base-url}/linuxkit-bzImage ${kernel-params}
initrd ${base-url}/linuxkit-initrd.img
boot
linuxkit/run_packet.go at 456f2623d57e547df11184e00fd2fae89b2da994 · linuxkit/linuxkit · GitHub
iPXEスクリプトが使われるのはサーバー作成時のみで、それ以降はローカルディスクから起動されます。今回のようにディスクにインストールしていない状態でサーバーを落とすと起動できなくなり作り直しになります。
さいごに
簡単にですがLinuxKitで作成したイメージをPacketのベアメタルサーバーで動かす方法と仕組みを見てきました。基本的には同じような方法で、他の物理サーバーでもLinuxKitで作成したイメージを動かせると思います。
今回はデフォルトのType0のみで試しましたが構成の異なる他のタイプやARMのサーバーも試してみると面白そうです。
- support drivers needed on packet.net · Issue #1245 · linuxkit/linuxkit · GitHub
- DockerCon and open source planning · Issue #1429 · linuxkit/linuxkit · GitHub
-
サーバー作成時に公開鍵を登録していないと接続に失敗しまうようなので、もし登録してなければ左メニューの「SSH Keys」から登録しておく ↩