Stackdriver Loggingでログのエクスポート

# お題
以前、GKE上で動くアプリを公開し、[Stackdriver Logging](https://cloud.google.com/logging/)（以降、SDL）でアプリが出力したログを確認するところまでやったが、SDL上のログには[保持期間](https://cloud.google.com/logging/quotas#logs_retention_periods)というものがあり、放っておくと消える。
当然、ログの退避方法というのがあるので、試してみる。

# 環境
### # OS
<pre>
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="17.10 (Artful Aardvark)"
</pre>

### # gcloud
<pre>
$ gcloud version
Google Cloud SDK 217.0.0
app-engine-go 
app-engine-java 1.9.65
app-engine-python 1.9.75
beta 2018.07.16
bigtable 
bq 2.0.34
cbt 
cloud-build-local 
cloud-datastore-emulator 2.0.2
cloud_sql_proxy 
container-builder-local 
core 2018.09.17
docker-credential-gcr 
gsutil 4.34
kubectl 2018.09.17
pubsub-emulator 2018.02.02
</pre>

### # kubectl
<pre>
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.7", GitCommit:"0c38c362511b20a098d7cd855f1314dad92c2780", GitTreeState:"clean", BuildDate:"2018-08-20T10:09:03Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"9+", GitVersion:"v1.9.7-gke.6", GitCommit:"9b635efce81582e1da13b35a7aa539c0ccb32987", GitTreeState:"clean", BuildDate:"2018-08-16T21:33:47Z", GoVersion:"go1.9.3b4", Compiler:"gc", Platform:"linux/amd64"}
</pre>

# 実践
## ■[以前の投稿](https://qiita.com/sky0621/items/aadeb53a5be2800066de)のおさらい

### １）クラスタ作成
<pre>
$ gcloud container clusters create my-cluster-1-min --zone asia-northeast1-a --preemptible --machine-type=f1-micro --disk-size=10 --num-nodes=3
　〜省略〜
Creating cluster my-cluster-1-min...done.                                                                                                                                                                  
Created [https://container.googleapis.com/v1/projects/【プロジェクトID】/zones/asia-northeast1-a/clusters/my-cluster-1-min].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/asia-northeast1-a/my-cluster-1-min?project=【プロジェクトID】
kubeconfig entry generated for my-cluster-1-min.
NAME              LOCATION           MASTER_VERSION  MASTER_IP      MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
my-cluster-1-min  asia-northeast1-a  1.9.7-gke.6     【IPアドレス】 f1-micro      1.9.7-gke.6   3          RUNNING
</pre>

### ２）WebAPIアプリを内包するコンテナをデプロイ（※前提：GCRに対象イメージ格納済み）
<pre>
$ kubectl run go-webapi-for-gke-study-server --image gcr.io/【プロジェクトID】/go-webapi-for-gke-study@sha256:e38c30b2dae0364ba91ab66f7b7247a392dac952f317143c475efe11a98dcf40 --port 80
deployment.apps "go-webapi-for-gke-study-server" created
</pre>

### ３）サービス公開
<pre>
kubectl expose deployment go-webapi-for-gke-study-server --type "LoadBalancer"
service "go-webapi-for-gke-study-server" exposed
</pre>

### ４）ログはStackdriver Loggingに溜まる？
#### GKEの設定（指定なしならデフォルトでStackdriver Logging利用となる）
![01.png](https://qiita-image-store.s3.amazonaws.com/0/180599/58ecb975-8dc3-acc4-39fa-832258011c58.png)

#### 公開されたサービスにブラウザでアクセスすると？
##### まず、Podのログを見ると、ちゃんとアクセスされたログ（INFO, WARN, ERRORそれぞれ）が出ている。
<pre>
$ kubectl get pods
NAME                                              READY     STATUS    RESTARTS   AGE
go-webapi-for-gke-study-server-56bb9576f5-ljsm7   1/1       Running   0          1m
$
$ kubectl logs go-webapi-for-gke-study-server-56bb9576f5-ljsm7

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.6
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:80
{"level":"info","ts":1537626936.8119755,"caller":"go-webapi-for-gke-study/main.go:21","msg":"INFO LEVEL with severity","severity":"INFO"}
{"level":"warn","ts":1537626936.8120918,"caller":"go-webapi-for-gke-study/main.go:22","msg":"WARN LEVEL with severity","severity":"WARN"}
{"level":"error","ts":1537626936.8121026,"caller":"go-webapi-for-gke-study/main.go:23","msg":"ERROR LEVEL with severity","severity":"ERROR","stacktrace":"main.main.func1\n\t/go/src/github.com/sky0621/go-webapi-for-gke-study/main.go:23\ngithub.com/sky0621/go-webapi-for-gke-study/vendor/github.com/labstack/echo.(*Echo).Add.func1\n\t/go/src/github.com/sky0621/go-webapi-for-gke-study/vendor/github.com/labstack/echo/echo.go:480\ngithub.com/sky0621/go-webapi-for-gke-study/vendor/github.com/labstack/echo.(*Echo).ServeHTTP\n\t/go/src/github.com/sky0621/go-webapi-for-gke-study/vendor/github.com/labstack/echo/echo.go:583\nnet/http.serverHandler.ServeHTTP\n\t/usr/local/go/src/net/http/server.go:2619\nnet/http.(*conn).serve\n\t/usr/local/go/src/net/http/server.go:1801"}
</pre>

##### Stackdriver Logging上でもログ出力を確認
![02.png](https://qiita-image-store.s3.amazonaws.com/0/180599/865c2515-aa92-37c6-2436-3cbb42ff6e83.png)

## ■ログのエクスポート

[参考]
https://cloud.google.com/logging/docs/export/
https://cloud.google.com/logging/docs/export/configure_export_v2

ログのエクスポートをするためには、「シンク」というものを作成する必要がある。
「シンク」によって、Stackdriver Loggingに流れてくるログのうち、”どのようなログ”を”どこ”にエクスポートするかが決められる。

### １）「シンク」によるエクスポート先としてGCSのバケットを作っておく
![04.png](https://qiita-image-store.s3.amazonaws.com/0/180599/f3505aad-2e8b-8ac5-3d29-c72b22001650.png)
![05.png](https://qiita-image-store.s3.amazonaws.com/0/180599/1cf71bcb-8079-e142-d761-dadf486257b6.png)
![06.png](https://qiita-image-store.s3.amazonaws.com/0/180599/f37d1fda-8b95-d93c-0e9a-9d20b1cf315b.png)

### ２）ログビューアによる「シンク」の作成
![03.png](https://qiita-image-store.s3.amazonaws.com/0/180599/5e571dc7-cfb8-947e-5424-b3abb2532ec2.png)
![07.png](https://qiita-image-store.s3.amazonaws.com/0/180599/f5640985-b800-879c-35b0-f5a7bbd9753f.png)
もろもろ埋める。
**ログレベルとして「ERROR」のものをGCSの先ほど作成したバケットにエクスポートする指定でシンク作成**
![08.png](https://qiita-image-store.s3.amazonaws.com/0/180599/d3d47beb-b739-d4f0-32b2-88e1b7ccfc92.png)
![09.png](https://qiita-image-store.s3.amazonaws.com/0/180599/bec09248-3359-95e3-e2bf-dd343cfbda17.png)
![10.png](https://qiita-image-store.s3.amazonaws.com/0/180599/bc3a7902-2678-cb4b-1153-b9d9a788c4cf.png)

### ３）ログがGCSに溜まるか確認
実際に溜まっていることを確認しようとしたが、GCSの場合は[１時間単位でまとめて送信される](https://cloud.google.com/logging/docs/export/using_exported_logs)（なんなら初回は２〜３時間かかることもあるとのこと）そうなので、いったん送信まで待つ。

ちなみに、ログのエクスポート先としてはGCSの他にBigQueryとCloud Pub/Subがある。
こちらであれば、GCSと違って即時送信であるらしい。
ということで、GCSへの送信を待っている間に、Cloud Pub/Subへのエクスポートを試してみよう。

### ４）Cloud Pub/Subにトピックとサブスクリプションを作成
##### トピックを作成
![11.png](https://qiita-image-store.s3.amazonaws.com/0/180599/6a4ff8ca-22b3-d5c4-e0e3-81f0478f4f3e.png)
![12.png](https://qiita-image-store.s3.amazonaws.com/0/180599/e00aee99-82fd-cd3e-3b7b-92605a99ed85.png)

##### サブスクリプションを作成
![13.png](https://qiita-image-store.s3.amazonaws.com/0/180599/92f34f21-bd99-8b95-fb54-c6428fa0c4e3.png)
![14.png](https://qiita-image-store.s3.amazonaws.com/0/180599/6ed1542b-f754-6ead-ddd3-c197d7e3fe2d.png)

### ５）Cloud Pub/Subへエクスポートする「シンク」を作成
![15.png](https://qiita-image-store.s3.amazonaws.com/0/180599/6ac09930-b7d0-9bd4-8b01-44915ad9dc9d.png)

### ６）ログがCloud Pub/Subに溜まるか確認
<pre>
$ gcloud pubsub subscriptions list
---
ackDeadlineSeconds: 10
messageRetentionDuration: 604800s
name: projects/【プロジェクトID】/subscriptions/my-ss-sink
pushConfig: {}
topic: projects/【プロジェクトID】/topics/my-tpc-sink
</pre>
<pre>
$ gcloud pubsub subscriptions pull projects/fs-work-1978/subscriptions/my-ss-sink --auto-ack
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────────────┬───────────────────────────────────────────────────────┐
│                                                                                                                                                                                                                                                                                                                                                                                                                                                                DATA                                                                                                                                                                                                                                                                                                                                                                                                                                                                │    MESSAGE_ID   │                       ATTRIBUTES                      │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────────────┼───────────────────────────────────────────────────────┤
│ {"insertId":"ftl347f6mk9e0","jsonPayload":{"caller":"go-webapi-for-gke-study/main.go:22","level":"warn","msg":"WARN LEVEL with severity","ts":1537631639.4484},"labels":{"compute.googleapis.com/resource_name":"fluentd-gcp-v2.0.17-j26ns","container.googleapis.com/namespace_name":"default","container.googleapis.com/pod_name":"go-webapi-for-gke-study-server-56bb9576f5-ljsm7","container.googleapis.com/stream":"stderr"},"logName":"projects/fs-work-1978/logs/go-webapi-for-gke-study-server","receiveTimestamp":"2018-09-22T15:54:04.187127526Z","resource":{"labels":{"cluster_name":"my-cluster-1-min","container_name":"go-webapi-for-gke-study-server","instance_id":"2599213054701599462","namespace_id":"default","pod_id":"go-webapi-for-gke-study-server-56bb9576f5-ljsm7","project_id":"fs-work-1978","zone":"asia-northeast1-a"},"type":"container"},"severity":"WARNING","timestamp":"2018-09-22T15:53:59Z"} │ 211335298657122 │ logging.googleapis.com/timestamp=2018-09-22T15:53:59Z │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────┴───────────────────────────────────────────────────────┘
</pre>
想定通り、WARNレベルのログだけが溜まってた。

# まとめ
お遊びや勉強用にGCP使っている分には不要だけど、プロダクションとしてはログの退避は必須なので、ここは覚えておくべき事柄。
ちなみに ```gcloudコマンド```使う場合は下記参照。
https://cloud.google.com/logging/docs/reference/tools/gcloud-logging#exporting_logs

GCSの方は、まだ送信されないので、送信されたらこの記事は更新することにして、いったん公開しよう。

[追記]
GCSにERRORレベルのログが集約されたJSONファイルが出力されていることを確認
![16.png](https://qiita-image-store.s3.amazonaws.com/0/180599/1fa96f0c-dabd-e358-fe1d-fbed63a35b7d.png)