APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

GAE/Go1.9から1.11にマイグレーションしようとして躓いたところ

はじめに

先進サービス開発事業部の山岡です。

GAE/Goは1.6, 1,8, 1.9, 1.11, 1.12(beta)と随時新しいGolangバージョンに対応してきていますが、1.11からはGAEのバックエンドがgVisorベースの2nd Generationとなり大きな変更点が複数ありました。 *1 1.11ではまだ互換性を保っていますが、GAE付属のサービス(ex. Memcache, Search等々)は今後使えなくなるようなので今の内からどのような影響がありそうかを調べ把握しておく必要があるでしょう。

今回は実際に小規模なアプリを1.11にマイグレーションしようとしたら色々とトラブルが発生したのでその内容と対処法を書いておきます。

goappとappcfg.pyが使えない

今までGoogle Cloud SDKのGo拡張には goapp が付属されてきていましたが1.11からはこれを使用することができないので検証用のローカルサーバーは dev_appserver.py を使うようにしましょう(オプションは大体同じような雰囲気なので然程困らないと思います)。

また appcfg.py についても使用することができず、これを実行しようとすると RuntimeError: The runtime: 'go111' is only supported with gcloud. と怒られてしまいますので、デプロイは gcloud app deploy を使う必要があります。

なおappcfg.pyと違い普通にデプロイするといきなりトラフィックまで切り替わってしまうので、必要に応じて --no-promote を付けてデプロイまでで止めておきましょう。

app.yamlでのアクセス制御ができない

これまでは app.yamlhandler 内に login:requiredlogin:admin 等と書いておくことで特定のURLに対しGoogleアカウントベースのアクセス制御をかけることができ大変便利でした。しかしこれも2nd Genからは廃止となり、しかも完全な互換サービスは今の所無いようです。

どう対処するかはアプリ側の要件に依存するかと思いますが、今回は知らない人が入れなければそれでいい程度の要件であったためBasic認証をかけることで対処しました。

2019/07/01訂正: 1.11は1stGen扱いとなりこの制約は無くなりました。gVisorベースで動いてはいるものの基本的に1.9と互換性がある形に戻されました。

appengine.NewContext() でpanicが起こる

ローカルサーバーを起動した後にアクセスすると appengine: NewContext passed an unknown http.Request が発生する事象に見舞われました。

これに関しては原因は追求しきれなかったのですが google.golang.org/appengine のバージョンを1.0から1.5に更新してみたところ解決することができました。

ローカルと実環境でワーキングディレクトリの位置が変わる

ローカルサーバーで動作確認をした後でGAE実環境にアップロードしたところなぜかスタティックなファイルへのアクセスで no such file or directory が発生しました。

GCPUGのノウハウ集 *2 によるとローカルサーバーと実環境ではワーキングディレクトリの位置が異なるため発生する事象だそうです。

今回は go.modmain.go をプロジェクトルートに置くように配置して対処しました。下記のように形だけのものにしたので既存のコードにはほぼ影響ありません。

package main

import (
    "github.com/org/project/app"
)

func main() {
    app.Run()
}

デプロイにCloud Buildの権限が必要

CircleCIから gcloud app deploy をしたところ下記のようなエラーが発生しました。どうも裏側で透過的にCloud Buildを使用しているようで、それに関する権限が無いとデプロイに失敗します。サービスアカウントに Cloud Build Editor の権限を付与することで無事にデプロイできるようになりました。

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 0 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
ERROR: (gcloud.app.deploy) Error Response: [13] Permission to create cloud build is denied. 'Cloud Build Editor' role is required for the deployment: https://cloud.google.com/cloud-build/docs/securing-builds/configure-access-control#permissions.
make: *** [Makefile:15: deploy] Error 1
Exited with code 2

f:id:ryo-yamaoka:20190419173047p:plain
CircleCIに付与してある権限

終わりに

今回マイグレーションしたWebアプリは小規模なものでしたが、知らないと面倒なところが多かったです。

移行先サービスが完全ではないので2nd Genに今すぐ全面対応するのは辛い場合が多いと思いますが、後方互換性が確保されているGAE/Go1.11へは早めに移行しておきその後ゆっくりと1st GenのAPIから脱却していくのが良さそうです。