GithubHelp home page GithubHelp logo

gcpug / nouhau Goto Github PK

View Code? Open in Web Editor NEW
654.0 654.0 23.0 13.65 MB

Google Cloud Platformのノウハウを共有するRepository

Home Page: https://gcpug.jp

License: MIT License

Go 100.00%
google-cloud-platform

nouhau's People

Contributors

apstndb avatar flatfisher avatar knsh14 avatar orfeon avatar sfujiwara avatar sinmetal avatar takanakahiko avatar tenntenn avatar tomgithubn avatar veysond avatar vvakame avatar yoichiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nouhau's Issues

ワイルドカード テーブルを使用した複数テーブルの照会時に、スキーマの差異をどうするか?

課題

https://cloud.google.com/bigquery/docs/querying-wildcard-tables 利用時に対象のtableでschemaに差異がある場合、queryが失敗するので、どうにかしたい。
どのtableが欠けているのかも分からないので、結構厳しい。

対処する案

すんなり解決するのは難しい。
いくつかの案を記すが、根性が必要。

案1

対象のcolumnがstructの場合はUDFでstructの中の欠けた値にデフォルト値を入れることで解決できるかもしれない。

案2

tableのschemaをAPIで調べて、欠けているtableを調べて、欠けているtableはviewを作るなどして、対処する。

Google App Engine / Cloud Functions のアーキテクチャについて公開情報を集めるスレ

新しい GAE/SE の素性が明らかになってきたので、分かっていることを書いていく。

API Client Library for GoでStandardSQLを実行する

UseLegacySql bool json:"useLegacySql,omitempty"`` なので、 false を設定しても省略されてリクエストに乗らない。
そのため、 `ForceSendFields: []string{"UseLegacySql"},` を設定して、必ず `UseLegacySql` を投げてもらうように設定する。

        job, err := bq.Jobs.Insert(form.ProjectID, &bigquery.Job{
		Configuration: &bigquery.JobConfiguration{
			Query: &bigquery.JobConfigurationQuery{
				Query:    form.Query,
				Priority: "Batch",
				DefaultDataset: &bigquery.DatasetReference{
					ProjectId: form.DstProjectID,
					DatasetId: form.DstDatasetID,
				},
				AllowLargeResults: true,
				CreateDisposition: "CreateIfNeeded",
				DestinationTable: &bigquery.TableReference{
					ProjectId: form.DstProjectID,
					DatasetId: form.DstDatasetID,
					TableId:   form.DstTableID,
				},
				TimePartitioning: &bigquery.TimePartitioning{
					Type: "DAY",
				},
				UseLegacySql:    false,
				ForceSendFields: []string{"UseLegacySql"},
			},
		},
	}).Do()
	if err != nil {
		log.Errorf(ctx, "Failed to insert query job: %v", err)
		return nil, err
	}

Cloud SchedulerからCloud SpannerのInsntaceのNodeCountを操作する

以下の記事でCloud SchedulerからGCPのAPIを直接操作するというのが出ている。
サンプルとしてはCompute EngineのManaged Instance GroupのSizeを変えている。

https://medium.com/google-cloud/automatic-oauth2-using-cloud-scheduler-and-tasks-to-call-google-apis-55f0a8905baf

Cloud Spannerでもなんとなくやってみようかなという気持ちになったので、やってみた。

NodeCountの変更は https://cloud.google.com/spanner/docs/reference/rest/v1/projects.instances/patch を利用して行うので、 https://developers.google.com/apis-explorer/#search/spanner.instances.update/m/spanner/v1/spanner.projects.instances.patch?name=projects%252Fhoge%252Finstances%252Ffuga&_h=3&resource=%257B%250A++%2522instance%2522%253A+%250A++%257B%250A++++%2522nodeCount%2522%253A+3%250A++%257D%252C%250A++%2522fieldMask%2522%253A+%2522nodeCount%2522%250A%257D& みたいなリクエストを送ることになる。

Cloud Scheduler用のService Accountを作成し、以下のようなコマンドを実行すればいいはず。

gcloud beta scheduler jobs update http migtest  --schedule "5 * * * *" --http-method=PATCH \
  --uri="https://spanner.googleapis.com/v1/projects/hoge/instances/fuga"  --oauth-service-account-email=cloud-scheduler@hoge.iam.gserviceaccount.com    \
  --message-body='{"instance": {"nodeCount": 2},"fieldMask": "nodeCount"}' \
  --headers=Content-Type=application/json \
  --oauth-token-scope=https://www.googleapis.com/auth/cloud-platform

しかし、このコマンドはエラーになる。
エラーは Valid choices are [delete, get, head, post, put]. で、Cloud Scheduler HTTPがPATCHに対応してないので、発生するエラー。
PATCH対応については https://issuetracker.google.com/issues/118662028 でリクエストされている。

なので、とりあえず X-HTTP-Method-Override https://cloud.google.com/apis/docs/http?hl=en#long_request_urls でPATCHに上書きする!

gcloud beta scheduler jobs update http migtest  --schedule "5 * * * *" --http-method=POST \
  --uri="https://spanner.googleapis.com/v1/projects/hoge/instances/fuga"  --oauth-service-account-email=cloud-scheduler@hoge.iam.gserviceaccount.com    \
  --message-body='{"instance": {"nodeCount": 1},"fieldMask": "nodeCount"}' \
  --headers=Content-Type=application/json,X-HTTP-Method-Override=PATCH \
  --oauth-token-scope=https://www.googleapis.com/auth/cloud-platform

これでCloud SchedulerだけでNodeCountを変更できる。
エラーとかのハンドリングが何もできないので、実用的かどうかは何とも言い難い。

以下の内容は @apstndb さんに教えてもらいました!

App Engine for Goでインスタンス起動時に一度だけ行う処理のサンプルを作成

あると嬉しいサンプル

インスタンス起動時に、DatastoreやCloud Storageなどにアクセスし、設定値を持ってくるようなサンプル。

参考資料

https://www.slideshare.net/takuyaueda967/gaegosync

なにが難しそう?

  • まだ、実行されていない時に呼び出したgoroutineが待ってる状態になるのが難しい?
  • 初期化が失敗した時に、再度初期化を実行するのが難しい?

BigQueryでRECORDフィールドのうち特定のフィールドのみ変更するSQLの書き方

WHAT

BigQueryでRECORDフィールドの中の一部を最小限の記述で置き換え・削除できるSQLの書き方。

WHY

Google AnalyticsやStackDriver loggigのexportテーブルなどで、ネストされたフィールド(RECORDフィールド)のうち一部だけを置き換えたり削除して新しいテーブルを作りたい場合がある。

だが現状、入れ子となるレコードの一部フィールドだけを直接書き換えるSQLは作れないため、該当RECORDフィールドを外してSTRUCTで作り直すSQLを作る必要がある。
(例: SELECT * EXCEPT(record), STRUCT(f1, f2, f3 + 1 AS f3) AS record FROM xxx.xxx)

RECORDフィールドが大量の子フィールドを持っていた場合、STRUCT内部で並べるフィールドが多すぎてSQLの保守性が悪化する。
(例: SELECT * EXCEPT(record), STRUCT(f1, f2, f3, f4,,,,,, f100 + 1 AS f100) AS record FROM xxx.xxx)

大量の子フィールドをもつRECORDでも一部置き換えをシンプルな記述で書く方法が知りたい。

bq queryでGoogle Driveのファイルを読み込む時の認証方法

bq queryで Google Driveのファイルに対して、Queryを実行する 時に認証を少し工夫する必要がある。

単純に以下のようにコマンドを実行するとGoogle DriveのScopeが無いと言われる。
単純にgcloud auth loginした場合は、GCPのScopeをFullで取得しているだけなので、G Suite系のScopeを持っていないからだ。

$ bq query --nouse_legacy_sql 'SELECT * FROM `gcpug.google_drive.sheet`'

Access Denied: BigQuery BigQuery: No OAuth token with Google Drive scope was found.

解決策

一度tokenをrevokeした後、 --enable-gdrive-access を付けて、gcloud auth loginをすれば、Google DriveのScopeを含んで、ログインできる。

$ gcloud auth revoke
$ gcloud auth login --enable-gdrive-access

この時、先に gcloud auth revoke しないと、 以下のエラーになるので、注意

BigQuery: No OAuth token with Google Drive scope was found.

AEDatastoreとCloudDatastoreでSaveStructの挙動に違いがある

https://gcpug.slack.com/archives/C2J8XMRKL/p1509346656000074

type Inner struct {
    A string
    B string
}

type Data struct {
    Slice []Inner
}

みたいな構造をPropertyListにした時、違う結果になる。
Sliceの長さを3とした時

  • AEDatastoreでは3要素×2プロパティ=6プロパティに変換される(Multipleというフィールドがある
  • CloudDatastoreでは1要素(Sliceプロパティ) in 3要素(Sliceの長さ) in 2要素(A, Bプロパティ) というネストされた構造になる

検索の仕方は両方 Slice.A とかなので、実用上の違いはないかもしれない…?
BigQueryにexportした時のスキーマ構成とかに影響があるかな…?くらい(未検証

Google App Engine Standard for Go のProject構成

WHAT

Google App Engine Standard for Go のProject構成のExampleをまとめる。Deploy時におらおら、GOPATHとかをshellで変更したりする流派もあった気がする。

  • GOPATH
  • Dir構成

Refs

WHY

いくつかの流派が存在して、ちょいちょい話題になるため。
Go1.11ではgVisor化とGo 1.11 Modulesが入ってくるので、変わるかもしれない。

Google Cloud Next 2018 まとめ

Blog

Google Cloud Platform Blog

GOOGLE CLOUD BIG DATA AND MACHINE LEARNING BLOG

G Suite

Google Cloud Platform Japan Blog

Release

Cloud Service Platform

GKE On-Pre

Istio Integration

Knative

Serverless add-on for Google Kubernetes Engine

Cloud Functions

Cloud Firestore

Cloud Datastore

Automatic upgrade to Cloud Firestore in Datastore mode

Some time after Cloud Firestore is released for general availability, we will begin contacting owners of existing Cloud Datastore databases to schedule an automatic upgrade to Cloud Firestore in Datastore mode.
If you have an application that uses Cloud Datastore, you will not need to update your application code and we will notify you about the schedule of your application's upgrade to Datastore Mode.
The upgrade will not require downtime.

Cloud Bigtable

Cloud Spanner

  • Import/Export
  • DML (Coming Soon)
  • Query Stats (Coming Soon)

Cloud Dataflow

BigQuery

Querying Clustered Tables

BQML

BigQuery GIS

Auto ML

Vision, Natural Language (日本語はたぶんまだ), Translation (日本語はたぶんまだ?)がBetaで登場した。
試すには、ProjectのAuto ML APIをEnableにした後、ドキュメントのQuick StartとかにあるLinkからConsoleに行く

https://cloud.google.com/automl/?hl=en

Auto ML モデルのダウンロードに関するQA

@sfujiwara がMeetUpで聞いてきた。

Q AutoMLでモデルをダウンロードしたい
A 時期は未定だが、できるようにする予定
Q ダウンロードできないのは TensorFlow のグラフからネットワークがバレるとまずいから?
A yes

Vision API

https://cloud.google.com/vision/docs/beta?hl=en

Edge TPU

https://cloud.google.com/edge-tpu/

Cloud Build

EAP Request Form

VersioningとLifecycleを同時に設定した場合の挙動

Q

BucketにVersioning=enable, Lifecycle:DELETEを指定した場合、DELETEは過去Versionも含めて削除するのか?

A

削除する。

そのため、オペミス対策でVersioning=enableを設定し、料金節約のためにLifecycle:DELETEを設定すると、意図通りに動く。

DataflowがGCSに途中ファイルを書き出す注意点

WHAT

DataflowのTextIOが途中ファイルを出力する際の注意点をまとめる。

WHY

DataflowでTextIOを使うと途中ファイルを書き出して最後にまとめる挙動をしている。
そのために一見関係ないことで悪影響を及ぼすことがあるのでそうした影響をまとめる。
(凍結したGCSに途中ファイルを書き出して削除しようとしてJobが失敗するなど)

CircleCI 2.0 で Google Cloud * Emulator を使う

Cloud PubSub を使ったソフトウェアの CI を Circle CI 2.0 上で Google Cloud Pub/Sub Emulator でテストしたくなることがある。
emulator を Secondary Container として動かすことでわりとうまく行ったので共有する。
ここでは pubsub-emulator を使ったが、 cloud-datastore-emulator などの他のエミュレータでも同様にできるはず。

emulator が立ち上がる前にテストが始まると fail してしまうが sleep の時間を決めるのは大変なので jwilder/dockerize で待つようにしている。

version: 2
jobs:
  test:
    docker:
      - image: google/cloud-sdk:174.0.0
      - image: google/cloud-sdk:174.0.0
        command: [gcloud, beta, emulators, pubsub, start, '--host-port=localhost:8085']
    environment:
       PUBSUB_EMULATOR_HOST: localhost:8085
    steps:
      # 省略
      - run:
          name: install dockerize
          command: curl -sfL https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz | tar -C /usr/local/bin -xzv
          environment:
            DOCKERIZE_VERSION: v0.3.0
      - run:
          name: Wait for pubsub emulator
          command: dockerize -wait tcp://${PUBSUB_EMULATOR_HOST} -timeout 1m
      - run:
          name: goapp test
          command: goapp test ${PKG}

cloud.google.com/go/spanner v0.18.0 はBuildが通らない

問題

https://github.com/GoogleCloudPlatform/google-cloud-go のspannerをv0.18.0で利用しようとすると、Buildが通らない

vendor/cloud.google.com/go/spanner/go18.go:36:2: too many arguments to return
	have ("context".Context, *"github.com/sinmetal/gcp_playground/vendor/go.opencensus.io/trace".Span)
	want ("context".Context)
vendor/cloud.google.com/go/spanner/go18.go:44:2: undefined: "github.com/sinmetal/gcp_playground/vendor/go.opencensus.io/trace".EndSpan

原因

v0.18.0 で入った Added OpenCensus support. で利用している https://github.com/census-instrumentation/opencensus-go のversionが噛み合わなくてBuildが通らない

該当箇所

https://github.com/GoogleCloudPlatform/google-cloud-go/blob/06da8ec9c2e2f6e11a89d644bbedf2e3e040bcd7/spanner/go18.go#L36go.opencensus.io/trace.StartSpann の戻り値が2つ返ってくるのがおそらく正しいが、 https://github.com/GoogleCloudPlatform/google-cloud-go/blob/767c40d6a2e058483c25fa193e963a22da17236d/spanner/go18.go#L36 は1つしか受け取ってないので、死ぬ

解決策

v.17.0 を利用するか master を利用する

Google App Engine for Go v1.6を使い続ける方法

Google Cloud SDK 177.0.0 (2017-10-25)

Go 1.8 is now generally available and the default Go runtime.
https://cloud.google.com/sdk/docs/release-notes?hl=en#17700_2017-10-25

Go 1.8がGAになったことにより、 app.yamlapi_version: go1 を指定した場合 Go 1.8が使われるようになった。
1.6を使いたい場合は、以下のように明示的に設定する必要がある。

runtime: go
api_version: go1.6

Go 1.8に上げるための道のりについては #5 を参照!

Google App Engine Go 1.11で "google.golang.org/appengine" を利用する場合、必ず appengine.Main() を呼ぶ必要がある

WHAT

Go 1.11の最もシンプルな公式のサンプルでは、 google.golang.org/appengine は使っておらず、 http.ListenAndServe を普通に使っている。

https://github.com/GoogleCloudPlatform/golang-samples/blob/28db7057e0a97a7b724da148177e4bc3a48e294f/appengine/go11x/helloworld/helloworld.go#L21

google.golang.org/appengine packageを使わない場合、上記でも問題なく動作するが、 google.golang.org/appengine packageを利用して、DatastoreやMemcacheなどを利用する場合、最初に必ず appengine.Main() を呼ぶ必要がある。

package main

import (
	"net/http"

	"google.golang.org/appengine"
)

func main() {
	http.HandleFunc("/", handler)

	appengine.Main()
}

appengine.Main() を呼んでいない場合、DatastoreやMemcacheを利用する時に not an App Engine context でエラーとなる。

WHY

appengine.Main() の中でHTTP Handlerをセットする時に、appengine.Contextを設定するようになっている。 https://github.com/golang/appengine/blob/ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06/internal/api.go#L93

ドキュメント的には https://cloud.google.com/appengine/docs/standard/go111/go-differences#writing_a_main_packageOr, if your service is using the google.golang.org/appengine package, include a call to appengine.Main(). と書いてある。

Stackdriver Traceを強制的に出力する

WHAT

Stackdriver Traceを強制的に出力する方法

Google App Engine

App Engineの場合はリクエストヘッダーに "X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE" を追加することで、そのリクエストを強制的にトレースできる。

各値の説明とcurlのサンプルは以下の通り。

  • TRACE_ID は、128 ビットの番号を表す 32 文字の 16 進数値です。リクエストを束ねるつもりがないのであれば、リクエスト間で一意の値にする必要があります。これには UUID を使用できます。

  • SPAN_ID は、(符号なしの)スパン ID の 10 進表現です。トレースの最初のスパンでは 0 にする必要があります。後続のリクエストでは、SPAN_ID を親リクエストのスパン ID に設定します。ネストしたトレースについて詳しくは、TraceSpan(REST、RPC)の説明をご覧ください。

  • このリクエストをトレースするには、TRACE_TRUE を 1 に設定する必要があります。リクエストをトレースしない場合は 0 を指定します。

curl "http://www.example.com" --header "X-Cloud-Trace-Context:105445aa7843bc8bf206b120001000/0;o=1"

Refs

Client Library

TraceのStartSpan時にサンプリングの設定を追加できる。 Goの場合は https://godoc.org/go.opencensus.io/trace#AlwaysSample を設定すれば、必ず出力される。

ctx, span := trace.StartSpan(ctx, "/process", trace.WithSampler(trace.AlwaysSample()))
defer span.End()

WHY

  • サンプリングしてTraceに出力されるので、リクエストの間隔が長いと、全然出力されないことがある。
  • 10sec毎にループで回してたりすると、ほぼ出てこない。
  • 開発環境は自分でたくさんリクエストを起こすのがめんどい。

Cloud Datastore Import/Export Example

Exportした内容を別のGCP ProjectにImportしようとすると、地味にハマる

IAM

https://cloud.google.com/datastore/docs/export-import-entities?hl=en#permissions

だいたいドキュメントに書いてあるとおりだが、Importを実行しているのは {projectid}@appspot.gserviceaccount.com のようなので、こいつをRoleを割り当ててやる必要がある。

Kind指定

うまいやり方があるのかもしれないが、 sinmetalが試した限りでは、全Kind Importするか、指定した1つのkindしかImportすることができなかった。
また、kindを指定する場合、Exportする側も1つのkindだけ指定してExportしておく必要があった。

以下はHoge Kindのみを持っていきたい時の gcloud datastore のサンプル。
Export時に overall_export_metadata を末尾に持つファイルが複数できあがるが、指定するのは最もrootにいる overall_export_metadata を指定する。

Export

gcloud datastore export --async --kinds='Hoge' gs://datastore-backup/hoge

Import

gcloud datastore import --kinds='Hoge' gs://datastore-backup/hoge/hoge.overall_export_metadata

kanikoってなに?

https://cloudplatform.googleblog.com/2018/04/introducing-kaniko-Build-container-images-in-Kubernetes-and-Google-Container-Builder-even-without-root-access.html

docker daemon 不要で Dockerfile からコンテナイメージをビルドするやつ
Docker Daemon は root 権限要求したりするので、利用場所を選ぶ

k8sの中でDockerをBuildすることの議論のissue kubernetes/kubernetes#1806

Docker Daemonの課題に触れた日本語の記事 https://deeeet.com/writing/2015/02/17/docker-bad-points/

大量のObject Deleteについて

  • Price
  • Transfer Service
  • Lifecycle Management

Transfer Serviceを利用して、ゴミ箱bucketにObjectに移動させて、Lifecycle Managementで削除するTips

GKE 1.10からGCP Scopeの指定方法が変わる

WHAT

GKE 1.10から、GCP Scopeの指定の方法が変更される。
元々はCluster作成時に指定し、全てのNodePoolが同じ設定になるようになっていた。
GKE1.10からは、NodePool追加時にGCP Scopeを指定できるようになった。
それに伴いDefaultのScopeが変わっている。
Scopeの指定がない場合、以下のようなScopeが設定される。
image

Cloud Consoleには2018/10/01時点では、NodePool追加時にGCP Scopeを設定する機能が無いため、必ず上記の gke-default になってしまう。
指定したい場合は、 gcloud container node-pools create でNodePoolを作成してやる必要がある。以下はCommandのExample

gcloud container node-pools create core8pool --cluster sinmetal-tokyo --zone asia-northeast1-b --enable-autoscaling --max-nodes 8 --min-nodes 1 --scopes https://www.googleapis.com/auth/cloud-platform --machine-type n1-highcpu-8

https://cloud.google.com/sdk/gcloud/reference/container/node-pools/create

WHY

GKEでDefault Service Account使っていて、GCP Scopeを指定してる人が苦しまないように書いたTips
しんめたるはテスト環境で雑にFull Scope指定してCluster作ってたので、新しいNodePoolをCloud Consoleから追加したら、全部Permission Deniedになって、苦しんだ。

GCP News May 2018

App Engine

Standardのautomatic scalingに設定が数週間後に増える予定

  • max_instances
  • target_cpu_utilization
  • target_throughput_utilization

https://groups.google.com/forum/#!msg/google-appengine/kXhLEKapFeM/rz7zdMuDAQAJ

Apache Beam

Apache Beam ベースの Dataprep みたいなやつ?

Apache Beam のコア開発者が複数人居る Talend が Apache Beam ベースの Dataprep みたいなやつ?を無料でリリースしたらしい。今は AWS Marketplace でしかデプロイできないみたいですが、Cloud PubSub 等を使う Cloud Dataflow の Runner も作れるっぽい

https://www.talend.com/blog/2018/05/08/introducing-talend-data-streams-self-service-streaming-data-integration-for-everyone/

Cloud TPU

v3.0 発表

CIDRがクラスB(172.16.0.0/12)のVMからMemoryStoreへ接続できない

Problem

VPC作成時に自動サブネット作成を無効にし、さらにサブネットのCIDRをクラスB(172.16.0.0/12)で作成した場合、そのネットワーク上に作成したVMからMemoryStoreへ接続できない。

Why

一部のネットワーク事業者ではクラスBに対して172/8でフィルタリングしている場合があり、MemoryStoreも同様にフィルタリングしていると思われる。

ref:
https://stackoverflow.com/questions/54528482/can-not-connect-memorystore-from-the-vm?answertab=active#tab-top
https://www.arin.net/knowledge/address_filters.html

Workaround

  • VPC作成時に自動サブネット作成を有効にする。
    • この場合はクラスBでもMemoryStoreへ接続できた。
  • VPC作成時に自動サブネット作成を無効にする場合はサブネットのCIDRをクラスA or クラスCにする。

GAE Admin API を使って動的にスケーリングオプションを変更する

あまり知られていないが App Engine Admin API の中には gcloud appappcfg.py が内部的に呼ぶような API が含まれているだけでなく、コマンドラインから行うことができない機能も提供されている。
例えば下記のように apps.services.versions.patch を呼ぶと automatic scaling の min_instances を再デプロイなしで変更できる。

$ curl -X PATCH "https://appengine.googleapis.com/v1/apps/${GAE_PROJECT}/services/${GAE_SERVICE}/versions/${GAE_VERSION}?updateMask=automaticScaling.standardSchedulerSettings.minInstances" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{"automaticScaling": {"standardSchedulerSettings":{"minInstances": 2}}}'

よく見ると専用コマンドを使わずに GAE/SE にデプロイする方法なども説明されているのでやってみると面白いかも。
https://cloud.google.com/appengine/docs/admin-api/deploying-overview?hl=en

Google Cloud SDK 190.0.1 で goapp がImportErrorでコケる

問題

goapp実行時にエラーが発生する

$ goapp

Traceback (most recent call last):
  File "/Users/sinmetal/bin/google-cloud-sdk/platform/google_appengine/goapp", line 40, in <module>
    from google.appengine.tools import goroots
ImportError: cannot import name goroots

解決策

google-cloud-sdk/platform/google_appengine/google/appengine/tools に自分で goroots.py を作成すれば解決できる。

  • goroots.py の内容
GOROOTS = {'go1': 'goroot-1.8', 'go1.6': 'goroot-1.6'}

根本解決のための本体のissue

golang/appengine#124

Stackdriver LoggingでJsonPayloadに大きな数値を出力すると誤差が出る

WHAT

Stackdriver LoggingのJsonPayloadに大きな数値を出力すると、誤差が出る。
JavaScriptで誤差が出る時と同じ値になるので、どこかでNode.jsとかが処理をしている?

gcloud logging write projects/gcpugjp/logs/bignum --log-http --payload-type=json '{"num": 36028797018963966, "text": "36028797018963966"}'
=======================
==== request start ====
uri: https://logging.googleapis.com/v2/entries:write?alt=json
method: POST
== headers start ==
Authorization: --- Token Redacted ---
accept: application/json
accept-encoding: gzip, deflate
content-length: 201
content-type: application/json
user-agent: google-cloud-sdk x_Tw5K8nnjoRAqULM9PFAC2b gcloud/217.0.0 command/gcloud.logging.write invocation-id/c4ec4b9252264851b33d9ac029133c8d environment/None environment-version/None interactive/True from-script/False python/2.7.14 (Macintosh; Intel Mac OS X 16.7.0)
== headers end ==
== body start ==
{"entries": [{"jsonPayload": {"num": 36028797018963966, "text": "36028797018963966"}, "logName": "projects/gcpugjp/logs/bignum", "resource": {"type": "global"}, "severity": "DEFAULT"}]}
== body end ==
==== request end ====
---- response start ----
-- headers start --
-content-encoding: gzip
alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"
cache-control: private
content-length: 3
content-type: application/json; charset=UTF-8
date: Tue, 02 Oct 2018 10:25:37 GMT
server: ESF
status: 200
transfer-encoding: chunked
vary: Origin, X-Origin, Referer
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
-- headers end --
-- body start --
{}

-- body end --
total round trip time (request+response): 0.182 secs
---- response end ----
----------------------
Created log entry.

投げたPayloadはnumもtextも 36028797018963966 だが、取得するとnumは 36028797018963968 になっている。

gcloud logging read projects/gcpugjp/logs/bignum
---
insertId: iljpr3f1gkkso
jsonPayload:
  num: 36028797018963968
  text: '36028797018963966'
logName: projects/gcpugjp/logs/bignum
receiveTimestamp: '2018-10-02T10:25:37.510646519Z'
resource:
  labels:
    project_id: gcpugjp
  type: global
timestamp: '2018-10-02T10:25:37.510646519Z'
---

どうまるめられるかのメモ

36028797018963970→36028797018963970:  0
36028797018963969→36028797018963970: +1
36028797018963968→36028797018963970: +2
36028797018963967→36028797018963970: +3
36028797018963966→36028797018963970: +2
36028797018963965→36028797018963964: -1
36028797018963964→36028797018963964:  0
36028797018963963→36028797018963964: +1
36028797018963962→36028797018963960: -2
36028797018963961→36028797018963960: -1
36028797018963960→36028797018963960:  0
36028797018963959→36028797018963960: +1
36028797018963958→36028797018963960: +2
36028797018963957→36028797018963956: -1
36028797018963956→36028797018963956:  0
36028797018963955→36028797018963956: +1
36028797018963954→36028797018963950: -4
36028797018963953→36028797018963950: -3
36028797018963952→36028797018963950: -2
36028797018963951→36028797018963950: -1
36028797018963950→36028797018963950:  0
 36028797018963859→36028797018963858: -1
26028797018963969→26028797018963969:  0

WHY

GKEで標準出力に1lineでJsonを出力すれば https://cloud.google.com/logging/docs/structured-logging として扱ってくれるが、大きな数値はまるめられちゃうので、stringに変換するなどの工夫が必要そう。

GCP CLI Auth

以下のコマンドの影響範囲や、Revokeの方法をまとめる

  • gcloud auth login
  • gcloud auth application-default login
  • appcfg.py でのログイン

go modulesを利用するとデプロイが遅くなる問題の解決策

Go 1.11から export GO111MODULE=on と環境変数を設定することでgo modulesを利用することができる。
Google App Engine 2nd genと Cloud Functionsはgo modulesに対応している。

しかしデプロイが遅くなるので、従来通りvendorディレクトリを用意してデプロイすることで高速になる。
私の環境のGoogle App Engineでは 4:20が2:20くらいになったので約2分速くなる。

また日常の開発ではgo modulesを使いたいという場合にはデプロイ時だけvendorを用意してgo modulesをオフにするとよい。

go mod vendor
export GO111MODULE=off
gcloud app deploy xxxxx
export GO111MODULE=on
rm vendor -rf

以下のようにすることでgcloudコマンド実行時だけoffにすることもできる

go mod vendor
GO111MODULE=off gcloud app deploy xxxxx
rm vendor -rf

Cloud Functionsは試していないが、おそらく同じはず。

go.modgo.sum.gcloudignore に追加することでvendorを利用できるとドキュメントにあるが、実際には GO111MODULE=off が必要である。

https://cloud.google.com/functions/docs/concepts/go-runtime#vendor_directory

Go 1.13以降go modules onがデフォルトになってしまうとこの回避方法が使えなくなる可能性はある。

またgo modulesを使うと遅くなる原因は恐らくGCP側でgo getが走ってビルドするためなので、将来的にソースコードと同様に依存ファイルもキャッシュされるようになればgo modulesでも高速になるかもしれない。

Terraform GCP Provider 1.13.0でService Enableが動かない

Problem

Terraform GCP Provider 1.13.0 で google_project_services を利用すると、403で転ける。転けた時にAPIがDisableになるっぽいので、全体的に死ぬ。

Try Log

google_project_services.tf

resource "google_project_services" "project" {
  project = "sinmetal-terraform"

  services = ["cloudapis.googleapis.com",
    "iam.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudbuild.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "storage.googleapis.com",
    "pubsub.googleapis.com",
  ]
}

terraform apply log

terraform apply
2018/06/04 20:51:24 [WARN] Invalid log level: "1". Defaulting to level: TRACE. Valid levels are: [TRACE DEBUG INFO WARN ERROR]
google_storage_bucket.sinmetal-terraform-20180327b: Refreshing state... (ID: sinmetal-terraform-20180327b)
google_storage_bucket.sinmetal-terraform-20180327a: Refreshing state... (ID: sinmetal-terraform-20180327a)
google_bigquery_dataset.log-dataset: Refreshing state... (ID: logging-sinmetal-org:organization_audit_log)
google_storage_bucket.sinmetal-terraform-20180327c: Refreshing state... (ID: sinmetal-terraform-20180327c)
google_logging_organization_sink.organization-auditlog-sink: Refreshing state... (ID: organizations/69165754818/sinks/organization-auditlog-sink)
google_logging_organization_sink.organization-gae-sink: Refreshing state... (ID: organizations/69165754818/sinks/organization-gae-sink)
google_project_iam_binding.log-writer: Refreshing state... (ID: logging-sinmetal-org/roles/bigquery.dataEditor)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + google_project_services.project
      id:                  <computed>
      disable_on_destroy:  "true"
      project:             "sinmetal-terraform"
      services.#:          "9"
      services.1109577435: "cloudbuild.googleapis.com"
      services.1560437671: "iam.googleapis.com"
      services.1610229196: "bigquery-json.googleapis.com"
      services.1954675454: "serviceusage.googleapis.com"
      services.2117420113: "pubsub.googleapis.com"
      services.238136042:  "cloudapis.googleapis.com"
      services.3266434626: "bigquery.googleapis.com"
      services.3644083179: "cloudresourcemanager.googleapis.com"
      services.3872232641: "storage.googleapis.com"


Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

google_project_services.project: Creating...
  disable_on_destroy:  "" => "true"
  project:             "" => "sinmetal-terraform"
  services.#:          "" => "9"
  services.1109577435: "" => "cloudbuild.googleapis.com"
  services.1560437671: "" => "iam.googleapis.com"
  services.1610229196: "" => "bigquery-json.googleapis.com"
  services.1954675454: "" => "serviceusage.googleapis.com"
  services.2117420113: "" => "pubsub.googleapis.com"
  services.238136042:  "" => "cloudapis.googleapis.com"
  services.3266434626: "" => "bigquery.googleapis.com"
  services.3644083179: "" => "cloudresourcemanager.googleapis.com"
  services.3872232641: "" => "storage.googleapis.com"
google_project_services.project: Still creating... (10s elapsed)

Error: Error applying plan:

1 error(s) occurred:

* google_project_services.project: 1 error(s) occurred:

* google_project_services.project: Error creating services: Error enabling service ["storage.googleapis.com" "iam.googleapis.com" "bigquery-json.googleapis.com" "cloudapis.googleapis.com" "bigquery.googleapis.com" "cloudbuild.googleapis.com"] for project "sinmetal-terraform": googleapi: Error 403: The caller does not have permission, forbidden

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

terraform debug log

All Log

2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 2018/06/04 20:51:44 [DEBUG] Got true while polling for operation operations/acf.05d81ad7-cf50-4947-834f-4da0104f443d's 'done' status
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 2018/06/04 20:51:44 [DEBUG] Waiting for state to become: [success]
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 2018/06/04 20:51:44 [WARN] Invalid log level: "1". Defaulting to level: TRACE. Valid levels are: [TRACE DEBUG INFO WARN ERROR]
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 2018/06/04 20:51:44 [DEBUG] Google API Request Details:
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: ---[ REQUEST ]---------------------------------------
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: POST /v1beta1/projects/sinmetal-terraform/services:batchEnable?alt=json HTTP/1.1
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Host: serviceusage.googleapis.com
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: User-Agent: google-api-go-client/0.5 Terraform/0.11.3-dev (+https://www.terraform.io)
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Content-Length: 175
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Content-Type: application/json
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Accept-Encoding: gzip
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 
2018-06-04T20:51:44.060+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: -----------------------------------------------------
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 2018/06/04 20:51:44 [WARN] Invalid log level: "1". Defaulting to level: TRACE. Valid levels are: [TRACE DEBUG INFO WARN ERROR]
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 2018/06/04 20:51:44 [DEBUG] Google API Response Details:
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: ---[ RESPONSE ]--------------------------------------
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: HTTP/2.0 403 Forbidden
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Alt-Svc: quic=":443"; ma=2592000; v="43,42,41,39,35"
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Cache-Control: private
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Content-Type: application/json; charset=UTF-8
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Date: Mon, 04 Jun 2018 11:51:46 GMT
2018-06-04T20:51:44.865+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Server: ESF
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Vary: Origin
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Vary: X-Origin
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: Vary: Referer
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: X-Content-Type-Options: nosniff
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: X-Frame-Options: SAMEORIGIN
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: X-Xss-Protection: 1; mode=block
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: {
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:   "error": {
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:     "code": 403,
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:     "message": "The caller does not have permission",
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:     "errors": [
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:       {
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:         "message": "The caller does not have permission",
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:         "domain": "global",
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:         "reason": "forbidden"
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:       }
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:     ],
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:     "status": "PERMISSION_DENIED"
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4:   }
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: }
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: 
2018-06-04T20:51:44.866+0900 [DEBUG] plugin.terraform-provider-google_v1.13.0_x4: -----------------------------------------------------

WHY

GCP Provider 1.13.0からAPIのEnable/Disableを行うAPIを、 Service Management API から Service Usage API に変更している。

https://github.com/terraform-providers/terraform-provider-google/blob/master/CHANGELOG.md#1130-may-24-2018

google_project_service/google_project_services now use the Service Usage API. Users of those resources will need to enable the API at https://console.cloud.google.com/apis/api/serviceusage.googleapis.com.

https://github.com/terraform-providers/terraform-provider-google/blob/master/CHANGELOG.md#1130-may-24-2018

その後、Service Usage API側で仕様変更か何かがあったのか、動かなくなってしまったようだ。
この問題は hashicorp/terraform-provider-google#1538 で議論されている。

GCP ドキュメントの歩き方

GCP のドキュメントに関するバッドノウハウみたいな話はわりと頻出なのでまとまっていると良いのかもしれない、ということで少し書いてみた。

日本語ドキュメントによくある問題

  • 訳が適切でないことがある(今は改善されたが無料階層など)
  • ページ(サービス)の更新に追従できていなくて古い。下記のような致命的なものもある。
    • リリースノートの項目が更新されていない
    • 既に GA になったものが日本語ドキュメントだと alpha と書かれているままだったりしたことがある
    • 課金体系の変更に追従していなかったりする
  • ドキュメント構成の変更に追従できていない
    • サイドバーのドキュメント構成が古いままで、新しいドキュメントにたどり着けないことがある

サイドバーが表示されていないのはどういう状況か

?hl=ja
2018-04-09 14 59 47

?hl=en
2018-04-09 15 00 04

言語設定の方法(下に行くほど優先度が強いため上のものを上書きする)

  • ブラウザの言語設定(accept-language ヘッダ)
    • 全体の言語設定を英語にしたくない人は言語設定別にブラウザのプロファイルを分けるなどの手がある
  • ページフッタの言語設定ドロップボックス 2018-04-09 15 16 57
    • https://cloud.google.com/i18n/setlang/ によりセッションクッキー(例 Cookie: django_language=ja)として設定されるので、閉じると設定が消える
  • URL query string の hl フィールドを使うとブラウザの言語設定、 Cookie に影響されずに言語を指定できる
    • リンクを共有する場合は同じ言語で見えることを保証するために明示的につけると良い

ベストプラクティス

個人的には Concept, 概念 のところを一度大まかに把握したい時には日本語を参照するけど、日本語だと事実が変わっていることがあるので調査は常に英語でやっている。
一般のドキュメントは末尾の最終更新日を見て、英語の最終更新日もしくはリリースノート等で確認できる機能のアップデートと比べて古くなければ問題ないと判断しても良いかも。(ただし、日本語版が元にした版はアップデートよりも古い場合がある)
2018-04-09 15 16 16

2019年6月追記

2019年5月下旬頃にページヘッダからも言語設定できるようになった。ある程度ウィンドウ幅が広くないと出てこない様子。
スクリーンショット 2019-06-06 17 35 53

Stackdriver料金体系変更に備えて

WHAT

2018年6月30日からStackdriverの料金体系が大きく変わっていくので、それに備える
https://cloud.google.com/stackdriver/pricing_v2?hl=en

料金体系変更の概要

今までは Standard Tier , Premium Tier の2つの料金体系で、 Premium Tier にするとAlert先の増加など、機能が解放されるという形だった。
新しい料金体系は、機能はすべて同じで、LoggingやMetricなどのトラフィック量に対して課金されるようになった。
ある程度、無料枠があるので、小さなProjectは機能がフルに使えるようになってハッピーな感じだが、トラフィックが多い大きなProjectは大きく課金されないようにログの除外などの設定をしてあげる必要がある。

Stackdriver 料金変更スケジュール

Feature Price1 Free allotment per month Effective date  
Logging $0.50/GB First 50 GB/project 2018/06/30  
Monitoring data $0.2580/MB: 150–100,000MB$0.1510/MB: 100,000–250,000MB$0.0610/MB: >250,000 MB All GCP metrics2Non-GCP metrics: <150MB 2018/06/30  
Monitoring API calls $0.01/1,000 API calls First 1 million API calls 2018/06/30  
Trace ingestion $0.20/million spans First 2.5 million spans 2018/09/30  
Trace retrieval $0.02/million spans First 25 million spans 2018/09/30

WHY

無料だったものが有料になるものも存在するため、料金にびっくしりないように。

エッジキャッシュにコンテンツを乗せない方法

WHAT

App Engine Static Serverを利用している時にエッジキャッシュにコンテンツを乗せない方法

WHY

社内アプリなど、限定範囲に公開しているコンテンツをエッジキャッシュに乗せるとpublicになってしまうため。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.