このページでは、Google Kubernetes Engine クラスタで監査ロギングを使用する方法について説明します。
概要
Kubernetes 対応のすべてのクラスタでは Kubernetes Audit Logging を使用して、Kubernetes API サーバーに対して行われた呼び出しを時系列でログに記録します。Kubernetes 監査ログのエントリは、不審な API リクエストの調査、統計情報の収集、不要な API 呼び出しに対するモニタリング アラートの作成に役立ちます。
GKE クラスタは Kubernetes Audit Logging を Cloud Audit Logs および Stackdriver Logging に統合します。Kubernetes 監査ログのエントリは、Google Cloud Platform プロジェクトで表示できます。
プロジェクトの監査ログには、Kubernetes により書き込まれたエントリに加えて、Kubernetes Engine により書き込まれたエントリがあります。
Audit Logging 一般提供は GKE 1.11.4 以降で使用できます。
始める前に
このタスクの準備として、次の手順を行います。
- Google Kubernetes Engine API が有効になっていることを確認します。 Google Kubernetes Engine API の有効化
- Cloud SDK がインストール済みであることを確認します。
- デフォルトのプロジェクト ID を設定します。
gcloud config set project [PROJECT_ID]
- ゾーンクラスタを使用する場合は、デフォルトのコンピューティング ゾーンを設定します。
gcloud config set compute/zone [COMPUTE_ZONE]
- リージョン クラスタを使用する場合は、デフォルトのコンピューティング リージョンを設定します。
gcloud config set compute/region [COMPUTE_REGION]
gcloud
を最新バージョンに更新します。gcloud components update
プロジェクトに Kubernetes Engine クラスタが必要です。既存のクラスタを使用することも、このトピックの演習用に新しいクラスタを作成することもできます。既存のクラスタを使用する場合は、クラスタに最近のアクティビティがあることを確認してください。たとえば、Deployment を最近作成していない場合は、次のコマンドを入力して Deployment を作成できます。
kubectl run log-exercise --image nginx
Kubernetes Audit Logging について調べます。
プロジェクトの監査ログ
GCP プロジェクトには、次の監査ログがあります。
- 管理アクティビティ ログ
- データアクセス ログ
管理アクティビティのロギングはデフォルトで有効になっており、追加料金は不要です。
データアクセスのロギングはデフォルトでは無効になっており、有効にすると追加料金が発生します。データアクセスのロギングを有効にする方法と関連する費用の詳細については、データアクセス ログの構成をご覧ください。
Kubernetes Engine はアクセスの透明性のロギングをサポートしていません。
さまざまな Google Cloud Platform サービスによって、プロジェクトのログにエントリが書き込まれます。Kubernetes サービスは、プロジェクトの監査ログにもエントリを書き込みます。Kubernetes Engine クラスタの場合、以下のサービスによって書き込まれたログエントリが最も重要です。
サービス | 表示名 |
---|---|
k8s.io | Kubernetes |
container.googleapis.com | Kubernetes Engine |
プロジェクトの管理アクティビティ ログの表示
Console
GCP Console で、[ロギング] メニューの [ログ] ページに移動します。
ページの上部で、リソースタイプを選択するためのプルダウン メニューを見つけます。プルダウン メニューで、[Kubernetes クラスタ] を選択します。
必要に応じて、[ロケーション] を指定するか、[すべてのロケーション] を選択します。ロケーションを選択すると、そのロケーションにある特定のクラスタを選択できます。
右側にある次のメニューは、ログを選択するためのメニューです。プルダウン メニューで、[アクティビティ] を選択して [OK] をクリックします。
デフォルトでは、すべてのログレベルが表示されます。ログレベル(警告など)を指定するには、ログレベルのプルダウン メニューで選択します。
直近 1 時間のログエントリのみが表示されることがあります。1 時間前のログエントリが表示されない場合は、[古いログを読み込む] をクリックします。
上で説明したプルダウン メニューのすぐ上にある [ラベルまたはテキスト検索でフィルタ] ボックスで、下矢印をクリックしてプルダウン メニューを開きます。メニューで、[高度なフィルタに変換] を選択します。
テキスト ボックスに次のようなフィルタが表示されます。
resource.type="k8s_cluster" logName="projects/my-project/logs/cloudaudit.googleapis.com%2Factivity"
行の先頭にある矢印をクリックして、ログエントリの 1 つを開きます。エントリの
logName
フィールドの値はprojects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity
です。
gcloud
プロジェクトの管理アクティビティ ログの最初の 2 つのログエントリを一覧表示します。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity"' \ --limit 2 \ --freshness 300d
ここで、[PROJECT_ID] はプロジェクト ID です。
出力には 2 つのログエントリが表示されます。各ログエントリの logName
フィールドの値が projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity
である点に注意してください。
insertId: 18yao5jem14og labels: cluster_version: 1.8.8-gke.0 logName: projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity ...
基本および高度なフィルタ インターフェース
GCP Console では、[ログ] ページに基本と高度という 2 つのフィルタリング インターフェースがあります。2 つのフィルタリング インターフェースについて詳しくは、ログビューアのフィルタ インターフェースをご覧ください。
管理アクティビティ ログに書き込むサービスを表示する
Console
GCP Console で、[ロギング] メニューの [ログ] ページに移動します。
[ログ] ページが高度なモードでない場合は、高度なモードに切り替えます。フィルタ ボックスで、右側の下向き矢印をクリックして、[高度なフィルタに変換] を選択します。
フィルタ ボックスで、既存のテキストを削除して、以下のフィルタを入力します。
logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity" protoPayload.serviceName="k8s.io"
ここで、[PROJECT_ID] はプロジェクト ID です。
[フィルタを送信] をクリックします。
管理アクティビティ ログに
k8s.io
サービスによって書き込まれたすべてのエントリが一覧表示されます。つまり、これらのエントリは Kubernetes コントロール プレーンによって書き込まれました。ここで、
k8s.io
以外のサービスにより書き込まれたログエントリを探します。フィルタ ボックスで、serviceName="k8s.io"
をserviceName!="k8s.io"
に変更します。[フィルタを送信] をクリックします。管理アクティビティ ログに
k8s.io
サービスによって書き込まれなかったログエントリが一覧表示されます。ログエントリの 1 つを開いて、
protoPayload
フィールドを展開します。serviceName
の値を確認して、そのログエントリを書き込んだサービスを調べます。次に、
container.googleapis.com
サービスによって書き込まれたログエントリを探します。つまり、これらのエントリは Kubernetes Engine コントロール プレーンによって書き込まれました。フィルタ ボックスで、serviceName!="k8s.io"
をserviceName="container.googleapis.com"
に変更します。[フィルタを送信] をクリックします。
gcloud
プロジェクトの管理アクティビティ ログに k8s.io
サービスによって書き込まれた最初の 2 つのログエントリを一覧表示します。つまり、これらのエントリは Kubernetes コントロール プレーンによって書き込まれました。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity" AND protoPayload.serviceName="k8s.io"' \ --limit 2 \ --freshness 300d
ここで、[PROJECT_ID] はプロジェクト ID です。
出力で、protoPayload:serviceName
の値が k8s.io
であることがわかります。
protoPayload: ... serviceName: k8s.io
ここで、k8s.io
以外のサービスにより書き込まれたログエントリを探します。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity" AND protoPayload.serviceName!="k8s.io"' \ --limit 2 \ --freshness 300d
出力には、管理アクティビティ ログに k8s.io
サービスによって書き込まれなかったログエントリが一覧表示されます。
logName: projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity ... protoPayload: ... serviceName: compute.googleapis.com ...
ログエントリの 1 つで、protoPayload.serviceName
の値を見て、ログエントリを書き込んだサービスを確認します。
次に、container.googleapis.com
サービスによって書き込まれたログエントリを探します。つまり、これらのエントリは Kubernetes Engine コントロール プレーンによって書き込まれました。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity" AND protoPayload.serviceName="container.googleapis.com"' \ --limit 2 \ --freshness 300d
ここで、[PROJECT_ID] はプロジェクト ID です。
管理アクティビティ ログをリソースタイプでフィルタリングする
管理アクティビティ ログ内の各ログエントリは、特定のタイプのリソースに該当します。以下は、Kubernetes クラスタに最も関連するリソースタイプです。
リソースタイプ | 表示名 |
---|---|
k8s_cluster | Kubernetes クラスタ |
gke_cluster | GKE クラスタ オペレーション |
Kubernetes API サーバーによって書き込まれたログエントリは、k8s_cluster
リソースタイプに該当します。これらのログエントリは、クラスタ内の Kubernetes リソース(ポッド、デプロイ、シークレットなど)のオペレーションを記述します。
Kubernetes Engine API サーバーによって書き込まれたログエントリは、gke_cluster
リソースに該当します。これらのログエントリは、クラスタの作成や削除などのオペレーションを記述します。
Console
GCP Console で、[ロギング] メニューの [ログ] ページに移動します。
[ログ] ページが基本モードでない場合は、基本モードに切り替えます。フィルタ ボックスで、右側の下向き矢印をクリックして、[フィルタを解除して基本モードに戻る] を選択します。
リソースタイプを選択するプルダウン メニューで、[Kubernetes クラスタ] を選択します。これは、
k8s_cluster
リソースタイプの表示名です。ログを選択するプルダウン メニューで、[アクティビティ] を選択して [OK] をクリックします。
管理アクティビティ ログで
k8s_cluster
リソースタイプに該当するすべてのログエントリが一覧表示されます。ログエントリの 1 つを開いて、
resource
フィールドを展開します。type
フィールドの値がk8s_cluster
であることを確認します。次に、プルダウン メニューで [GKE クラスタ オペレーション] を選択します。これは、
gke_cluster
リソースタイプの表示名です。ログを選択するプルダウン メニューで、[アクティビティ] を選択して [OK] をクリックします。管理アクティビティ ログで
gke_cluster
リソースタイプに該当するすべてのログエントリが一覧表示されます。
gcloud
プロジェクトの管理アクティビティ ログで k8s_cluster
リソースタイプに該当するログエントリの最初の 2 つを一覧表示します。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity" AND resource.type="k8s_cluster"' \ --limit 2 \ --freshness 300d
ここで、[PROJECT_ID] はプロジェクト ID です。
出力で、resource:type
フィールドの値が k8s_cluster
であることがわかります。
resource: ... type: k8s_cluster
次に、プロジェクトの管理アクティビティ ログで gke_cluster
リソースタイプに該当するログエントリの最初の 2 つを一覧表示します。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity" AND resource.type="gke_cluster"' \ --limit 2 \ --freshness 300d
出力で、resource:type
フィールドの値が gke_cluster
であることがわかります。
resource: ... type: gke_cluster
管理アクティビティ ログのフィルタの例
GCP Console で試すことができるフィルタの例をいくつか示します。各フィルタで、[PROJECT_ID] を該当するプロジェクト ID で置き換えてください。
自動化されたシステムの変更は除き、役割ベースのアクセス制御への変更を見つけます。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.methodName:"io.k8s.authorization.rbac.v1" NOT protoPayload.authenticationInfo.principalEmail:"system"
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.methodName:"io.k8s.authorization.rbac.v1.roles" NOT protoPayload.authenticationInfo.principalEmail:"system"
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.methodName:"io.k8s.authorization.rbac.v1.rolebindings" NOT protoPayload.authenticationInfo.principalEmail:"system"
同様のクエリを使用して、clusterroles
と clusterrolebindings
への変更を見つけることができます。
証明書署名リクエストを見つけます。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.resourceName:"certificates.k8s.io/v1beta1/certificatesigningrequests"
未認証のウェブ リクエストを見つけます。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.authenticationInfo.principalEmail:"system:anonymous"
kubelet のブートストラップ ID 呼び出しを見つけます。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.authenticationInfo.principalEmail:"kubelet"
ノード認証リクエストを見つけます。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.authenticationInfo.principalEmail:"system:node"
IP 範囲外の呼び出しを見つけます。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.requestMetadata.callerIp!="127.0.0.1" protoPayload.requestMetadata.callerIp!="::1" NOT protoPayload.requestMetadata.callerIp:"[IP Prefix] "
管理アクティビティ ログで、k8s_cluster
リソースタイプに該当し、Deployment の作成を記述しているエントリを探します。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.methodName:"deployments.create"
管理アクティビティ ログで、k8s_cluster
リソースタイプに該当し、principalEmail
の値が system:anonymous
のエントリを探します。こうしたエントリは、おそらく認証に失敗したことを表しています。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.authenticationInfo.principalEmail="system:anonymous"
管理アクティビティ ログで、gke_cluster
リソースタイプに該当し、クラスタの作成を記述しているエントリを探します。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="gke_cluster" protoPayload.methodName="google.container.v1.ClusterManager.CreateCluster"
管理アクティビティ ログで、gke_cluster
リソースタイプに該当し、severity
の値が ERROR
のエントリを探します。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="gke_cluster" severity="ERROR"
管理アクティビティ ログで、k8s_cluster
リソースタイプに該当し、シークレットへの書き込みリクエストを記述しているエントリを探します。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.methodName:"io.k8s.core.v1.secrets" NOT protoPayload.methodName:"get" NOT protoPayload.methodName:"list" NOT protoPayload.methodName:"watch"
管理アクティビティ ログで、k8s_cluster
リソースタイプに該当し、特定のユーザーからのポッド リクエストを記述しているエントリを探します。
logName="projects/[PROJECT_ID] /logs/cloudaudit.googleapis.com%2Factivity" resource.type="k8s_cluster" protoPayload.methodName:"io.k8s.core.v1.pods" protoPayload.authenticationInfo.principalEmail="dev@example.com"
フィルタを構成する方法について詳しくは、高度なログフィルタをご覧ください。
ログエントリの構造
すべてのログエントリは、LogEntry 型のオブジェクトです。詳細については、監査ログについてをご覧ください。
データアクセス ログの有効化
プロジェクトの Identity and Access Management(IAM)ポリシーを取得します。
gcloud projects get-iam-policy [PROJECT_ID] > my-policy.yaml
ここで、[PROJECT_ID] はプロジェクト ID です。
my-policy.yaml
を開いて IAM ポリシーを表示します。ポリシーには、多くの場合以下のような bindings
オブジェクトが含まれています。
bindings: - members: - serviceAccount:xxx.gserviceaccount.com - serviceAccount:yyy.gserviceaccount.com role: roles/container.clusterAdmin - members: ...
my-policy.yaml
に、auditConfigs
オブジェクトを作成するか、既存の auditConfigs
オブジェクトに追加して、ADMIN_READ
、DATA_WRITE
、DATA_READ
が auditLogConfigs
の下にリストされるようにします。
auditConfigs: - auditLogConfigs: - logType: ADMIN_READ - logType: DATA_WRITE - logType: DATA_READ service: allServices
etag
の値は変更しないでください。
更新されたファイルに my-policy-2.yaml
と名前を付けて保存します。
プロジェクトの IAM ポリシーを設定します。
gcloud projects set-iam-policy [PROJECT_ID] my-policy-2.yaml
ここで、[PROJECT_ID] はプロジェクト ID です。
プロジェクトのデータアクセス ログの表示
Console
GCP Console で、[ロギング] メニューの [ログ] ページに移動します。
[ログ] ページが基本モードでない場合は、基本モードに切り替えます。フィルタ ボックスで、右側の下向き矢印をクリックして、[フィルタを解除して基本モードに戻る] を選択します。
ページの上部で、リソースタイプを選択するためのプルダウン メニューを見つけます。プルダウン メニューで、[Kubernetes クラスタ] を選択します。
ログを選択するメニューで、data_access を選択して [OK] をクリックします。
[ラベルまたはテキスト検索でフィルタ] ボックスの右側で、下矢印をクリックしてプルダウン メニューを開きます。メニューで、[高度なフィルタに変換] を選択します。
テキスト ボックスに次のようなフィルタが表示されます。
resource.type="k8s_cluster" logName="projects/my-project/logs/cloudaudit.googleapis.com%2Fdata_access"
ログエントリの 1 つを開き、エントリの
logName
フィールドの値がprojects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Fdata_access
であることに注意します。
gcloud
プロジェクトのデータアクセス ログのうち、最初の 2 つのログエントリを一覧表示します。
gcloud logging read \ 'logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Fdata_access"' \ --limit 2 \ --freshness 30d
ここで、[PROJECT_ID] はプロジェクト ID です。
出力には 2 つのログエントリが表示されます。各ログエントリの logName
フィールドの値が projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Fdata_access
である点に注意してください。
insertId: "x0vy9eej0j54" labels: {…} logName: "projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Fdata_access" ...
ログエントリのエクスポートと保存
ログエントリは、一定の時間 Stackdriver Logging で保持されます。この期間を保持期間といいます。この期間が経過すると、エントリは削除されます。
ログエントリの保持時間を長くするには、ログを Cloud Storage、BigQuery、Cloud Pub/Sub などの Google サービスにエクスポートします。
指標とアラートの設定
Stackdriver Monitoring を使用して、ログエントリに基づいて指標を設定できます。また、ログベースの指標を使用してグラフやアラートを設定できます。
監査ポリシー
Kubernetes 監査ポリシーにより、Kubernetes API サーバーによってエクスポートされるログエントリが決まります。Kubernetes Engine 監査ポリシーにより、管理アクティビティ ログに入るエントリと、データアクセス ログに入るエントリが決まります。
Kubernetes Engine の監査ポリシーについて詳しくは、Kubernetes Engine の監査ポリシーをご覧ください。
次のステップ
- Kubernetes Audit Logging
- Kubernetes Engine の監査ポリシー
- Kubernetes Engine のセキュリティの概要
- [Cloud Audit Logging]