ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

Grenadine: 「普通のアプリケーション」がチェックポイント/リストアの恩恵を享受する

ここ数日、 Grenadine (グレナデン)と名付けたOSSをやっていっていました。

github.com

Grenadine は、CRIUを用いて、いわゆるコンテナ化をしていないような、VMにデプロイしているようなサーバ型アプリケーション(Webなら、Rails, Django, node.js ...)でもチェックポイント/リストアの恩恵を受けられるようにするためのツールです。

criu.org

今日はこのできたばかりのGrenadineを軽く紹介します。チェックポイント/リストア、と言われてもピンと来ないとは思うので、簡単なデモの手順を示しつつ。

続きを読む

ID Mapping/User Namespace再入門 その(2)

シリーズ2回めです。今回もベースは自分のためのまとめであり、調査不足な点はぜひ突っ込んでください...。

前回:

udzura.hatenablog.jp

今回から、User Namespace の各コンテナでの対応状況を見ていく。

コンテナの非特権に対する対応

前提として、前回のUser Namespaceが解決する課題を再掲する。

主に以下の二つの課題が解決できる。

  • もし特権を付与したコンテナをunjailされた場合等に、ホストのファイルシステムを操作されるなどの被害を最低限にしたい
  • 一般ユーザで、なるべく安全にコンテナを作成したい

前者と後者は、関連してはいるが実現方法が少し異なることは留意すべき。rootless Dockerや一般ユーザでのlxc-startは後者に、LXDによるUser Namespaceの分離は前者に属すると考えられそう。その辺りを踏まえて、各種コンテナランタイムでの対応状況をまとめておく。

Docker (rootless mode)

続きを読む

Rubyでも SO_REUSEPORT 使いたい!

一般に同じアドレスを同じポートではlistenできない。しかし、ソケットのオプションに SO_REUSEPORT というものがあり、Linuxではカーネル3.9以降で利用できる。

ソケットを作成した後に setsockopt(2)SO_REUSEPORT が有効になるように指定すると、同じアドレス・同じポートでのbind/listenが可能になり、リクエストが来た際にはリスンしているソケットそれぞれに回されていく。

ただ、この機能はRubyTCPServerクラス ではすぐには利用できない。 TCPServer#new/open の終了時点でアドレスがリスンされ、setsockoptするタイミングがないため。ではどうするかというと、 Socket クラスでの各メソッド Socket#setsockopt/bind/listen を直接使えば良い。

続きを読む

ID Mapping/User Namespace再入門 その(1)

前のシリーズが終わる前に新シリーズを書いていく。

皆さんのIDはマッピングされていますか?

User Namespace とは?

まず、TenForwardさんによる日本語でのとてもわかりやすい解説がすでに存在するので、そちらを参照してから...。

gihyo.jp

User Namespace自体は、Linux名前空間機能の一つであり、ホストのユーザID(グループIDも含むが、簡便のためこの記事では「ユーザID」とだけ表現する)の振り出し方とコンテナ(名前空間)内部のIDの振り出し方を分離する機能である。

実は、User Namespaceを(unshare(2)などで)分離しただけでは、ホストのユーザIDが見えなくなるだけで、コンテナ内部では全てのIDがnobodyになってしまい、現実のプログラムを動かせない。Network Namespaceにおいて、分離後vethなどを引き出さないと結局現実の環境で使えないのと同じイメージである。

ということでこの際にホストのユーザIDとコンテナ内部IDとの対応関係を指定する必要がある。例えば、ホストの ID=100000 ~ ID=165534 を、コンテナの ID=0 ~ ID=65534 に対応させる、ということができる。この機能がID Mappingである。

そして、これもまた重要なのであるが、この場合にコンテナ内部で ID=0 に割り振られたユーザには、そのプロセスでの特権が与えられる。とはいえ、(時刻など)ホスト全体であったり、ホストの名前空間の操作に関わることはできない。一方で、そのプロセスのために別の名前空間を分離している場合は、その名前空間での操作が可能になる。たとえば、Network Namespaceを一緒に分離していればネットワークデバイスの設定ができるし、UTS Namespaceを一緒に分離していればホスト名の変更ができる。

また、User Namespaceはホストの一般ユーザが作成できる。非特権コンテナにおいては、User Namespaceのこういった特徴を利用して一般ユーザがなるべく安全にコンテナを作成できるようにしている。

User Namespace が解決してくれる問題

主に以下の二つの課題が解決できる。

  • もし特権を付与したコンテナをunjailされた場合等に、ホストのファイルシステムを操作されるなどの被害を最低限にしたい
  • 一般ユーザで、なるべく安全にコンテナを作成したい

User Namespace をユーザランドの実装的にはどう実現しているのか

続きを読む