GAE Standard Environmentの正体と未来を推測する

Google App Engine Standard Environment（昔からある方のGAE環境）で使われているコンテナ技術がBorgと呼ばれるGoogle独自の実装である、というのは既に公開情報になっています[^1]。一方で、その上でどんなバイナリが動くのか、どのlibcが採用されているか、などの情報は意外と表に出てきていません。今回その正体らしきものが見えた気がするので紹介します。

[^1]: たとえば 「[YAPC Asia 2015「Google Cloud Platformの謎テクノロジーを掘り下げる」のまとめ - Qiita](http://qiita.com/kazunori279/items/3ce0ba40e83c8cc6e580)」 など

## 推測：GAE Standard Environmentのサンドボックス環境はNaClである

根拠らしきものは後で示しますが、GAE Standard Environmentは普通のLinux環境ではなく、Google Native Client (NaCl)というGoogle独自のサンドボックス基盤の上で動いていると考えられます。

NaClは一般にはGoogle Chrome上でネイティブバイナリを動かすための技術として知られています。現在ではその後継となるPNaClや、さらにはasm.jsやWebAssemblyの登場によりNaCl自体は死に体のように見えるわけですが、実はブラウザとは全然違う場所で生き残っているとしたら面白い話ではないでしょうか。

## NaClの概要

NaClはサンドボックス環境一式を提供するもので、次のような構成要素で成り立っています。

- 検証可能なバイナリを出力するコンパイラツールチェイン (gcc, binutils, etc.)
- ユーザプログラムを検証して起動する service runtime
  - 同一プロセス内で動作
  - システムコールを提供
- service runtime と libc の間に安定した ABI を提供する integrated runtime
- newlib と glibc から選べる libc

（「[NaCl について - 兼雑記](http://shinh.hatenablog.com/entry/20131218/1387328729)」 より引用・一部追記）

要するに、NaClはコンパイル結果のアセンブリとランタイムと両方の組み合わせで安全性を保証するような仕組みになっています。逆に言うと、NaCl環境で動くバイナリを作るには専用のクロスコンパイル環境を準備する必要があるわけです。

## GAE/PHPの裏に見え隠れするNaClの影

筆者がGAEを使っていてNaClという単語を見つけたのは、GAE/PHP環境で `phpinfo()` の結果を眺めていたときでした。共有ライブラリのパスを指定する環境変数の中に「nacl」というキーワードが見えます。

<img width="512" alt="gae-php-env-vars.png" src="https://qiita-image-store.s3.amazonaws.com/0/46856/ba56d175-c7ae-23a3-105b-4ae38595f928.png">

また、GitHubのGCPアカウント以下にGAE用の修正が入ったPHPソースコードを見つけました[^2]。オリジナルのPHPとの差分を見ていると、やはり「nacl」とか「__native_client」などのキーワードが見つかります。

[^2]: https://github.com/GoogleCloudPlatform/appengine-php/

<img width="604" alt="php-src-nacl.png" src="https://qiita-image-store.s3.amazonaws.com/0/46856/b92d14ab-fdce-44af-a1f1-2fcb48dc0ca6.png">


他にも違和感のある点がありました。PHPは通常の環境では複数リクエストを受け付けるのに複数プロセスを起動するのが普通で、複数スレッドモデルで使うことは滅多にありません。しかし、GAE/PHP環境のPHPはスレッドセーフのビルドオプションが指定されているのです。

<img width="210" alt="gae-php-zts.png" src="https://qiita-image-store.s3.amazonaws.com/0/46856/b7b2deb0-3a5a-1c77-bff5-3325d365e1dd.png">

NaCl環境にはPOSIXスレッドサポートはあるものの、そもそもプロセスの概念が無いので、やや実績の少ないスレッドモデルでの実行を選択したのではないでしょうか。

このように、NaClの採用を仮定すると今まで疑問に感じていた内容と符合する点が多い印象です。証拠としては弱いのですが、個人的にはかなり確度が高そうだと感じています。

## GAE/Go環境ではx86_64バイナリが動いている気がする

一方、GAE/Goは普通のx86_64バイナリが動いているようです。GAE/Goのプロジェクトをデプロイするとデプロイディレクトリ以下に `_ah/exe` という実行ファイルが作られるのですが、これを読み出してreadelfで確認したところNaClのバイナリではなく普通のLinux用バイナリのようでした。

謎は深まるばかりですが、何らかの理由でGoだけはサンドボックス不要という判断があるのかもしれません。もしくは、そもそもPHPがNaCl上で動いているというのが嘘なのかもしれません。

## GAE Standard Environmentの未来

筆者の推測通りGAE StandardでNaClが採用されているとしたら、この環境自体に未来はあるのでしょうか。

NaCl自体はGoogle社内でも見捨てられた存在になりつつある印象です。PepperとNaClのチームは解散したという情報も見つかります[^3]。長い目で見れば死にゆく環境と考えて間違いはなさそうです。

[^3]: 「Pepper and NaCl are destaffed.」 (https://bugs.chromium.org/p/chromium/issues/detail?id=239656#c160 より)

とはいえGAE Standard Environmentは既存顧客も多いので、移行先なしに廃止というわけにもいかないでしょう。現状維持で当分残すというのが現実解なのではないでしょうか。

また、筆者の推測が正しいとすればStandard Environmentの対応言語の増加や既存言語のバージョンアップにはNaCl対応パッチが必要になり、それなりのコストを払う必要があります。その意味で、Python 3やPHP 7への対応もハードルが高い可能性がありそうです[^4]。新バージョンが必要ならFlexible Environmentに引っ越せ、という方針さえありうるかもしれません。

[^4]: C実装の変更量が大きければ大きいほど大変な作業だと思うので、現行のPHP 5.5からPHP 5.6への対応であればまだ現実的かもしれません。とはいえ、PHPユーザーとしてもそんな古いバージョンに今さら対応してもらっても全然嬉しくないですよね。

ただし、GAE上でも言語によってNaClのありなしが違っている可能性もあります。筆者はGoだけはNaClなし、その他3言語はNaClありで動いているのではないか？と推測しています。もしそうだとすれば、GAE/Go環境は当分メンテナンスされそうだ、という予測も成り立ちそうです。

Standard Environmentで他の言語のバージョンアップが長く止まっている中、Goだけは1.8へのバージョンアップの噂が聞こえてきているのもそうした理由があるのかもしれません。

以上、Google社外から妄想だらけの内容をお送りしました。

（2017/03/19 00:30追記）apstndbさんからコメント欄にて、現在GAE Standard EnvironmentのJava 8サポートがクローズドテストまで進んでいるという話を教えてもらいました。GoogleさんがStandard Environmentへの投資を続けているというのは大変良いニュースで、あまり悲観的になる必要は無いのかもしれません。

## 落穂拾い

GAE/PHP環境で `phpinfo()` を実行すると次のようなLinuxカーネルのバージョン表示が確認できます。

<img width="614" alt="gae-php-uname.png" src="https://qiita-image-store.s3.amazonaws.com/0/46856/e555a6ad-efbb-0ad6-837a-efc0806a7ac8.png">

これはuname(2)システムコールの結果をそのまま表示するもので、通常であれば動作環境のOSの情報が表示されます。つまり、この環境はx86_64 Linux環境なのかな？と思ってしまいます。

しかし、PHPのソースコードを確認するとunameシステムコールが失敗する環境ではビルド環境のunameの値が表示されるような実装になっています。つまり、これはGoogle社内のNaCl用クロスコンパイル環境の情報が表示されているだけ、という可能性も考えられるのです。

## 追記

NaClって単語を見つけて勢いで記事を書いてみたものの、chroot+cgroup+seccompを想定する方が普通な気もします。ただ、じゃあなんでPython 3とPHP 7対応しないの？という疑問を考えると、何かしら厄介な環境なんじゃないか、いくら要望を出されてもやりたくない理由があるんじゃないか、と思ったりしたわけです。

実際のところどうなんでしょうね…

## 参考URL

- [NaCl について - 兼雑記](http://shinh.hatenablog.com/entry/20131218/1387328729)
- [NaCl のメモリレイアウトについて - 兼雑記](http://shinh.hatenablog.com/entry/20140105/1388933650)