gcpug / nouhau Goto Github PK
View Code? Open in Web Editor NEWGoogle Cloud Platformのノウハウを共有するRepository
Home Page: https://gcpug.jp
License: MIT License
Google Cloud Platformのノウハウを共有するRepository
Home Page: https://gcpug.jp
License: MIT License
https://cloud.google.com/bigquery/docs/querying-wildcard-tables 利用時に対象のtableでschemaに差異がある場合、queryが失敗するので、どうにかしたい。
どのtableが欠けているのかも分からないので、結構厳しい。
すんなり解決するのは難しい。
いくつかの案を記すが、根性が必要。
対象のcolumnがstructの場合はUDFでstructの中の欠けた値にデフォルト値を入れることで解決できるかもしれない。
tableのschemaをAPIで調べて、欠けているtableを調べて、欠けているtableはviewを作るなどして、対処する。
新しい GAE/SE の素性が明らかになってきたので、分かっていることを書いていく。
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
}
https://play.golang.org/p/Qrqo9kXRjl9
func init()
で好きなmiddlewareでラップして、それをCloud Functionsで実行できるので便利かもなという雰囲気
以下の記事でCloud SchedulerからGCPのAPIを直接操作するというのが出ている。
サンプルとしてはCompute EngineのManaged Instance GroupのSizeを変えている。
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 さんに教えてもらいました!
#41 の姉妹ポエム
インスタンス起動時に、DatastoreやCloud Storageなどにアクセスし、設定値を持ってくるようなサンプル。
https://www.slideshare.net/takuyaueda967/gaegosync
BigQueryでRECORDフィールドの中の一部を最小限の記述で置き換え・削除できるSQLの書き方。
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でも一部置き換えをシンプルな記述で書く方法が知りたい。
みんな好きに書いてね!
#WHAT
Datastoreに保存しているPropertyの型を途中で変えた時に、行う処理
#WHY
時折質問があるので、Tipsに書いておこうと思って。
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.
https://gcpug.slack.com/archives/C2J8XMRKL/p1509346656000074
type Inner struct {
A string
B string
}
type Data struct {
Slice []Inner
}
みたいな構造をPropertyListにした時、違う結果になる。
Sliceの長さを3とした時
検索の仕方は両方 Slice.A
とかなので、実用上の違いはないかもしれない…?
BigQueryにexportした時のスキーマ構成とかに影響があるかな…?くらい(未検証
Google App Engine Standard for Go のProject構成のExampleをまとめる。Deploy時におらおら、GOPATHとかをshellで変更したりする流派もあった気がする。
いくつかの流派が存在して、ちょいちょい話題になるため。
Go1.11ではgVisor化とGo 1.11 Modulesが入ってくるので、変わるかもしれない。
https://tokyo2018.gdgjapan.org/ のGCPUGの人たちのスライドまとめ
Firebase Auth for Googleを利用してログインし、Firestoreでドメイン指定を行いたい!
gcpug.jp
アカウント限定みたいなことをしたい
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.
Vision, Natural Language (日本語はたぶんまだ), Translation (日本語はたぶんまだ?)がBetaで登場した。
試すには、ProjectのAuto ML APIをEnableにした後、ドキュメントのQuick StartとかにあるLinkからConsoleに行く
https://cloud.google.com/automl/?hl=en
@sfujiwara がMeetUpで聞いてきた。
Q AutoMLでモデルをダウンロードしたい
A 時期は未定だが、できるようにする予定
Q ダウンロードできないのは TensorFlow のグラフからネットワークがバレるとまずいから?
A yes
https://cloud.google.com/vision/docs/beta?hl=en
https://cloud.google.com/edge-tpu/
Open Go Fridayより
1分より短い間隔でやる場合のバッチのパターン
BucketにVersioning=enable, Lifecycle:DELETEを指定した場合、DELETEは過去Versionも含めて削除するのか?
削除する。
そのため、オペミス対策でVersioning=enableを設定し、料金節約のためにLifecycle:DELETEを設定すると、意図通りに動く。
Google App Engine Standard 1.9 (1st generation) から 1.11 (2nd generation) に移行すると、何が嬉しくて何が悲しいかを記す
Go 1.9 から Go 1.11に移行する時に何を考えるべきかをまとめる
この辺のバグっぽいものを踏んで悲しい気持ちになった。
https://stackoverflow.com/questions/24420817/ioerror-cannot-identify-image-file
https://stackoverflow.com/questions/19230991/image-open-cannot-identify-image-file-python
解決するには
のどちらかが良さそう。
DataflowのTextIOが途中ファイルを出力する際の注意点をまとめる。
DataflowでTextIOを使うと途中ファイルを書き出して最後にまとめる挙動をしている。
そのために一見関係ないことで悪影響を及ぼすことがあるのでそうした影響をまとめる。
(凍結したGCSに途中ファイルを書き出して削除しようとしてJobが失敗するなど)
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}
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#L36 の go.opencensus.io/trace.StartSpann
の戻り値が2つ返ってくるのがおそらく正しいが、 https://github.com/GoogleCloudPlatform/google-cloud-go/blob/767c40d6a2e058483c25fa193e963a22da17236d/spanner/go18.go#L36 は1つしか受け取ってないので、死ぬ
v.17.0
を利用するか master
を利用する
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.yaml
で api_version: go1
を指定した場合 Go 1.8が使われるようになった。
1.6を使いたい場合は、以下のように明示的に設定する必要がある。
runtime: go
api_version: go1.6
Go 1.8に上げるための道のりについては #5 を参照!
Go 1.11の最もシンプルな公式のサンプルでは、 google.golang.org/appengine
は使っておらず、 http.ListenAndServe
を普通に使っている。
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
でエラーとなる。
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_package に Or, if your service is using the google.golang.org/appengine package, include a call to appengine.Main().
と書いてある。
Stackdriver Traceを強制的に出力する方法
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"
TraceのStartSpan時にサンプリングの設定を追加できる。 Goの場合は https://godoc.org/go.opencensus.io/trace#AlwaysSample を設定すれば、必ず出力される。
ctx, span := trace.StartSpan(ctx, "/process", trace.WithSampler(trace.AlwaysSample()))
defer span.End()
Exportした内容を別のGCP ProjectにImportしようとすると、地味にハマる
https://cloud.google.com/datastore/docs/export-import-entities?hl=en#permissions
だいたいドキュメントに書いてあるとおりだが、Importを実行しているのは {projectid}@appspot.gserviceaccount.com
のようなので、こいつをRoleを割り当ててやる必要がある。
うまいやり方があるのかもしれないが、 sinmetalが試した限りでは、全Kind Importするか、指定した1つのkindしかImportすることができなかった。
また、kindを指定する場合、Exportする側も1つのkindだけ指定してExportしておく必要があった。
以下はHoge Kindのみを持っていきたい時の gcloud datastore
のサンプル。
Export時に overall_export_metadata
を末尾に持つファイルが複数できあがるが、指定するのは最もrootにいる overall_export_metadata
を指定する。
gcloud datastore export --async --kinds='Hoge' gs://datastore-backup/hoge
gcloud datastore import --kinds='Hoge' gs://datastore-backup/hoge/hoge.overall_export_metadata
Project Aで作られたService Accountが、Project BのResourceを操作する時、APIを実行するのはProject Aになるので、QuotaやPriceはProject Aに入る。
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/
Transfer Serviceを利用して、ゴミ箱bucketにObjectに移動させて、Lifecycle Managementで削除するTips
GKE 1.10から、GCP Scopeの指定の方法が変更される。
元々はCluster作成時に指定し、全てのNodePoolが同じ設定になるようになっていた。
GKE1.10からは、NodePool追加時にGCP Scopeを指定できるようになった。
それに伴いDefaultのScopeが変わっている。
Scopeの指定がない場合、以下のようなScopeが設定される。
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
GKEでDefault Service Account使っていて、GCP Scopeを指定してる人が苦しまないように書いたTips
しんめたるはテスト環境で雑にFull Scope指定してCluster作ってたので、新しいNodePoolをCloud Consoleから追加したら、全部Permission Deniedになって、苦しんだ。
https://groups.google.com/forum/#!msg/google-appengine/kXhLEKapFeM/rz7zdMuDAQAJ
Apache Beam のコア開発者が複数人居る Talend が Apache Beam ベースの Dataprep みたいなやつ?を無料でリリースしたらしい。今は AWS Marketplace でしかデプロイできないみたいですが、Cloud PubSub 等を使う Cloud Dataflow の Runner も作れるっぽい
VPC作成時に自動サブネット作成を無効にし、さらにサブネットのCIDRをクラスB(172.16.0.0/12)で作成した場合、そのネットワーク上に作成したVMからMemoryStoreへ接続できない。
一部のネットワーク事業者ではクラス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
あまり知られていないが App Engine Admin API の中には gcloud app
や appcfg.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
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 = {'go1': 'goroot-1.8', 'go1.6': 'goroot-1.6'}
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
GKEで標準出力に1lineでJsonを出力すれば https://cloud.google.com/logging/docs/structured-logging として扱ってくれるが、大きな数値はまるめられちゃうので、stringに変換するなどの工夫が必要そう。
以下のコマンドの影響範囲や、Revokeの方法をまとめる
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.mod
と go.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 で google_project_services を利用すると、403で転ける。転けた時にAPIがDisableになるっぽいので、全体的に死ぬ。
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
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.
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: -----------------------------------------------------
GCP Provider 1.13.0からAPIのEnable/Disableを行うAPIを、 Service Management API から Service Usage API に変更している。
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 で議論されている。
terraformでほい!する
cf. https://www.terraform.io/docs/providers/google/index.html
特定のGoogle Groupに所属しているユーザのみを指定したセキュリティルールをなんとかしたい
[email protected]
に所属している人だけ見えるみたいなことをしたい
現象は掲題の通り。
Dataset内のML Modelを削除すると解消される。
GCP のドキュメントに関するバッドノウハウみたいな話はわりと頻出なのでまとまっていると良いのかもしれない、ということで少し書いてみた。
?hl=en
を指定すると「Deploying Containers on VMs and Managed Instance Groups」に飛び、更に ?hl=ja
を指定すると「VM およびマネージド インスタンス グループへのコンテナのデプロイ」に飛ぶaccept-language
ヘッダ)
https://cloud.google.com/i18n/setlang/
によりセッションクッキー(例 Cookie: django_language=ja
)として設定されるので、閉じると設定が消えるhl
フィールドを使うとブラウザの言語設定、 Cookie に影響されずに言語を指定できる
個人的には Concept
, 概念
のところを一度大まかに把握したい時には日本語を参照するけど、日本語だと事実が変わっていることがあるので調査は常に英語でやっている。
一般のドキュメントは末尾の最終更新日を見て、英語の最終更新日もしくはリリースノート等で確認できる機能のアップデートと比べて古くなければ問題ないと判断しても良いかも。(ただし、日本語版が元にした版はアップデートよりも古い場合がある)
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は大きく課金されないようにログの除外などの設定をしてあげる必要がある。
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 |
無料だったものが有料になるものも存在するため、料金にびっくしりないように。
App Engine Static Serverを利用している時にエッジキャッシュにコンテンツを乗せない方法
社内アプリなど、限定範囲に公開しているコンテンツをエッジキャッシュに乗せるとpublicになってしまうため。
https://gcpug.jp のトップページに「 GCP お役立ち Link集がおすすめです。」と
https://github.com/gcpug/nouhau/tree/master/general/poem/link
へのリンクがあったのですが、開くと404 not foundが表示されていました。
リンク先はこちらが正しい?
https://github.com/gcpug/nouhau/tree/master/general/note/link
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.