Kubernetes における StdOut ログのホワイトリスト運用のベストプラクティス¶
環境準備¶
Kubernetes 環境(以下 K8s)がすでに存在することを前提とします。本実践は、セルフホストの Kubernetes v1.23.1、Guance Datakit バージョン 1.2.13、Nginx 1.17 に基づいています。
Datakit はすでにデプロイ済みであり、Datakit の設定ファイル container.conf は ConfigMap 経由で管理されています。
注意: Alibaba Cloud Container Service for Kubernetes その他のクラウドプロバイダーの Kubernetes でも、設定の考え方は同様です。
前提条件¶
K8s 環境における Nginx のログ出力は、ファイル出力ではなく StdOut 方式です。Guance Datakit は DaemonSet としてデプロイされると、デフォルトで K8s 内部の全 StdOut ログ出力を収集します。これには、CoreDNS(ログ出力を有効化する必要あり)などのクラスター内部コンポーネントの StdOut 出力も含まれます。本ドキュメントで扱うログはすべて StdOut 方式で出力されるものです。
補足:StdOut は、開発者がコードを記述する際にログのコンソール出力方式として選択するものです。例:
ホワイトリストの要件¶
Datakit のデプロイ完了後、指定した業務 Pod のログや K8s クラスターコンポーネントのログをオンデマンドで収集し、後から追加される未指定の業務 Pod のログは収集しません。また、同一 Pod 内の複数コンテナのログについては、そのうちの 1 つまたは複数のみを収集します。
本ドキュメントでは、Guance のコレクターである Datakit の異なるログフィルタリング方法を用いてこれを実現します。具体的には、ログに Annotation を付与する方法(Pod 内部の他のコンテナが出力するログのフィルタリングを含む)と、container.conf 内の container_include_log = [] を組み合わせて使用します。
より詳細なログ処理の原理については、<Datakit ログ処理概要> を参照してください。
実装方法¶
方法 1: container_include_log = [] を使用する¶
クラスターコンポーネントの coredns と nginx のログのみを収集します。container_include_log には、正規表現構文を用いてイメージ名を指定します。
詳細は <コンテナイメージに基づくメトリクスとログ収集の設定> を参照してください。
[inputs.container]
docker_endpoint = "unix:///var/run/docker.sock"
containerd_address = "/var/run/containerd/containerd.sock"
enable_container_metric = true
enable_k8s_metric = true
enable_pod_metric = true
## 収集対象/除外対象のコンテナログ。デフォルトでは全コンテナを収集。グロブパターン対応。
container_include_log = ["image:*coredns*","image:*nginx*"]
container_exclude_log = ["image:pubrepo.guance.com/datakit/logfwd*", "image:pubrepo.guance.com/datakit/datakit*"]
exclude_pause_container = true
## テキスト文字列から ANSI エスケープコードを除去
logging_remove_ansi_escape_codes = false
kubernetes_url = "https://kubernetes.default:443"
## 認証レベル:
## bearer_token -> bearer_token_string -> TLS
## 認証には bearer token を使用('bearer_token' が優先)
## linux: /run/secrets/kubernetes.io/serviceaccount/token
## windows: C:\var\run\secrets\kubernetes.io\serviceaccount\token
bearer_token = "/run/secrets/kubernetes.io/serviceaccount/token"
# bearer_token_string = "<your-token-string>"
[inputs.container.tags]
# some_tag = "some_value"
# more_tag = "some_other_value"
実装効果¶
指定したイメージ名の Pod ログのみをオンデマンドで収集します。下図のとおりです。
方法 2: container_include_log = [] と Annotation の組み合わせ¶
クラスターコンポーネントの coredns と nginx のログのみを収集すると同時に、Annotation によって nginx にマークを付けます。もちろん、container_include_log でホワイトリストに登録されていないイメージ(例:busybox)でも、Annotation 方式でマークすれば収集可能です。これは、Annotation 方式の優先度が高いためです。
より詳細なログ処理の原理については、<Datakit ログ処理概要> を参照してください。
Nginx の Annotation マーク
labels:
app: nginx-pod
annotations:
datakit/logs: |
[
{
"disable": false,
"source": "nginx-source",
"service": "nginx-source",
"pipeline": "",
"multiline_match": ""
}
]
spec:
[inputs.container]
docker_endpoint = "unix:///var/run/docker.sock"
containerd_address = "/var/run/containerd/containerd.sock"
## 収集対象/除外対象のコンテナメトリクス。デフォルトでは収集しません。グロブパターン対応。
container_include_metric = []
container_exclude_metric = ["image:*"]
## 収集対象/除外対象のコンテナログ。デフォルトでは全コンテナを収集。グロブパターン対応。
container_include_log = ["image:*coredns*","image:*nginx*"]
container_exclude_log = []
exclude_pause_container = true
## テキスト文字列から ANSI エスケープコードを除去
logging_remove_ansi_escape_codes = false
## ログの最大長。デフォルトは 32766 バイト。
max_logging_length = 32766
kubernetes_url = "https://kubernetes.default:443"
## 認証レベル:
## bearer_token -> bearer_token_string -> TLS
## 認証には bearer token を使用('bearer_token' が優先)
## linux: /run/secrets/kubernetes.io/serviceaccount/token
## windows: C:\var\run\secrets\kubernetes.io\serviceaccount\token
bearer_token = "/run/secrets/kubernetes.io/serviceaccount/token"
# bearer_token_string = "<your-token-string>"
[inputs.container.tags]
# some_tag = "some_value"
# more_tag = "some_other_value"
実装効果¶
方法 3: Pod 内の特定コンテナログをフィルタリングする¶
クラスターコンポーネントの coredns と nginx のログのみを収集します。同時に、nginx の Annotation マーク内の "only_images" フィールドを使用して、収集対象とするコンテナのイメージを指定します。つまり、Pod 内部にもホワイトリスト戦略を適用します。
Pod 内ホワイトリスト有効化前¶
下図のとおり、nginx と busybox の両方のログが収集されます。
Pod 内ホワイトリスト有効化¶
labels:
app: nginx-pod
annotations:
datakit/logs: |
[
{
"disable": false,
"source": "nginx-source",
"service": "nginx-source",
"pipeline": "",
"only_images": ["image:*nginx*"],
"multiline_match": ""
}
]
spec:
実装効果¶
Pod 内の Nginx ログのみが保持されます。
まとめ¶
実際には、ホワイトリスト戦略の使用は推奨しません。ホワイトリストは多くの問題を引き起こす可能性があり、デバッグも容易ではありません。また、予期しない効果が生じることもあります(例えば、開発者がログを出力したのに見えない場合、それは特定のタグが付与されていないことが原因かもしれません)。ログの発生源をフィルタリングする場合、ブラックリストが無効になっても、最悪のケースではデータが収集されてしまいます。ブラックリストによるフィルタリングは、例えば Datakit コレクターの container.conf 内で以下のように設定します。
方法 1 は、Annotation を使用せず、コレクター container.conf に組み込まれたフィルタリング方式を用いる、より低レイヤーな実装です。しかし、この方法は方法 2 に劣ります。なぜなら、マーク方式ではログの発生源により適切なタグを付与できるため、将来の問題分析やフィルタリングが容易になり、また柔軟性も高まるからです。マークは業務 Pod 上に付与されるため、同一の業務イメージに対してきめ細かいログフィルタリング管理が可能です。
方法 3 は、特定の業務シナリオに応じて、不要な Sidecar などのログをフィルタリングし、ノイズを低減する効果があります。



