Raspberry Pi実機無しでゴールデンイメージを作成する(SORACOM接続用サンプル)

Raspberry Piの構築をAnsibleで行っていましたが、最初にネットワーク使えるようにするまでに、ほんの少しだけ手作業の設定が必要でした。

そこで、ネットワーク設定を含む全てのマシンで必要な共通のゴールデンイメージとして持って、マシンごとの個別部分をAnsilbleで行う方法に切り替えることで方式を考えることにしました。

最初は普通にRaspberry Piで設定した内容をイメージバックアップ取れば良いかなと思っていたのですが、以下のリポジトリを使ったPackerを使う方法があることがわかりタイトルの方式を採ることにしました。

github.com

全体図

前提

Docker使うことで他はインストール無しでいけます。

  • Linux
  • Docker

コード全体

以下に上げてあります。

github.com

使い方

リポジトリのClone

git clone https://github.com/yomon8/raspberry-pi-imager.git
cd raspberry-pi-imager/

イメージの書き換え

リポジトリのトップにPackerのテンプレートファイルとして packer_raspberrypi.json というファイルがあります。

JSONにあるiso_url のURLと iso_checksum の項目はベースとなるRaspberry Pi OSのイメージとなるので必要に応じて最新に変更してください。

provisioners でsshを有効化用のフラグファイルを配置しているのと、Ansibleを実行しているのがわかります。

$ cat ./packer_raspberrypi.json
{
  "variables": {
    "img_mount_path": "/mnt/raspbian"
  },
  "builders": [
    {
      "type": "arm-image",
      "iso_url": "https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip",
      "iso_checksum": "sha256:c5dad159a2775c687e9281b1a0e586f7471690ae28f2f2282c90e7d59f64273c",
      "mount_path": "{{ user `img_mount_path` }}"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "touch /boot/ssh"
      ]
    },
    {
      "type": "shell-local",
      "inline": [
        "sudo -E ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 ansible-playbook -i '{{ user `img_mount_path` }}', -v -c chroot /build/ansible/main.yaml"
      ]
    }
  ]
}

イメージはFull版なら以下URLに、

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

Lite版なら以下URLにあります。

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

iso_url のURLと iso_checksum の値をそれぞれ以下から取得します。

Ansibleを調整

初期では以下の通り何も設定されていない状態なので、タスクを入れます。

$ cat ansible/main.yaml
---
- hosts: all
  tasks:
    - ping:

今回はとりあえずSORACOMから繋ぎたかったので、こちらの設定を入れています。

Ansibleからsetup_air.shを実行してRaspberry PiとSORACOM Airを設定する - YOMON8.NET

こんな感じです。

$ cat ansible/main.yaml
---
- hosts: all
  tasks:
    - name: Download soracom setup tool
      get_url:
        url: https://soracom-files.s3.amazonaws.com/setup_air.sh
        dest: /tmp/setup_air.sh
        force: true

    - name: Setup soracom air
      become: true
      shell: >
        /bin/bash /tmp/setup_air.sh

    - name: Delete /tmp/setup_air.sh
      become: true
      file:
        path: /tmp/setup_air.sh
        state: absent

実行する

実行はコマンド一本です。

./build.sh

まずはOSイメージのビルドが始まります。初回はベースイメージのダウンロードに時間がかかりますが、2回目移行は ./packer_cache ディレクトリにイメージがキャッシュされるので速度上がります。

==> arm-image: Retrieving Image
==> arm-image: Trying https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip
==> arm-image: Trying https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip?checksum=sha256%3Ac5dad159a2775c687e9281b1a0e586f7471690ae28f2f2282c90e7d59f64273c
2021-05-07-raspios-buster-armhf-lite.zip 331.34 MiB / 444.09 MiB   74.61% 01m07ss

以下のようなエラーが出たら再度実行したらうまくいく時があります。

Ansibleの実行が完了して、イメージのビルドが終わりました。

SDカードに焼く

dd コマンドで以下の用に焼いても良いですし、

$ sudo dd bs=4 if=./output-arm-image/image of=/dev/{YOUR_DEVICE}

Raspberry Pi Imagerを利用しても良いです。

パラメータ変更

buildersのパラメータを変更することも可能です。

例えば output_filename というパラメータで出力先のファイル名を変更可能です。

他のパラメータはこちらに記載があります。

   },
    "builders": [
        {
            "type": "arm-image",
            "iso_url": "https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-lite.zip",
            "iso_checksum": "sha256:c5dad159a2775c687e9281b1a0e586f7471690ae28f2f2282c90e7d59f64273c",
            "output_filename": "output-arm-image/my-custom-image.img",
            "mount_path": "{{ user `img_mount_path` }}"
        }
    ],

設定可能なパラメータは以下などを参考にしてください。

https://github.com/solo-io/packer-builder-arm-image/blob/v0.1.6/pkg/builder/builder.go#L63-L122

最後に

最後にこれで何か嬉しいかということを書いて終わりにします。

更なる自動化

元々Raspberry Piで何か作る時にはAnsibleで構築作業を自動化しているのですが、最初のネットワークを繋ぐところだけはマニュアル作業が残ってしまっていました。この仕組みを使えば残るはイメージを焼く手順だけとなります。

イメージサイズを削減できる

また、通常通りMicroSDからイメージをバックアップするよりもはるかに小さな容量イメージを作ることができることも嬉しいことの一つです。

実際に今回作ったイメージを見てみると 1.8GB 、圧縮すれば更に半分以下にできるので、ネットワークドライブ等でも何とか共有できる範囲のサイズです。当然最後にSDカードに焼くのも早いです。

$ ls -lh output-arm-image/
total 1.8G
-rw-r--r-- 1 root root 1.8G  812 20:34 image

ドキュメント化

Packerのテンプレートファイルにイメージ作成がドキュメント化されるので、どのベースイメージを使っているかをGit管理できるのも嬉しいところです。

参考

仕組みとしては以下の記事に近いことをしていると思います。

Raspberry Pi のセルフビルド環境を QEMU で作る - Qiita