Back to the news overview

LXC 3.0.0 リリースのお知らせ

2018/03/27

はじめに

LXC チームは LXC 3.0.0 のリリースをお知らせできることをうれしく思います!

このリリースは LXC 2.1.0 のリリース以来 6 ヶ月に及ぶ集中した作業の成果で、LXC プロジェクトの 3 つ目の LTS リリースとなります。そして、2023 年までサポートされます。

主な変更点

すべてのコマンドでの lxc-start <コンテナ名> という文法のサポート

LXC のコマンドラインツールは -n を省略してコンテナ名を指定して実行できるようになりました。例えば、以下のように実行できます:

chb@conventiont|~
> lxc-start xenial

chb@conventiont|~
> lxc-info xenial
Name:           xenial
State:          RUNNING
PID:            12765
Memory use:     15.24 MiB
KMem use:       3.72 MiB
Link:           veth99VMO3
 TX bytes:      858 bytes
 RX bytes:      2.49 KiB
 Total bytes:   3.33 KiB

chb@conventiont|~
> lxc-attach xenial
root@xenial:/# exit

chb@conventiont|~
> lxc-stop xenial

すべてのレガシーな設定項目の削除

LXC 3.0 以降、レガシーな設定項目はすべてサポートされません。
廃止された設定と、対応する新しい設定のすべてのリストは、LXC 2.1 リリースのお知らせ を参照してください。

lxc-update-config ツールを使って、古い無効な設定を新しいフォーマットに変換できます。

リソース制限を含む単一階層の cgroup のフルサポート

LXC が、新しい単一階層構造の cgroup (cgroup v2、cgroup2) を完全にサポートしました。この機能を使い、単一階層構造の cgroup で制限を設定するために、lxc.cgroup2.[コントローラ名] という設定項目を追加しました。
さらに詳しい情報を得るには、"LXC Lands Unified cgroup Hierarchy Support" というブログポストをご覧ください。

レガシーな cgmanager、cgfs cgroup ドライバの削除

LXC から、cgmanagercgfs というレガシーな cgroup ドライバを削除し、多数のコードを削除しました。さらに詳しい情報を得るには、"On The Way To LXC 3.0: Removal of cgmanager And cgfs cgroup Drivers" というブログポストをご覧ください。

テンプレートと言語バインディングの分離

コンテナイメージのビルドシステムの新しいプロジェクトである distrobuilder が立ち上がりましたので、従来のテンプレートベースのコンテナビルドシステムは削除されました。さらに詳しい情報を得るには、"On The Way To LXC 3.0: Splitting Out Templates And Language Bindings" というブログポストをご覧ください。

移行を簡単にするために、以前のテンプレートスクリプトと設定ファイルは 別のリポジトリ に残しており、LXC 3.0.0 と同時に lxc-templates としてリリースしています。

以下のテンプレートは LXC 3.0 ツリーにも残っており、フルサポートされます:

  • lxc-busybox (通常テストに使われる)
  • lxc-download (プロジェクトでビルド済みのイメージをダウンロードする)
  • lxc-local (ローカルでビルドされたイメージをインポートする (例えば distrobuilder などで))
  • lxc-oci (OCI アプリケーションコンテナイメージを使う)

cgroup PAM モジュールの LXC ツリーへの移動

LXC は常に非特権コンテナを完全にサポートしてきています。非特権コンテナは特権を持たないユーザが実行します。この実行を行うための重要な要素が、特権を持たないユーザが書き込み権を持つ cgroup を作成する PAM モジュールでした。この PAM モジュールが LXCFS から LXC に移されました。これにより、ユーザが完全に非特権のコンテナをさらに簡単に実行できるようになりました。
さらに詳細な情報を得るには、"On The Way To LXC 3.0: Moving The Cgroup Pam Module Into The LXC Tree (Including A Detour About Fully Unprivileged Containers)" というブログポストをご覧ください。

新しい OCI テンプレートの追加

このテンプレートで、OCI フォーマットからアプリケーションコンテナを作成できるようになります。例えば:

  • ../oci にあるローカルの OCI レイアウトからコンテナを作成するには:

sudo lxc-create -t oci -n a1 -- -u oci:../oci:alpine

  • docker hub からイメージを取得してコンテナを作成するには:

sudo lxc-create -t oci -n u1 -- -u docker://ubuntu

URL は skopeo copy と同じ形式で指定します。

コンソールのロギング用のシンプルで効率的なリングバッファ

LXC はコンテナのコンソールをファイルにロギングする機能をサポートしています。これによりコンテナ内のユーザが、実際にはホスト上で必要なだけたくさんのデータを書き込み、コンテナに与えられたクォータをバイパスできる可能性があるという不幸な副作用をもたらしました。

この基本的な実装は、コンテナの再起動ではリセットされない、非常に大きくなる可能性のあるファイルを読む必要があり、照会が少し厄介なものでもありました。

LXC 3.0 ではコンソールロギングにリングバッファが導入されました。このメモリ内のバッファはサイズ制限があり、LXC API の新しい関数で照会できます。いつでもリセットでき、コンテナのシャットダウン時にダンプすることもできます。

seccomp の引数を使ったシステムコールのフィルタ

引数を使ってシステムコールをフィルタリングするために、seccomp バージョン 2 の仕様が以下のような形に拡張されました:

syscall_name action [index,value,op,valueTwo] [index,value,op]...

ここでタプル [index,value,valueTwo,op] の引数は以下のような意味です:

  1. index (uint32_t):
    システムコール引数のインデックス。
  2. value (uint64_t):
    "index" で指定されるシステムコール引数の値。
  3. valueTwo (uint64_t, optional):
    "index" で指定されるシステムコール引数の値。このオプショナルな値は SCMP_CMP_MASKED_EQ との組み合わせで使うときのみ有効です。
  4. op (char *):
    システムコール引数の演算子。有効な演算子は libseccomp >= v2.3.2 で定義された定数です。

    • SCMP_CMP_NE or (!=)
    • SCMP_CMP_LE or (<=)
    • SCMP_CMP_EQ or (==)
    • SCMP_CMP_GE or (>=)
    • SCMP_CMP_GT or (>)
    • SCMP_CMP_MASKED_EQ or (&=)


    便宜上 liblxc は、上記の libseccomp 定数の後にかっこで示された標準の演算子表記も、同等の表記法として理解します。
    同じシステムコールに対して複数のエントリを指定することは正しいことに注意してください。

拡張されたバージョン 2 プロファイルの例:

2
blacklist allow
reject_force_umount  # comment this to allow umount -f;  not recommended
[all]
kexec_load errno 1 [0,1,SCMP_CMP_LE][3,1,==][5,1,SCMP_CMP_MASKED_EQ,1]
open_by_handle_at errno 1
init_module errno 1
finit_module errno 1
delete_module errno 1
unshare errno 9 [0,0x10000000,SCMP_CMP_EQ]
unshare errno 2 [0,0x20000000,SCMP_CMP_EQ]

アプリケーションコンテナのデーモン化のサポート

最小限の動きをする init を pid 1 で実行し、指定したプログラムを pid 2 で実行するアプリケーションコンテナを、デーモンとして起動できるようになりました。

lxc-* ツールからのすべての内部シンボルの削除

lxc-* ツールは、もっぱら公開された LXC API にのみ、依存するようになりました。

hidepid={1,2} プロパティを使ってマウントされた /proc の扱い

ホストの /proc が、/proc/PID ディレクトリに対するアクセスを制限する hidepid={1,2} を指定してマウントされている場合でも、コンテナにアタッチできるようになりました。

マウント時のマウントプロパゲーションのサポート

lxc.mount.entrylxc.mount.fstab で指定されるマウントエントリに、マウントプロパゲーション (private, shared, slave, unbindable, rprivate, rshared, rslave, runbindable) が指定できるようになりました。

確実なスレッドセーフ

この項目に関する詳細は Mutexes And fork()ing In Shared Libraries というブログポストをご覧ください。

aufs ストレージドライバの削除

LXC 2.1 で廃止予定となっていた aufs ストレージドライバが、今回正式に削除されました。

コーディングスタイル、コードのクリーンアップ

コーディングスタイル に基づいて、コードベース全体に渡って広く、コードのクリーンアップを実行しました。

新たな設定項目

lxc.cgroup2.[controller name]

単一階層構造の cgroup (cgroup v2) に設定する値を指定します。controller name はコントロールグループそのままの名前です (訳注: cgroup 以下に現れるファイル名そのまま)。使える名前や指定する値の書式は LXC が指示することはありません。コンテナ実行時点のカーネルの機能に依存します。例えば lxc.cgroup2.memory.high のようになります。

lxc.hook.version

環境変数経由の新しいスタイルで引数を渡すには 1 に設定します。そうでなく、引数として渡すには 0 に設定します。この設定は、古い方法でスクリプトに引数として渡されているすべてのフック引数に影響します。特に、コンテナ名のセクション (例: 'lxc', 'net') とフックタイプ (例: 'clone', 'mount', 'pre-mount') 引数に影響します。新しいスタイルのフックが使われる場合、引数は環境変数として利用できます。コンテナ名は LXC_NAME に設定されます(これはこの設定項目に設定されている値とは関係なく設定されます)。セクションは LXC_HOOK_SECTION に設定されます。そしてフックタイプは LXC_HOOK_TYPE に設定されます。この設定は、コンテナの名前空間を参照するファイルディスクリプタのパスをどのように渡すかにも影響します。1 に設定した場合、名前空間ごとに別の環境変数 LXC_[NAMESPACE IDENTIFIER]_NS に設定されます。0 に設定すると、パスは stop フックの引数として渡されます。

lxc.execute.cmd

デフォルトで実行するバイナリのコンテナの root からの絶対パスを指定します。このオプションは execute() API 経由で呼ばれて実行されるアプリケーションコンテナのデフォルトバイナリを指定するために使います。システムコンテナの lxc.init.cmd に相当します。

lxc.init.cwd

ワーキングディレクトリとして使うコンテナ内の絶対パスです。

lxc.proc.[proc file name]

設定したい proc 以下のファイル名。指定できるファイル名は /proc/PID/ 以下に存在するものです。例えば lxc.proc.oom_score_adj = 10 のように使います。

lxc.console.buffer.size

このオプションを設定すると、LXC はインメモリのリングバッファを割り当てます。コンテナのコンソールはリングバッファに出力されます。リングバッファは少なくとも標準ページサイズの大きさでなければなりません。ページサイズより小さい値を与えた場合は、LXC はページサイズのリングバッファを割り当てます。ページサイズは通常は 4kB です。auto を指定すると、LXC は 128kB のリングバッファを割り当てます。リングバッファサイズを数値指定する場合、値がバイトに変換されるときに 2 の累乗になります。サイズ接頭辞付きの単位として kBMBGB が使えます。(この場合の変換は 1024 の倍数に基づいています。つまり kB == KiBMB == MiBGB == GiB という意味です。)

lxc.console.size

LXC は lxc.console.logfile で指定したコンソールログのサイズを、このオプションで設定した値に制限します。ログファイルのサイズは少なくとも標準ページサイズでなければなりません。ページサイズ以下の値を設定した場合は、LXC はログファイルのサイズをページサイズに設定します。ページサイズは通常は 4kB です。auto を指定すると、LXC はログファイルのサイズを 128kB に制限します。ログファイルサイズの値を数値指定する場合、値がバイトに変換されるときに 2 の累乗になります。サイズ接頭辞付きの単位として kBMBGB が使えます。(この場合の変換は 1024 の倍数に基づいています。つまり kB == KiBMB == MiBGB == GiB という意味です。) ディスク上のコンソールリングバッファとミラーになるようにしたい場合は、lxc.console.sizelxc.console.buffer.size の値を同じ値に設定します。

lxc.console.rotate

lxc.console.logfile で指定したコンソールログファイルをローテートするかどうかを指定します。

lxc.mount.entryrelative オプション

マウントポイントの指定で relative オプションを付けると、マウントされたコンテナの root からの相対パスとなります。

lxc.mount.entry = /dev/null proc/kcore none bind,relative 0 0

dev/null${LXC_ROOTFS_MOUNT}/dev/null と展開し、コンテナ内の proc/kcore にマウントします。

lxc.mount.auto で指定する cgroup マウントの force プロパティ

cgroup:mixed:force:

force を指定すると、LXC はあらゆる状況でコンテナのための cgroup マウントを実行します。それ以外は cgroup:mixed と同様です。これは主に cgroup 名前空間が有効な場合に便利です。この場合は完全に安全ですので、LXC は通常コンテナの init バイナリが cgroup をマウントしたままの状態にしておきます。

cgroup:ro:force:

force を指定すると、LXC はあらゆる状況でコンテナのための cgroup マウントを実行します。それ以外は cgroup:ro と同様です。これは主に cgroup 名前空間が有効な場合に便利です。この場合は完全に安全ですので、LXC は通常コンテナの init バイナリが cgroup をマウントしたままの状態にしておきます。

cgroup:rw:force:

force を指定すると、LXC はあらゆる状況でコンテナのための cgroup マウントを実行します。それ以外は cgroup:rw と同様です。これは主に cgroup 名前空間が有効な場合に便利です。この場合は完全に安全ですので、LXC は通常コンテナの init バイナリが cgroup をマウントしたままの状態にしておきます。

cgroup-full:mixed:force:

force を指定すると、LXC はあらゆる状況でコンテナのための cgroup マウントを実行します。それ以外は cgroup-full:mixed と同様です。これは主に cgroup 名前空間が有効な場合に便利です。この場合は完全に安全ですので、LXC は通常コンテナの init バイナリが cgroup をマウントしたままの状態にしておきます。

cgroup-full:ro:force:

force を指定すると、LXC はあらゆる状況でコンテナのための cgroup マウントを実行します。それ以外は cgroup-full:ro と同様です。これは主に cgroup 名前空間が有効な場合に便利です。この場合は完全に安全ですので、LXC は通常コンテナの init バイナリが cgroup をマウントしたままの状態にしておきます。

cgroup-full:rw:force:

force を指定すると、LXC はあらゆる状況でコンテナのための cgroup マウントを実行します。それ以外は cgroup-full:rw と同様です。これは主に cgroup 名前空間が有効な場合に便利です。この場合は完全に安全ですので、LXC は通常コンテナの init バイナリが cgroup をマウントしたままの状態にしておきます。

lxc.namespace.clone

コンテナ作成時に作成する名前空間を指定します。作成する名前空間はスペース区切りのリストで指定します。指定する名前空間名は、/proc/PID/ns ディレクトリ内に存在する標準の名前空間指示子でなければなりません。lxc.namespace.clone を明示的に設定していない場合は、カーネルがサポートするすべての名前空間と現在の設定が使われます。

新しいマウント、ネット、IPC 名前空間を作る場合は lxc.namespace.clone=mount net ipc と指定します。

lxc.namespace.keep

コンテナが、作成元のプロセスから継承する (新しい名前空間を作らずに元のプロセスの名前空間のまま実行する) 名前空間を指定します。継承する名前空間はスペース区切りのリストで指定します。指定する名前空間名は、/proc/PID/ns ディレクトリ内に存在する標準の名前空間指示子でなければなりません。lxc.namespace.keep はブラックリストを指定するオプションです。つまり、コンテナに特定の名前空間を使い続けることを強制したい場合に便利です。

ネットワーク、ユーザ、IPC 名前空間を元のプロセスの名前空間のままで実行したい場合は lxc.namespace.keep=user net ipc と指定します。

PID 名前空間を共有すると、ほとんどの init で動作しない可能性があることに注意してください。

コンテナが新しいユーザ名前空間をリクエストし、そのコンテナがネットワーク名前空間は継承したい場合は、ユーザ名前空間も同様に継承する必要があることに注意してください。

lxc.namespace.share.[namespace identifier]

他のコンテナやプロセスから継承する名前空間を指定します。[namespace identifier] には、/proc/PID/ns ディレクトリ内に現れる名前空間のひとつが入ります。

他のプロセスから名前空間を継承するには、lxc.namespace.share.[namespace identifier] の値をプロセスの PID に設定します。例えば lxc.namespace.share.net=42 のようになります。

他のコンテナから名前空間を継承するには、lxc.namespace.share.[namespace identifier] の値をコンテナ名に設定します。例えば lxc.namespace.share.pid=c3 のようになります。

標準の liblxc のパスとは異なるコンテナパスに存在する他のコンテナから名前空間を継承するには、lxc.namespace.share.[namespace identifier] をそのコンテナのフルパスで指定します。例えば lxc.namespace.share.user=/opt/c3 のようになります。

名前空間を継承するためには、呼び出し元が継承元のプロセスまたはコンテナに対して十分な権限を持っている必要があります。

システムコンテナ間での PID 名前空間の共有は、ほとんどの init システムではうまく動作しない可能性があることに注意が必要です。

ふたつのプロセスが異なるユーザ名前空間に存在し、そのうちのひとつが他のネットワーク名前空間を継承したい場合、通常はユーザ名前空間も同様に継承する必要があることに注意が必要です。

lxc.sysctl.[kernel parameters name]

設定したいカーネルパラメータを指定します。指定できるパラメータは /proc/sys 以下に存在するものです。 すべての sysctl パラメータが仮想化(名前空間化)されているわけではないことに注意してください。仮想化されていない sysctl を設定すると、システムワイドで設定が変更されてしまいます。 sysctl(8) 値を指定しないでこの設定を指定した場合は、この設定より前に設定されたパラメータをクリアします。

lxc.hook.start-host

コンテナのセットアップが済んだあと、コンテナの init を実行する直前に、ホストの名前空間で実行するためのフックです。

これはいくつかのユースケースを満たすはずです。一例が CNI のサポートです。
例えば、root 所有のコンテナ内のネットワーク設定を次のように置き換えます。

lxc.net.0.type = empty
lxc.hook.start-host = /bin/lxc-start-netns

where /bin/lxc-start-netns contains:

=================================

echo "starting" > /tmp/debug
ip link add host1 type veth peer name peer1
ip link set host1 master lxcbr0
ip link set host1 up
ip link set peer1 netns "${LXC_PID}"
=================================

NIC peer1 は期待通りコンテナ内に配置されました。
これが動作するためには、この時点では lxc-info は動作しないので、コンテナの init の pid を環境変数 LXC_PID として与える必要があります。

API 拡張

console_log()

新しい API 拡張

int console_log(struct lxc_container *c, struct lxc_console_log *log);

が追加されました。これは、新たに追加されたコンテナのインメモリリングバッファとのやりとりをサポートするために追加されました。次の構造体に利用可能な引数と返り値が含まれています。

struct lxc_console_log {
    /* Clear the console log. */
    bool clear;

    /* Retrieve the console log. */
    bool read;

    /* This specifies the maximum size to read from the ringbuffer. Setting
     * it to 0 means that the a read can be as big as the whole ringbuffer.
     * On return callers can check how many bytes were actually read.
     * If "read" and "clear" are set to false and a non-zero value is
     * specified then up to "read_max" bytes of data will be discarded from
     * the ringbuffer.
     */
    uint64_t *read_max;

    /* Data that was read from the ringbuffer. If "read_max" is 0 on return
     * "data" is invalid.
     */
    char *data;
};
reboot2()

新しい API 拡張として reboot2() が追加されました。この関数は再起動が成功するまで待ちます。この関数は引数としてタイムアウト値を取ります。タイムアウト値が > 0 の場合、reboot2() はタイムアウトに達するまで再起動を待ちます。もしタイムアウトが 0 に設定された場合、reboot2() は再起動を待ちません。もし -1 に設定された場合、reboot2() は無期限に再起動を待ちます。

CRIU の migrate() API 呼び出しに対する MIGRATE_FEATURE_CHECK

pre-copy や post-copy マイグレーションのようなマイグレーションの最適化機能においては、単純に CRIU のバージョンを見るだけでは、機能のサポートを判断できません。そのような機能はアーキテクチャ・カーネル・CRIU のコンビネーションに依存し、CRIU は機能がサポートされているかどうかを問い合わせるインターフェースを持っています。

migrate() API の呼び出し経由で、先に挙げたような機能のサポートを CRIU に問い合わせる LXC インターフェースが追加されました。LXD での最近の pre-copy マイグレーションのサポートでは、この機能が使われ、pre-copy マイグレーションを使うかどうかを自動で検出しています。

既存の migrate() API コマンドに加えて、新しいコマンド MIGRATE_FEATURE_CHECK を追加しました。

struct migrate_opts は、メンバ features_to_check によって拡張されています。これは、CRIU の機能を問い合わせるかどうかを指示するビットマスクです。

現時点では、FEATURE_MEM_TRACKFEATURE_LAZY_PAGES 機能がサポートされているかどうかを問い合わせるだけです。

attach() API 呼び出しに対する LXC_ATTACH_TERMINAL の追加

新しい端末の割り当てが API 自身に移されました。呼び出し元は LXC_ATTACH_TERMINAL を設定し、コンテナにアタッチする前に、ホストの devpts から割り当てられた新しい端末にアタッチするように要求できます。

サポートとアップグレード

LXC 3.0.0 は 2023 年 6 月までサポートされる最新の LTS リリースです。
LXC 1.0 に加えて LXC 2.0 は、致命的なバグ修正とセキュリティ修正のみなされます。

LXC チームは 3.0 ブランチへのアップグレードの計画を立てることを強くおすすめします。libpam-cgfs が LXC へ移動しますので、LXC 3.0 へのアップグレードと同時に LXCFS 3.0 へのアップグレードを行うと、機能のコンフリクトを避けることができるでしょう。

ダウンロード

コントリビューター

LXC 3.0.0 のリリースは、全部で 42 名の貢献によりリリースされました。