このページでは、Grafana ユーザー インターフェースと Log Query API の両方を使用してログをクエリして可視化し、サービス イベントとアクティビティに関する分析情報を取得する方法について詳しく説明します。
Google Distributed Cloud(GDC)エアギャップにデプロイされたワークロードとサービスからログを収集したら、ログの分析を開始できます。ログを分析するには、有益な Grafana パネルでログを可視化してフィルタするか、HTTP または gRPC 呼び出しを使用して Log Query API から直接ログにアクセスして、プログラムでアクセスします。
ログにアクセスするには、次の 2 つの方法のいずれかを使用します。
- Grafana パネル: Grafana インスタンスのログパネルから、プロジェクトのアクティビティ レコードに関する分析情報を取得します。このパネルでは、特定のログをクエリして特定できるため、ニーズに合わせたきめ細かいデータ オブザーバビリティを実現できます。Grafana は、ワークロード データのフィルタリングと分析、包括的な可視化のためのカスタマイズされたダッシュボードとパネルの作成を行うためのユーザー フレンドリーなインターフェースを提供します。
- Log Query API: プログラムでアクセスする場合は、プロジェクトの Log Query API から直接ログをクエリします。ログクエリ API は、HTTP と gRPC をサポートする非 Kubernetes API であり、独自のエンドポイントを公開します。標準の API アクセス方法に従って、Distributed Cloud の特定の組織内でのみこの API にアクセスします。
始める前に
ログにクエリを実行して可視化するには、必要な権限が必要です。
IAM 組織ロールをリクエストする
組織の IAM 管理者に連絡して、次のロールをリクエストします。
- 組織 Grafana 閲覧者(
organization-grafana-viewer): Grafana モニタリング インスタンスのダッシュボードで、組織に関連するオブザーバビリティ データを可視化します。 - ログクエリ(
log-query-api-querier-pa): Log Query API にアクセスして、platform-obsプロジェクトのプラットフォーム ログをクエリします。
IAM プロジェクト ロールをリクエストする
プロジェクトの IAM 管理者に連絡して、次のロールをリクエストしてください。
- プロジェクト Grafana 閲覧者(
project-grafana-viewer): プロジェクトの名前空間にある Grafana モニタリング インスタンスのダッシュボードで、プロジェクト関連のオブザーバビリティ データを可視化します。 - ログクエリ(
log-query-api-querier): Log Query API にアクセスして、プロジェクト Namespace のアプリケーション ログをクエリします。
次の表に、PA と AO のペルソナの Role 要件をまとめます。
| ペルソナ | オブジェクト | クラスタ | ロール | 名前空間 | グループ / ユーザー |
|---|---|---|---|---|---|
| PA | grafana |
管理 API サーバー | project-grafana-viewer |
platform-obs |
グループ |
| PA | log-query-api |
管理 API サーバー | log-query-api-querier-pa |
platform-obs |
グループ |
| PA | grafana |
管理 API サーバー | project-grafana-viewer |
platform-obs |
ユーザー |
| PA | log-query-api |
管理 API サーバー | log-query-api-querier-pa |
platform-obs |
ユーザー |
| AO | grafana |
管理 API サーバー | project-grafana-viewer |
PROJECT_NAMESPACE |
グループ |
| AO | log-query-api |
管理 API サーバー | log-query-api-querier |
PROJECT_NAMESPACE |
グループ |
| AO | grafana |
管理 API サーバー | project-grafana-viewer |
PROJECT_NAMESPACE |
ユーザー |
| AO | log-query-api |
管理 API サーバー | log-query-api-querier |
PROJECT_NAMESPACE |
ユーザー |
次のいずれかの構成を選択して、管理 API サーバーのユーザー グループ(Config 1)または個々のユーザー(Config 2)に Grafana へのアクセス権を付与します。構成ごとに、kubectl コマンドを実行して RoleBinding を直接作成するか、RoleBinding YAML マニフェストを指定された Infrastructure as Code(IaC)ファイルパスに保存して GitOps を介して適用できます。
構成 1
この構成により、管理 API サーバー上の PA Grafana と AO Grafana にアクセスする権限がユーザー グループに付与されます。この構成を設定したら、このドキュメントの Grafana ダッシュボード セクションを参照して、Grafana でログを表示します。
kubectl コマンド
次のコマンドを実行して、
RoleBindingを直接作成します。kubectl --kubeconfig KUBECONFIG create rolebinding RULE_NAME -n platform-obs --group=GROUP_NAME --role=project-grafana-viewer例:
kubectl --kubeconfig KUBECONFIG_PATH create rolebinding project-grafana-viewers-binding --role=project-grafana-viewer --group=my-team --namespace=platform-obsIaC ファイルパス
または、IaC を使用して
RoleBindingを管理するには、次のパスに YAML ファイルを作成します。/infrastructure/zonal/zones/ZONE/org-admin/rolebindings/GROUP_NAME/YAML_FILEYAML ファイル
次の
RoleBindingマニフェストを IaC ファイルパスの YAML ファイルに保存します。apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: RULE_NAME namespace: platform-obs subjects: - kind: Group name: GROUP_NAME apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: project-grafana-viewer apiGroup: rbac.authorization.k8s.io
構成 2
この構成により、ユーザーは Management API サーバー上の PA と AO Grafana にアクセスする権限が付与されます。この構成を設定したら、このドキュメントの Grafana ダッシュボード セクションを参照して、Grafana でログを表示します。
kubectl コマンド
次のコマンドを実行して、
RoleBindingを直接作成します。kubectl --kubeconfig KUBECONFIG create rolebinding RULE_NAME -n platform-obs --user=EMAIL_ADDRESS --role=project-grafana-viewer例:
kubectl --kubeconfig KUBECONFIG_PATH create rolebinding project-grafana-viewers-binding --role=project-grafana-viewer --user=my-email@example.com --namespace=platform-obsIaC ファイルパス
または、IaC を使用して
RoleBindingを管理するには、次のパスに YAML ファイルを作成します。/infrastructure/zonal/zones/ZONE/org-admin/rolebindings/EMAIL_ADDRESS/YAML_FILEYAML ファイル
次の
RoleBindingマニフェストを IaC ファイルパスの YAML ファイルに保存します。apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: RULE_NAME namespace: platform-obs subjects: - kind: User name: EMAIL_ADDRESS apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: project-grafana-viewer apiGroup: rbac.authorization.k8s.io
次のように置き換えます。
KUBECONFIG: このRoleBindingが適用されるNAMESPACEを含む特定のクラスタの kubeconfig ファイルのパス。KUBECONFIG_PATH: サンプル コマンドの kubeconfig ファイルのパス。RULE_NAME: Namespace 内のこのRoleBindingリソースの一意の名前(pa-project-grafana-viewerなど)。NAMESPACE: このRoleBindingが作成され、適用される Kubernetes Namespace。前の表のNamespace列を探します。EMAIL_ADDRESS: ロールを付与するユーザーの ID(application-operator@example.comなど)。ROLE: ユーザーに付与する権限を含むRoleの名前。前の表に記載されているロールを探します。GROUP_NAME: PA ユーザーが属するGroupの名前(pa-groupなど)。ZONE: ゾーンの名前。YAML_FILE:RoleBindingリソースの YAML ファイルの名前。
これらのロールの詳細については、IAM 権限を準備するをご覧ください。
ログのクエリとフィルタ
次のいずれかの方法を選択して、クエリを作成し、プロジェクト ワークロードからログをフィルタします。
Grafana ログパネル
このセクションでは、Grafana のログパネルを使用してログにアクセスする方法について説明します。
Grafana エンドポイントを特定する
次の URL は、プロジェクトの Grafana インスタンスのエンドポイントです。
https://GDC_URL/PROJECT_NAMESPACE/grafana
次のように置き換えます。
GDC_URL: GDC の組織の URL。PROJECT_NAMESPACE: プロジェクトの Namespace。たとえば、
org-1組織のplatform-obsプロジェクトの Grafana エンドポイントはhttps://org-1/platform-obs/grafanaです。
Grafana ユーザー インターフェースでログを表示する
Grafana ユーザー インターフェースでログをクエリします。
- GDC コンソールで、プロジェクトを選択します。
- ナビゲーション メニューで、[オペレーション] > [ロギング] を選択します。
[View all in Grafana Loki] をクリックします。
新しいページが開き、Grafana エンドポイントとユーザー インターフェースが表示されます。
ユーザー インターフェースで、ナビゲーション メニューから explore [Explore] をクリックして、[Explore] ページを開きます。
[Explore] バーのメニューから、ユニバースのタイプに応じてログを取得するデータソースを選択します。
シングルゾーン ユニバース: 次のいずれかのデータソースを選択して、ユニバースのシングルゾーンのロギングデータを表示します。
- オペレーション ログ: オペレーション ログを表示します。
- 監査ログ: 監査ログを表示します。
マルチゾーン ユニバース: Grafana は、異なるゾーンに接続して、ゾーン間のデータを表示できます。次のいずれかのデータソースを選択すると、ログインしているゾーンに関係なく、ユニバースの任意のゾーンのロギング データを表示できます。
- オペレーション ログ ZONE_NAME: 特定のゾーンのオペレーション ログを表示します。
- 監査ログ ZONE_NAME: 特定のゾーンの監査ログを表示します。
また、単一のダッシュボードでゾーン間のデータ可視化を行い、クエリに複数のゾーンを追加するには、データソースとして [混合] を選択します。
LogQL(Log Query Language)式を使用して、[ログ] パネルからログを検索するクエリを入力します。この手順は、次のいずれかの方法で行います。
- インタラクティブなクエリビルダー インターフェースを使用します。[クエリを実行] をクリックします。
- テキスト フィールドにクエリを直接入力し、Shift+Enter キーを押してクエリを実行します。
クエリに一致するログがページに表示されます。ログのクエリを実行した後、ログをエクスポートできます。[エクスポート] をクリックして、ログを書式なしテキストまたは CSV 形式でダウンロードします。ログの期間を選択することもできます。
![[監査ログ] オプションが [探索] ページで選択され、監査ログが取得されます。](https://docs.cloud.google.com/static/distributed-cloud/hosted/docs/latest/gdcag/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 をご覧ください。
Log Query API
このセクションでは、Log Query API を使用してログにアクセスする方法について説明します。
Log Query API エンドポイントを特定する
ログクエリ API は、監査ログとオペレーション ログをクエリするために次の 2 つのエンドポイントを公開します。
監査ログ エンドポイント:
audit-log-query-api.ORG_DOMAINオペレーション ログのエンドポイント:
operational-log-query-api.ORG_DOMAIN
ORG_DOMAIN は、組織のドメイン名に置き換えます。このプロパティは、gdcloud config list コマンドを使用して表示できます。ドメイン名は org-name.zone.google.gdch.com 構文に従う必要があります。たとえば、zone1 ゾーンのテスト環境にある org-1 という名前の組織には、org-1.zone1.google.gdch.test のようなドメインがあります。
Log Query API には、次の 3 つのエンドポイント オプションがあります。
- labels: プロジェクトのすべてのラベルを一覧表示します。
- labels/labels/LABEL/values: プロジェクトの特定のラベル値を一覧表示します。
- logs: 特定のプロジェクトのログを一覧表示します。
詳細については、API ドキュメントをご覧ください。
クエリを送信する
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: ログをクエリする Log Query 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: ログのクエリ元となる Log Query 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: ログのクエリ元となる Log Query 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: ログをクエリする Log Query API エンドポイント。
サーバーフラグが指定されていない場合、デフォルトのリクエストは
localhostに到達します。
サンプルクエリとラベル
ログのクエリに使用できるデフォルトのラベルの一部を次に示します。
cluster: クラスタの名前。namespace: プロジェクトの名前空間。node: ノード名。pod: Pod 名。container: コンテナ名。
次のコードサンプルは、ラベルと値を使用してさまざまなログをクエリする方法を示しています。
サーバーログを選択します。
{cluster="admin", namespace="kube-system", resources="k8s_container", container="kube-apiserver"}クラスタ監査ログを選択します。
{cluster="admin", resources="k8s_audit"}