0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ROSAからCloudWatchへのログ転送コストを抑える② - Filterで不要なログを削減する

0
Posted at

はじめに

前回の記事では、ROSAからAmazon CloudWatch Logsへログを転送する際に、ClusterLogForwarderのInputを利用して転送対象のログを絞り込む方法を紹介しました。

ROSAからCloudWatchへのログ転送コストを抑える① - Inputで転送対象を絞る #AWS - Qiita

Inputを利用すると、ApplicationログをNamespaceやLabelで絞り込んだり、InfrastructureログやAuditログをsource単位で絞り込むことができます。

一方、次のようなケースはInputだけでは対応できません。

  • Inputで取得したログから、さらに特定条件のログを除外したい
  • /healthなど特定の内容を含むログを除外したい
  • 特定のログレベルを除外したい
  • ログ自体は残しつつ、CloudWatchで利用しないフィールドを削除したい

このような場合に利用できるのが、ClusterLogForwarderのFilterです。

今回はOpenShift Logging 6.6を前提に、ログ量の削減に利用できるdroppruneについて紹介します。

また、実運用ではクラスターで発生するすべてのログを事前に把握することは難しいため、設定方法だけでなく、どのようにログ削減を進めていくかについても最後に考察します。

検証環境

本記事では以下の環境を前提とします。

  • Red Hat OpenShift Service on AWS(ROSA)
  • Red Hat OpenShift Logging 6.6
  • ClusterLogForwarderからAmazon CloudWatch Logsへのログ転送を設定済み

CloudWatch Logsへの転送設定自体については本記事では割愛します。

ClusterLogForwarderのFilterについて

Filterは、Inputで収集したログをOutputへ転送する前に、ログレコードを除外・加工するための機能です。

今回利用するFilterは次の2つです。

Filter 用途
drop 条件に一致したログレコード全体を除外する
prune ログレコード内の不要なフィールドを削除する

例えば、/healthへのアクセスログ自体が不要であればdrop、ログ自体は必要でもKubernetesのAnnotationなどをCloudWatchで利用しない場合はpruneを利用します。

dropで不要なログを除外する

dropは、指定した条件に一致するログレコードを除外するFilterです。

基本的な設定は次のようになります。

spec:
  filters:
    - name: drop-marketplace
      type: drop
      drop:
        - test:
            - field: .kubernetes.namespace_name
              matches: openshift-marketplace

各項目の内容は以下の通りです。

項目 内容
field 条件判定に利用するログレコードのフィールド
matches 指定した値または正規表現に一致する場合にTrue
notMatches 指定した値または正規表現に一致しない場合にTrue

1つのフィールドに対してmatchesnotMatchesを同時に指定することはできません。

また、指定したfieldがログレコードに存在しない場合、その条件はFalseとして評価されます。

複数の条件を指定する

1つのtest内に複数条件を指定した場合はAND条件になります。

drop:
  - test:
      - field: .log_type
        matches: application
      - field: .kubernetes.namespace_name
        matches: sample

この場合は、

.log_type = application
AND
.kubernetes.namespace_name = sample

の両方を満たすログが除外されます。

一方、複数のtestを指定した場合はOR条件です。

drop:
  - test:
      - field: .kubernetes.namespace_name
        matches: namespace-a
  - test:
      - field: .kubernetes.namespace_name
        matches: namespace-b

この場合はnamespace-aまたはnamespace-bのログが除外されます。

dropで利用する正規表現

matchesnotMatchesには正規表現を指定できます。

ここでは、本記事で利用する基本的な表現だけ紹介します。

表現 意味
^ 文字列の先頭
$ 文字列の末尾
.* 任意の0文字以上
.+ 任意の1文字以上
`A B`

例えば、

^openshift-.*

と指定すると、openshift-から始まる文字列に一致します。

openshift-marketplace
openshift-monitoring
openshift-ingress

などが対象になります。

正規表現を利用すると複数のログをまとめて除外できますが、dropではログレコード自体が削除されます。

条件を広くしすぎて必要なログまで除外しないよう、実際のログを確認した上で設定する必要があります。

dropの利用例

Part①では、Inputで転送対象を絞り込む方法を紹介しました。

dropでは、Inputで取得したログに対して、ログレコードに含まれるフィールドを条件にさらにログを除外できます。

そのため、InfrastructureログやAuditログなどでも、対象となるフィールドがログレコードに存在すれば、その値を条件に除外できます。

特定Namespaceのログを除外する

例えば、Infrastructureログのうちopenshift-marketplace Namespaceのログを除外する場合は、.kubernetes.namespace_nameを条件に指定します。

spec:
  filters:
    - name: drop-marketplace
      type: drop
      drop:
        - test:
            - field: .kubernetes.namespace_name
              matches: "^openshift-marketplace$"

Applicationログについては、Namespaceが事前に分かっている場合はPart①で紹介したInput側で絞り込む方がシンプルです。

/healthなど特定のログを除外する

dropではKubernetesのメタデータだけでなく、.messageを条件にログの内容を判定できます。

例えばApacheから次のようなアクセスログが継続的に出力されているとします。

10.0.0.1 - - [08/Sep/2026:10:00:00 +0900] "GET /health HTTP/1.1" 200 2

この/healthへのアクセスログをCloudWatchで使用しない場合は、次のように設定できます。

spec:
  filters:
    - name: drop-healthcheck
      type: drop
      drop:
        - test:
            - field: .message
              matches: 'GET /health '

/health/readyの両方を対象にする場合は、例えば次のように指定できます。

matches: 'GET /(health|ready) '

実際に指定する正規表現は、Applicationが出力するログフォーマットに合わせて調整します。

ログレベルで除外する

dropでは.levelを条件にログを除外することもできます。

例えば、実際のログレコードで.leveldebugが設定されており、DEBUGログをCloudWatchへ転送する必要がない場合は、次のように設定できます。

spec:
  filters:
    - name: drop-debug
      type: drop
      drop:
        - test:
            - field: .level
              matches: debug

どのログレベルまでCloudWatchへ転送するかは、システムの監視や障害調査の方針に合わせて決めます。

Applicationログでは、ログの出力形式によって.levelに期待した値が設定されているとは限らないため、実際のログを確認した上で設定します。

pruneで不要なフィールドを削除する

ここまで紹介したdropは、ログレコード自体を削除する方法です。

一方、ログ自体は必要でも、ログレコードに付与されているすべての情報をCloudWatchで利用するとは限りません。

このような場合に利用できるのがpruneです。

pruneでは不要なフィールドを削除することで、1レコードあたりのサイズを小さくできます。

OpenShift Logging 6.6では、削除対象を指定するinと、保持対象を指定するnotInが利用できます。

inで不要なフィールドを指定する

inには削除するフィールドを指定します。

例えば、KubernetesのAnnotationやID情報をCloudWatchで利用しない場合は、次のように設定できます。

spec:
  filters:
    - name: prune-fields
      type: prune
      prune:
        in:
          - .kubernetes.annotations
          - .kubernetes.namespace_id
          - .kubernetes.pod_id

inに指定したフィールドが削除され、それ以外のフィールドは残ります。

notInで必要なフィールドを指定する

notInでは、ログレコードに残すフィールドを指定します。

指定されていないフィールドは削除されます。

例えば、次のような設定です。

spec:
  filters:
    - name: prune-fields
      type: prune
      prune:
        notIn:
          - ."@timestamp"
          - .log_type
          - .log_source
          - .message
          - .level
          - .kubernetes.namespace_name
          - .kubernetes.pod_name
          - .kubernetes.container_name

inが不要なフィールドを指定する方法なのに対して、notInは残したいフィールドを指定する方法です。

pruneで削除できないフィールド

pruneでは、すべてのフィールドを自由に削除できるわけではありません。

OpenShift Logging 6.6では、次のフィールドは必須フィールドとなっており、pruneで削除できません。

.log_type
.log_source
.message
.kubernetes.namespace_name
.kubernetes.pod_name
.kubernetes.container_name
.level

例えば、次のように.messageを削除対象として指定することはできません。

prune:
  in:
    - .message

削除できない必須フィールドを指定した場合でも、ClusterLogForwarder CR自体は受け付けられます。

ただし、Operatorによる検証でvalidation conditionがFalseになります。

そのため、CRを作成できたからといって設定が有効とは限らない点には注意が必要です。

notInを利用する場合も、必須フィールドを削除対象にしないよう注意します。

なお、innotInを両方指定した場合は、notInが先に処理され、保持対象を決めた後にinに指定したフィールドが削除されます。

pruneで残すフィールドをどう考えるか

pruneを設定する際に、ログに含まれるすべてのフィールドを確認し、「不要なもの」を1つずつ探して削除する方法もあります。

しかし、実運用で発生するログの種類やフィールドをすべて事前に把握することは難しいです。

ログを削減するために、発生するすべてのログを把握する必要はありません。

障害発生時に、

  • いつ発生したか
  • どこで発生したか
  • 何が発生したか

を確認できる情報を基準に、残すフィールドを決める方が現実的です。

例えば、次のような情報です。

確認したいこと 主なフィールド
いつ発生したか @timestamp
どこで発生したか Namespace、Pod、Container
何が発生したか message

つまり、

「どのフィールドが不要か」をすべて調査する

のではなく、

「障害調査で必要になる情報は何か」を先に決める

という考え方です。

Namespace、Pod、Container、messageなどは必須フィールドのため削除できませんが、それ以外にCloudWatchで利用しないメタデータを削除することで、ログレコードを軽量化できます。

CloudWatch Logsでは取り込まれるデータ量が料金に影響するため、不要なフィールドを削除して1レコードあたりのサイズを小さくすることは、ログ取り込み量の削減につながります。

【考察】実運用ではどのようにログを削減するか

ここからはOpenShift Loggingの仕様ではなく、実際にログ転送量を削減する場合の進め方についての考察です。

ログ転送を開始する前に、クラスターで発生するすべてのログを把握し、不要なログをあらかじめ洗い出しておくことは現実的ではありません。

そのため、実運用では次の流れでログ削減を検討していく方法が考えられます。

1. Inputで明確に不要な範囲を除外する

まず、転送前から不要と判断できるログをInputで除外します。

例えば、CloudWatchへ転送するApplicationのNamespaceが決まっている場合は、Inputで対象Namespaceを絞り込みます。

Part①で紹介した通り、Inputで除外できるログについては、まずInput側で対象を整理します。

2. pruneで運用に必要なフィールドを整理する

次に、障害発生時に「いつ、どこで、何が起きたか」を確認できるよう、CloudWatchへ残す情報を整理します。

ここでは、個々のログメッセージをすべて確認して削除対象を探すのではなく、障害調査で必要な情報を基準に保持するフィールドを決めます。

特にnotInを利用する場合は、不要なフィールドを探すのではなく、必要なフィールドを基準に保持対象を決めることができます。

この方法であれば、個々のログ内容に依存せず、広い範囲のログに同じ削減ルールを適用できます。

3. 実際にCloudWatchへ転送されたログを確認する

運用を開始した後、CloudWatchへ転送されたログを確認します。

例えば、次のような傾向が見つかるかもしれません。

  • /healthへのアクセスログが大量に出力されている
  • 特定のInfrastructure Namespaceから大量のログが出力されている
  • DEBUGやINFOレベルのログが想定以上に多い

この段階で、ログレコード自体を除外できるかを検討します。

4. 明確に不要なログをdropする

実際のログを確認した上で、CloudWatchでの運用に不要と判断できるログをdropします。

例えば、

  • /healthなどの定型的なアクセスログ
  • 転送する必要のないInfrastructure Namespace
  • 不要なログレベル

などです。

最初からすべての不要ログを洗い出すのではなく、

Inputで明確な範囲を絞る
        ↓
pruneで必要なフィールドに絞る
        ↓
実際のログを確認する
        ↓
dropで不要なログを追加で除外する

という形で段階的にチューニングすることで、事前調査の負担を抑えながらログ取り込み量を削減できます。

まとめ

今回はClusterLogForwarderdroppruneを利用して、CloudWatch Logsへのログ取り込み量を削減する方法を紹介しました。

それぞれの役割は次のように整理できます。

方法 役割
Input 収集するログの範囲を絞る
drop 不要なログレコード自体を除外する
prune 必要なログから不要なフィールドを削除する

dropは不要なログレコードそのものを削除できる一方、どのログを削除してよいか判断するには、実際に発生するログを確認する必要があります。

そのため、まずInputで明確に不要な範囲を絞り、pruneで障害調査に必要な情報を残しながらログレコードを軽量化します。

その後、実際にCloudWatchへ転送されたログを確認し、明確に不要なログをdropしていくことで、運用実態に合わせてログ取り込み量を削減できます。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?