このページでは、Grafana ユーザー インターフェースを使用してログをクエリして可視化し、サービス イベントとアクティビティに関する分析情報を取得する方法について詳しく説明します。
Google Distributed Cloud(GDC)エアギャップ アプライアンスにデプロイされたワークロードとサービスからログを収集したら、分析を開始できます。ログを分析するには、情報提供用の Grafana パネルでログを可視化してフィルタするか、プログラムによるアクセス用に gRPC 呼び出しを行います。
ログには次の方法でアクセスできます。
- Grafana パネル: Grafana インスタンスのログパネルを使用して、プロジェクトのアクティビティ レコードに関する分析情報を取得します。このパネルでは、特定のログをクエリして特定できるため、ニーズに合わせて調整されたきめ細かいデータ オブザーバビリティを実現できます。Grafana は、ワークロード データのフィルタリングと分析、包括的な可視化のためのカスタマイズされたダッシュボードとパネルの作成を行うためのユーザー フレンドリーなインターフェースを提供します。
始める前に
Grafana ユーザー インターフェースでログをクエリして可視化するために必要な権限を取得するには、組織の IAM 管理者またはプロジェクトの IAM 管理者に、事前定義された組織の Grafana 閲覧者ロールまたはプロジェクトの Grafana 閲覧者ロールのいずれかを付与するよう依頼します。必要なアクセスレベルと権限に応じて、組織またはプロジェクトで Grafana ロールを取得できます。
または、Log Query API からログをクエリするために必要な権限を取得するには、プロジェクトの IAM 管理者に、プロジェクトの Namespace で Log Query API Querier ロールを付与するよう依頼します。
これらのロールの詳細については、IAM 権限を準備するをご覧ください。
ログのクエリを作成する
システム モニタリング インスタンスの UI からログをクエリすると、プロジェクトから運用ログを取得するデータソースを選択し、クエリの統合ビューを取得できます。結果をフィルタリングするには、クエリ言語式を使用してラベルでログを検索します。たとえば、クエリで cluster ラベルと namespace ラベルを、それぞれクラスタとプロジェクトの Namespace を識別する値に設定できます。
システム モニタリング インスタンス エンドポイント
アプリケーション オペレーター(AO)向け
次の URL は、プロジェクトのモニタリング インスタンスのエンドポイントです。
https://GDC_URL/PROJECT_NAMESPACE/grafana
次のように置き換えます。
- GDC_URL: GDC 内の組織の URL。
- PROJECT_NAMESPACE: プロジェクトの Namespace。
プラットフォーム管理者(PA)向け
次の URL は、プロジェクトのモニタリング インスタンスのエンドポイントです。
https://GDC_URL/platform-obs/grafana
GDC_URL は、GDC の組織の URL に置き換えます。
ログのクエリとフィルタ
次のいずれかの方法を選択して、クエリを作成し、プロジェクト ワークロードからログをフィルタします。
このセクションでは、Grafana の [ログ] パネルを使用してログにアクセスする方法について説明します。
Grafana エンドポイントを特定する
アプリケーション オペレーター(AO)向け
次の URL は、プロジェクトのモニタリング インスタンスのエンドポイントです。
https://GDC_URL/PROJECT_NAMESPACE/grafana
次のように置き換えます。
- GDC_URL: GDC 内の組織の URL。
- PROJECT_NAMESPACE: プロジェクトの Namespace。
プラットフォーム管理者(PA)向け
次の URL は、プロジェクトのモニタリング インスタンスのエンドポイントです。
https://GDC_URL/platform-obs/grafana
GDC_URL は、GDC の組織の URL に置き換えます。
Grafana ユーザー インターフェースでログを表示する
Grafana ユーザー インターフェースでログをクエリします。
- GDC コンソールで、プロジェクトを選択します。
- ナビゲーション メニューで、[オペレーション] > [ロギング] を選択します。
- [Grafana Loki で全て表示] をクリックします。
新しいページで Grafana エンドポイントが開き、ユーザー インターフェースが表示されます。
- ユーザー インターフェースで、ナビゲーション メニューの [Explore] Explore をクリックして、[Explore] ページを開きます。
- [Explore] バーのメニューから、ユニバースのタイプに応じて、ログを取得するデータソースを選択します。
単一ゾーンのユニバース: 次のいずれかのデータソースを選択して、ユニバースの単一ゾーンのロギング データを表示します。
オペレーション ログ: オペレーション ログを表示します。
監査ログ: 監査ログを表示します。
オペレーション ログ ZONE_NAME: 特定のゾーンのオペレーション ログを表示します。
監査ログ ZONE_NAME: 特定のゾーンの監査ログを表示します。
また、単一のダッシュボードでゾーン間のデータ可視化を行い、クエリに複数のゾーンを追加するには、データソースとして [混合] を選択します。
LogQL(ログクエリ言語)式を使用して、ログパネルからログを検索するクエリを入力します。この手順は、次のいずれかの方法で行います。
- インタラクティブなクエリビルダー インターフェースを使用します。[クエリを実行] をクリックします。
- テキスト フィールドにクエリを直接入力し、Shift+Enter キーを押してクエリを実行します。
クエリに一致するログがページに表示されます。ログをクエリした後、ログをエクスポートできます。[エクスポート] をクリックして、ログをプレーン テキストまたは CSV 形式でダウンロードします。ログの期間を選択することもできます。
![[監査ログ] オプションが [探索] ページで選択され、監査ログが取得されます。](https://docs.cloud.google.com/static/distributed-cloud/hosted/docs/latest/appliance/platform/images/audit-logs-ui.png?hl=ja)
図 1: Grafana ユーザー インターフェースから監査ログをクエリするメニュー オプション。
図 1 の [監査ログ] オプションには、Grafana からクエリを作成して監査ログを取得できるインターフェースが表示されます。
さまざまなログをクエリするラベルと値の例については、サンプルクエリとラベルをご覧ください。
ログの期間を選択する
特定の期間のログをクエリする手順は次のとおりです。
Grafana で [Time Picker] メニューをクリックします。
メニューから、次のいずれかの操作を行います。
- 相対的な時間範囲オプション(過去 30 分など)を選択します。
- カレンダーから特定の日時を選択し、[期間を適用] をクリックして、カスタムの絶対期間を設定します。
必要に応じて、[時間設定を変更] をクリックして、期間コントロールからタイムゾーンと会計年度の設定を変更します。
期間設定はダッシュボードごとに保存されます。一定期間のクエリの詳細については、https://grafana.com/docs/loki/latest/reference/api/#query-loki-over-a-range-of-time をご覧ください。
クエリを送信する
HTTP クライアントまたは gRPC クライアントを使用して、ログクエリ API エンドポイントにクエリを送信します。
HTTP
手順に沿って HTTP クライアントで API に直接アクセスします。
kubectlに認証の管理を任せるか、自分で認証を処理できます。curl、wgetなどの HTTP クライアント、または作成して管理する HTTP クライアントを使用して、Log Query API をクエリします。次の例では、curlツールを使用して API をクエリしています。wgetコマンドでも同様の形式を使用できます。cURL リクエストを認証します。
- gdcloud CLI をダウンロードしてインストールします。
gdcloud の
core/organization_console_urlプロパティを設定します。gdcloud config set core/organization_console_url https://GDC_URLGDC_URLは、GDC の組織の URL に置き換えます。-
gdcloud auth login ユーザー名とパスワードを使用して認証し、ログインします。
指定したアカウントの ID トークンを環境変数にエクスポートします。
export TOKEN="$($HOME/gdcloud auth print-identity-token --audiences=https://LOG_QUERY_API_ENDPOINT)"LOG_QUERY_API_ENDPOINTは、ログのクエリ元となる Log Query API エンドポイントと、接続するドメインに置き換えます。そのため、audiencesフラグの値は、たとえばhttps://operational-log-query-api.org-1.zone1.google.gdch.testになります。ログインに成功すると、
gdcloud auth print-identity-tokenコマンドを使用して cURL リクエストで認証ヘッダーを使用できます。詳細については、gdcloud auth print-identity-token をご覧ください。
プロジェクトのすべてのラベルを一覧表示する場合は、次のクエリを送信します。
curl -H "Authorization: Bearer ${TOKEN}" \ https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels \ -H "Content-Type: application/json" -v次のように置き換えます。
LOG_QUERY_API_ENDPOINT: ログのクエリ元となる ログクエリ API エンドポイント。PROJECT_NAMESPACE: プロジェクトの Namespace。
プロジェクトの特定のラベル値を一覧表示する場合は、次のクエリを送信します。
curl -H "Authorization: Bearer ${TOKEN}" \ https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels/labels/LABEL/values \ -H "Content-Type: application/json" -v次のように置き換えます。
LOG_QUERY_API_ENDPOINT: ログのクエリ元となる ログクエリ API エンドポイント。PROJECT_NAMESPACE: プロジェクトの Namespace。LABEL: 値をクエリする特定のラベル。
特定のプロジェクトのログをクエリする場合は、
logs_filterクエリを作成して、リクエストの本文に含めます。curl -X GET -H "Authorization: Bearer ${TOKEN}" \ https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/logs \ -H "Content-Type: application/json" -d \ '{"logs_filter": {"labels_equal": {"LABEL": "LABEL_VALUE"}}}' -v次のように置き換えます。
LOG_QUERY_API_ENDPOINT: ログのクエリ元となる ログクエリ API エンドポイント。PROJECT_NAMESPACE: プロジェクトの Namespace。LABEL: ログのクエリを行う特定のラベル。LABEL_VALUE: ログのクエリを行うラベル値。
logs_filterクエリの作成に関するすべてのオプションについては、API ドキュメントをご覧ください。
gRPC
gRPC は、さまざまなプログラミング言語で広くサポートされており、HTTP クライアントよりも効率的な通信方法を提供します。
gRPC を使用してログをクエリするには、次の前提条件を満たす必要があります。
- Google 提供のプロトコル バッファに基づいて独自のクライアント ライブラリを作成します。
- クライアントで認証を実装します。
- 再試行を実装します。
プロトコル バッファについては、API ドキュメントをご覧ください。
次の例は、認証されていない gRPC クライアントを使用して Go プログラムからログをクエリする方法を示しています。この例では、コードの依存関係をインポートする Bazel ビルドファイルを含む golang パッケージを作成したことを前提としています。
次のコードを
client.goという名前の Go プログラムに保存します。package main import ( "context" "crypto/tls" "flag" "fmt" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" pb "<import path to generated log query api protos>/pkg/apis/public/logging/v1/proto" "google.golang.org/grpc" ) var serverAddr = flag.String("server", "localhost:8080", "server address") func main() { flag.Parse() tc := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) conn, err := grpc.Dial(*serverAddr, grpc.WithTransportCredentials(tc)) if err != nil { panic(error.Error(fmt.Errorf("create client connection failed: %v", err))) } defer conn.Close() c := pb.NewLogsClient(conn) md := metadata.Pairs("clienttest", "test") ctx := metadata.NewOutgoingContext(context.Background(), md) err = listLabels(ctx, c, "project-foo") if err != nil { panic(error.Error(err)) } if err := listLabelValues(ctx, c, "project-foo", "resource-bar"); err != nil { panic(error.Error(err)) } if err := listLogs(ctx, c, "project-foo", &pb.ListLogsFilter{ LabelsEqual: map[string]string{"resource-bar": "resource-bar-value"}, OrderAscending: true, }); err != nil { panic(error.Error(err)) } } // List all labels for a project. func listLabels(ctx context.Context, c pb.LogsClient, project string) error { lbr := &pb.ListLabelsRequest{ Parent: project, PageSize: 1000, // PageSize can be configured to limit the number of responses per page. } resp, err := c.ListLabels(ctx, lbr) if err != nil { return fmt.Errorf("list labels: %v", err) } fmt.Printf("%v", resp) return nil } // List specific label values for a project. func listLabelValues(ctx context.Context, c pb.LogsClient, project string, label string) error { lbr := &pb.ListLabelValuesRequest{ Parent: project, Label: label, PageSize: 1000, // PageSize can be configured to limit the number of responses per page. } resp, err := c.ListLabelValues(ctx, lbr) if err != nil { return fmt.Errorf("list label values: %v", err) } fmt.Printf("%v", resp) return nil } // List logs for a specific project. func listLogs(ctx context.Context, c pb.LogsClient, project string, lf *pb.ListLogsFilter) error { lbr := &pb.ListLogsRequest{ Parent: project, LogsFilter: lf, PageSize: 5, // PageSize can be configured to limit the number of responses per page. } resp, err := c.ListLogs(ctx, lbr) if err != nil { return fmt.Errorf("list logs: %v", err) } fmt.Printf("logs: %v", resp) return nil }Go プログラムを実行します。
go run PATH_TO_API/client.go -server=LOG_QUERY_API_ENDPOINT:443次のように置き換えます。
PATH_TO_API: API ファイルのパス。LOG_QUERY_API_ENDPOINT: ログのクエリ元となる ログクエリ API エンドポイント。
サーバーフラグが指定されていない場合、デフォルトのリクエストは
localhostに到達します。
サンプルクエリとラベル
ログのクエリに使用できるデフォルトのラベルを次に示します。
cluster: クラスタの名前。namespace: プロジェクトの Namespace。node: ノード名。pod: Pod 名。container: コンテナ名。
次のコードサンプルは、ラベルと値を使用してさまざまなログをクエリする方法を示しています。
サーバーログを選択します。
{cluster="admin", namespace="kube-system", resources="k8s_container", container="kube-apiserver"}クラスタ監査ログを選択します。
{cluster="admin", resources="k8s_audit"}