フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

クラウドインスタンスでAndroid仮想デバイスを「ハードウェア仮想化付きで」動かす

みなさんこんにちは。エンジニアの佐藤です。今回はAndroid開発について書かせていただきたいと思います。と言っても、Androidアプリではなく、開発環境であるAndroid Studioについてです。

これまでの話

筆者は業務をしばしばVDI(仮想デスクトップ)環境で行なっています。
理由はネットワークの速度とリソースの柔軟性です。
VDIをホストするクラウドインスタンスは、ネットワークが速く、安定しています。オフィスの回線とは比較になりません。多量のデータを出し入れする仕事では、効率が上がります。また、CPU、メモリ、ストレージもその時の仕事に合わせて確保し、終わったら解放できますので、経済的です。

しかし、スマホ開発は別でした。これらの開発ではエミュレータを実行する必要があり、エミュレータは通常、ハードウェア仮想化機能を利用します。(仮想化オフでも動きますが、とてつもなく遅い。) 一方、クラウドインスタンスはそれ自体ハードウェア仮想化の中で動作しているため、ここでさらにハードウェア仮想化を利用するアプリを動かすことは、できなかったのです。

いえ、あるにはあったのですが、以下のような特別な仕掛けが必要でした。
Nested virtualization: How to run nested KVM on AWS or Google Cloud https://blogs.oracle.com/ravello/run-nested-kvm-on-aws-google

仕方がないので筆者は苦肉の策で、クラウドインスタンスAndroid Studioと、ローカル環境のエミュレータをつないだりしていました。

Android仮想デバイスとDocker開発環境をつなぐ http://blog.flect.co.jp/cloud/2017/04/androiddocker-c3b5.html

昨年ついにインスタンスで仮想化機能が提供に

しかし昨年、ついにクラウドインスタンスでもハードウェア仮想化が利用可能になりました。ありがたいことに、追加コストはかかりません。

AWSについては情報がありませんが、AzureとGCPでサポートが表明されました。

Introducing nested virtualization for Google Compute Engine. Thursday, September 28, 2017
https://cloudplatform.googleblog.com/2017/09/introducing-nested-virtualization-for.html

Nested Virtualization in Azure. Posted on July 13, 2017
https://azure.microsoft.com/en-us/blog/nested-virtualization-in-azure/

今回はこの機能を使って、GCPインスタンスで実行される仮想デスクトップ上でAndroid仮想デバイス(AVD)を「ハードウェア仮想化を使って」実行してみたいと思います。結論から言うと、この試みは目論見通りに成功しました。

手順

GCPインスタンスでハードウェア仮想化を有効にする手順は、以下の公式ドキュメントに書かれています。

Enabling Nested Virtualization for VM Instances https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances

手順はまず、ハードウェア仮想化を有効にした起動イメージを作成することから始まり、コマンドラインで実行する必要があります。この有効化、ライセンス付与という形態を取っていますが課金はありません。

gcloud compute images create nested-vm-imad
  --source-disk masashi-tw02  --source-disk-zone asia-east1-b \
  --licenses "https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx"

次にこの起動イメージでインスタンスをスタートします。このときプロセッサアーキテクチャにHaswellまたはSkylakeを指定します。

gcloud compute instances create example-nested-vm --zone asia-east1-b \
  --image nested-vm-image

このインスタンスSSHでログインして以下のコマンドを打って、「1」が返ることを確認します。

grep -cw vmx /proc/cpuinfo
1

これでハードウェア仮想化が有効になったはずです。Android Studioを実行してみましょう。

筆者は前出の「Docker開発環境」を使いました。ハードウェア仮想化とはつまりCPUの特別命令セットの使用のことですので、コンテナを特権モード(privileged=true)で動作させれば動作するのではないかと目論んでのことです。Android Studioを直接インストールするのではなく、インストール済みのコンテナをスタートさせました。

ハードウェア仮想化が、動いた!

Android Studioを起動したらAVD一覧を開き、AVDを追加します。この時 Select system image の所で「x86 images」の中から選択します。

f:id:masashi-sato-flect:20180714230243p:plain

こうして作成したAVDを起動すると。。。ありゃ、エラーです。

/dev/kvm のアクセス権が無いと言われてしまったので、このデバイスのオーナーをAVDの実行ユーザーに変えました。

sudo chown user1.user1 /dev/kvm

再度AVDを起動すると。。。動きました!この速度、確かにハードウェア仮想化の速さです。

f:id:masashi-sato-flect:20180714230430p:plain

試しにHello Worldを動かしてみると、ローカル環境同様に開発アプリがAVDにロードされました。

f:id:masashi-sato-flect:20180714230321p:plain

使えるの?

ようやく念願の「クラウド仮想デスクトップ+AVD」が実現したのですが、その性能はいかほどのものでしょうか。正直に言いますと、 「耐えられないほどではないが、かなり遅い」というのが筆者の正直な印象です。

ハードウェア仮想化を有効にしてもなお遅い理由として、仮想デスクトップなのでグラフィックのハードウェア支援が一切無いことが原因として考えられます。特にスマホアプリはアニメーションを多用し、通常は中間フレームはハードウェア支援で描画しますので、これを全部CPUでこなして、かつ、ネットワークで転送しなければならないというハンディが動作を遅くしていることは容易に想像できます。

ですが、全てのアプリケーションが常時激しいアニメーションを行うわけではないと思いますので、これは使い方次第なのではないでしょうか。

もう一つの問題として、AVDが多量のリソースを消費することがあります。図はAVDの実行中にtopコマンドでメモリ消費を調べたものですが、3GBを超えるメモリが使われています。

f:id:masashi-sato-flect:20180714230349p:plain

今時のスマホの性能を考えると仕方がないのかもしれませんが、しかし、この点についてはクラウドですし、メモリもCPUも時間買いできますので、必要なだけ確保すれば良いと思います。

ローカル環境と比べてメリットもあります。Android StudioもAVDも、初回インストール時のダウンロード容量がとにかく多く、オフィスや家庭の回線では非常に辛いものがあります。この点クラウドインスタンスのネットワークは高速でかつ安定しているので、なんでもサクサクダウンロードできてしまいます。 スタートアップまでの時間は、まちがいなくクラウドの方が速いでしょう。インストール済みコンテナやイメージを素早く展開できるという利点もあります。

今回の知見は、機会があればぜひ活用したいと思います。最後までお読みいただきありがとうございました。