Fuchsia を GCE でビルドしてみた
Fuchsia のビルド、Zircon カーネルデバッグを GCE で行った際の記録です。
ビルド時間を計測しました。
自宅環境の問題
- ローカルリポジトリ更新(jiri update)が遅い
- ビルド(fx build)が遅い
これを GCE で解決できないか、検討してみます。
予算は、月 500 円前後。
自宅環境
Chromebox 上の Linux で開発しています。
- OS:Debian 10(on Crostini)
- CPU:Celeron 3865U(vCPUx2)
- メモリ:18GB
- ストレージ:SSD 337GB
方針
費用削減のため、作業用途によって VM の構成を変えます。
-
VM 最小構成(e2-micro)
- ソースコード編集(VSCode Remote SSH でリモート接続)
- fx qemu & gdb デバッグ(ssh でリモート接続)
-
VM ビルド構成(e2-standard-8)
- fuchsia リポジトリ更新(ssh でリモート接続)
- fx build ビルド(ssh でリモート接続)
(追記 e2-standard-4 で十分)
事前準備
- Google Cloud Platform アカウント登録
- Google Cloud Platform プロジェクト作成
-
gcloud インストール
VM をコンソールから操作するのに必要
VM 作成
-
最小構成(e2-micro)で VM 作成
@localgcloud compute instances create instance-test \ --machine-type=e2-micro \ --zone=us-west1-b \ --boot-disk-size=100GB \ --boot-disk-type=pd-standard \ --image-family=debian-10 \ --image-project=debian-cloud \ --preemptible \ --no-restart-on-failure \ --maintenance-policy=TERMINATE
- --machine-type=e2-micro
vCPUx2、メモリ 1GB 構成 - --zone=us-west1-b
us-west1-b(オレゴン)で動作(無料枠の条件) - --boot-disk-size=100GB、--boot-disk-type=pd-standard
永続ブートディスクに 100GB HDD を使用 - --image-family=debian-10, --image-project=debian-cloud
Debian 10 の最新イメージを使用。
(追記)Debian 11 がリリースされました。11 に変更する予定です - --preemptible、--no-restart-on-failure、--maintenance-policy=TERMINATE
プリエンプティブルに必要な設定(自動再起動オフ、メンテナンス時に VM 停止)
- --machine-type=e2-micro
-
ビルド構成(e2-standard-8)へ VM 変更
最小構成をビルド構成に更新する。
これを実行したあとで、ビルド、リポジトリ更新する。@localgcloud compute instances set-machine-type instance-test \ --machine-type e2-standard-8
- --machine-type=e2-standard-8
vCPUx8、メモリ 32GB 構成
- --machine-type=e2-standard-8
-
最小構成(e2-micro)へ VM 変更
ビルド構成を最小構成に更新する。
これを実行したあとで、ソースコード変更、デバッグする。@localgcloud compute instances set-machine-type instance-test \ --machine-type e2-micro
料金
-
無料部分
- e2-micro@us-west1-b(vCPUx2、メモリ 1GB)、プリエンプティブル
-
有料部分
-
e2-standard-8(vCPUx8、メモリ 32GB)、プリエンプティブル
なるべく安くしたいので、割安になるプリエンプティブルにする。
0.08041 ドル/時
1 時間可動した場合、1 ドル 110 円で約 9 円 -
標準永続ディスク(HDD)100GB
fuchsia のリポジトリ、ビルド成果物に必要なストレージは、50GB 〜 80GB ほど。
30GB まで無料。超えた 70GB が課金対象のはず。秒単位で課金。
追記:秒単位の課金が30GB * 0.04 * 110 = 132円
を超えるまでは無課金、超えると100GB
を対象に課金された。-
0.04 ドル/(GB・月)
70GB、1 か月可動した場合、1 ドル 110 円で 308 円
追記:100GB、1 か月可動した場合、1 ドル 110 円で 440 円。無課金分 132 円を引くと 308 円となる -
永続ディスクや外部 IP アドレスなど、VM に接続しているリソースは、削除されるまで課金対象になります
-
-
外部 IP アドレス(エフェメラル)
-
0.004 ドル/時
1 時間可動した場合、1 ドル 110 円で 0.44 円 -
エフェメラル 外部 IP アドレスは VM 停止中は課金されない
エフェメラル IP アドレスについては、関連付けられた VM インスタンスが実行中のときに限り、Google Cloud はそのアドレスを使用中であると見なします。インスタンスが停止または削除されると、Google Cloud はエフェメラル IP アドレスを解放し、このアドレスを使用中と見なしません
-
-
SSH でリモート接続
gcloud compute ssh instance-test
今回は、VM の外部 IP アドレス宛に SSH で接続します。
fuchsia リポジトリ更新
以下、SSH でログインした VM 内での作業です。
cd ~
sudo apt install -y curl git unzip gcc # fuchsiaビルドに必要
sudo apt install -y tmux # 回線切断時の備え
tmux # 以下の作業は tmux 内
curl -s "https://fuchsia.googlesource.com/fuchsia/+/HEAD/scripts/bootstrap?format=TEXT" | base64 --decode > bootstrap.sh
chmod u+x ./bootstrap.sh
計測結果
VM | 時間 |
---|---|
e2-micro | 125m 23s |
e2-standard-8 | 5m 41s |
(参考)自宅 | 65m 55s |
計測方法
time ./bootstrap.sh
fuchsia リポジトリサイズ
cd ~/fuchsia
du -sm ./
22239
リポジトリサイズは約 22GB でした。
環境変数のセット
export PATH="/home/{ユーザ名}/fuchsia/.jiri_root/bin:$PATH"
fx
コマンドへのパスを通します。
ビルド
計測結果
VM | PRODUCT.BOARD | ビルド時間 | 成果物(MB) | リポジトリ+成果物(MB) |
---|---|---|---|---|
e2-micro | bringup.x64 | N/A | N/A | |
e2-micro | core.x64 | N/A | N/A | |
e2-micro | terminal.x64 | N/A | N/A | |
e2-micro | workstation.x64 | N/A | N/A | |
e2-standard-8 | bringup.x64 | 41m 12s | 23,983 | 46,151 |
e2-standard-8 | core.x64 | 66m 34s | 41,620 | 63,771 |
e2-standard-8 | terminal.x64 | 81m 2s | 50,818 | 72.923 |
e2-standard-8 | workstation.x64 | 80m 54s | 56,334 | 78,428 |
(参考)自宅 | workstation.x64 | 512m 25s | - | - |
計測方法
time ( fx set bringup.x64 && fx build ) # ビルド時間
du -sm ./out # 成果物のサイズ
du -sm ./ # リポジトリ+成果物のサイズ
備考
-
e2-micro
ではメモリが足りずfx set
が終了するため、計測不能 -
試行回数は設定ごとに 1 回
terminal.x64
とworkstation.x64
がほぼ同じ時間なのは違和感があるが、大まかな時間がわかったので良しとする -
試行ごとに
rm -rf ./out
で成果物を削除した(キャッシュを使用しないため) -
./out 以下に成果物(中間成果物を含む)が生成される
今回は、必要な永続ディスクのサイズを確かめるために、全成果物のサイズを知りたい -
今回は費用削減のため、永続ディスクを
HDD
にしてる。割高なSSD
に変更するとより早くなるかもしれない -
自宅計測は、並行して別の作業をしていたので、その分遅くなっているはず
普段の環境でもビルドと並行して作業は行う。今回の趣旨(普段の自宅環境と GCE の比較)に沿っているため問題ない
(参考)e2-micro の結果
$ fx set bringup.x64
ERROR: error running gn gen: signal: killed
$ sudo dmesg | tail -n 3
[ 241.838718] Out of memory: Kill process 625 (gn) score 812 or sacrifice child
[ 241.847841] Killed process 625 (gn) total-vm:942816kB, anon-rss:818768kB, file-rss:0kB, shmem-rss:0kB
[ 241.881940] oom_reaper: reaped process 625 (gn), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
メモリが足りず、OOM(Out Of Memory)でプロセスが終了していました。
VSCode でソースコード編集
SSH 設定の準備
gcloud compute instances start instance-test
gcloud compute config-ssh
VSCode Remote SSH で使用する、~/.ssh/config
のホストを生成します。
- Q. 次回の VM 起動時に、外部 IP アドレス変わったときはどうなる?
A. VM 起動ごとに、gcloud compute config-ssh
を実行する。~/.ssh/config
の当該ホストの IP アドレスが更新される
VSCode Remote SSH
- コード編集は全く重くない、快適
Zircon カーネルデバッグ
QEMU と gdb で Zircon カーネルデバッグを行います。
準備
sudo apt install -y gdb
カーネルイメージのロード時にベースアドレスをランダム化する KASLR(Kernel Address Space Layout Randomization) の影響で、zircon.elf に記載のアドレスは GDB で使用できないです。
(2021 年 7 月時点でランダム化はまだされてないですが、zircon.elf に記載のアドレスとは異なるアドレス(決め打ち)にロードされるようには実装されています)
これを解決するために、zircon.elf-gdb.py
が必要です。
.gdbinit
に下記を追加します。
add-auto-load-safe-path /home/{ユーザ名}/fuchsia/out/default/kernel_x64/zircon.elf-gdb.py
修正パッチをプルリクエスト中です。
デバッグ
-
コンソール
@VMfx qemu -- -s -S
-s -S
オプションで gdb のアタッチを待ちます -
別のコンソール
@VM(e2-micro)cd out/default # デバッグ時ソースコード表示のために移動が必要 gdb ./kernel_x64/zircon.elf ... (gdb) target extended-remote :1234 # qemuにアタッチ (gdb) b lk_main (gdb) c
fx qemu
では、multiboot、physboot ブートローダと Zircon カーネルが動作します。
上記例では、zircon.elf のlk_main()
にブレークポイントをセットしています。
continue することで、multiboot、physboot の実行、カーネルのロード、_start
を実行し、lk_main()
で停止します
わかったこと
- GCE(e2-standard-8)は自宅に比べて、リポジトリ更新で 11 倍、ビルド時間で 6 倍、早い
- fuchsia のリポジトリ+成果物のサイズは、46GB〜78GB(ただし、PRODUCT.BOARD 依存)
システム領域と合わせても、永続ストレージは 100GB あれば足りる - 費用は
652 円/月
程度と予想
週 3 日(月 12 日)、5 時間/日(最小構成 3 時間、ビルド構成 2 時間)と仮定する。- e2-standard-8:318 円
- e2-standard-4 の場合:159 円
- 永続ディスク:308 円
- 外部 IP アドレス:26 円
- e2-standard-8:318 円
おわりに
GCE を使って、ローカルリポジトリ更新、ビルド時間が遅い問題を解決できました。
GCE のビルド時間は想像以上に高速でした。また、リモートでのソースコード編集・デバッグもまったく問題なかったです。
この用途では、自宅に高速なマシンは不要と言えそうです。
自宅で組み込み機器のデバッグをするさいには、GCE から成果物をダウンロードする必要があります。
「GCE → 自宅」向きの通信は課金対象なので、これも検討が必要です。
費用についてはe2-standard-8
と、安価(1.1 円/時)なe2-meduim
を組み合わせることで、さらに安くできそうです。
(ローカルリポジトリ更新後の 1 回のみ強力なe2-standard-8
でビルドし、ソースコード編集後は安価なe2-meduim
でビルドするなど)
付録
試行錯誤中に気づいたことです。
非プリエンプティブル → プリエンプティブルは可能だが、逆は不可能
-
非プリエンプティブル → プリエンプティブル
gcloud compute instances set-scheduling instance-test \ --preemptible \ --no-restart-on-failure \ --maintenance-policy=TERMINATE 成功
-
プリエンプティブル → 非プリエンプティブル
gcloud compute instances set-scheduling instance-test \ --restart-on-failure \ --maintenance-policy=MIGRATE 失敗
最小構成は無料枠(Always Free 枠)なので、割安になるが動作制限のかかるプリエンプティブルにはしない予定でした。
しかし、一度プリエンプティブルにすると、非プリエンプティブルに変更できなくなることから、最小構成時もプリエンプティブルにしました。
永続ディスクサイズ変更
ビルド成果物が確保したサイズで収まらないときに、ディスクサイズを大きくするために利用しました。
gcloud compute disks resize instance-test --size=100GB
ブート用の永続ディスクの名前instance-test
は、インスタンス名と同じ。
上記は 100GB にリサイズする例です。
検討時に、60GB→80GB→100GB と増やしていきました。
config-ssh は 対象インスタンスを可動させた状態で実行する
-
インスタンス停止中はエラー
# インスタンス停止中 $ gcloud compute config-ssh WARNING: No host aliases were added to your SSH configs because you do not have any running instances. Try running this command again after running some instances.
-
インスタンス起動中は成功
$ gcloud compute instances start instance-test $ gcloud compute config-ssh You should now be able to use ssh/scp with your instances. For example, try running: $ ssh instance-test.us-west1-b.{プロジェクト名}
scripts/gce/
リポジトリ中に、GCE で fuchsia を動作させるスクリプトを発見しました。
cd $FUCHSIA_ROOT
fx set core.x64 --release
fx build # ... 1
fx gce create-fuchsia-image # ... 2
fx gce create-instance # ... 3
sleep 60
fx gce serial # ... 4
fx gce delete-instance # ... 5
- ローカル環境でビルドを行う
- GCE で動作させる fuchsia のイメージファイルを作成
- VM を起動し fuchsia を動作
- (仮想的な)シリアル通信で接続する
- VM を削除
Discussion