LXD 2.0: イメージの管理 [5/12]

## この文書について

この文書は、連載記事「[LXD 2.0: Blog post series](https://www.stgraber.org/2016/03/11/lxd-2-0-blog-post-series-012/)」（[日本語版目次](http://qiita.com/m-shibata/items/029b19d90af2a79116c2)）の一つである以下の記事を翻訳したものです。

* https://www.stgraber.org/2016/03/30/lxd-2-0-image-management-512/

この文書のライセンスは原文と同じく、[Creative Commons BY-NC-SA 2.5](http://creativecommons.org/licenses/by-nc-sa/2.5/)のもとに提供されています。

![CC-BY-NC-SA 2.5](http://i.creativecommons.org/l/by-nc-sa/2.5/88x31.png)

---------


## コンテナイメージ

以前にLXCを使ったことがある場合、LXCの「テンプレート」機能を覚えているかもしれません。これは基本的には、コンテナのファイルシステムを作り、いくつかの設定を行う、シェルスクリプトでした。

ほとんどのテンプレートは、ローカルマシーン上で個々のディストリビューションのブートストラッピングを行うことで、ファイルシステムを作成Sしていました。これは時間のかかる作業であり、すべてのディストリビューションで使える手法というわけでもなく、高速なネットワークが必要な機能でした。

LXCの1.0の時に、「ダウンロード」テンプレートについて紹介しました。これを使うと、テンプレートスクリプトを使って中央サーバーで構築し、圧縮・署名したコンテナイメージをHTTPS経由でダウンロードできます。多くのユーザーはコンテナを生成する古い方法から、より高速で確実にコンテナを生成できるこの新しい方法に移行しました。

LXDでは、このイメージベースのワークフローをさらに一歩進めました。すべてのコンテナはイメージから生成し、LXDのイメージストアが最新版を保持し続けられるように、より高機能なイメージキャッシュと事前ロード機能をサポートしました。


## LXDイメージの操作方法

イメージフォーマットの詳細を説明する前に、LXDがイメージをどのように扱うか簡単に見ておきましょう。

### イメージのインポート

すべてのコンテナはイメージから作られます。イメージはリモートイメージサーバー上に存在し、完全なハッシュ文字列やその省略形、もしくは別名によって取得し、最終的にLXDのコンテナはこのローカルイメージから作成されます。

たとえば次のように取得します：

```
lxc launch ubuntu:14.04 c1
lxc launch ubuntu:75182b1241be475a64e68a518ce853e800e9b50397d2f152816c24f038c94d6e c2
lxc launch ubuntu:75182b1241be c3
```

これらはすべてリモート上の同じイメージ（執筆時点では）を指定しています。最初に実行した時、このリモートイメージはローカルのLXDイメージストアにイメージキャッシュとして取り込まれ、その後コンテナはこのイメージキャッシュから生成されることになります。

同じコマンドを次に実行した時、LXDは（フィンガープリントでない方法で参照した場合のみ）イメージが最新かどうかのみ確認し、最新版であれば、新規にダウンロードすることなくコンテナを作成します。

あるイメージがローカルのイメージストアにキャッシュされた後、最新版かどうかチェックすることなくそのイメージからコンテナを作成・起動したい場合は、次のように実行します：

```
lxc launch 75182b1241be c4
```

最後に、ローカルのイメージの名前が「`my-image`」の場合、単純に次のように指定することで起動できます：

```
lxc launch my-image c5
```

自動的なキャッシュ機能やキャッシュの有効期限についての挙動を変更したい場合は、[以前の投稿](http://qiita.com/m-shibata/items/346a481ef476c3c29f8a)を参照してください。

### イメージの手動インポート

#### イメージサーバーからコピーする

リモートのあるイメージをローカルのイメージストアにコピーしたいけれども、すぐにコンテナを作りたいわけではない場合、「`lxc image copy`」コマンドを使えば単純にコピーのみを実行できます。またイメージフラグの操作にも使えます。

```
lxc image copy ubuntu:14.04 local:
```

上記は単純にリモートイメージをローカルのイメージストアにコピーしているだけです。

コピーしたイメージをフィンガープリントよりも覚えやすい名前で参照したい場合、コピー時にエイリアスオプションで別名を追加できます：

```
lxc image copy ubuntu:12.04 local: --alias old-ubuntu
lxc launch old-ubuntu c6
```

おおもとのサーバーのエイリアスセットをそのまま利用したいかもしれません。LXDはエイリアスセットのコピーもサポートしています：

```
lxc image copy ubuntu:15.10 local: --copy-aliases
lxc launch 15.10 c7
```

上記のコピー操作はすべて、一度きりのコピーです。つまりリモートイメージの最新版をローカルのイメージストアに保存します。キャッシュイメージと同様に、コピーしたイメージも常に最新版に保ちたい場合、「`--auto-update`」フラグを指定してください：

```
lxc image copy images:gentoo/current/amd64 local: --alias gentoo --auto-update
```

#### アーカイブファイルから取り込む

LXDイメージをアーカイブファイルとして受け取った場合、次のように取り込むことができます：

```
lxc image import <アーカイブ>
```

取り込み時に、別名を付けることも可能です：

```
lxc image import <アーカイブ> --alias random-image
```

一つのLXDイメージが二つのアーカイブファイルになっている場合もあります。この場合は、片方がLXDのメタデータです。通常はファイル名からどちらがメタデータかわかりますが、不明な場合はサイズが小さい方をメタデータとして扱ってください。二つのアーカイブの場合は、次のように取り込みます：

```
lxc image import <メタデータアーカイブ> <rootfsアーカイブ>
```

#### URLを指定して取り込む

「`lxc image import`」にはURLも指定できます。もしパスを指定した`LXD-Image-URL`とハッシュを指定した`LXD-Image-Hash`をヘッダーとして提供できるHTTPSのウェブサーバーがあれば、LXDはそこからイメージストアにイメージを取得できます。

たとえば次のように取得します：

```
lxc image import https://dl.stgraber.org/lxd --alias busybox-amd64
```

イメージを取得する時、リモートサーバーが適切なイメージを返すかどうか確認するために、LXDもいくつかのヘッダーを設定します。設定するヘッダーは、`LXD-Server-Architectures`と`LXD-Server-Version`です。

これは簡易的なイメージサーバーとして使えます。より利用者が簡単にイメージを取り込む方法を用意するために、何か静的なウェブサーバーをそのまま使えるということです。


### ローカルイメージストアの管理

ここまででローカルのイメージストアにいくつかのイメージが保存されています。次はその内容の確認方法を見て行きましょう。既に何度も見てきたように、そこからコンテナを作成できます。しかしローカルのイメージストアに対して、他にもいくつかの操作を行えます。

#### イメージの一覧

ストアにあるすべてのイメージを表示するには「`lxc image list`」を実行するだけです：

```
stgraber@dakara:~$ lxc image list
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
|     ALIAS     | FINGERPRINT  | PUBLIC |                     DESCRIPTION                      |  ARCH  |   SIZE   |         UPLOAD DATE          |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| alpine-32     | 6d9c131efab3 | yes    | Alpine edge (i386) (20160329_23:52)                  | i686   | 2.50MB   | Mar 30, 2016 at 4:36am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| busybox-amd64 | 74186c79ca2f | no     | Busybox x86_64                                       | x86_64 | 0.79MB   | Mar 30, 2016 at 4:33am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| gentoo        | 1a134c5951e0 | no     | Gentoo current (amd64) (20160329_14:12)              | x86_64 | 232.50MB | Mar 30, 2016 at 4:34am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| my-image      | c9b6e738fae7 | no     | Scientific Linux 6 x86_64 (default) (20160215_02:36) | x86_64 | 625.34MB | Mar 2, 2016 at 4:56am (UTC)  |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| old-ubuntu    | 4d558b08f22f | no     | ubuntu 12.04 LTS amd64 (release) (20160315)          | x86_64 | 155.09MB | Mar 30, 2016 at 4:30am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
| w (11 more)   | d3703a994910 | no     | ubuntu 15.10 amd64 (release) (20160315)              | x86_64 | 153.35MB | Mar 30, 2016 at 4:31am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
|               | 75182b1241be | no     | ubuntu 14.04 LTS amd64 (release) (20160314)          | x86_64 | 118.17MB | Mar 30, 2016 at 4:27am (UTC) |
+---------------+--------------+--------+------------------------------------------------------+--------+----------+------------------------------+
```

別名やフィンガープリントに対してフィルタリングをかけられます：

```
stgraber@dakara:~$ lxc image list amd64
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
|     ALIAS     | FINGERPRINT  | PUBLIC |               DESCRIPTION               |  ARCH  |   SIZE   |          UPLOAD DATE         |
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
| busybox-amd64 | 74186c79ca2f | no     | Busybox x86_64                          | x86_64 | 0.79MB   | Mar 30, 2016 at 4:33am (UTC) |
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
| w (11 more)   | d3703a994910 | no     | ubuntu 15.10 amd64 (release) (20160315) | x86_64 | 153.35MB | Mar 30, 2016 at 4:31am (UTC) |
+---------------+--------------+--------+-----------------------------------------+--------+----------+------------------------------+
```

「`key=value`」を使ったイメージプロパティのフィルタリングも可能です：

```
stgraber@dakara:~$ lxc image list os=ubuntu
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
|    ALIAS    | FINGERPRINT  | PUBLIC |                  DESCRIPTION                |  ARCH  |   SIZE   |          UPLOAD DATE         |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
| old-ubuntu  | 4d558b08f22f | no     | ubuntu 12.04 LTS amd64 (release) (20160315) | x86_64 | 155.09MB | Mar 30, 2016 at 4:30am (UTC) |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
| w (11 more) | d3703a994910 | no     | ubuntu 15.10 amd64 (release) (20160315)     | x86_64 | 153.35MB | Mar 30, 2016 at 4:31am (UTC) |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
|             | 75182b1241be | no     | ubuntu 14.04 LTS amd64 (release) (20160314) | x86_64 | 118.17MB | Mar 30, 2016 at 4:27am (UTC) |
+-------------+--------------+--------+---------------------------------------------+--------+----------+------------------------------+
```

指定したイメージについて、LXDが把握しているすべての情報を表示するには「`lxd image info`」を使います：

```
stgraber@castiana:~$ lxc image info ubuntu
Fingerprint: e8a33ec326ae7dd02331bd72f5d22181ba25401480b8e733c247da5950a7d084
Size: 139.43MB
Architecture: i686
Public: no
Timestamps:
 Created: 2016/03/15 00:00 UTC
 Uploaded: 2016/03/16 05:50 UTC
 Expires: 2017/04/26 00:00 UTC
Properties:
 version: 12.04
 aliases: 12.04,p,precise
 architecture: i386
 description: ubuntu 12.04 LTS i386 (release) (20160315)
 label: release
 os: ubuntu
 release: precise
 serial: 20160315
Aliases:
 - ubuntu
Auto update: enabled
Source:
 Server: https://cloud-images.ubuntu.com/releases
 Protocol: simplestreams
 Alias: precise/i386
```

#### イメージの編集

イメージのプロパティやフラグを編集するには次のコマンドを実行します：

```
lxc image edit <別名やフィンガープリント>
```

規定のテキストエディターが起動し、次のように編集できます：

```
autoupdate: true
properties:
 aliases: 14.04,default,lts,t,trusty
 architecture: amd64
 description: ubuntu 14.04 LTS amd64 (release) (20160314)
 label: release
 os: ubuntu
 release: trusty
 serial: "20160314"
 version: "14.04"
public: false
```

必要に応じてプロパティを変更してください。たとえば`autoupdate`のオンオフや、イメージの公開設定（あとで説明します）などを変更できます。

#### イメージの削除

イメージを削除したい場合は次のように実行するだけです：

```
lxc image delete <別名やフィンガープリント>
```

注意点として、キャッシュについては削除すべきではありません。これはLXD自身が、期限が過ぎたら自動的に削除するからです（標準では最後に使われてから10日間で削除されます）。

#### イメージのエクスポート

イメージストアにあるイメージを、イメージアーカイブとして取得したい場合、「`lxc image export`」を使えます：

```
stgraber@dakara:~$ lxc image export old-ubuntu .
Output is in .
stgraber@dakara:~$ ls -lh *.tar.xz
-rw------- 1 stgraber domain admins 656 Mar 30 00:55 meta-ubuntu-12.04-server-cloudimg-amd64-lxd.tar.xz
-rw------- 1 stgraber domain admins 156M Mar 30 00:55 ubuntu-12.04-server-cloudimg-amd64-lxd.tar.xz
```

## イメージフォーマット

LXDは`Unified`と`Split`という二つのイメージフォーマットをサポートしています。これらはどちらもLXD固有の考え方で、後者についてはファイルシステムを他のコンテナや仮想マシンで使用する場合に便利です。

LXDは主にシステムコンテナに注力しています。アプリケーションコンテナ用の「標準的な」イメージフォーマットはサポートしませんし、その予定もありません。

イメージはとても単純です。コンテナのファイルシステムと、イメージが作られた日時や期限、アーキテクチャなどを記述したメタデータ、さらにファイルテンプレートからなります。

データの詳細については[イメージフォーマットのページ](https://github.com/lxc/lxd/blob/master/doc/image-handling.md)を参照してください。


### Unifiedイメージ（単一のアーカイブ）

UnifiedイメージフォーマットはLXD自身がイメージを生成するときに使うフォーマットです。一つの大きなアーカイブファイルであり、`rootfs`ディレクトリにはコンテナのファイルシステムが、アーカイブのルートには`metadata.yaml`ファイルが、`templates`ディレクトリにはテンプレートが含まれています。

アーカイブにはいくつもの圧縮方式（圧縮をしないことも含めて）を使用できます。イメージのハッシュには圧縮したアーカイブに対する`sha256`を使用します。

### Splitイメージ（二つのアーカイブ）

Splitイメージフォーマットは誰かが自家製のイメージをローリング・リリースしたり、すでに圧縮されたファイルシステムアーカイブを持っている場合に使われます。

用途の異なる二つのアーカイブからなります。一つはLXDで使用するメタデータを保存した`metadata.yaml`をルートに持ち、`templates`ディレクトリにテンプレートデータを持っているアーカイブです。

もう一つのアーカイブは、そのルートのコンテナのファイルシステムを直接格納しているだけのアーカイブです。多くのディストリビューションは新しいマシンへのブートストラッピング用に既にそのようなアーカイブを持っているはずです。このイメージフォーマットではそのようなアーカイブをそのまま修正せずに利用できます。

それぞれのアーカイブにはいくつもの圧縮方式（圧縮しないことも含めて）を利用できます。またアーカイブごとに異なる圧縮方式を利用できます。イメージのハッシュには、メタデータとルートファイルシステムのアーカイブを結合した上で、`sha256`で生成します。

### イメージのメタデータ

典型的な`metadata.yaml`ファイルは次のような内容になっています：

```
architecture: "i686"
creation_date: 1458040200
properties:
 architecture: "i686"
 description: "Ubuntu 12.04 LTS server (20160315)"
 os: "ubuntu"
 release: "precise"
templates:
 /var/lib/cloud/seed/nocloud-net/meta-data:
  when:
   - start
  template: cloud-init-meta.tpl
 /var/lib/cloud/seed/nocloud-net/user-data:
  when:
   - start
  template: cloud-init-user.tpl
  properties:
   default: |
    #cloud-config
    {}
 /var/lib/cloud/seed/nocloud-net/vendor-data:
  when:
   - start
  template: cloud-init-vendor.tpl
  properties:
   default: |
    #cloud-config
    {}
 /etc/init/console.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty1.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty2.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty3.override:
  when:
   - create
  template: upstart-override.tpl
 /etc/init/tty4.override:
  when:
   - create
  template: upstart-override.tpl
```

#### プロパティ

必須フィールドは、作成日時（UNIX EPOCH）とアーキテクチャの二つだけです。それ以外のフィールドはすべて、設定しなくても良く、適切にイメージを取り込めます。

プロパティは、そのイメージの内容を利用者が把握するために使われます。たとえば「`description`」プロパティは「`lxc image list`」で表示されます。他のプロパティも利用者がイメージを「`key/value`」検索するときに使うことができます。

これらのプロパティは「`lxc image edit`」で経集可能です。作成日時とアーキテクチャフィールドは不変です。

#### テンプレート

テンプレート機構を使うと、コンテナの中のファイルをコンテナのライフサイクルにあわせて生成や再生成できます。

[pongo2テンプレートエンジン](https://github.com/flosch/pongo2)を使っており、コンテナに関して把握していることはすべてテンプレートに書き出しています。独自のコンテナプロパティを定義し、カスタムイメージで利用したり、特定のファイルを含めるように通常のLXDプロパティを変更したい場合に、この方法が使えます。

上記の例にもあるように、Ubuntuイメージではcloud-initを提供し、いくつかのinitスクリプトを停止するために、この仕組みを利用しています。


## 独自のイメージの作成

LXDは完全なLinuxシステムを動作することに注力しています。つまり、クリーンなディストリビューションをそのまま使う場合がほとんどで、独自のイメージを作成することはあまりないだろう考えています。

しかしながら、独自のイメージを作成した方が便利なケースもあります。プロダクションサーバー用に事前設定イメージを作成したり、公式では作成していないディストリビューションやアーキテクチャのイメージを作りたい場合等がこれに該当します。

### コンテナをイメージに変換

LXDでイメージを作成するもっとも簡単な方法は、そのコンテナをそのままイメージに変換することです。
The easiest way by far to build an image with LXD is to just turn a container into an image.

次のような方法で変換できます：

```
lxc launch ubuntu:14.04 my-container
lxc exec my-container bash
<何か必要な変更を加える>
lxc publish my-container --alias my-new-image
```

過去に作成したコンテナのスナップショットをイメージに変換することもできます：

```
lxc publish my-container/some-snapshot --alias some-image
```


## 手動でイメージを作成

独自のイメージを作成する方法も単純です。

1. コンテナのファイルシステムを作成します。その方法は使用するディストリビューションに依存します。UbuntuやDebianの場合は、`debootstrap`を使うことになるでしょう。
2. そのディストリビューションがコンテナの中で動作するように調整します（必要な場合のみ）。
3. コンテナファイルシステムのアーカイブ（tarball）を作成します。圧縮してもかまいません。
4. 上記の例を参考に、`metadata.yaml`ファイルを作成します。
5. `metadata.yaml`ファイルを取り込んだ別のアーカイブを作成します。
6. この二つのアーカイブをLXDイメージとして取り込みます：
    ```
    lxc image import <メタデータアーカイブ> <ルートファイルシステムアーカイブ> --alias some-name
    ```

ちゃんと動くようになるまで、いろいろと調整しながら、何回かこの手順を繰り返すことになるでしょう。もしかするとテンプレートやプロパティを追加する必要があるかもしれません。


## イメージの公開

LXDデーモンはイメージサーバーの機能も備えています。基本的にイメージストアに保存されたイメージはすべて非公開設定になっており、認められたクライアントのみがそのイメージを取得できます。もしこれをイメージサーバーとして公開したい場合は、いくつかのイメージに公開タグを付け、LXDイメージをネットワークから接続できるようにしなくてはなりません。

### LXDサーバーを公開状態にする

LXDイメージを共有するもっとも簡単な方法は、LXDデーモンを公開状態にすることです。

まずは次のように設定します：

```
lxc config set core.https_address "[::]:8443"
```

リモートの利用者は次のコマンドを実行することで、上記の設定を行ったサーバーを公開されたイメージサーバーとして追加できます：

```
lxc remote add <some name> <IP or DNS> --public
```

これにより既定のイメージサーバーの一つとして利用できます。「`--public`」を指定することで、リモートサーバーへのアクセス時に認証は不要になります。クライアントは、イメージサーバー上で公開設定になっているイメージにのみアクセスできます。

イメージを公開設定にするには、「`lxc image edit`」を使って`public`フラグを`true`に変更してください。


### 静的なウェブサーバーを使う

前述したように、「`lxc image import`」は静的なHTTPサーバーからのダウンロードもサポートしています。必要なものは次のとおりです：

As mentioned above, “lxc image import” supports downloading from a static http server. The requirements are basically:

* サーバーは適切な証明書、TLS 1.2、EC Ciphersを使ったHTTPS接続をサポートしていなければなりません。
* 「`lxc image import`」で指定したURLにアクセスした時、サーバーはそのレスポンスに`LXD-Image-Hash`ヘッダーと`LXD-Image-URL`ヘッダーを追加しなくてはなりません。

上記を動的に生成したい場合、LXDサーバーがイメージを取得する際に提供する`LXD-Server-Architectures`ヘッダーと`LXD-Server-Version`ヘッダーを、サーバー側で確認することができます。これによりLXDサーバーのアーキテクチャにあわせた正しいイメージを返すことができます。


### simplestreamsサーバーを構築する

「`ubuntu:`」リモートと「`ubuntu-daily:`」リモートは、（「`images:`」とは異なり）LXDのプロトコルを使用していません。simplestreamsと呼ばれるプロトコルを使用しています。

simplestreamsは基本的にイメージサーバーを記述するフォーマットで、プロダクトのリストやプロタクトに関連するファイルをJSONを用いて記述します。

これはOpenStackやJuju、MAASのようなツールでもシステムイメージの検索やダウンロード、ミラーなどに使われており、LXDもイメージ取得のネイティブプロトコルとしてsimplestreamsをサポートしています。

LXDイメージを提供する方法としては簡単ではありませんが、もしイメージを上記のツールでも使えるようにしたいのであれば、一考の余地はあるでしょう。

詳しいことは[simplestreamsのサイト](https://launchpad.net/simplestreams)を参照してください。


## まとめ

この記事で、どのようにLXDがイメージを管理するのか、またどのようにイメージを構築・配布するのかを把握できたものと期待しています。このようなグローバルな配布システムを使って、確実かつ簡単に同じイメージを利用できることは、古いLXCからの大きな一歩であり、再生成可能なインフラストラクチャーへと導いてくれるでしょう。


## その他の情報

* LXDのウェブサイト：[https://linuxcontainers.org/ja/lxd/](https://linuxcontainers.org/ja/lxd/)
* 開発はGitHub上で行なっています：[https://github.com/lxc/lxd](https://github.com/lxc/lxd)
* メーリングリスト：[https://lists.linuxcontainers.org](https://lists.linuxcontainers.org)
* IRCチャンネル：#lxcontainers on irc.freenode.net

LXDを試してみたいのであれば、[オンラインのデモページ](https://linuxcontainers.org/ja/lxd/try-it/)からLXDとそのガイドツアーを体験できます。