Raspberry Pi 向けのイメージを Packer で作成する

# Raspberry Pi 向けのイメージを Packer で作成する

## 概要

Raspberry Pi でミドルウェアの設定などをいじって動かしていると試行錯誤の最中はともかく、構成が固まった後に何をしたかわからなくなりがちです。

そこで、 Packer を使って最初から設定されているイメージを作成し、そのイメージで Raspberry Pi を動かすことを試みます。

## 本編

### Packer とは

https://www.packer.io/

Builder と Provisioner を組み合わせてマシンのイメージを作成するツールです。詳しくは説明しないので気になる方は各自で調べましょう。

- Builder: ターゲットとするプラットフォームに向けたイメージを生成する。例えば EC2 や VirtualBox など。
- Provisioner: マシンの設定をする。例えば Shell や　Ansible など。

### ARM 向けの Packer

Packer 公式で様々な Builder を提供していますが、その中の一つに QEMU を使ったものがあります。こちらを使っても Raspberry Pi が採用している ARM 向けのイメージは作成可能で実際にリポジトリ[^direct-qemu]も存在していますが、環境依存のものがあったり、設定が少し難しかったりするのでここでは次のリポジトリの方法をとります。

[^direct-qemu]: https://github.com/Demonsthere/raspberry-packer_scripts

https://github.com/solo-io/packer-builder-arm-image

このリポジトリでは Packer の Builder として arm-image を作っています。 Raspberry Pi に特化しているので Packer の設定そのものはシンプルになります。

ただし、 Linux 上でしか動かないいくつかのコマンドに依存しているのでここでは Vagrant [^vagrant]経由で使用することにします。

[^vagrant]: https://www.vagrantup.com/ Packer と同じく　HashiCorp 製の仮想環境を管理するツール。

### 実際に動かしてみる

`packer-builder-arm-image` のリポジトリをクローンして、試しに Vagrant を起動するとそれだけでデフォルトの設定でイメージが生成されます。
依存しているイメージの取得が遅かったりするので心にゆとりを持って作業しましょう。


```bash
$ git clone https://github.com/solo-io/packer-builder-arm-image
$ cd packer-builder-arm-image
$ vagrant up
$ ls output-arm-image.img
```

初回の立ち上げでは VM のプロビジョニング作業にしばらく時間がかかると思いますが、 2 回目以降は各種のキャッシュが効いてくるのでそこまで時間はかかりません。

### カスタマイズ

#### ベースイメージの変更

さて、実際にイメージが作成できるのは確認できたと思いますが、ベースのイメージが古くなっているので新しいものをベースにして試してみましょう。

https://downloads.raspberrypi.org/raspbian_lite/images/

ここでは `2018-11-15` のイメージを選びました。設定する際にイメージのチェックサムも必要なのでついでに確認しておきましょう。

```bash
$ curl https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2018-11-15/2018-11-13-raspbian-stretch-lite.zip.sha256
47ef1b2501d0e5002675a50b6868074e693f78829822eef64f3878487953234d  2018-11-13-raspbian-stretch-lite.zip
```

下記のファイルをリポジトリ直下に作成します。

```json:my-image.json
{
  "variables": {
  },
  "builders": [{
    "type": "arm-image",
    "iso_url" : "https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2018-11-15/2018-11-13-raspbian-stretch-lite.zip",
    "iso_checksum_type":"sha256",
    "iso_checksum":"47ef1b2501d0e5002675a50b6868074e693f78829822eef64f3878487953234d",
    "last_partition_extra_size" : 1073741824
  }],  
  "provisioners": [
    {
      "type": "shell",
      "inline": ["apt-get update && apt-get install -y golang"]
    }
  ]
}
```

基本的には `example.json` をコピーして編集しただけです。このファイルをもとにイメージの生成をしてみます。

```bash
$ PACKERFILE=my-image.json vagrant provision --provision-with build-image
```

これでベースイメージを変更することができました。

#### そのほかのカスタマイズ

`my-image.json` を作った際に `provisioners` という項目があったと思います。 Packer ではこの部分を好きに変えることで最終的に生成されるイメージをカスタマイズすることができます。

自分の用途に合わせて必要なミドルウェアやその設定を入れたイメージを作成してみましょう。 `packer-builder-arm-image` の README にもいくつか参考になる設定が記載されています。

### エミュレート

作成したイメージの動作を確認したかったらどうすればいいでしょうか。環境にもよりますがもし QEMU が導入できる環境であれば Raspberry Pi のエミュレーションをすることが可能です。
イメージにあったカーネルを取得したりする必要はあるもののそのまま確認できるのはなかなか便利です。

```bash
$ wget https://github.com/dhruvvyas90/qemu-rpi-kernel/raw/master/kernel-qemu-4.14.50-stretch
$ wget https://github.com/dhruvvyas90/qemu-rpi-kernel/raw/master/versatile-pb.dtb
$ qemu-system-arm \
  -kernel kernel-qemu-4.14.50-stretch \
  -hda ./output-arm-image.img \
  -dtb ./versatile-pb.dtb \
  -cpu arm1176 -m 256 \
  -M versatilepb -no-reboot -serial stdio \
  -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" \
  -net nic -net user,hostfwd=tcp::5022-:22 
```

/boot に関してはおそらく　dtd がマウントされてしまい確認することはできません。

## まとめ

イメージを物理的に MicroSD カードなんかに焼く作業はどうしても発生するのでその度にクラウドって便利だなということを実感する日々です。