Topics

・関数型プログラミングとオブジェクト指向のパラダイムとしての対立 国内の【自称】関数型コミュニティと海外の論調の違い

ガラパゴス・ネットスラング=「関数型ポエム」という呪詛、先入観的読書と、フェアなレビューの登場

Qiitaの騒動から派生して、東北大学の住井 英二郎@esumii氏、らくだの卯之助@camloeba氏その他が、犯罪者集団に合流して2ちゃんねるでの誹謗中傷チームの「8賢者」「ウィザード組」とかアホなことをやってる件について

JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン

2016年のnode、ES6、React、Babel、Atomエディタ界隈の方向性

Dockerじゃないsystemd-nspawn+machinectlが非常に良い

99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その1】「計算機科学のほんとうの基礎」を理解していない。IQ145のJKと同じ事を語るMITの権威とSICPという聖典の権威を借りてマインドコントロールを解いてみよう

99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その2】関数型プログラミングのイミュータブルな世界観とイミュータブルな実世界を完全に統合

10年先を行く斬新な関数型(FRP)データベースについて説明する 99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その3】

[React (.js Facebook)解説 関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間 サポート記事【静的HTML編】React 解説【動的HTML-FRP編】

量子コンピュータが超高速である原理と量子論とそれに至るまでの科学哲学史をゼロからわかりやすく解説01量子コンピュータが超高速である原理と量子論とそれに至るまでの科学哲学史をゼロからわかりやすく解説02

『関数型プログラミングに目覚めた!』のレビュー(Day-1)について

LISPデータ構造の問題点の指摘と抜本的解法としての新プログラミング言語の策定/純粋関数型言語「SPINOZA」

著書『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』 [Day1]たち読み記事 無料公開中

『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』を大変多くの方々にお買い求めいただき、感謝します。本書の全目次を公開し、質問を受け付けます。

2016年2月10日水曜日

Dockerじゃないsystemd-nspawn+machinectlが非常に良い

前回

自作FRPライブラリTimeEngineをブラッシュアップして
http://timeengine.github.io/
を公開しました。
次回は、その日本語訳、
Reactの応用技術、あるいはReact再入門についての記事をUPしますのでお楽しみに!

と書いていたのですが、Dockerじゃないsystemd-nspawn+machinectlが非常に良い、ので予定を変更して、こちらを先にエントリします。いろいろ印象を忘れないうちに。TimeEngineに関してはとりあえず自分がすでに英文で書いたものを和訳してどこかにUPしておいたほうが、何か別展開や国内のためになるかな程度のことなのでお急ぎの方は上記リンクから英文読んでください。そちらも全部仕上がっているとは言えないですし、行き届いていないところをセルフチェックするために和訳もしておこうという感じです。

実用的で枯れた技術「コンテナ」

UNIX/Linuxの世界では、OSのコンテナ技術はずいぶんと昔から存在していました。

Dockerの持つ意味とこれから起こること(NTT DATA)

実用的で枯れた技術「コンテナ」
メインフレームや商用UNIXの世界では、コンテナ型仮想化技術は古くから使われていました。Solaris Containers, HP-UX Containersなど、アプリケーションの実行環境とワークロードを安全かつ低オーバーヘッドで分離することを目的としたこれらの技術は、ミッションクリティカル領域での事例も十分あり、20世紀の時代から使われている極めて実用的で枯れた技術でした。ところが、Linuxの世界でコンテナ技術は長らく脚光を浴びることがありませんでした。コンテナ技術不遇の時代、Linuxの世界で「実行環境とワークロードを安全に分離する」のは、ソフトウエアによるハードウエアのエミュレーション、すなわち、仮想マシンを動作させる仮想化技術が主たる役割を担ってきました。クラウドサービス、特にIaaSの実用化は世の中の仮想マシンの数を爆発的に増大させました。スモールスタートが可能、需要に応じて迅速にリソース量を変化させられる、低レイヤーの運用管理はクラウド事業者におまかせ、スケールメリットによる圧倒的低コスト……流行らないわけがありません。
“ご注文は仮想マシンでよろしかったでしょうか?”
そんな中、整備が遅れていたLinuxカーネルのコンテナ技術(namespaces, cgroups)が出揃い、さらに、それをフル活用したDocker参考1がリリースされてから、多くの人が気付きはじめました。当初やりたいことは、「実行環境とワークロードを安全に分離する」ことであり、「ハードウエアをエミュレーションする」ことは、その手段として最適だったのか?もっと軽量で取り扱いしやすい方法があったのではないか?と。

私はLinux使う前はOracleに買収される前のSunMicrosystemsが全力で開発していたSolarisをデスクトップ環境でも愛用していて、その頃は、他のOSの追随を許さないZONE(Solarisコンテナ)もある、ZFSもある、ものすごい先進的なOSだ!ということでLinuxなぞ使いたくなかった時期がありました。
もちろんLinuxを試したり、またSolarisに戻ったりと試行錯誤していたのですが、SunがOracleに買収されていろいろ残念なことになったり、LinuxはLinuxでしぶとく進化を続けたりして結局Solarisには戻らなくなってしまいました。開発元のSunは、Solarisコンテナ、ZFS、VirtualBoxなど、単一の会社で素晴らしい技術を世に先んじてリリースするという、技術力が傑出していた素晴らしい会社でした。

仮想化がなぜ素晴らしいのか?

色々言われていますが、大局的観点からいうと、それはハードウェア=物質的制約からの開放である、と言えます。

根本的には、「情報処理」というのは、情報を処理するのであって、ハードウェアを処理する行為ではありません。ハードウェアというのは情報処理のために必要な手段であり、土台にすぎず、情報処理の目的ではありません。必要なハードウェアは物質なので物質的な制約が存在しています。まず、物質としての固有の厳然たる単位が存在します。つまり、このサーバ一台と別のサーバを繋げて、それぞれメモリがいくらでドライブが、、、などなど諸々の制約があり、それぞれの単位にはそれぞれ物質としての経済的コストもかかります。

この情報処理として本質なマネージメントではないハードウェアのレイヤーの上位のレイヤーで抽象化して、一切合切の物質的わずらわしさから開放されたい、開放しよう、というのが「仮想化」であるということになります。

Sunの技術者が開発した先進的なファイルシステムであるZFSもHDDやらのファイルストレージというハードウェアの仮想化です。Windowsでは、今でもなおファイルシステムの構造が今でも、Cドライブが根本とかそういうことになっているわけですが、そもそもUNIXでは、ドライブという物質的概念は抽象化されて常にルートディレクトリが根本です。物理的なドライブは各ディレクトリに「仮想化」されてマウントできる、という設計思想になっています。しかしこの場合であっても、なおあらかじめボリュームから切り出すパーティションのサイズを決め打ちして各ディレクトリに配分する、というのは、どの程度配分すれば十分なのか?また無駄にならないのか?と決め打ちするだけのある種の知見や職人技が必要とされ、ある種の思い切りというか勇気が必要な作業でもあります。これをストレージプールというハードウェアの論理的集合体としてまとめて、臨機応変にファイルシステムに配分できるようにしたのがZFSです。

結局のところ、ZFSにせよVMWare,VirtualBoxにせよコンテナにせよ、ハードウェアを先に全部まとめて後から論理的にリソースを配分するという仮想化技術は、まったく同じ設計思想に基づいています。

古くて新しいコンテナ仮想化~Dockerで新たなアプリケーション配布スタイルへ~

(NTT DATA)

enter image description here

という認識が、Dokcerの普及によって広く一般的になりつつある、気もするのですが、旧来からあったUNIXのコンテナ技術であるSolarisゾーンはVMwareなどのようにハードウェアをエミュレートするものではないものの、1つのSolarisカーネル上で複数のSolarisを動作させる複数の仮想 Solaris環境です。

Dockerは1コンテナ=1アプリ=1プロセスのような設計思想ですが、旧来のSolaris的コンテナ技術からいえば、結構極端である、と言えます。

SolarisやLinuxのように同じカーネルを共用出来る場合は、ハードウェア仮想化というのは必要ではなく、コンテナ仮想化のほうが効率的なのでコンテナのほうを使いたいわけですが、SolarisゾーンみたいなのがUNIX系のコンテナだと思っていた自分にとっては、1コンテナ=1アプリ=1プロセスだ、というDockerの設計思想による制約は個人的には馴染みません。

もちろん、Dockerには1アプリがコンテナの粒度に統一してそれを配布する、というパッケージングによるマーケティング、人気の理由があるわけですが、人気があって普及しているからといって技術的に優れているわけではなく、それは単にそのような設計思想がトレンドに馴染んだということにすぎません。
Dockerはコンテナはアプリであり、データはデータ・ボリュームに分離すべきであり、そのオプションと利用法がどうとか、Dockerコンテナ内でsshdを実行してはいけない理由があって、HOWTOがあったりと、手軽さのための設計思想が、柔軟性、自由度をあまりにも制約しすぎていて使いづらい技術だな、というのが私の印象です。

MicroSoft Azure クラウドマシン上でのコンテナ

ということで、触ってはみたが、まったくハマれなかったDockerですが、最近Azureのクラウドマシンで、Arch-Linuxのサーバを建てたいと思って調べてみましたが、ローリングアップデートリリースなArchはサーバ界でいまいち人気ないようでイメージが存在しませんでした。そこで、CoreOS+DockerコンテナでArchインストールすればいいやとおもって、とりあえずやってみたのですが、やはりコレジャナイ感が半端なく、別の方策、より従来のコンテナ技術らしい派閥のUbuntu+LXD( LXC)コンテナをトライしようとしましたが、やはりArchはまったく人気がないようでイメージが存在しませんでした。もちろん多分自分でイメージを構築するとかやり方は存在するんでしょうが、わからないし、結構大変な気がして何のために作業をやっているのかわからない危険性を感じました。そうやって調べているうちに発見したのが、systemd-nspawn+machinectlという選択肢でした。

Dockerじゃないsystemd-nspawn+machinectlが非常に良い

Dockerより柔軟なコンテナ型仮想化 systemd-nspawn を使ってみた

Docker の愚痴
Dockerはコンテナ内でのsystemdに問題があり、systemctlでサービスの起動ができません。
というより本来そんな操作で動かすものじゃない・・・。
なんとか動かす手順もあるんですが、まぁ〜〜〜これが面倒くSay YO ☆
そもそもDockerは1コンテナ=1プロセスにすべきみたいな思想を掲げているんですが、この辺が私に合わない。
進歩の激しいOSS界で1コンテナ=1プロセスなんて無謀というか意味あんのっていうか。
規模の大きいサービスを1つだけ動かすみたいな場合はそれの方がいいでしょうけど、個人、もしくは少人数でそんな細切れコンテナ管理したくはないかな。
Dockerが合わない、わからないって人は大抵この話題ですよね。
どうせチューニングは必要になるんだし、それならコンテナに一時的に入ってイジったほうが手っ取り早くない?
んで色々イジってたら面倒臭くなるんだって。
まぁメールとかDBとかスタンダードなものは分けたい気持ちはわからんでもないですよ。

systemd-nspawnを活用してVPSの構成を根底から見直した

systemd-nspawnで使うmachinectlが素晴らしい事になってた

systemd-nspawn+machinectlで検索しても日本語は皆無に近い状況のなかの記事です。

非常に良いのに、あんまりにも周知されていない人気のなさを憂いた、というのがこのエントリの動機でもあります。

Dockerは過大評価、systemd-nspawnは過小評価されている。まあ確かに前者はブレイクして、後者は新規ではあるんですが、新規であっても目ざとく発見して客観的評価が得意そうな技術世界も世間の流れに追随するだけの人の子、というのは常々感じる不条理ではあります。

ちなみに、比較的認知されているCoreOSの開発者がDockerじゃないフルのコンテナ技術として開発したのが、systemd-nspawnベースのRocket ですがイマイチ人気出ません。あんまり良くないようでベースのsystemd-nspawnそのままが進化しているのでより不要感が半端ない状況のようです。

あぁ、そうそう最近rocket(rkt)の最新版を試しましたが、ぶっちゃけsystemd-nspawnが肌に合う人には向きません。
manifestファイル?これ利点ある?ないよね。
今から利点作るの?
まさかまたsupervisor使わせるの・・・?
なんてダサいんだろう。
enterさせるくせに一々これに稼働させるプロセス書かないといかんのかい?
しかもaciも偉そうに規格化だの言ってるけど、ただmanifestファイルとrootfsをtarで固めてるだけ。
当然runするのにも展開しなきゃいけないもんだから初動が糞遅い。
便利さはDocker未満で柔軟さはsystemd-nspawn未満ですかね。
全然期待していたものとは違いました。
systemd-nspawn好きでrktが安定したら移行しようとか思ってた人は早々に諦めた方が良いです。

npmライブラリの開発でもなんでもそうですが、依存する技術は、ソリッドでミニマルで基本的なものに限定したほうが、コントロール不能な外部要因としてのバグに翻弄されることもないし、rktじゃなくて、ベースのsystemd-nspawnで良いと思います。

systemd-nspawn+machinectlが非常に良いところ


  • 設計思想
    1コンテナ=1アプリ=1プロセスのような設計思想の縛りが存在せず、柔軟で自由。
    従来、本来のコンテナとしての設計。

  • スタンダード
    Linuxディストロの主流となったsystemdの一部として存在している、LinuxOSプロセス管理そのものの派生機能である。systemdベースのUbuntu,Debian,Arch,CentOSなどで使える。標準化的に問題なし。systemdの開発者であるLennart Poetteringが開発している。いわば謹製で純粋。

  • バグ、安定性、信頼性
    設計思想もそうだが、そもそもLinuxOSプロセス管理そのものの派生機能なので、バグの存在、安定性もろもろDockerその他よりもかなり信頼できる。

  • 新規性
    systemd自体がLinux世界で普及したのは比較的最近のことであり、さらに、systemd-nspawnというコンテナ技術が登場したのもかなり最近。現在活発に開発が進んでおり進化が早い。

    systemd-nspawnで使うmachinectlが素晴らしい事になってた
    なんとpull-tar,pull-raw,pull-dkrがあるじゃあないですか。
    これらは/usr/lib/machinesにダウンロードしてsystemd-nspawnで使える状態にするみたいですね。
    pull-dkrはその名の通り、docker hubなどからdockerイメージを引っ張ってこれちゃう。
    machinectl pull-dkr –verify=no base/archlinux –dkr-index-url=https://index.docker.io
    こんな感じで。
    ちょっとこれ凄くない?

という新規性もあるのですが、最初は確かにすごいな、と感じたのですが、いじっているうちに、不要かな、と思いました。個人的にこのDockerで一段と普及した、コンテナのイメージ⇔コンテナのワークフローが非常に煩雑で馴染みません。

  • ミニマルでシンプル、だからパワフル
    というのが設計でもっとも重要だと常に感じます。systemd-nspawnはそれなので、イメージなんちゃらとかあんまりいらんなあ、という感じ。

  • 統合性、透明性
    というのは、誤解されやすいワーディングではあるのですが、とにかく強くそう感じます。
    systemd-nspawnは、systemdeの一部として、同じ設計思想で同じ技術者によって開発されている技術なので、systemdと完全に統合されています。たとえば、上記引用記事の「Docker の愚痴」にもあるとおり、Dockerではコンテナ環境としてここに問題アリなのですが、systemd-nspawnではコンテナのなかでsystemdサービスはsystemctlで普通にenable,startして隔離してコントロールできます。「プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化」されます。カーネル共用しているコンテナなのでsystemdもホストと共用するしかない、というのはまったく事実でなく、非常に美しいです。

https://wiki.archlinuxjp.org/index.php/Systemd-nspawn

systemd-nspawn は chroot コマンドに似ていますが、chroot を強化したものです。
systemd-nspawn を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム構造だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため chroot よりも強力です。
systemd-nspawn は /sys, /proc/sys, /sys/fs/selinux などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードを作成することも不可能です。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールをロードすることも制限されます。
仕組みとしては Lxc-systemd や Libvirt-lxc と異なり、とてもシンプルなツールで設定を行います。

「chroot を強化したもの」という様式でファイルシステム構造を隔離するというのは、既存のホストOSの一部として安全に隔離されており、なお普通にホストでディレクトリ降りたらchrootで管理しているファイルシステムなので、透明に管理できます。つまり、Dockerコンテナ内のファイルを操作するには!?データボリュームが・・・というツール固有のオペレーションは一切不要で、透明にアクセスできます。逆に、隔離されたコンテナ内からホストのファイルを操作したい、という場合に、はじめてchrootの強化機能としてのsystemd-nspawnの役割が出てきます。

ネットワーク管理も、VMWareなどのハードウェアParavirtualizationに類似していて、ホストのイーサネット、ブリッジアダプターがゲストで仮想化されて渡されます。

systemd-nspawn -hすると該当部分はこんな感じ。

     --private-network      Disable network in container
     --network-interface=INTERFACE
                            Assign an existing network interface to the
                            container
     --network-macvlan=INTERFACE
                            Create a macvlan network interface based on an
                            existing network interface to the container
     --network-ipvlan=INTERFACE
                            Create a ipvlan network interface based on an
                            existing network interface to the container
  -n --network-veth         Add a virtual ethernet connection between host
                            and container
     --network-bridge=INTERFACE
                            Add a virtual ethernet connection between host
                            and container and add it to an existing bridge on
                            the host
  -p --port=[PROTOCOL:]HOSTPORT[:CONTAINERPORT]
                            Expose a container IP port on the host

もちろん、コンテナOS内の隔離された環境でSSHサーバ建てるなり自由にやれば良いわけで、一切の制約はありません。


以上、適当に列挙してみましたが、非常に良いです。
はじめてVMWareでOSの仮想化を体験した感慨が、Linuxのコンテナ仮想化でふたたび得られたという感じ。

仮想化がなぜ素晴らしいのか?というところでまとめましたが、Linuxのオペレーションにおいて、ハードウェアの抽象化は恩恵があるのですがVMWareなどのハードウェアParavirtualization、EC2、Azure
などのクラウドマシンによる仮想化は、まだパフォーマンスのオーバーヘッド、そしてクラウド上ではコストがかかります。しかし、systemd-nspawnコンテナを使えば、同等の体感が、コンテナというパフォーマンスのオーバーヘッドが極小の技術で可能になったのはメリットが甚大です。

systemd-nspawnでUbuntuServerホストのコンテナでArch仮想マシンを起動してみよう

結局、今回やりたかったことはこれです。
Azureのクラウドマシンで、Arch-Linuxのサーバを建てたいと思ったが、イメージも存在せずサポートもされていなかったので、UbuntuServer15.10のコンテナ内で、Archを起動したい。
UbuntuServerは、systemdベースでよくメンテナンスされており、カーネルバージョンが新しかったので選択。

systemd-nspawn は chroot コマンドに似ていますが、chroot を強化したものです。

と言う感じで、従来の既存技術の延長で、透明に管理できてしまいます。これが大きい。
つまりDockerのように固有のフォーマットのイメージをpullするには?また作成するには?とか新規に技術を習得すべき固有の仕様は全くないです。

ArchLinuxを使っているギークはArch-Linuxをインストールする場合、皆chrootでベースシステムの設定していくわけで、そのままやれば良い。

Archのダウンロードサイトには、ブートストラップファイルがあるので、ファイルをダウンロードして、適当なディレクトリで解凍して、ルートファイルシステムそのものをコンテナイメージとします。

# ken at kenubuntu07 in /zfspool/arch1 [7:59:18]
$ l
total 55K
drwxr-xr-x 16 root root   21 Feb 10 00:09 .
drwxr-xr-x  3 root root    5 Feb 10 07:42 ..
lrwxrwxrwx  1 root root    7 Sep 30 19:17 bin -> usr/bin
drwxr-xr-x  2 root root    5 Feb 10 00:09 boot
drwxr-xr-x  2 root root    2 Feb  1 15:43 dev
drwxr-xr-x 38 root root   95 Feb 10 00:35 etc
drwxr-xr-x  3 root root    3 Feb 10 00:02 home
lrwxrwxrwx  1 root root    7 Sep 30 19:17 lib -> usr/lib
lrwxrwxrwx  1 root root    7 Sep 30 19:17 lib64 -> usr/lib
drwxr-xr-x  2 root root    2 Sep 30 19:17 mnt
drwxr-xr-x  2 root root    2 Sep 30 19:17 opt
dr-xr-xr-x  2 root root    2 Feb  1 15:43 proc
-rw-r--r--  1 root root 1.3K Feb  1 15:43 README
drwxr-x---  3 root root    4 Feb 10 00:06 root
drwxr-xr-x  2 root root    2 Feb  1 15:43 run
lrwxrwxrwx  1 root root    7 Sep 30 19:17 sbin -> usr/bin
drwxr-xr-x  4 root root    4 Feb  9 23:57 srv
dr-xr-xr-x  2 root root    2 Feb  1 15:43 sys
drwxrwxrwt  2 root root    2 Feb  1 15:43 tmp
drwxr-xr-x  8 root root   10 Feb 10 00:09 usr
drwxr-xr-x 12 root root   16 Feb 10 00:09 var

ディレクトリが、/zfspool/arch1となっているのは、
AzureのUbuntuサーバにデータ用ディスクとして128GのSSDドライブを別途用意して、
UbuntuにZFS-Linuxをインストールし、/dev/sdc全体をZFSのプールにしてマウントした

$ sudo zpool create zfspool /dev/sdc

からです。

次に、Ubuntu15.10サーバにはあらかじめlxcbr0というブリッジアダプタが存在していたので、それをコンテナのネットワークブリッジアダプタとして利用するオプションを加えながら、上記ディレクトリを指定して「仮想マシン」をブートします。

$ sudo systemd-nspawn --directory=/zfspool/arch1 --network-bridge=lxcbr0 --boot
Spawning container arch1 on /zfspool/arch1.
Press ^] three times within 1s to kill container.
Failed to create directory /zfspool/arch1/sys/fs/selinux: Read-only file system
Failed to create directory /zfspool/arch1/sys/fs/selinux: Read-only file system
/etc/localtime is not a symlink, not updating container timezone.
systemd 228 running in system mode. (+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
Detected virtualization systemd-nspawn.
Detected architecture x86-64.

Welcome to Arch Linux!

Failed to install release agent, ignoring: File exists
display-manager.service: Cannot add dependency job, ignoring: Unit display-manager.service failed to load: No such file or directory.
[  OK  ] Listening on Network Service Netlink Socket.
[  OK  ] Reached target Remote File Systems.
[  OK  ] Started Dispatch Password Requests to Console Directory Watch.
[  OK  ] Listening on LVM2 metadata daemon socket.
[  OK  ] Created slice User and Session Slice.
[  OK  ] Started Forward Password Requests to Wall Directory Watch.
[  OK  ] Listening on Device-mapper event daemon FIFOs.
[  OK  ] Listening on Journal Socket (/dev/log).
[  OK  ] Listening on Journal Socket.
[  OK  ] Created slice System Slice.
[  OK  ] Created slice system-getty.slice.
         Mounting FUSE Control File System...
         Mounting Huge Pages File System...
[  OK  ] Reached target Swap.
         Starting Journal Service...
         Mounting POSIX Message Queue File System...
[  OK  ] Listening on /dev/initctl Compatibility Named Pipe.
         Starting Remount Root and Kernel File Systems...
[  OK  ] Reached target Encrypted Volumes.
[  OK  ] Reached target Paths.
[  OK  ] Reached target Slices.
[  OK  ] Mounted FUSE Control File System.
[  OK  ] Mounted Huge Pages File System.
[  OK  ] Mounted POSIX Message Queue File System.
[  OK  ] Started Remount Root and Kernel File Systems.
[  OK  ] Reached target Local File Systems (Pre).
[  OK  ] Reached target Local File Systems.
         Starting Load/Save Random Seed...
[  OK  ] Started Load/Save Random Seed.
[  OK  ] Started Journal Service.
         Starting Flush Journal to Persistent Storage...
[  OK  ] Started Flush Journal to Persistent Storage.
         Starting Create Volatile Files and Directories...
[FAILED] Failed to start Create Volatile Files and Directories.
See 'systemctl status systemd-tmpfiles-setup.service' for details.
         Starting Update UTMP about System Boot/Shutdown...
[  OK  ] Started Update UTMP about System Boot/Shutdown.
[  OK  ] Reached target System Initialization.
[  OK  ] Started Daily verification of password and group files.
[  OK  ] Started Daily rotation of log files.
[  OK  ] Listening on D-Bus System Message Bus Socket.
[  OK  ] Reached target Sockets.
[  OK  ] Started Daily Cleanup of Temporary Directories.
[  OK  ] Started Daily man-db cache update.
[  OK  ] Reached target Timers.
[  OK  ] Reached target Basic System.
         Starting Login Service...
[  OK  ] Started D-Bus System Message Bus.
         Starting Network Service...
         Starting Permit User Sessions...
[  OK  ] Started Login Service.
[  OK  ] Started Permit User Sessions.
[  OK  ] Started Console Getty.
[  OK  ] Reached target Login Prompts.
[  OK  ] Started Network Service.
[  OK  ] Reached target Network.
         Starting Network Name Resolution...
[  OK  ] Started Network Name Resolution.
[  OK  ] Reached target Multi-User System.
[  OK  ] Reached target Graphical Interface.

Arch Linux 4.2.0-27-generic (console)

arch1 login: 

美しいですね。
コンテナであっても、まるでVMWareの仮想マシンのブートを見ているようです。しかもコンテナなので、ブートは一瞬です。(今回Azureで作成したクラウドマシンのスペックで1秒以内)

Systemdと完全に統合されているので、隔離された仮想マシンで隔離されたSystemdのサービスが起動されています。

[FAILED] Failed to start Create Volatile Files and Directories.

という、Systemdの最近のバージョンのバグによるファイルシステムとの相性問題まで忠実に再現されているというオマケつき。
あとは、このArchブートストラップのファイルシステムの延長線上にPacmanでArchのフルシステムを構築していけばよいです。通常のArchインストールのように、インストールスクリプトなどを利用して、ここから外のターゲットディレクトリに向けて構築するのは不要なので、このchrootディレクトリのまま適当にベースシステムインストールして育てていきます。

通常のArchインストールのように、ネットワーク設定では普通に

# systemctl enable systemd-networkd  systemd-resolved

このように、SystemdUnitをsystemctl enableしていきます。

machinectlによるコンテナマシン管理

systemd-nspawnに付随するユーティリティmachinectlが存在しています。

$ machinectl -h
machinectl [OPTIONS...] {COMMAND} ...

Send control commands to or query the virtual machine and container
registration manager.

  -h --help                   Show this help
     --version                Show package version
     --no-pager               Do not pipe output into a pager
     --no-legend              Do not show the headers and footers
     --no-ask-password        Do not ask for system passwords
  -H --host=[USER@]HOST       Operate on remote host
  -M --machine=CONTAINER      Operate on local container
  -p --property=NAME          Show only properties by this name
  -q --quiet                  Suppress output
  -a --all                    Show all properties, including empty ones
  -l --full                   Do not ellipsize output
     --kill-who=WHO           Who to send signal to
  -s --signal=SIGNAL          Which signal to send
     --uid=USER               Specify user ID to invoke shell as
     --setenv=VAR=VALUE       Add an environment variable for shell
     --read-only              Create read-only bind mount
     --mkdir                  Create directory before bind mounting, if missing
  -n --lines=INTEGER          Number of journal entries to show
  -o --output=STRING          Change journal output mode (short,
                              short-monotonic, verbose, export, json,
                              json-pretty, json-sse, cat)
      --verify=MODE           Verification mode for downloaded images (no,
                              checksum, signature)
      --force                 Download image even if already exists
      --dkr-index-url=URL     Specify the index URL to use for DKR image
                              downloads

Machine Commands:
  list                        List running VMs and containers
  status NAME...              Show VM/container details
  show [NAME...]              Show properties of one or more VMs/containers
  start NAME...               Start container as a service
  login [NAME]                Get a login prompt in a container or on the
                              local host
  shell [[USER@]NAME [COMMAND...]]
                              Invoke a shell (or other command) in a container
                              or on the local host
  enable NAME...              Enable automatic container start at boot
  disable NAME...             Disable automatic container start at boot
  poweroff NAME...            Power off one or more containers
  reboot NAME...              Reboot one or more containers
  terminate NAME...           Terminate one or more VMs/containers
  kill NAME...                Send signal to processes of a VM/container
  copy-to NAME PATH [PATH]    Copy files from the host to a container
  copy-from NAME PATH [PATH]  Copy files from a container to the host
  bind NAME PATH [PATH]       Bind mount a path from the host into a container

Image Commands:
  list-images                 Show available container and VM images
  image-status [NAME...]      Show image details
  show-image [NAME...]        Show properties of image
  clone NAME NAME             Clone an image
  rename NAME NAME            Rename an image
  read-only NAME [BOOL]       Mark or unmark image read-only
  remove NAME...              Remove an image
  set-limit [NAME] BYTES      Set image or pool size limit (disk quota)

Image Transfer Commands:
  pull-tar URL [NAME]         Download a TAR container image
  pull-raw URL [NAME]         Download a RAW container or VM image
  pull-dkr REMOTE [NAME]      Download a DKR container image
  import-tar FILE [NAME]      Import a local TAR container image
  import-raw FILE [NAME]      Import a local RAW container or VM image
  export-tar NAME [FILE]      Export a TAR container image locally
  export-raw NAME [FILE]      Export a RAW container or VM image locally
  list-transfers              Show list of downloads in progress
  cancel-transfer             Cancel a download

このコマンドで、コンテナマシンを
poweroffしたり、 rebootしたりできます。
まさにVMWareの仮想マシンそのもの。美しいですね。.

ホストから

$ machinectl status arch1

と叩いてやると、コンテナマシンのIPやらSystemdのUnitツリーやら諸々の情報が確認できます。

arch1
           Since: Wed 2016-02-10 07:42:52 UTC; 33min ago
          Leader: 27171 (systemd)
         Service: nspawn; class container
            Root: /zfspool/arch1
           Iface: lxcbr0
         Address: 10.0.3.149
                  169.254.173.34
                  fe80::3433:76ff:fed0:b73a%3
              OS: Arch Linux
            Unit: machine-arch1.scope
                  ├─init.scope
                  │ └─27171 /usr/lib/systemd/systemd
                  └─system.slice
                    ├─dbus.service
                    │ └─27219 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
                    ├─systemd-journald.service
                    │ └─27203 /usr/lib/systemd/systemd-journald
                    ├─systemd-resolved.service
                    │ └─27224 /usr/lib/systemd/systemd-resolved
                    ├─systemd-logind.service
                    │ └─27218 /usr/lib/systemd/systemd-logind
                    ├─systemd-networkd.service
                    │ └─27220 /usr/lib/systemd/systemd-networkd
                    └─console-getty.service
                      └─27223 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt220

Feb 10 07:42:52 kenubuntu07 systemd[1]: Started Container arch1.

コンテナマシンをシャットダウン(パワーオフ)してみます。
ホストで以下のように叩きます。

$ machinectl poweroff arch1
[  OK  ] Stopped target Graphical Interface.
[  OK  ] Removed slice system-getty.slice.
[  OK  ] Stopped target Timers.
[  OK  ] Stopped Daily Cleanup of Temporary Directories.
[  OK  ] Stopped Session 28 of user ken.
         Starting Generate shutdown-ramfs...
[  OK  ] Stopped target Multi-User System.
         Stopping Network Name Resolution...
[  OK  ] Stopped target Login Prompts.
         Stopping Console Getty...
[  OK  ] Stopped Daily rotation of log files.
[  OK  ] Stopped Daily verification of password and group files.
[  OK  ] Stopped Daily man-db cache update.
         Stopping User Manager for UID 1000...
[  OK  ] Stopped Console Getty.
[  OK  ] Stopped Network Name Resolution.
[  OK  ] Stopped User Manager for UID 1000.
[  OK  ] Removed slice User Slice of ken.
         Stopping Login Service...
[  OK  ] Stopped target Network.
         Stopping Network Service...
         Stopping Permit User Sessions...
[  OK  ] Stopped Login Service.
[  OK  ] Stopped Permit User Sessions.
[  OK  ] Stopped target Remote File Systems.
[  OK  ] Stopped Network Service.
         Stopping D-Bus System Message Bus...
[  OK  ] Stopped D-Bus System Message Bus.
[  OK  ] Stopped target Basic System.
[  OK  ] Stopped target Slices.
[  OK  ] Removed slice User and Session Slice.
[  OK  ] Stopped target Paths.
[  OK  ] Stopped Dispatch Password Requests to Console Directory Watch.
[  OK  ] Stopped Forward Password Requests to Wall Directory Watch.
[  OK  ] Stopped target Sockets.
[  OK  ] Closed D-Bus System Message Bus Socket.
[  OK  ] Stopped target System Initialization.
         Stopping Load/Save Random Seed...
         Stopping Update UTMP about System Boot/Shutdown...
[  OK  ] Stopped target Encrypted Volumes.
[  OK  ] Stopped target Swap.
[  OK  ] Stopped target Local File Systems.
         Unmounting /proc/sys/kernel/random/boot_id...
         Unmounting /run/systemd/nspawn/incoming...
         Unmounting /run/user/1000...
         Unmounting Temporary Directory...
[  OK  ] Stopped Load/Save Random Seed.
[  OK  ] Stopped Update UTMP about System Boot/Shutdown.
[  OK  ] Unmounted /proc/sys/kernel/random/boot_id.
[  OK  ] Unmounted /run/systemd/nspawn/incoming.
[  OK  ] Unmounted Temporary Directory.
[  OK  ] Unmounted /run/user/1000.
[  OK  ] Reached target Unmount All Filesystems.
[  OK  ] Stopped target Local File Systems (Pre).
[  OK  ] Stopped Remount Root and Kernel File Systems.
[  OK  ] Started Generate shutdown-ramfs.
[  OK  ] Reached target Shutdown.
Sending SIGTERM to remaining processes...
Sending SIGKILL to remaining processes...
Powering off.
Container arch1 has been shut down.

美しいですね。もちろんシャットダウンも一瞬です。

セキュリティ

https://coreos.com/blog/qa-with-lennart-systemd/

September 16, 2015のインタビューで、systemd projectの開発者Lennart Poetteringによれば、すでにproduction readyだそうです。実務に耐えます。

systemd also contains the systemd-nspawn container manager. It’s a relatively minimal, yet powerful implementation of a container manager. Initially we wrote it for testing purposes, but nowadays we consider it ready for many production uses. In fact CoreOS’ rkt container tool makes use of it as the lower level container backend.

クラウドマシン、VPSやVPNの構成の再考

dockerでvpnサーバーをたてる技を駆使していたり、クラウドベースでVPNやってる場合でも、systemd-nspawnで構成を全部見直したくなる人もいるでしょう。

個人的には、Azureのクラウドマシンでコストを睨みながら無闇矢鱈にサーバインスタンス増やしていろいろやるよりも、1台のクラウドマシンを建てて、そのなかのコンテナマシンで構成したほうがよりハードウェアからの開放という至上命題としての仮想化として、リソースとコストに無駄がない優れた解法だなと感じています。

Popular Posts