ログのクエリと表示

このページでは、Grafana ユーザー インターフェースとログクエリ API の両方を使用してログのクエリと可視化を行い、サービス イベントとアクティビティに関する分析情報を取得する方法について詳しく説明します。

Google Distributed Cloud(GDC)エアギャップでデプロイされたワークロードとサービスからログを収集したら、 ログの分析を開始できます。ログを分析するには、情報提供型の Grafana パネルでログを可視化してフィルタするか、プログラムによるアクセス用に HTTP または gRPC 呼び出しを使用してログクエリ API から直接アクセスします。

ログには、次のいずれかの方法でアクセスできます。

  • [Grafana パネル]: Grafana インスタンスの [ログ] パネルで、プロジェクトのアクティビティ レコードに関する分析情報を取得します。このパネルでは、特定のログに対してクエリを実行して特定できるため、ニーズに合わせて詳細なデータ可観測性を提供できます。Grafana には、ワークロード データのフィルタと分析、包括的な可視化のためのカスタマイズされたダッシュボードとパネルの作成を行うための使いやすいインターフェースが用意されています。
  • ログクエリ API: プログラムによるアクセスの場合、 プロジェクトのログクエリ API から直接ログに対してクエリを実行します。ログクエリ API は、HTTP と gRPC をサポートする非 Kubernetes API であり、独自のエンドポイントを公開します。この API には、 標準の API アクセス方法に従って、 Distributed Cloud 内の特定の組織内でのみアクセスできます。

始める前に

Grafana ユーザー インターフェースでログのクエリと可視化に必要な権限を取得するには、組織 IAM 管理者またはプロジェクト IAM 管理者に、事前定義された組織 Grafana 閲覧者ロールまたはプロジェクト Grafana 閲覧者ロールのいずれかを付与するよう依頼してください。必要なアクセスレベルと権限に応じて、組織またはプロジェクトで Grafana ロールを取得できます。

または、ログクエリ API からログに対してクエリを実行するために必要な権限を取得するには、プロジェクト IAM 管理者に、プロジェクト名前空間でログクエリ API クエリ実行者ロールを付与するよう依頼してください。

これらのロールの詳細については、 IAM 権限を準備するをご覧ください。

ログのクエリとフィルタ

クエリを作成してプロジェクト ワークロードからログをフィルタするには、次のいずれかの方法を選択します。

Grafana [ログ] パネル

このセクションでは、Grafana の [ログ] パネルを使用してログにアクセスする方法について説明します。

Grafana エンドポイントを特定する

次の URL は、プロジェクトの Grafana インスタンスのエンドポイントです。

  https://GDC_URL/PROJECT_NAMESPACE/grafana

次のように置き換えます。

  • GDC_URL: GDC 内の組織の URL。
  • PROJECT_NAMESPACE: プロジェクトの名前空間。

    たとえば、 org-1 組織の platform-obs プロジェクトの Grafana エンドポイントは https://org-1/platform-obs/grafana です。

Grafana ユーザー インターフェースでログを表示する

Grafana ユーザー インターフェースでログに対してクエリを実行します。

  1. GDC コンソールで、プロジェクトを選択します。
  2. ナビゲーション メニューで、 [**オペレーション**] [>] [**ロギング**] を選択します。
  3. [Grafana Loki で全て表示] をクリックします。

    新しいページが開き、Grafana エンドポイントと ユーザー インターフェースが表示されます。

  4. ユーザー インターフェースで、 [explore Explore] をナビゲーション メニューからクリックして、[Explore] ページを開きます。

  5. [Explore] バーのメニューから、ユニバースのタイプに応じてログを取得する データソースを選択します。

    • 単一ゾーン ユニバース: 次のいずれかのデータ ソースを選択して、ユニバースの単一ゾーンからロギングデータを表示します。

      • オペレーション ログ: オペレーション ログを表示します。
      • 監査ログ: 監査ログを表示します。
    • マルチゾーン ユニバース: Grafana はさまざまなゾーンに接続して、 ゾーン間のデータを表示できます。ログインしているゾーンに関係なく、ユニバースの任意のゾーンからロギングデータを表示するには、次のいずれかのデータソースを選択します。

      • オペレーション ログ ZONE_NAME: 特定のゾーンのオペレーション ログを表示します。
      • 監査ログ ZONE_NAME: 特定のゾーンの監査ログを表示します。

      また、単一のダッシュボードでゾーン間のデータを可視化し、クエリに複数のゾーンを追加するには、データソースとして [Mixed] を選択します。

  6. LogQLこの手順は、次のいずれかの方法で行います。

    • インタラクティブなクエリビルダー インターフェースを使用します。[クエリを実行] をクリックします。
    • テキスト フィールドにクエリを直接入力し、 Shift+Enter を押してクエリを実行します。

    ページに、クエリに一致するログが表示されます。ログに対してクエリを実行したら、ログをエクスポートできます。[エクスポート] をクリックして、ログをプレーン テキストまたは CSV 形式でダウンロードします。ログの期間を選択することもできます

    [監査ログ] オプションが [探索] ページで選択され、監査ログが取得されます。

    図 1.Grafana ユーザー インターフェースから監査ログに対してクエリを実行するメニュー オプション。

    図 1 の [監査ログ] オプションには、Grafana からクエリを作成して監査ログを取得できるインターフェースが表示されます。

    さまざまなログに対してクエリを実行するラベルと値の例については、 サンプルクエリとラベルをご覧ください。

ログの期間を選択する

特定の期間のログに対してクエリを実行する手順は次のとおりです。

  1. Grafana で [Time Picker] メニューをクリックします。

  2. メニューから、次のいずれかの操作を行います。

    • 相対的な期間オプション(過去 30 分など)を選択します。
    • カレンダーから特定の日時を選択し、[期間を適用] をクリックして、カスタムの絶対期間を設定します。
  3. 必要に応じて、[時刻設定を変更] をクリックして、[タイムゾーン] と [会計年度] の設定を期間コントロールから変更します。

    時刻設定はダッシュボードごとに保存されます。一定期間のクエリの詳細については、 以下をご覧ください。 https://grafana.com/docs/loki/latest/reference/api/#query-loki-over-a-range-of-time

ログクエリ API

このセクションでは、ログクエリ API を使用してログにアクセスする方法について説明します。

ログクエリ 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 構文に従う必要があります。たとえば、org-1 という名前の組織が zone1 ゾーンにあり、テスト環境にある場合、ドメインは org-1.zone1.google.gdch.test のようになります。

ログクエリ API には、次の 3 つのエンドポイント オプションがあります。

  • labels: プロジェクトのすべてのラベルを一覧表示します。
  • labels/labels/LABEL/values: プロジェクトの特定の ラベル値を一覧表示します。
  • logs: 特定のプロジェクトのログを一覧表示します。

詳細については、API ドキュメントをご覧ください。

クエリを送信する

HTTP または gRPC クライアントを使用して、ログクエリ API エンドポイントにクエリを送信します。

HTTP

手順に沿って、 HTTP クライアントを使用して API に直接アクセスします。 認証の管理は kubectl に任せることも、自分で処理することもできます。

curlwget などの HTTP クライアント、または作成して管理する HTTP クライアントを使用して、ログクエリ API に対してクエリを実行します。次の例では、curl ツールを使用して API に対してクエリを実行します。wget コマンドでも同様の形式を使用できます。

  1. cURL リクエストを認証します。

    1. gdcloud CLI をダウンロードしてインストールします
    2. gdcloud core/organization_console_urlプロパティを設定します。

      gdcloud config set core/organization_console_url https://GDC_URL
      

      GDC_URL は、GDC 内の組織の URL に置き換えます。

    3. 構成済みの ID プロバイダでログインします:

      gdcloud auth login
      
    4. ユーザーとパスワードを使用して認証し、ログインします。

    5. 指定したアカウントの ID トークンを環境変数にエクスポートします。

      export TOKEN="$($HOME/gdcloud auth print-identity-token --audiences=https://LOG_QUERY_API_ENDPOINT)"
      

      LOG_QUERY_API_ENDPOINT を、ログに対してクエリを実行する ログクエリ API エンドポイントと、接続するドメインに置き換えます。したがって、audiences フラグの値は、たとえば https://operational-log-query-api.org-1.zone1.google.gdch.test になります。

      ログインに成功したら、gdcloud auth print-identity-token コマンドを使用して、cURL リクエストの認証ヘッダーを使用できます。詳細については、 gdcloud auth print-identity-token をご覧ください。

  2. プロジェクトのすべてのラベルを一覧表示する場合は、次のクエリを送信します。

    curl -H "Authorization: Bearer ${TOKEN}" \
    https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels \
    -H "Content-Type: application/json" -v
    

    次のように置き換えます。

  3. プロジェクトの特定のラベル値を一覧表示する場合は、次のクエリを送信します。

    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: プロジェクトの名前空間。
    • LABEL: 値に対してクエリを実行する特定のラベル。
  4. 特定のプロジェクトのログに対してクエリを実行する場合は、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: プロジェクトの名前空間。
    • LABEL: ログに対してクエリを実行する特定のラベル。
    • LABEL_VALUE: ログに対してクエリを実行するラベル値。

    API ドキュメント で、logs_filter クエリを作成するすべてのオプションをご覧ください。

gRPC

gRPC はさまざまなプログラミング言語で広くサポートされており、HTTP クライアントよりも効率的な通信方法を提供します。

gRPC を使用してログに対してクエリを実行するには、次の前提条件を満たす必要があります。

  • Google 提供のプロトコル バッファに基づいて独自のクライアント ライブラリを作成します。
  • クライアントに認証を実装します。
  • 再試行を実装します。

プロトコル バッファについては、 API ドキュメントをご覧ください。

次の例は、認証されていない gRPC クライアントを使用して Go プログラムからログに対してクエリを実行する方法を示しています。この例では、コードの依存関係をインポートする Bazel ビルドファイルを含む golang パッケージを作成していることを前提としています。

  1. 次のコードを 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
    }
    
  2. Go プログラムを実行します。

    go run PATH_TO_API/client.go -server=LOG_QUERY_API_ENDPOINT:443
    

    次のように置き換えます。

    サーバー フラグが指定されていない場合、デフォルトのリクエストは localhost に送信されます。

サンプルクエリとラベル

ログに対してクエリを実行するために使用できるデフォルトのラベルを次に示します。

  • cluster: クラスタの名前。
  • namespace: プロジェクトの名前空間。
  • node: ノード名。
  • pod: Pod 名。
  • container: コンテナ名。

次のコードサンプルは、ラベルと値を使用してさまざまなログに対してクエリを実行する方法を示しています。

  • サーバーログを選択します。

    {cluster="admin", namespace="kube-system", resources="k8s_container", container="kube-apiserver"}
    
  • クラスタ監査ログを選択します。

    {cluster="admin", resources="k8s_audit"}