Container Linux の ISOイメージを Terraform for さくらのクラウドで作成・管理

## 概要

![terraform-for-sakura-cloud.png](https://qiita-image-store.s3.amazonaws.com/0/13002/44ba82d5-fcd6-1c23-ece5-7fc8792fa35b.png)

CoreOS が提供している [Container Linux](https://coreos.com/os/) を例に、[さくらのクラウド](https://cloud.sakura.ad.jp/) の「[ISO イメージ](https://manual.sakura.ad.jp/cloud/storage/isoimage.html)」機能で、HashiCorp [Terraform](https://www.terraform.io/) を使った ISO のアップロードや管理方法を紹介します。なおこの手法は、さくらのクラウドの「パブリック ISO イメージ」を作る手順と一部が同じです。皆さまのご参考になればと思い、公開・共有いたします。

（なお、この投稿はさくらインターネット [Advent Calendar 2018](https://qiita.com/advent-calendar/2018/sakura) の 17 日めの投稿です。）

## 「ISO イメージ」機能

さくらのクラウドには、DVD-ROM や CD-ROM のような光学ディスクの「ディスクイメージ」を扱う ISO イメージ機能があります。インターネット上で配布されている様々な Linux ディストリビューションや OS の ISO イメージ（拡張子 .iso など）を FTP でアップロードし、仮想サーバに取り付けての起動や、読み込みできる機能です。

ISO イメージ機能を使えば、さくらのクラウド上では提供されていない OS をセットアップできます。あるいは、さくらのクラウドで提供されている OS やディストリビューションだとしても、自分が使いたいバージョンと異なる場合（新しすぎる、または、サポート終了に伴い既に公開が終了しているケース）や、自分の好きな通りにゼロから初期設定をしたい場合は、この ISO イメージ機能が役立ちます。（似たような機能で「パブリック・アーカイブ」がありますが、こちらは仮想ディスク・イメージのテンプレートです。これを使って仮想マシンを起動しますと、 IP アドレスやホスト名などが自動設定された状態で利用できます。）

ISO イメージは２種類です。

- パブリック ISO イメージ … さくらインターネットが提供している ISO イメージ（イメージ一覧は[こちら](https://manual.sakura.ad.jp/cloud/server/os-packages/archive-iso/list.html#id7)）。
- ISO イメージ … 自分でアップロードして自由に管理できる ISO イメージ。

ここで扱うのは後者の「ISOイメージです」。

## チームによる共同管理で発生する３つの課題

ISO イメージを、チームで管理・作業するにあたっては、課題が３つあります。

-  ファイル名がない ISO イメージを正確に管理するには
- ミス無く効率的な作業をするには
- 共同作業（特定の誰かに管理業務を任せない）をするには

これらの課題を、Terraform でどのように解決できるのか、以下で紹介します。

### ISO イメージの管理

まず１つめ。Linux ディストリビューションとして配布されている ISO イメージは、伝統的にはバージョンアップするごとに「ISOイメージのファイル名」が変わります。たとえば CentOS であればファイル名「CentOS-7-x86_64-Minimal-1810.iso」は「CentOS 7.6(1810)」の「x86_64」アーキテクチャであると分かります。

しかし、CoreOS Container Linux はファイル名が常に「coreos_production_iso_image.iso」です。仮にローカルにファイルが存在していても、そこからは「どの」バージョンなのか、ファイル名からは判別できません。RancherOS も同様ですが、常にバージョンアップが継続するディストリビューションでは、 ISO イメージの名前が変わらないです。

この結果、ISO イメージをアップロードする場合、誤って違うバージョンをアップロードしてしまう危険性があります。一番確実なのは自分で「coreos_1911.iso」のように名称変更する方法です。あるいは、ISO イメージではなく、ハッシュ値でも ISO イメージを確認するのが理想ですが、そうでなければブートするまでバージョンが分かりません。

ここで役立つのが Terraform です。Terraform は ISO イメージに付随するイメージ名やタグなどを HCL 形式（HashiCorp Configuration Language）のファイルとして管理できます。作業時に curl や wget で ISO イメージをリモートから取得したら、あとは、 Terraform で直ちに ISO イメージをアップロードし、自動でバージョン名とタグも付与します。作業が終わったら、ISO を削除するだけです。

なお、HashiCorp Packer も同様の機能を提供しますが、Packer の最終成果物は「アーカイブ」です。アーカイブ作成の過程で、URL を指定した ISO の自動ダウンロードやハッシュ確認は、手間が省ける便利な機能です。しかし、ISO ファイル名は固定であり、ISO のタグ付けにも対応していません。そのため ISO イメージに特化する作業としては Terraform を採用しました。

### ミス無く効率的な作業

通常 ISO イメージをアップロードするには、FTP クライアントを使います。が、これがなかなか面倒。コントロールパネル上で「ISO」のリソースを作成し、それから FTP 用の ID とパスワードを確認し、さらにクライアントを使って転送し、FTP を終了し、さらに名前やを設定する作業が必要です。単純作業ですが、複数の ISO イメージを管理していますと、時に心が折れそうになります。また、長時間の単純作業は、集中力の低下による作業ミスの誘因にもなりうるでしょう。

Terraform であれば、前述したアップロード工程を「terraform init」「terraform apply」を実行するだけで可能にします。あらかじめ Terraform では、 HCL 形式でクラウド上のリソースを定義できます。以下が実際に使用している Container Linux 用の .tf ファイルです。基本的に触るのは「ver」の部分だけです。

```
locals {
        name    = "CoreOS Container Linux"
        ver     = "1911.4.0"
        iso     = "coreos_production_iso_image.iso"
        distro  = "container-linux"
}

resource sakuracloud_cdrom "cdrom" {
        name = "${local.name} ${local.ver} (latest)"
        tags    = ["arch-64bit","distro-${local.distro}","distro-ver-${local.ver}","os-linux","current-stable"]
        size = "5"
        iso_image_file = "../${local.iso}"
        hash = "${md5(file("../${local.iso}"))}"
        description = "${local.iso}"
}
```

あとはコマンド実行すると、自動的にカレント・ディレクトリにある ISO をアップロードし、利用可能になります。仮にバージョンが変わるとしても、 .tf ファイルを書き直し、ISO をダウンロードした後に「terraform plan」「terraform apply」を再実行するだけです。深夜早朝や、徹夜明けの変なテンションの時も安全に作業できます。また、工夫したら ISO のバージョンアップをトリガとして、ISO のダウンロードや反映も全て自動化するのもできうるでしょう（そこまではまだ手がけていません）。

### 共同作業とバージョン管理

チームでの作業となると、ある作業が特定の誰かしかできない状態になると、ブラックボックス化したり業務負担が重なったり、あるいは並列に分担しながら業務ができないなどの課題があります。特に、手順書ベースの作業であれば、工程数が増えれば増えるほど、集中力を削がれますし、うっかりミスも起こりがちでしょう。

Terraform であれ「Terraform for さくらのクラウド」の動作環境を準備しておくだけで、誰でも確実に、人よりも素早く正確に作業ができます。また .tf ファイルを GItHub 上で管理しておけば、誰がどのタイミングで、何の意図で変更を行ったのかの記録も行えます。GitHub 上のファイルを常に「正」としておけば、設定情報が誤った派生バージョンが広まるのも阻止できますし、何か間違いや問題があったとしても、commit 履歴から経緯を確認できるのも容易です。

## 使うには？

必要なものは以下の通りです：

 * [Terraform 本体](https://terraforom.io/)
 * [Terraform for さくらのクラウド プラグイン](https://sacloud.github.io/terraform-provider-sakuracloud/)
 * [さくらのクラウド API](https://manual.sakura.ad.jp/cloud/api/apikey.html#id3) （Terraform がクラウドにアクセスするために必要です）

準備が調ったら、任意のディレクトリに先ほどの .tf ファイルを設置します。ファイルでは `locals` で変数を定義し、 `sakuracloud_cdrom` リソースを作成します。リソースの説明などで `${local.<変数名>}` として変数の値を参照します。
それから、 ISO イメージもダウンロードします。最終的に

```
$ terraform init	（環境の初期化）
$ terrafprm plan	（変更内容の事前確認）
$ terraform apply	（実際の設定投入）
（実行後の確認プロンプトで「YES」を入力）
```

を実行します。

詳しくみていきましょう。まずは初期化の `terraform init` です。

```
$ terraform  init

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

プラグインが認識されているのであれば、このようなメッセージが緑色で表示されます。エラーが出てしまう場合は、プララグインのセットアップが正常に完了しているかを確認します。

それから `terraform plan` です。

```
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + sakuracloud_cdrom.cdrom
      id:                <computed>
      content_file_name: "config"
      description:       "coreos_production_iso_image.iso"
      hash:              "5e1fb24644552e06a2532fc0da693f34"
      iso_image_file:    "../ISO/coreos_production_iso_image.iso"
      name:              "CoreOS Container Linux 1911.4.0 (latest)"
      size:              "5"
      tags.#:            "5"
      tags.0:            "arch-64bit"
      tags.1:            "distro-container-linux"
      tags.2:            "distro-ver-1911.4.0"
      tags.3:            "os-linux"
      tags.4:            "current-stable"
      zone:              <computed>


Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
```

新しい ISO イメージ（Terraformの `sakuracloud_cdrom` リソース）をアップロードします。この段階ではアップロードは終わっておらず、設定内容を確認するだけです。`1 to add` というのは、１つのリソースを追加するという意味。

最後に `terraform apply` で反映します。

```
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + sakuracloud_cdrom.cdrom
      id:                <computed>
      content_file_name: "config"
      description:       "coreos_production_iso_image.iso"
      hash:              "5e1fb24644552e06a2532fc0da693f34"
      iso_image_file:    "../ISO/coreos_production_iso_image.iso"
      name:              "CoreOS Container Linux 1911.4.0 (latest)"
      size:              "5"
      tags.#:            "5"
      tags.0:            "arch-64bit"
      tags.1:            "distro-container-linux"
      tags.2:            "distro-ver-1911.4.0"
      tags.3:            "os-linux"
      tags.4:            "current-stable"
      zone:              <computed>


Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

sakuracloud_cdrom.cdrom: Creating...
  content_file_name: "" => "config"
  description:       "" => "coreos_production_iso_image.iso"
  hash:              "" => "5e1fb24644552e06a2532fc0da693f34"
  iso_image_file:    "" => "../ISO/coreos_production_iso_image.iso"
  name:              "" => "CoreOS Container Linux 1911.4.0 (latest)"
  size:              "" => "5"
  tags.#:            "" => "5"
  tags.0:            "" => "arch-64bit"
  tags.1:            "" => "distro-container-linux"
  tags.2:            "" => "distro-ver-1911.4.0"
  tags.3:            "" => "os-linux"
  tags.4:            "" => "current-stable"
  zone:              "" => "<computed>"
sakuracloud_cdrom.cdrom: Still creating... (10s elapsed)
sakuracloud_cdrom.cdrom: Still creating... (20s elapsed)
sakuracloud_cdrom.cdrom: Still creating... (30s elapsed)
sakuracloud_cdrom.cdrom: Creation complete after 39s (ID: 113001677701)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

それから ISO イメージの一覧画面からアップロードされているのを確認できます。コントロールパネルの `ストレージ` → `ISOイメージ` です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13002/b27f6eb7-df73-8e13-fe47-d2038cd8bf8c.png)


あとはサーバの作成時（シンプルモードを解除し）、ディスクソース「空のディスク」を選択すると「ISOイメージを使う」のメニューが出ますので、こちらを使います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13002/b520208d-da37-1b18-ae32-ae14aeada9ea.png)


このようにして Terraform for さくらのクラウドを活用しますと、手間になりがちな ISO イメージの管理も簡単かつ確実かつ効率的に行えます。ISO イメージにも様々な対応リソースがありますので、手作業の環境構築を脱却する手がかりとして、Terraform を使い始めてみてはいかがでしょうか。