Raspberry Piの構築をAnsibleで行っていましたが、最初にネットワーク使えるようにするまでに、ほんの少しだけ手作業の設定が必要でした。
そこで、ネットワーク設定を含む全てのマシンで必要な共通のゴールデンイメージとして持って、マシンごとの個別部分をAnsilbleで行う方法に切り替えることで方式を考えることにしました。
最初は普通にRaspberry Piで設定した内容をイメージバックアップ取れば良いかなと思っていたのですが、以下のリポジトリを使ったPackerを使う方法があることがわかりタイトルの方式を採ることにしました。
全体図
前提
Docker使うことで他はインストール無しでいけます。
- Linux
- Docker
コード全体
以下に上げてあります。
使い方
リポジトリの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 8月 12 20:34 image
ドキュメント化
Packerのテンプレートファイルにイメージ作成がドキュメント化されるので、どのベースイメージを使っているかをGit管理できるのも嬉しいところです。
参考
仕組みとしては以下の記事に近いことをしていると思います。