Fuchsia エミュレータを GCE で実行し、ローカルで画面表示する
はじめに
本記事は、「Fuchsia 開発環境を GCE 上に構築する」シリーズの一編です。
関連記事:
本記事では、Fuchsia エミュレータを GCE で実行し、ローカルで画面表示する方法を紹介します。
fx emu-remote
Fuchsia ではリモートでエミュレータを実行し、ローカルのブラウザで画面表示・操作できる仕組み fx emu-remote
があります。
プロトコルは WebRTC で、通信路は SSH のポートフォワーディングを利用します。
一連の流れは次の通りです。
- ローカルで Fuchsia のコード取得
fx emu-remote
コマンドのために必要 - GCE インスタンスで Fuchsia のコード取得
- ローカルから GCE インスタンスへ、ビルドとエミュレータ実行を指示
fx emu-remote --stream GCEインスタンス
→ GCE インスタンスでビルドfx build
、エミュレータ実行fx emu
- ローカルでブラウザ表示(WebRTC over SSH 経由)
事前準備
Fuchsia を GCE でビルドしてみた を参考に GCE インスタンス作成。
Fuchsia エミュレータを GCE のネストされた仮想化上で動かす を参考に GCE インスタンス上で KVM を有効にする。
ローカルですること
-
Fuchsia コードを取得
$ curl -s "https://fuchsia.googlesource.com/fuchsia/+/HEAD/scripts/bootstrap?format=TEXT" | base64 --decode | bash 環境変数 PATH の編集
- fx コマンドを使えるようにするため、PATH を編集
-
fuchsia/tools/devshell/emu-remote
を編集ssh_args=( - -6 # We want ipv6 binds for the port forwards. + # -6 # We want ipv6 binds for the port forwards. # Requests to the WebRTC service address locally go to the workstation. -L "${local_port}:localhost:${remote_port}" -o ExitOnForwardFailure=yes
- IPv6 を決め打ちで指定していたため、コメントアウトして無効にします
-
ビルド対象を指定
cd fuchsia/ fx set workstation.qemu-x64 --release
-
SSH コマンドで GCE インスタンスに接続できるようにする
gcloud compute instances start インスタンス名 gcloud compute config-ssh
-
~/.ssh/config
にエントリが作成されます -
今回のインスタンスでは外部 IP アドレスが毎回変わるので、起動ごとに
gcloud compute config-ssh
を実行します。インスタンス起動と
config-ssh
をまとめて実行する自作スクリプトを利用しています
-
リモート(GCE)ですること
-
Fuchsia コードを取得
cd ~/ curl -s "https://fuchsia.googlesource.com/fuchsia/+/HEAD/scripts/bootstrap?format=TEXT" | base64 --decode | bash 環境変数 PATH の編集
-
~/fuchsia
に配置 - fx コマンドを使えるようにするため、PATH を編集
-
-
パッケージのインストール
sudo apt install xvfb x11-xserver-utils
-
fx emu-remote
とfx emu
で使用するパッケージをインストール
-
-
KVM の準備
sudo usermod -a -G kvm ユーザ名
-
エミュレータからネットワークに接続したい場合(
fx emu
に-N
をつける場合)sudo ip tuntap add dev qemu mode tap user ユーザ名 && sudo ip link set qemu up
- インスタンス起動ごとに実行が必要です。~/.profile などに書いておくとよいかもしれません
実行
事前に GCE インスタンスを立ち上げて、gcloud compute config-ssh
を実行しておきます。
作業はローカルでのみ行います。
fx emu-remote --stream --no-open --no-turn instance-test.us-west1-b.gce-fuchsia ~/fuchsia -- -N -p touch
-
--stream
- リモートでエミュレータを起動する場合に指定する
- このオプションを指定しない場合、リモートでビルドした成果物をローカルにコピーし、ローカルでエミュレータを起動する。
emu-remote
という名前なんだから、デフォルトで--stream
を指定した動作をしてほしい・・・
-
--no-open
- 手動でブラウザを立ち上げる場合に指定する
- このオプションを指定しない場合、エミュレータ起動を 1 秒おきに監視し、起動確認後、自動的にブラウザを立ち上げようとする。
画面出力が煩わしいので、無効にしている
-
-- -N -p touch
-
--
以降は、fx emu
へ渡すオプション -
-N
エミュレータからネットワークにアクセスするときに必要(ネットワークを使わない場合は不要) -
-p touch
入力デバイスにマウスではなくタッチパネルを使用する。ブラウザから操作するには、これが必要
-
参考:
備考:
-
実際の用途
- ビルドは GCE に SSH ログインして手動で行う
- エミュレータ起動は、
fx emu-remote --no-build ...
として、ビルドなしで起動させる
-
--no-turn
は、TURN サーバーを使用しない場合に指定する今回は SSH トンネル経由でブラウザから直接、エミュレータに接続するので(NAT 越えしないので)TURN サーバーは不要と考えたが、
--no-turn
を指定すると、ブラウザで画面を開くことができなかった
ブラウザで開く
https://web-femu.appspot.com/?port=8080
をブラウザで開きます。
-
web-femu.appspot.com
が WebRTC クライアントだと思います - ローカルホストのポート 8080 を使用します
- ローカルホストのポート 8080 は、GCE のポート 8080(
fx emu
が使用するポート)に SSH トンネルで接続します
- ローカルホストのポート 8080 は、GCE のポート 8080(
ネットワーク転送量と費用
30 秒間、画面を操作しない場合
$ date && ss -tni 'dport == 8080'
Wed 22 Dec 2021 04:10:05 PM JST
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 [::1]:37200 [::1]:8080
cubic wscale:7,7 rto:201 rtt:0.123/0.081 ato:40 mss:32768 pmtu:65536 rcvmss:542 advmss:65464 cwnd:10 bytes_sent:133229 bytes_acked:133230 bytes_received:98051 segs_out:209 segs_in:340 data_segs_out:168 data_segs_in:171 send 21312.5Mbps lastsnd:1359 lastrcv:1377 lastack:1359 pacing_rate 42495.5Mbps delivery_rate 8192.0Mbps delivered:169 app_limited busy:343ms rcv_rtt:480385 rcv_space:66217 rcv_ssthresh:129432 minrtt:0.032
$ date && ss -tni 'dport == 8080'
Wed 22 Dec 2021 04:10:35 PM JST
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 [::1]:37200 [::1]:8080
cubic wscale:7,7 rto:201 rtt:0.113/0.03 ato:40 mss:32768 pmtu:65536 rcvmss:542 advmss:65464 cwnd:10 bytes_sent:137094 bytes_acked:137095 bytes_received:100761 segs_out:214 segs_in:350 data_segs_out:173 data_segs_in:176 send 23198.6Mbps lastsnd:4012 lastrcv:4040 lastack:4012 pacing_rate 46091.3Mbps delivery_rate 8192.0Mbps delivered:174 app_limited busy:343ms rcv_rtt:480385 rcv_space:66217 rcv_ssthresh:134852 minrtt:0.032
開始時(バイト) | 終了時(バイト) | 転送量(バイト) |
---|---|---|
98,051 | 100,761 | 2,710 |
- bytes_recieved フィールドを参照
- 2,710 B / 30 sec
30 秒間、連続して画面を操作する場合
$ date && ss -tni 'dport == 8080'
Wed 22 Dec 2021 04:13:08 PM JST
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 [::1]:37200 [::1]:8080
cubic wscale:7,7 rto:201 rtt:0.075/0.021 ato:40 mss:32768 pmtu:65536 rcvmss:542 advmss:65464 cwnd:10 bytes_sent:160284 bytes_acked:160285 bytes_received:117021 segs_out:246 segs_in:412 data_segs_out:203 data_segs_in:208 send 34952.5Mbps lastsnd:1062 lastrcv:1108 lastack:1062 pacing_rate 69327.3Mbps delivery_rate 8192.0Mbps delivered:204 app_limited busy:346ms rcv_rtt:480385 rcv_space:66217 rcv_ssthresh:167372 minrtt:0.032
$ date && ss -tni 'dport == 8080'
Wed 22 Dec 2021 04:13:39 PM JST
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 [::1]:37200 [::1]:8080
cubic wscale:7,7 rto:201 rtt:0.076/0.011 ato:40 mss:32768 pmtu:65536 rcvmss:542 advmss:65464 cwnd:10 bytes_sent:164922 bytes_acked:164923 bytes_received:120273 segs_out:253 segs_in:424 data_segs_out:209 data_segs_in:214 send 34492.6Mbps lastsnd:275 lastrcv:404 lastack:275 pacing_rate 68311.1Mbps delivery_rate 8192.0Mbps delivered:210 app_limited busy:346ms rcv_rtt:480385 rcv_space:66217 rcv_ssthresh:173876 minrtt:0.032
操作前(バイト) | 操作後(バイト) | 転送量(バイト) |
---|---|---|
117,021 | 120,273 | 3,252 |
- bytes_recieved フィールドを参照
- 3,252 B / 31 sec
ネットワーク転送量
以上より、30 秒の画面転送で約 3 KB かかると想定します。
-
3 KB / 30 sec
=6 KB / min
=360 KB / hour
GCE ネットワーク費用
月間使用量が 0 ~ 1 TB の場合 0.12 ドル/GB、1 ドル 110 円で約 13.2 円/GB。
— インターネット下り料金 | Google Cloud
1 時間、fx emu-remote
画面を転送する場合、4.752 円。
(0.12 * 110 * 360 / 1000 = 4.752)
付録
fx emu-remote の動作詳細
fx emu-remote --stream --no-open instance-test.us-west1-b.gce-fuchsia ~/fuchsia -- -N -p touch
実行時の主要な動作です。
-
GCE に SSH でログインし、ビルドを行う
ssh instance-test.us-west1-b.gce-fuchsia \ -S "~/.ssh/control-fuchsia-fx-remote" \ -o ControlMaster=auto \ "cd ~/fuchsia && ./.jiri_root/bin/fx build multiboot.bin fuchsia.zbi obj/build/images/fvm.blk"
-
ローカルホストのポート 8080 からリモートホストのポート 8080 へトンネルを掘ります。
fx emu
でエミュレータを起動しますssh instance-test.us-west1-b.gce-fuchsia \ -S "~/.ssh/control-fuchsia-fx-remote" \ -o ControlMaster=auto -L 8080:localhost:8080 \ -o ExitOnForwardFailure=yes \ "cd ~/fuchsia && xvfb-run ./.jiri_root/bin/fx emu -x 8080 -t \"curl -s -X POST https://networktraversal.googleapis.com/v1alpha/iceconfig?key=...\" -N -p touch"
- エミュレータの画面は Xvfb に出力
- エミュレータはポート 8080 で WebRTC を待ち受け
- curl は、TURN サーバーの設定に使用
ソースコード:emu-remote - Fuchsia
Discussion