はじめに
GCSの変更通知をCloud Functionsで受け取り、そこからKubernetes側にとある処理を実行したいな…と思ったときに結構ハマったのでメモです。
私は、社内用のbotを作るときしか、nodejsを触らないバックエンド側のエンジニアです。
暖かい目でコードを見て、厳しいご指摘くれると嬉しいです。
結果
下記のような結果となりました。
https://github.com/h-r-k-matsumoto/cloud-function-gke
ハマったポイント
Cloud Functionsからではgcloudコマンド使えないから認証できない。
適当に、 ~/.kube/config
を使おうとすると下記のようにエラーになりました。
サンプル ですら動きません。
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403
}
どうにも system:anonymous
となっている事から認証されていないっぽいですね。
対応
通常は、下記のような定義だと思います。
"users": [
{
"authProvider": {
config: {
"cmd-args": "config config- helper--format = json",
"cmd-path": "/usr/lib64/google-cloud-sdk/bin/gcloud",
"expiry": "2019-04-23T07:05:48Z",
"expiry-key": '{.credential.token_expiry}',
"token-key": '{.credential.access_token}'
},
"name": "gcp"
}
}
]
下記のように、authProvider
をばっさり消しちゃいます。この部分があると、 @kubernetes/client-node
ライブラリの、 cloud_auth.tsが動作してしまうためです。
"users": [
{
}
]
さみしいですね。で、変わりに何で認証するか?という部分ですが、
config.ts#L294
に、下記の記述があります。
if (user.token) {
token = 'Bearer ' + user.token;
}
そう。自分でtokenを設定してやれば良いわけですね。なので・・・下記のようにtokenを取得します。
async function getToken() {
let authResult = await auth.getClient({ scopes: 'https://www.googleapis.com/auth/cloud-platform' });
let accessToken = await authResult.getAccessToken().catch((err) => {
throw err;
})
return accessToken.token
}
そして、下記のように取得した値をセットしています。
users: [
{
user: {
token: token
}
}
]
その他
golangはあきらめたお話
最初は、golangで実装しようとしました。でも、golang 1.11だと、下記問題が発生しました。
..\..\..\..\..\pkg\mod\k8s.io\client-go@v11.0.0+incompatible\rest\request.go:598:31: not enough arguments in call to watch.NewStreamWatcher
have (*versioned.Decoder)
want (watch.Decoder, watch.Reporter)
なんていうgolang初心者にはつらいエラーが・・・。で、master使おうとすると、
>go build main.goform\lake\notification>go build main.go
go: finding google.golang.org/api/support/bundler latest
go: finding google.golang.org/api/support latest..\..\..\..\..\pkg\mod\contrib.go.opencensus.io\exporter\ocagent@v0.4.12\ocagent.go:24:2: unknown import path "google.golang.org/api/support/bundler": cannot find moduleproviding package google.golang.org/api/support/bundler
とライブラリ関係でエラーが出るので、ちょっと初心者には更に厳しいと思い nodejsで実装する事に変えました。
このやり方は正しいのかは分からない。
公式サイトや、stackoverflowなどでも探したのですが、Cloud Functionからの呼び出し方法は不明なままでした。
あくまで、これでやったら現時点では上手くいったよ。という内容となります。