スクリーンショット_2019-07-20_6

Prometheus likeなログ収集、Grafana Loki

本記事

この記事は2019年7月20日に執筆したものです。

本記事では、まだ公開後1年も立っていないGrafana LokiがもうすぐGAに入るかもしれない、という記事を拝見して、Grafana Lokiを検証してみた話です。今までGrafanaは業務以外の機会でよく使っていましたが、今回はProduction環境で使えるかどうかを、いろんなサービスと比較しながら記事を書いていこうと思います。

また、本記事ではLoki-canaryという機能を使ってLoki自体のローリングアップデートも安全に行える仕組みを解説します。

Metric, Logs and Traces

Kubecon 2019 Europeに以下のようなセッションがありました。

本記事での注目点をまとめます。

Metrics, LogsとTracesの3つは以下のような関係図であり、つまり方向性があるということです。

Metricsを見てログを見ることはあるでしょう。「あれ、エラーレートが高い」となってログをみて原因を探すというようにです。そして、ログをもとに、どのようなリクエストが分散システムでSystemでどのようになっているのかを探求する。という方向性です。Grafana Lokiを使えばよりいい相関を知ることができるのではないかという可能性がLokiの開発のモチベーションとのことです。

またGoogle自体もObservabilityとはMetrics, Logs, and Tracesであると言っています。Observabilityとは単に集めることではなくて、SLOやそれを損なうIncidentというような、信頼性に帰着することが大事です。繰り返しですが、そのようなためにも相関を見つける必要があるのです。

これより、実際にやっていきましょう。

検証環境

$ date
2019716日 火曜日 222611秒 JST

$ uname -v 
Darwin Kernel Version 18.5.0: Mon Mar 11 20:40:32 PDT 2019; root:xnu-4903.251.3~3/RELEASE_X86_64

Grafana Lokiとは

Grafana LokiとはPrometheusのようにLogを収集して、Grafanaで可視化するためのソフトウェアです。

PrometheusがMetricsを収集していたのに対して、Grafana LokiはLogを収集することが違います。

いくつかログ収集をしてくれるソフトウェアがある中で、

・テキストすべてにインデックスを貼るのではなくて、ログを圧縮して、メタデータに対してインデックスを貼るので、簡単に操作して運用できる。PrometheusのService Discoveryを使用している
・ログストリームにPrometheusのようにハグを貼ることができ、ログとメトリクスに同様のタグをはることができます。
・Kubernetesと相性がいい。Podのラベルを自動でラベルとして貼り付ける。

アーキテクチャ

可視化まで入れると、3つの構成要素でロギング基盤を構築することができます。

1. promtailというAgentがApplicationの(デフォルトでは)標準出力からログを収集して、ラベルを付与してLokiに対してログを転送
2. GrafanaはLokiからログを取り出して可視化

Grafana環境の構築

これより、ロギング基盤としてGrafana環境を整えていきます。

Applicationのデプロイ

以前のMercari Tech BlogでTelepresenceを検証するために使用したGolangアプリケーションをベースに進めていきましょう。皆さんも簡単にマイクロサービスを構築することができます。

このリポジトリのMakefileを使いたければHelm3.0-alpha版を使う必要があるのですが、競合をさけるために以下のようにします。macOSの場合は以下のようにしてください。

$ wget https://get.helm.sh/helm-v3.0.0-alpha.1-darwin-amd64.tar.gz
$ tar zxvf helm-v3.0.0-alpha.1-darwin-amd64.tar.gz
$ cp darwin-amd64/helm /usr/local/bin/helm3

他のOSは、次のリポジトリからダウンロードしてください。

まず、GKEクラスタを作成します。Loggerを追加したバージョンはimpl-loggingブランチにあるので、そちらを使用してください。注意点ですがTech Blogと違って、今回はCPUが幾分必要なため、Node数を変更してある(1->5)ので注意をしてください。

$ git checkout impl-logging
$ make init

そしてDocker Imageを作成し、GCRへPushします。

$ make build

次のステップでSecretが必要となるので、それを作成します。

$ echo "apiVersion: v1
kind: Secret
metadata:
 name: mysecret
type: Opaque
stringData:
 .env: |-
   SECRET_MESSAGE_PREFIX=Yeah" > secret.yml
$ kubectl apply -f secret.yml

そして、Helmを使ってデプロイをします。

$ make deploy

そして確認をしてみます。

$ kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
service-a-764ff58c48-5cgdw   1/1     Running   0          25s
service-b-78d966498-bnw9v    1/1     Running   0          24s

$ kubectl get services
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)          AGE
kubernetes   ClusterIP      10.60.0.1      <none>          443/TCP          44m
service-a    LoadBalancer   10.60.13.140   104.198.83.18   5050:30114/TCP   84s
service-b    ClusterIP      10.60.11.135   <none>          5100/TCP         83s​

試しにリクエストを送ってみましょう。

$ HOST=$(kubectl get svc service-a -o jsonpath="{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}")
$ curl -X POST 35.243.97.57:5050/api/serviceA -d '{"message":"Hi"}' | jq .
{
 "env": "test",
 "message": "Yeah Hi"
}

以下のようにLogが標準出力されます。

$ stern service
...
8-whs56 service-a {"level":"info","ts":1563279779.750329,"caller":"greet-service-api/main.go:17","msg":"handling request"}

PromtailとLokiのデプロイ

同様にHelm3を使用していきます。まずLokiのChart repositoryを登録してください。

$ helm3 repo add loki https://grafana.github.io/loki/charts; helm3 repo update

そしてHelmを使ってデプロイします。

$ helm3 install loki loki/loki-stack
NAME: loki
LAST DEPLOYED: 2019-07-16 21:38:15.989851 +0900 JST m=+0.317420819
NAMESPACE: default
STATUS: deployed

NOTES:
The Loki stack has been deployed to your cluster. Loki can now be added as a datasource in Grafana.

See http://docs.grafana.org/features/datasources/loki/ for more detail.​

Deploymentなど他のものもインストールされていますが、DaemonSetsとStatefulSetsは以下のようにインストールされています。

Grafanaのデプロイ

以下のようにGrafanaをデプロイします。

$ helm3 install grafana stable/grafana

UIへアクセスするためにPasswordをします。

$  kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

そして、ポート転送してアクセスします。

$ POD_NAME=$(kubectl get pods --namespace default -l "app=grafana,release=grafana" -o jsonpath="{.items[0].metadata.name}")z
$ kubectl --namespace default port-forward $POD_NAME 3000

そして以下の設定します。

Logを見てみる

以下の例では、Application nameでlogを可視化しています。

また、コンテナ名でも取得することができます。

また標準エラー出力でも取得できます。

また、Textに対して検索をかけることもできます。

 {app_kubernetes_io_name="service-a"}(duration|latency)\s*(=|is|of)\s*[\d\.]+

また、現在LokiはGrafana Dashboardでは可視化がまだできないことに注意が必要です。つまり「ログを検索できる」サービスであることが分かります。

Prometheusのと相性

現時点ではGrafana DashboardにLokiで収集したLogを可視化をすることはできないので、PrometheusでMetricを集めたとしても相関を見ることは簡単ではないでしょう。しかしながら、開発方針としてはPrometheusがMetricsにつけるようにLogにも同じタグを付けるので、相性のよいものに必然的になるでしょう。

またLoki自体のモニタリングも/metricsというパスがあるのでMetricを簡単に取得できます。

Loki Canary

Lokiをローリングアップデートしていると、どうしてもログが失われてしまうケースがあります。

そのようなときにLokiへログがきていないことを通知する仕組みが必要です。仕組みとしては以下のとおりです。

1. Loki-canaryが定期的にログを書き込み、PromtailがこのログをLokiへ送信する
2. Loki-canaryはlokiへWebsocketを通してログをTailします。
3. 1と2を通してログが収集できているか確認します

ログがどのくらい失われているかを検証できる仕組みです。

まとめ

今回はGrafana Lokiを使ってLog収集をしました。Prometheusのように簡単にアプリケーションのログを収集し、Metricsと整合性のいい形でタグをつけることができて、非常に便利であると感じました。

しかしながら、Dashboardで可視化をすることができなかったり、するので機能としてはまだ不十分であると感じます。

しかしSREとして入社してから、より強くMetricとLogは補完的なものであり、Incidentをはじめとしてあらゆるリバースエンジニアリングのお道具箱として活躍することを確信しているので、モニタリングをする上ではログ収集や可視化は必要不可欠なものです

最後までありがとうございました。

参考文献


この記事が気に入ったら、サポートをしてみませんか?気軽にクリエイターを支援できます。

10
merpay.inc 新卒SRE / Chaos EngineeringとCashlessに関心があります