Haconiwaの近況報告です。みなさんは、庭ですか?
まず、haconiwa-0.3.0 今すぐダウンロードは以下です:
次に何があったかを話します。
(サンプルコマンドの色々な操作は、rootで行う前提となっております)
haconiwa new
で設定ファイルのテンプレートを作れるようにしました
ファイル名を指定するだけでOKです。コンテナ名やrootfsのロケーションはオプションで指定可能です。ヘルプを参照。
root@localhost:~/hacos# haconiwa new ./test.haco assign new haconiwa name = haconiwa-2c876e2f assign rootfs location = /var/lib/haconiwa/2c876e2f create ./test.haco
以下のように、それぞれの設定項目の説明をコメントでやっていきつつ、サンプルを作成しています。編集してもいいですが、ひとまずそのまま動かせます。
なお、この時点ではコンテナ(rootfs)の作成をしていませんのでお気軽にnewできます。
# -*- mode: ruby -*- Haconiwa.define do |config| # The container name and container's hostname: config.name = "haconiwa-2c876e2f" # The first process when invoking haconiwa run: config.init_command = "/bin/bash" # If your first process is a daemon, please explicitly deamonize by: # config.deamonize! # The rootfs location on your host OS # Pathname class is useful: root = Pathname.new("/var/lib/haconiwa/2c876e2f") config.chroot_to root # ... end
haconiwa create
でrootfsの作成とシェルによるプロビジョンができます
生成されたファイルには以下のような項目が存在します。
# The bootstrap process... # Choose lxc or debootstrap: config.bootstrap do |b| b.strategy = "lxc" b.os_type = "alpine" # b.strategy = "debootstrap" # b.variant = "minbase" # b.debian_release = "jessie" end # Check that the required binary is installed(lxc-create / debootstrap)
これはコンテナの初期化、具体的にはコンテナの新しいrootとなるファイルシステム(rootfs)を作成するための設定を記述する箇所です。
今のところ、以下の2つの戦略をサポートしています。
lxc-create
で作るdebootstrap
で作る
具体的な設定項目は README を。
なお、rootfsの作成のために対応する外部コマンドが必要ですので、事前にパッケージマネージャ等でインストールしておいてください。
また、簡単なプロビジョニングもサポートしています。今のところシェルスクリプトのみですが...(name:
オプションで名前をつけて、後述する haconiwa provision
でピンポイントで再実行したりもできます)
# The provisioning process... # You can declare run_shell step by step: config.provision do |p| p.run_shell <<-SHELL apk add --update bash SHELL end
プロビジョニング単体で行うための haconiwa provision
も別途用意しています。
root@localhost:~/hacos# haconiwa create ./test.haco Start bootstrapping rootfs with lxc-create... [bootstrap.lxc]: Obtaining an exclusive lock... done [bootstrap.lxc]: [bootstrap.lxc]: ==> Fetching and/or verifying APK keys [bootstrap.lxc]: alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub: OK [bootstrap.lxc]: alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub: OK [bootstrap.lxc]: alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub: OK [bootstrap.lxc]: alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub: OK [bootstrap.lxc]: alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub: OK [bootstrap.lxc]: [bootstrap.lxc]: ==> Fetching apk-tools static binary [bootstrap.lxc]: tar: Ignoring unknown extended header keyword 'APK-TOOLS.checksum.SHA1' ... Command success: /bin/sh -xe exited 0 Success!
(Ubuntu Xenialでプロビジョンが失敗することがあるのを確認しています。以下のような操作で進むかもしれない)
HACO_ROOTFS=/var/lib/haconiwa/2c876e2f sudo cp /etc/{resolv.conf,hosts} $HACO_ROOTFS/etc/
既存のnamespaceに入ることができます、すなわち ip netns
等で事前作成したNetwork namespaceを使えます
さて、コンテナを作成したら今までと同様 hacoiwa run
で立ち上げることができますが...
hacoファイルにこういう記述があります。
# The namespaces to unshare: config.namespace.unshare "mount" config.namespace.unshare "ipc" config.namespace.unshare "uts" config.namespace.unshare "pid" # You can use existing namespace via symlink file. e.g.: # config.namespace.enter "net", via: "/var/run/netns/sample001"
今まで、network namespaceのunshareは非推奨だった(単にunshareしても使えなかった)のですが、ネットワークの分離のサポートの第一歩として、すでに作成済みのnetnsを利用できるようにしてみました。
以下のようにシュッシュと新しいnetnsを作ります。
ip netns add haco001 ip link add haco01 type veth peer name eth101 ip link set haco01 up ip link set eth101 netns haco001 up ip addr add 172.16.0.10/24 dev haco01 ip netns exec haco001 ip addr add 172.16.0.11/24 dev eth101 ip netns exec haco001 ip link set lo up
ホストはこんな感じに:
root@localhost:~/hacos# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:33:82:8a brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3 valid_lft forever preferred_lft forever 3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:44:64:c9 brd ff:ff:ff:ff:ff:ff inet 192.168.98.202/24 brd 192.168.98.255 scope global enp0s8 valid_lft forever preferred_lft forever # ... 7: haco01@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether ca:df:a0:95:a6:da brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.16.0.10/24 scope global haco01 valid_lft forever preferred_lft forever
新しいnetns内部ではこんな感じになります:
root@localhost:~/hacos# sudo ip netns exec haco001 ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 6: eth101@if7: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000 link/ether fa:37:14:16:6b:b4 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.16.0.11/24 scope global eth101 valid_lft forever preferred_lft forever
ここで、設定の以下の箇所をコメントインし、こんな感じに変えます。
# You can use existing namespace via symlink file. e.g.: # config.namespace.enter "net", via: "/var/run/netns/sample001" config.namespace.enter "net", via: "/var/run/netns/haco001"
haconiwa run
すると、さっき作成したnetnsに確かに入っていると確認できます。ちなみにこのままでは外に出られませんので、より実用的にはブリッジなりIPマスカレードなりをやっていく必要があります...
root@localhost:~/hacos# haconiwa run ./test.haco / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 6: eth101@if7: <NO-CARRIER,BROADCAST,MULTICAST,UP,M-DOWN> mtu 1500 qdisc noqueue state LOWERLAYERDOWN qlen 1000 link/ether fa:37:14:16:6b:b4 brd ff:ff:ff:ff:ff:ff inet 172.16.0.11/24 scope global eth101 valid_lft forever preferred_lft forever # ping も通る / # ping 172.16.0.10 PING 172.16.0.10 (172.16.0.10): 56 data bytes 64 bytes from 172.16.0.10: seq=0 ttl=64 time=0.058 ms 64 bytes from 172.16.0.10: seq=1 ttl=64 time=0.121 ms 64 bytes from 172.16.0.10: seq=2 ttl=64 time=0.073 ms ^C --- 172.16.0.10 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.058/0.084/0.121 ms
なお、デフォルトで生成される設定で、 sysfs を新しいネームスペースでリマウントする(ここもhacoファイルでいじれたりします。READMEに書いてます)ので、親のデバイスが見えるということもありません。参考
/ # ls -l /sys/class/net/ total 0 lrwxrwxrwx 1 root root 0 Aug 22 02:47 eth101 -> ../../devices/virtual/net/eth101 lrwxrwxrwx 1 root root 0 Aug 22 02:47 lo -> ../../devices/virtual/net/lo
[開発] CIの高速化
開発の話なのですが、CIを高速化しました。具体的には ./mruby
配下をキャッシュしただけなんですが...
こうだったのが
こうなったのでだいぶ能率あがる感あります :)
単にmrubyをキャッシュするだけでは困る場面もあるので、ひとまず rake consistent
というコマンドを打つと、 mruby_version.lock
というファイルに従って、もしバージョンが変わっていればmrubyのリチェックアウト(それに伴いmrbgemsのクリンナップ)を行ってくれます。
ということでmrubyのバージョンを上げるのも簡単になっています。
NEW_HASH=22dc84f72adfd742f7079b1862d3f033e4781550 echo $NEW_HASH > mruby_version.lock rake consistent
haconiwaの開発に興味のある方は是非頭の片隅に ;)
ということで、そろそろ割と普通にコンテナを作れるようになった気がするのですが、大事な機能とかUnixっぽい流儀とかで抜けがあるかもしれない。
PR/Issue 歓迎します(日本語でも歓迎しますが、私の方で参考英訳を添付するかもしれません)。
ところで、個人的な話ですが来るRubyKaigiのspeakerに選ばれております。
当日は、このHaconiwaのお話をする予定ですので、Rubyist、mrubyist、コンテナ人間の皆様は京都で握手しましょう!
Enjoy handmaid container~