イメージの扱い#

LXD はイメージをベースとしたワークフローを使用します。 LXD にはビルトイン のイメージ・ストアがあり、ユーザーが外部のツールがそこからイメージをインポート できます。

その後、それらのイメージからコンテナが起動されます。

ローカルのイメージを使ってリモートのインスタンスを起動できますし、リモートの イメージを使ってローカルのインスタンスを起動することもできます。こういった ケースではイメージはターゲットの LXD にキャッシュされます。

ソース#

LXD は 3 つの異なるソースからのイメージのインポートをサポートします。

  • リモートのイメージサーバ (LXD か simplestreams)

  • イメージファイルの direct push

  • リモートのウェブサーバ上のファイル

リモートのイメージサーバ (LXD か simplestreams)#

これは最も一般的なイメージソースで 3 つの選択肢のうちインスタンスの作成時に直接サポートされている唯一の選択肢です。

この選択肢では、イメージサーバは検証されるために必要な証明書(HTTPS のみがサポートされます)と共にターゲットの LXD サーバに提供されます。

次にイメージそのものがフィンガープリント (SHA256) あるいはエイリアスによって選択されます。

CLI の視点では、これは以下の一般的なアクションによって実行されます。

  • lxc launch ubuntu:22.04 u1

  • lxc launch images:centos/8 c1

  • lxc launch my-server:SHA256 a1

  • lxc image copy images:gentoo local: --copy-aliases --auto-update

上記の ubuntuimages のケースではリモートは simplestreams を読み取り専用のサーバプロトコルとして使用し、イメージの複数のエイリアスの 1 つによりイメージを選択します。

my-server リモートのケースでは別の LXD サーバがあり、上記の例ではフィンガープリントによってイメージを選択します。

イメージファイルの direct push#

これは主に外部サーバから直接イメージを取得できない隔離された環境で有用です。

そのような状況ではイメージファイルは他のシステムで以下のコマンドを使ってダウンロードできます。

  • lxc image export ubuntu:22.04

その後ターゲットのシステムにイメージを転送してローカルイメージストアーに手動でインポートします。

  • lxc image import META ROOTFS --alias ubuntu-22.04

lxc image import は統合イメージ (単一ファイル) と分割イメージ (2つのファイル) の両方をサポートします。 上の例では後者を使用しています。

リモートのウェブサーバ上のファイル#

単一のイメージをユーザーに配布するためだけにフルのイメージサーバを動かすことの代替として、 LXD は URL を指定してイメージをインポートするのもサポートしています。

ただし、この方法にはいくつか制限があります。

  • 統合ファイル(単一ファイル)のみがサポートされます

  • リモートサーバが追加の http ヘッダーを返す必要があります

LXD はサーバに問い合わせをする際に以下のヘッダーを設定します。

  • LXD-Server-Architectures にはクライアントがサポートするアーキテクチャーのカンマ区切りリストを設定します

  • LXD-Server-Version には使用している LXD のバージョンを設定します

リモートサーバが LXD-Image-HashLXD-Image-URL を設定することを期待します。 前者はダウンロードされるイメージの SHA256 ハッシュで後者はイメージをダウンロードする URL です。

これによりかなり複雑なイメージサーバがカスタムヘッダーをサポートする基本的なウェブサーバだけで実装できます。

クライアント側では以下のように使用できます。

lxc image import URL --alias some-name

インスタンスやスナップショットを新しいイメージとして公開する#

インスタンスやスナップショットの 1 つを新しいイメージに変換できます。 これは lxc publish で CLI 上で実行できます。

これを行う際には、たいていの場合公開する前にインスタンスのメタデータやテンプレートを lxc config metadatalxc config template コマンドを使って整理するのが良いでしょう。 さらにホストの SSH キーや dbus/systemd の machine-id などインスタンスに固有な状態も削除するのが良いでしょう。

インスタンスから tarball を生成した後圧縮する必要があるので、公開のプロセスはかなり時間がかかるかもしれません。 この操作は特に I/O と CPU の負荷が高いので、公開操作は LXD により 1 つずつ順に実行されます。

キャッシュ#

リモートのイメージからインスタンスを起動する時、リモートのイメージが ローカルのイメージ・ストアにキャッシュ・ビットをセットした状態で ダウンロードされます。イメージは、 images.remote_cache_expiry に 設定された日数だけ使われない (新たなインスタンスが起動されない) か、 イメージが期限を迎えるか、どちらか早いほうが来るまで、プライベートな イメージとしてローカルに保存されます。

LXD はイメージから新しいインスタンスが起動される度にイメージの last_used_at プロパティを更新することで、イメージの利用状況を記録しています。

自動更新#

LXD はイメージを最新に維持できます。デフォルトではエイリアスで指定し リモートサーバから取得したイメージは LXD によって自動更新されます。 これは images.auto_update_cached という設定で変更できます。

(images.auto_update_interval が設定されない限り) 起動時とその後 6 時間毎に、 LXD デーモンはイメージ・ストア内で自動更新対象となっていて ダウンロード元のサーバが記録されている全てのイメージのより新しい バージョンがあるかを確認します。

新しいイメージが見つかったら、イメージ・ストアにダウンロードされ、 古いイメージを指していたエイリアスは新しいイメージを指すように変更され、 古いイメージはストアから削除されます。

リモート・サーバからイメージを手動でコピーする際に、特定のイメージを 最新に維持するように設定することもできます。

ユーザーがイメージのキャッシュから新しいインスタンスを作成しようとした時に、 アップストリームの新しいイメージ更新が公開されており、ローカルの LXD が キャッシュに古いイメージを持っている場合は、 LXD はインスタンスの作成を 遅らせるのではなく、古いバージョンのイメージを使います。

この振る舞いは現在のイメージが自動更新されるように設定されている時のみに 発生し、 images.auto_update_interval を 0 にすることで無効にできます。

プロファイル#

lxc image edit コマンドを使ってイメージにプロファイルのリストを関連付けできます。 イメージにプロファイルを関連付けた後に起動したインスタンスはプロファイルを順番に適用します。 プロファイルのリストとして nil を指定すると default プロファイルのみがイメージに関連付けされます。 空のリストを指定すると、 default プロファイルも含めて一切のプロファイルをイメージに適用しません。 イメージに関連付けされたプロファイルは lxc launch--profile--no-profiles オプションを使ってインスタンス起動時にオーバーライドできます。

特別なイメージプロパティ#

プレフィックスrequirementsで始まるイメージプロパティ(例:requirements.XYZ)は、 LXDがホストシステムと当該イメージで生成されるインスタンスの互換性を判断するために使用されます。 これらの互換性がない場合にはLXDはそのインスタンスを起動しません。

現在のところ、以下の要件がサポートされています。

キー

タイプ

デフォルト

説明

requirements.secureboot

string

-

"false" に設定すると、イメージがセキュアブートで起動しないことを示します。

requirements.cgroup

string

-

"v1" "に設定されている場合、ホストでCGroupV1が実行されている必要があることを示します。

イメージの形式#

LXD は現状 2 つの LXD に特有なイメージの形式をサポートします。

1 つめは統合された tarball で、単一の tarball がインスタンスの root と 必要なメタデータの両方を含みます。

2 つめは分離されたモデルで、 2 つのファイルを使い、 1 つは root を 含み、もう一つはメタデータを含みます。

LXD 自身によって生成されるのは前者の形式で、 LXD 特有のイメージを使う 際はこちらの形式を使うべきです。

後者は、今日既に利用可能なものとして存在している LXD 以外の rootfs tarball を使ってイメージを簡単に作成できるように想定されているものです。

統合された tarball#

tarball は圧縮できます。そして次のものを含みます。

  • rootfs/

  • metadata.yaml

  • templates/ (省略可能)

このモードではイメージの識別子は tarball の SHA-256 です。

分離された tarball#

2 つの (圧縮しても良い) tarball 。 1 つはメタデータ、もう 1 つは rootfs です。

metadata.tar は以下のものを含みます。

  • metadata.yaml

  • templates/ (省略可能)

rootfs.tar は、そのルートに Linux の root ファイルシステムを含みます。

このモードではイメージの識別子はメタデータと rootfs の tarball を(この順番で) 結合したものの SHA-256 です。

サポートされている圧縮形式#

LXD は広範な tarball の圧縮アルゴリズムをサポートしますが、互換性のために gzip か xz が望ましいです。

分離されたイメージではコンテナの場合は rootfs ファイルはさらに squashfs 形式でフォーマットすることもできます。 仮想マシンでは rootfs.img ファイルは常に qcow2 であり、オプションで qcow2 のネイティブ圧縮を使って圧縮することもできます。

中身#

コンテナでは rootfs のディレクトリ (あるいは tarball) は完全なファイルシステムのツリーを含み、それが / になります。 VM ではこれは代わりに rootfs.img ファイルでメインのディスクデバイスになります。

テンプレートのディレクトリはコンテナ内で使用される pongo2 形式のテンプレート・ファイルを含みます。

metadata.yaml はイメージを (現状は) LXD で稼働されるために必要な情報を 含んでおり、これは以下のものを含みます。

architecture: x86_64
creation_date: 1424284563
properties:
  description: Ubuntu 22.04 LTS Intel 64bit
  os: Ubuntu
  release: jammy 22.04
templates:
  /etc/hosts:
    when:
      - create
      - rename
    template: hosts.tpl
    properties:
      foo: bar
  /etc/hostname:
    when:
      - start
    template: hostname.tpl
  /etc/network/interfaces:
    when:
      - create
    template: interfaces.tpl
    create_only: true

architecturecreation_date の項目は必須です。 properties は 単にイメージのデフォルト・プロパティの組です。 os, release, namedescription の項目は必須ではないですが、記載されることが多いでしょう。

テンプレートで when キーは以下の 1 つあるいは複数が指定可能です。

  • create (そのイメージから新しいインスタンスが作成されたときに実行される)

  • copy (既存のインスタンスから新しいインスタンスが作成されたときに実行される)

  • start (インスタンスが開始される度に実行される)

テンプレートは常に以下のコンテキストを受け取ります。

  • trigger: テンプレートを呼び出したイベントの名前 (string)

  • path: テンプレート出力先のファイルのパス (string)

  • container: インスタンスのプロパティ (name, architecture, privileged そして ephemeral) の key/value の map (map[string]string) (廃止予定。代わりに instance を使用してください)

  • instance: インスタンスのプロパティ (name, architecture, privileged そして ephemeral) の key/value の map (map[string]string)

  • config: インスタンスの設定の key/value の map (map[string]string)

  • devices: インスタンスに割り当てられたデバイスの key/value の map (map[string]map[string]string)

  • properties: metadata.yaml に指定されたテンプレートのプロパティの key/value の map (map[string]string)

create_only キーを設定すると LXD が存在しないファイルだけを生成し、 既存のファイルを上書きしないようにできます。

一般的な規範として、パッケージで管理されているファイルをテンプレートの 生成対象とすべきではないです。そうしてしまうとインスタンスの通常の操作で 上書きされてしまうでしょう。

利便性のため、以下の関数が pongo のテンプレートで利用可能となっています。

  • config_get("user.foo", "bar") => user.foo の値か、未設定の場合は "bar" を返します。