nouhau icon indicating copy to clipboard operation
nouhau copied to clipboard

App Engine Standard Go 1.9 migration to Go 1.11 の知見

Open sinmetal opened this issue 5 years ago • 12 comments

WHAT

App Engine Standard Go 1.9 migration to Go 1.11の知見を集約していく このissueにそのまま書いてもよいし、やった時に書いたBlogなどへのLinkでもよい

  • 移行時にやったこと
  • 移行時にはまったことや解決策, ワークアラウンド

WHY

App Engine Standardにはたくさんの機能が存在していて、開発環境なども絡むと結構ややこしいので、色んな人のケースを集めてみよう。

Refs

sinmetal avatar Jul 01 '19 08:07 sinmetal

https://speakerdeck.com/emahiro/go-conference-2019-spring-go1-dot-9-to-go1-dot-11

emahiro avatar Jul 01 '19 09:07 emahiro

https://techblog.ap-com.co.jp/entry/2019/04/19/174903

ryo-yamaoka avatar Jul 01 '19 09:07 ryo-yamaoka

ドキュメント読んでて気づかなかったのでシェアします。

Go1.11ランタイムではAppEngineTokenSourceをつかっていると怒られました。

2019/07/01 10:45:54 google: AppEngineTokenSource is deprecated on App Engine standard second generation runtimes (>= Go 1.11) and App Engine flexible. Please use DefaultTokenSource or ComputeTokenSource.

そうしないとGCP APIが叩けません。

oauth2/google: can't get a token from the metadata service; not running on GCE

KeisukeYamashita avatar Jul 01 '19 11:07 KeisukeYamashita

AppEngineTokenSource が deprecated なのは事実として、 ComputeTokenSource に delegate しているはずなので動かないとしたら golang.org/x/oauth2 のバグのような気もしますね。

https://godoc.org/golang.org/x/oauth2/google#AppEngineTokenSource

Second generation App Engine runtimes (>= Go 1.11) and App Engine flexible: AppEngineTokenSource is DEPRECATED on second generation runtimes and on the flexible environment. It delegates to ComputeTokenSource, and the provided context and scopes are not used. Please use DefaultTokenSource (or ComputeTokenSource, which DefaultTokenSource will use in this case) instead.

https://github.com/golang/oauth2/blob/master/google/appengine_gen2_flex.go#L21

apstndb avatar Jul 01 '19 11:07 apstndb

2018年11月時点で動くようには書かれているはずなので、動かなかった条件が少し知りたいところですね。 aetest とか dev_appserver.py で動かないのは間違いないと思います。 https://github.com/golang/oauth2/pull/341

apstndb avatar Jul 01 '19 11:07 apstndb

oauth2/google: can't get a token from the metadata service; not running on GCE

これはAppEngineTokenSourceにしていたときにエラーが出たもので、DefaultTokenSourceにするとすんなり解決したためComputeTokenSourceは試していません。

2019/07/01 10:45:54 google: AppEngineTokenSource is deprecated on App Engine standard second generation runtimes (>= Go 1.11)

ここはGo1.11はsecond generation runtimes扱いなんだとびっくりしましたw

KeisukeYamashita avatar Jul 02 '19 06:07 KeisukeYamashita

試しに google.AppEngineTokenSource を使ったものを App Engine Go 1.11 にデプロイしてみたところAppEngineTokenSource is deprecated のログは出力されたものの動いたので、動かないというのはやはり何か前提条件がおかしい気がしますね。

oauth2/google: can't get a token from the metadata service; not running on GCE

が出ているということは、デプロイ先がおかしい OR デプロイしないローカル環境での結果ではないでしょうか。 下は実際に動かしてみたもの。

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/appengine"
)
func main() {
	http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
		tokenSource := google.AppEngineTokenSource(r.Context())
		client := oauth2.NewClient(r.Context(), tokenSource)
		resp, err := client.Get(fmt.Sprintf(`https://appengine.googleapis.com/v1/apps/%s/services`, os.Getenv("GOOGLE_CLOUD_PROJECT")))
		if err != nil {
			http.Error(rw, err.Error(), http.StatusInternalServerError)
			return
		}
		defer resp.Body.Close()
		io.Copy(rw, resp.Body)
	})
	appengine.Main()
}
runtime: go111
service: go111-tokensource

apstndb avatar Jul 02 '19 08:07 apstndb

移行時にはまったことや解決策, ワークアラウンド

  • ソースコードはGitHubのprivate repoで管理している
  • デプロイするアプリケーションは社内で開発しているprivate repoにあるライブラリに依存している
  • Go1.11ランタイムを使用し、ローカルではGo Moduleによる依存関係解決をしている

ような場合、そのままgcloud app deployしてしまうとGAEのapp_builderさんがCloudBuildマシンから認証が必要なGitHubリポジトリにアクセスしようとしてビルド出来ないので、デプロイ前に小細工が必要でした

具体的には

go mod vendor
mv ./go.mod ./go.mod.temp
mv ./go.sum ./go.sum.temp
gcloud app deploy

のように、vendorフォルダを作った後、go.modファイルをリネームするなり何なりしてやる必要があります go111ランタイムの初期の頃はgcloud app deployする際に環境変数GO111MODULEが参照されているような挙動だったのですが、いつからかgo.modファイルがあるかどうかでGo Moduleを使うかどうかが変わるようになりました

nanasi880 avatar Jul 04 '19 08:07 nanasi880

実は go mod vendor については Cloud Functions のドキュメントの方が詳しくて、 go.mod を無視するために .gcloudignore が使えることも書いてあったりしますね。こちらに挙動が合わせられている様子。 https://cloud.google.com/functions/docs/writing/specifying-dependencies-go?hl=en#using_a_vendor_directory

apstndb avatar Jul 04 '19 09:07 apstndb

https://github.com/gcpug/nouhau/tree/master/app-engine/note/gaego111-private-repo-deploy も合わせてどうぞ!

sinmetal avatar Jul 04 '19 09:07 sinmetal

誘導ありがとうございます 今は.gcloudignoreでちゃんと間引けるようになってるんですね :)

nanasi880 avatar Jul 05 '19 03:07 nanasi880

dev_appserver.pyにbug。

handlers:

- url: /hello
  script: auto

- url: /(.+)
  static_files: static/\1
  upload: static/.*

上記の様に scriptハンドラを上書きするURLパターンのstatic_filesハンドラがあると、scriptハンドラが処理されず404エラーとなる。 (dev_appserverはgo1.11の場合にscriptハンドラを全て無視してデフォルトハンドラで処理している為)

プロダクションでは問題なし。

↓issue https://issuetracker.google.com/issues/128170900

hogedigo avatar Jul 05 '19 06:07 hogedigo