ブログ

PrometheusでOracleデータベースを監視する方法

Google Cloudとコンテナの継続的なセキュリティ

本文の内容は、2020年12月16日にDavid de Torres Huertaが投稿したブログ(https://sysdig.com/blog/monitor-oracle-database-prometheus/)を元に日本語に翻訳・再構成した内容となっております。

この記事では、エクスポーターでメトリクスを生成するPrometheusを使用してOracle Databaseを監視する方法を説明します。また、リソースの使用量とパフォーマンスを監視すべき主なメトリクスと、Oracleデータベースの問題やインシデントを検出するために何をアラートすべきかをレビューします。

なぜOracle Databaseを監視することが重要なのか?

エネルギー供給会社のサイト信頼性エンジニア(SRE)であるガブリエラ氏は、専用ホストで稼働するデータベース・エンジンとしてオラクルを使用しています。同社の残りのサービスやアプリケーションは、クラウドネイティブのマイクロサービスに移行され、Kubernetesでオーケストレーションされ、VPNを介してOracle Databaseと通信しています。

ユーザーからは、彼女のデータベースで長く続いているクエリーによるエラーが報告されています。開発者はこの問題を再現することができません。原因はリソースの枯渇でしょうか?最適化されていないクエリーが多くの結果を返しているのでしょうか?より多くの情報がなければ、この問題を解決する方法はありません。

さらに悪いことに、ガブリエラは、会社の活動の増加に合わせてデータベースが通常よりも成長していることに気付きました。彼女の会社にとっては良いニュースですが、彼女はそれに応じてキャパシティを計画しなければなりません。

ガブリエラ は自動アラートを必要としています。これにより、SRE チームは、エラーが増加したときにトラブルシューティングを行い、サービスレベル目標(SLO)を達成することができます。また、Oracleデータベースのモニタリングを改善することで、テーブルとテーブルスペースのサイズを評価し、どこで成長が起こっているかを明らかにすることができるようになります。

OracleDB Prometheus エクスポーター

OracleDB エクスポータは、データベースに接続し、Prometheus形式のメトリクスを生成するアプリケーションです。

メトリクスが利用可能になると、SREチームのPrometheusサーバーを使用して、データの可視化や探査のためのダッシュボードを作成することができます。また、データベースの問題をリアルタイムでチームに報告できるアラームをプログラムすることもできます。これにより、部門の SLO を満たすために、インシデントを時間内にトラブルシューティングして解決することができます。

ガブリエラがどのようにしてこのエクスポーターを実装し、どのようなダッシュボードとアラームを作成したかを見てみましょう。

Prometheus エクスポーターのセットアップ

ここでは、OracleDB エクスポーターをインストールしてPrometheusでメトリクスを収集し、Oracleデータベースを監視するための設定方法を紹介します。エクスポータをdockerイメージやバイナリとしてホストに直接デプロイすることも可能ですが、Kubernetesクラスターでのデプロイを想定しています。

December_005.png

Kubernetes で OracleDB エクスポーターを実行するには、標準の Prometheus アノテーションを追加するデプロイメントを使用します。こうすることで、PrometheusサーバーはOracleDB exporterエンドポイントを自動検出し、さらなる設定なしでメトリクスを収集することができます。

spec:
template:
   metadata:
     annotations:
       prometheus.io/scrape: "true"
       prometheus.io/port: "9161"
       prometheus.io/path: "/metrics" 

エクスポーターは、メトリクスにアクセスして生成するために、Oracleデータベースの接続文字列を必要とします。このパラメータは環境変数としてエクスポーターに渡されます。接続文字列にはデータベースにアクセスするためのユーザーとパスワードが含まれているため、Kubernetes Secretを使用して保存します。

Oracle Databaseへの接続文字列のシークレットを作成するには、以下のコマンドを使用します。

kubectl create secret generic oracledb-exporter-secret \
    --from-literal=datasource='YOUR_CONNECTION_STRING' 

デプロイメントでは、このように環境変数を設定します。

env:
       - name: DATA_SOURCE_NAME
         valueFrom:
           secretKeyRef:
             name: oracledb-exporter-secret
             key: datasource 

接続文字列が正しい形式であることを確認してください。

system/password@//database_url:1521/database_name.your.domain.com

接続文字列が正しいかどうかは、SQL*Plusのdockerイメージを使って確認することができます。

docker run --net='host' --rm --interactive guywithnose/sqlplus sqlplus system/password@//database_url:1521/database_name.my.domain.com

👉 Tip: Oracle v12では、データベース名の後にドメインが必要です。Oracle v19では、データベース名のみが必要です。

不明なサービスエラーが発生している場合は、接続文字列(database_urlの後の接続文字列の最後の部分)で使用しなければならないサービスを確認することができます。そのためには、データベースのコンテナを入力して、cliツールのlsnrctlを使用します。

Oracle v12では、このコマンドはディレクトリ/u01/app/oracle/product/12.2.0/dbhome_1/に、Oracle v19では/opt/oracle/product/19c/dbhome_1/binにあります。

最後に、OracleDB エクスポーターにいくつかのカスタムメトリクスを追加します。カスタムメトリクスとは、エクスポーターがすでに提供している標準メトリクスに追加するものです。

遅いクエリ、バグクエリ、大きなテーブルのメトリクスを取得するために追加します。

カスタムメトリクスを利用するためには:

  • デプロイメントでは、新しいメトリクスを格納したファイルへのルートを持つ環境変数を追加します。
  • この新しいファイルをConfigMapからボリュームとしてマウントします。

Deploymentの完全な設定は以下の通りです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: oracledb-exporter
  namespace: database-namespace
spec:
  selector:
    matchLabels:
      app: oracledb-exporter
  replicas: 1
  template:
    metadata:
      labels:
        app: oracledb-exporter
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9161"
        prometheus.io/path: "/metrics"
    spec:
      containers:
      - name: oracledb-exporter
        ports:
        - containerPort: 9161
        image: iamseth/oracledb_exporter
        env:
        - name: DATA_SOURCE_NAME
          valueFrom:
            secretKeyRef:
              name: oracledb-exporter-secret
              key: datasource
        - name: CUSTOM_METRICS
          value: /tmp/custom-metrics.toml
        volumeMounts:
          - name:  custom-metrics
            mountPath:  /tmp/custom-metrics.toml
            subPath: custom-metrics.toml
      volumes:
        - name: custom-metrics
          configMap:
            defaultMode: 420
            name: custom-metrics 

これがカスタムメトリクスを含む ConfigMap です (カスタムメトリクスを含むプレーンファイルはエクスポーターリポジトリにあります)。

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-metrics
  namespace: database-namespace
data:
  custom-metrics.toml: |
    [[metric]]
    context = "slow_queries"
    metricsdesc = { p95_time_usecs= "Gauge metric with percentile 95 of elapsed time.", p99_time_usecs= "Gauge metric with percentile 99 of elapsed time." }
    request = "select  percentile_disc(0.95)  within group (order by elapsed_time) as p95_time_usecs, percentile_disc(0.99)  within group (order by elapsed_time) as p99_time_usecs from v$sql where last_active_time >= sysdate - 5/(24*60)"
    [[metric]]
    context = "big_queries"
    metricsdesc = { p95_rows= "Gauge metric with percentile 95 of returned rows.", p99_rows= "Gauge metric with percentile 99 of returned rows." }
    request = "select  percentile_disc(0.95)  within group (order by rownum) as p95_rows, percentile_disc(0.99)  within group (order by rownum) as p99_rows from v$sql where last_active_time >= sysdate - 5/(24*60)"
    [[metric]]
    context = "size_user_segments_top100"
    metricsdesc = {table_bytes="Gauge metric with the size of the tables in user segments."}
    labels = ["segment_name"]
    request = "select * from (select segment_name,sum(bytes) as table_bytes from user_segments where segment_type='TABLE' group by segment_name) order by table_bytes DESC FETCH NEXT 100 ROWS ONLY"
    [[metric]]
    context = "size_user_segments_top100"
    metricsdesc = {table_partition_bytes="Gauge metric with the size of the table partition in user segments."}
    labels = ["segment_name"]
    request = "select * from (select segment_name,sum(bytes) as table_partition_bytes from user_segments where segment_type='TABLE PARTITION' group by segment_name) order by table_partition_bytes DESC FETCH NEXT 100 ROWS ONLY"
    [[metric]]
    context = "size_user_segments_top100"
    metricsdesc = {cluster_bytes="Gauge metric with the size of the cluster in user segments."}
    labels = ["segment_name"]
    request = "select * from (select segment_name,sum(bytes) as cluster_bytes from user_segments where segment_type='CLUSTER' group by segment_name) order by cluster_bytes DESC FETCH NEXT 100 ROWS ONLY"
    [[metric]]
    context = "size_dba_segments_top100"
    metricsdesc = {table_bytes="Gauge metric with the size of the tables in user segments."}
    labels = ["segment_name"]
    request = "select * from (select segment_name,sum(bytes) as table_bytes from dba_segments where segment_type='TABLE' group by segment_name) order by table_bytes DESC FETCH NEXT 100 ROWS ONLY"
    [[metric]]
    context = "size_dba_segments_top100"
    metricsdesc = {table_partition_bytes="Gauge metric with the size of the table partition in user segments."}
    labels = ["segment_name"]
    request = "select * from (select segment_name,sum(bytes) as table_partition_bytes from dba_segments where segment_type='TABLE PARTITION' group by segment_name) order by table_partition_bytes DESC FETCH NEXT 100 ROWS ONLY"
    [[metric]]
    context = "size_dba_segments_top100"
    metricsdesc = {cluster_bytes="Gauge metric with the size of the cluster in user segments."}
    labels = ["segment_name"]
    request = "select * from (select segment_name,sum(bytes) as cluster_bytes from dba_segments where segment_type='CLUSTER' group by segment_name) order by cluster_bytes DESC FETCH NEXT 100 ROWS ONLY" 

SecretとConfigMapを作成したら、Deploymentを適用して、ポート9161でOracleデータベースからメトリクスを取得しているかどうかを確認します。

すべてがうまくいっていれば、Prometheusはエクスポーターのアノテーション付きポッドを自動検出し、数分でメトリクスのスクレイピングを開始します。PrometheusのWebインタフェースの「targets」セクションで、oracledb_で始まるメトリクスを探すことができます。

何を監視するか

これで、ガブリエラが Prometheus にメトリクスを収集させたので、Oracle データベースの監視を開始することができます。

序章で説明した問題に対処するために監視したいメトリクスをいくつか見てみましょう。まずはパフォーマンス・メトリクスから始めます。

待ち時間:エクスポーターは、Oracleデータベースのさまざまなアクティビティにおける待ち時間の一連のメトリクスを提供しています。これらはすべて接頭辞oracledb_waittime_で始まり、データベースがどこでより多くの時間を費やしているかを評価するのに役立ちます。I/O、ネットワーク、コミット、同時実行などが考えられます。このようにして、Oracle データベースの全体的なパフォーマンスに影響を与える可能性のあるシステムのボトルネックを特定することができます。

December_006.png

遅いクエリー:クエリーによっては、結果を返すのに他のクエリーよりも時間がかかる場合があります。この時間がアプリケーションで設定されている応答を受け取るためのタイムアウトよりも長い場合、データベースからのタイムアウトエラーとみなしてクエリーを再試行します。このような動作は、システムに余計な負荷をかけてしまい、全体のパフォーマンスにも影響を与えます。

上記の設定では、過去5分間に実行されたクエリの応答時間のパーセンタイル95と99の情報を与える2つのカスタムメトリクスがあります。これらのメトリクスは以下の通りです。

  • oracledb_slow_queries_p95_time_usecs
  • oracledb_slow_queries_p99_time_usecs
December_007.png

ビッグクエリー:クエリが大量の行を返すことがあります。これは、開発中に予想されていたことであったり、メモリやネットワーキングの過負荷を引き起こしたり、高集中的な(そして遅い)I/O操作を引き起こしたりする無計画な動作であったりします。

これらの問題を検出するために、ConfigMapでは、過去5分間に返された行数によるクエリーのパーセンタイル95と99を監視するための2つのメトリクスを提供しています。

  • oracledb_big_queries_p95_rows
  • oracledb_big_queries_p99_rows
December_008.png

アクティブなセッション: Oracle データベースでアクティブなセッションを監視することが重要です。設定された制限以上のセッションがある場合、データベースは新しい接続を拒否し、アプリケーションのエラーを引き起こします。この情報を与えるメトリクスは oracledb_sessions_value であり、ラベルのステータスはより多くの情報を与えることができます。

December_009.png

アクティビティ:データベースによって実行される操作を監視することも重要です。これを行うには、以下のメトリクスに頼ることができます。

  • oracledb_activity_execute_count
  • oracledb_activity_parse_count_total
  • oracledb_activity_user_commits
  • oracledb_activity_user_rollbacks
December_010.png

これらのメトリクスから、どのような最適化を行えばシステムに大きな影響を与えるかを知ることができます。たとえば、クエリを最適化したり、パーサキャッシュをチューニングすることで、ハードパースを実行する必要がなくなり、ソフトパースを利用できるようになります。

さて、Oracleデータベースを監視している間に注意すべきリソース利用のいくつかの側面を見てみましょう。

リソース使用率:データベース管理者が持っている懸念の一つは、様々な種類のリソースの使用状況と、それらが枯渇状態に陥っていないかということです。OracleDB エクスポーターは、現在の利用率と各種類のリソースの限界に関する情報を提供する2つのメトリクスを提供します。

  • oracledb_resource_current_utilization
  • oracledb_resource_limit_value

これら 2 つのメトリクスには、参照するリソースの種類を識別するためのラベル resource_name があります。リソースのリストは、Oracle 公式ドキュメントにあります。監視すべき興味深いリソースには以下のものがあります。

  • sessions
  • processes
  • transactions
  • enqueue_resources
  • dml_locks
  • enqueue_locks
  • sort_segment_locks
  • temporary_table_locks
December_011.png

テーブルスペース:オラクルは、テーブルスペースで空間を整理します。各テーブルスペースには、オブジェクトが格納されているデータファイルが含まれています。各テーブルスペースの現在の使用量と空きバイト数を監視できる2つのメトリクスがあります。

  • oracledb_tablespace_bytes
  • oracledb_tablespace_free
December_012.png

テーブルスペースの空き容量を監視することで、ディスクの増加を計画して実装し、データベースのリソースが一杯になる前にスケールアップすることができます。

トップテーブル:場合によっては、各テーブルがデータベース内の利用可能なサイズをどのように利用しているかを評価することに興味があるかもしれません。エクスポーターで設定したカスタムメトリクスのいくつかは、管理スペースとユーザースペースの両方のトップ100テーブル、テーブルパーティション、およびクラスターのサイズに関する情報を提供します。

  • size_user_segments_top100_table
  • size_user_segments_top100_table_partition
  • size_user_segments_top100_cluster
  • size_dba_segments_top100_table
  • size_dba_segments_top100_table_partition
  • size_dba_segments_top100_cluster
December_013.png

これは、データベースからスペースを解放する必要があり、特にユーザーテーブルで、使用されていない列を削除したり、古いレコードを削除したりするような、最大のテーブルのデータの可能性のあるクリーニングを検討したい場合に興味深いものです。

何をアラートするか

どのメトリクスが監視する価値があるのか、その理由を見てきました。しかし、データベースには、SRE チームによる即時のアクションを必要とする問題がいくつかあり、問題を見つけるために誰かがダッシュボードをチェックするのを待つことはできません。

ガブリエラのチームに話を戻すと、彼らにはいくつかの SLA を満たす必要があり、彼らの部門には可用性とパフォーマンスを維持する必要がある SLO 予算があります。彼らが目標を達成するために役立つアラートが表示されます。

データベースがダウンしました。これはおそらく最も重要なものの一つです。メトリクスoracledb_upが1に等しいことは、エクスポーターがデータベースに接続できることです。接続は多くの原因で利用できない可能性がありますが、エクスポーターがデータベースにアクセスできない場合、データベースは他のアプリケーションでも利用できない可能性が高いです。この promQL クエリは、Oracle データベースが利用できない場合にトリガーされます。

oracledb_up < 1

リソースの利用率が限界に近い場合: oracledb_resource_current_utilization と oracledb_resource_limit_value メトリクスを使用して、リソースの利用率が 85% のような特定の限界よりも高い場合にアラートを作成することができます。

このアラートは、リソースがどれくらいクリティカルか不安定かに応じて、後からリソースごとに微調整することができます。また、リソースに制限が定義されている場合にのみトリガーするように、PromQLクエリに別のチェックを追加します(0よりも高い場合に定義されます)。

((oracledb_resource_current_utilization / oracledb_resource_limit_value)
  > 0.85)
and (oracledb_resource_limit_value > 0) 

リミットを超えたセッションの予測: いくつかの重要なリソースについては、問題が発生する前に対応するために予測アラートを作成することができます。これらのアラートは、線形回帰を使用してメトリクスの値を予測します。

以下の例のクエリーでは、過去2日間のセッション数が次の5日間で枯渇状態に向かっているかどうかを確認します。少なくとも25~30%のサンプルを使って予測して回帰を行うことをお勧めします。また、現在の利用状況が利用可能なセッションの75%を超えた場合にアラートを出すための句を入れます(リミットが設定されている場合)。

クエリーは次のようになります:

(predict_linear(oracledb_resource_current_utilization{resource_name="sessions"}[2d],3600*24*5) > oracledb_resource_limit_value{resource_name="sessions"})
and ((oracledb_resource_current_utilization{resource_name="sessions"} / oracledb_resource_limit_value{resource_name="sessions"})
  > 0.75)
and (oracledb_resource_limit_value{resource_name="sessions"} > 0) 

テーブルスペースの空き容量が少ない:前に見たように、テーブルスペースが空き容量の限界に達しそうになったときに SRE チームに警告するアラートを設定することができます。これは絶対値またはパーセンテージで行うことができます。

(oracledb_tablespace_bytes / 
(oracledb_tablespace_bytes + oracledb_tablespace_free)) 
> 0.85

10秒以上の応答時間のパーセンタイル99 クエリーの応答時間のパーセンタイル99は、システムの全体的なパフォーマンスを決定することができます。全体的な応答時間の増加は、同時処理やデータの後の処理に負のドミノ効果をもたらすことを覚えておいてください。アプリケーションで定義されているタイムアウトに近いレスポンスタイムを設定することで、SRE チームはこのような状況に対処することができます。

この PromQL アラートは、過去 5 分間の応答時間のパーセンタイル 99 が 10 秒を超えたときにトリガーされます。

oracledb_slow_queries_p99_time_usecs * 1000000 > 10

この例では10秒のしきい値を使用しましたが、この値はデータベースを照会するアプリケーションの要件に合わせて調整することができます。

返された行のパーセンタイル99が1Mよりも高い: 前述したように、クエリーで返された行の数が制御されていないと、ディスクやネットワークを集中的に処理することになり、データベースの応答時間やメモリ使用量に影響を与える可能性があります。

このPromQLは、過去5分間に返された行のパーセンタイル99が100万行を超えたときにトリガーされます。

oracledb_big_queries_p99_rows > 1000000

このアラートは、5 分間のウィンドウや行数を調整するなど、さらに調整が必要な場合があります。このメトリクスのパーセンタイルを計算するために使用する時間のウィンドウを変更するには、ConfigMapで定義したカスタムメトリクスにアクセスして、次の行を見つけてください。

request = "select  percentile_disc(0.95)  within group (order by rownum) as p95_rows, percentile_disc(0.99)  within group (order by rownum) as p99_rows from v$sql where last_active_time >= sysdate - 5/(24*60)"

そこでは、<number_of_minutes>/(24*60)で5/(24*60)を変更する分を編集することができます。

PromCat.ioのその他のリソース

PromCat.ioには、ダッシュボードとこのブログ記事で紹介したアラートが用意されており、すぐにGrafanaで使用することができます。これらの統合は、Sysdigがキュレーション、テスト、メンテナンスを行っています。

December_014.png

SysdigでOracleデータベースを監視する

SysdigはPrometheusとネイティブ互換性があり、エンタープライズグレードのPrometheusサービスを提供しています。つまり、エージェントはPrometheusのエクスポート先から直接メトリクスをネイティブに収集し、データをSysdig Monitorに送信することができます。

また、SysdigはPromCat.ioを介して一連の統合を提供しており、このブログ記事で紹介したダッシュボードやアラートをSysdig Monitorのアカウントで使用することができます。

December_015.png

まとめ

この記事では、Prometheusを使用してOracleデータベースを監視する方法を説明しました。OracleDB Prometheus エクスポーターをインストールして構成し、Oracleデータベースに接続し、パフォーマンスとリソース使用率の洞察を得るためのカスタム・メトリクスを追加する方法を示しました。最後に、SREチームがOracleデータベースを監視するために設定する必要のあるメトリクスとアラートに関して深く説明しました。

次はあなたの番です。上記の例を使用して、OracleDB Prometheus エクスポーターを設定し、自分で試してみることができます。このブログ記事で紹介されているメトリクスを調べ、SLOに基づいてアラートをプログラムすることができます。

このエクスポータやその他のPrometheusの統合についての詳細は、Sysdigチームが管理・キュレーションしているPromCat.ioのオープンソースリポジトリでご覧ください。必ずこのリポジトリを訪れて、Prometheusのモニタリングに必要なリソースを見つけてください。

Sysdig Essentialsの1ヶ月間の無料トライアルをご覧ください。Prometheusと完全に互換性のあるエンタープライズグレードのSaaSプラットフォームでメトリクスを探索するためにSysdig Monitorの機能をフルに利用することができます。今すぐSysdigをお試しください!

Sysdigに関するお問い合わせはこちらから

最近の投稿

カテゴリー

アーカイブ

ご質問・お問い合わせはこちら

top