Troubleshooting

このページでは、Kubernetesクラスター展開でCloudNativePGのトラブルシューティングを行う方法に関する基本情報を見つけることができます。

ヒント

Kubernetes管理者として、 kubectl ページをブックマークする必要があります!

スタート前に

Kubernetes環境

トラブルシューティングアクティビティで違いをmakeことができるのは、基礎となるKubernetesシステムに関する明確な情報を提供することです。

必ず確認してください:

  • 使用しているKubernetesのディストリビューションとバージョン PostgreSQLが実行されているノードの仕様

  • 可能な限り、ストレージを含む実際の StorageConfiguration について 稼動に入る前に行ったクラスとベンチマーク。

  • クラスターで使用している関連Kubernetesアプリケーション(つまり、 プロメテウス、グラファナ、イスティオ、証明書マネージャー、…)

便利なユーティリティ

必須の kubectl ユーティリティに加えて、トラブルシューティングのために、次のプラグイン/ユーティリティをシステムで使用可能にすることをお勧めします。

  • kubectl の cnpg

  • jq 、軽量で柔軟なコマンドラインJSONプロセッサ

  • grep 、1つ以上の入力ファイルを検索します

指定されたパターンへのマッチを含む行の場合。ほとんどの * nixディストリビューションですでに利用可能です。 Windows OSを使用している場合は、 grep の代わりに findstr を使用するか、直接 wsl を使用できます。 お好みの* nixディストリビューションをインストールし、上記のツールを使用します。

ログ

CloudNativePGによって作成および制御されるすべてのリソースは、Kubernetesが期待するように標準出力にログを記録し、JSONformatに直接記録します。そのため、 kubectl logs コマンドを使用して、特定のリソースからログを取得する必要があります。

詳細については、次を入力してください。

kubectl logs --help

ヒント

JSONログは機械読み取りには最適ですが、人間にとっては読み取りがハードです。 jq コマンドを使用して使いやすさを改善することをお勧めします。例、 | jq -C で kubectl logs コマンドを*パイプ*することができます。

注釈

以下のセクションでは、CloudNativePGのトラブルシューティングに関して、さまざまなリソースに関するログを取得する方法の例を示します。

オペレーター情報

デフォルトでは、CloudNativePG演算子はKubernetesの cnpg-system 名前空間に Deployment としてインストールされます(詳細については 展開に関する詳細 を参照)。

以下を実行することにより、演算子ポッドのリストを取得できます。

kubectl get pods -n cnpg-system

注釈

通常の状況では、演算子が実行しているポッドが1つあり、 cnpg-controller-manager- で始まる名前で識別されます。演算子を高可用性用にセットアップした場合、より多くのエントリーが必要です。これらのポッドは、 cnpg-controller-manager 名前付けのデプロイメントによって管理されます。

以下を使用して、pod <POD> で実行されている演算子に関する関連情報を収集します。

kubectl describe pod -n cnpg-system <POD>

次に、次を実行して同じポッドからログを取得します。

kubectl logs -n cnpg-system <POD>

演算子に関する詳細情報を収集する

次を実行して、CloudNativePG演算子の展開(マルチ演算子の展開がある場合)のすべてのポッドからログを取得します。

kubectl logs -n cnpg-system \
  deployment/cnpg-controller-manager --all-containers=true

ちなみに

上記のコマンドに -f フラグを追加して、リアルタイムでログを追跡できます。

以下を実行して、ログをJSONファイルに保存します。

kubectl logs -n cnpg-system \
  deployment/cnpg-controller-manager --all-containers=true | \
  jq -r . > cnpg_logs.json

kubectl-cnpg プラグインを使用してCloudNativePG演算子バージョンを取得します。

kubectl-cnpg status <CLUSTER>

出力:

Cluster in healthy state
Name:               cluster-example
Namespace:          default
System ID:          7044925089871458324
PostgreSQL Image:   ghcr.io/cloudnative-pg/postgresql:14.2-3
Primary instance:   cluster-example-1
Instances:          3
Ready instances:    3
Current Write LSN:  0/5000000 (Timeline: 1 - WAL File: 000000010000000000000004)

Continuous Backup status
Not configured

Streaming Replication status
Name               Sent LSN   Write LSN  Flush LSN  Replay LSN  Write Lag       Flush Lag       Replay Lag      State      Sync State  Sync Priority
- ---               --------   ---------  ---------  ----------  ---------       ---------       ----------      -----      ----------  -------------
cluster-example-2  0/5000000  0/5000000  0/5000000  0/5000000   00:00:00        00:00:00        00:00:00        streaming  async       0
cluster-example-3  0/5000000  0/5000000  0/5000000  0/5000000   00:00:00.10033  00:00:00.10033  00:00:00.10033  streaming  async       0

Instances status
Name               Database Size  Current LSN  Replication role  Status  QoS         Manager Version
- ---               -------------  -----------  ----------------  ------  ---         ---------------
cluster-example-1  33 MB          0/5000000    Primary           OK      BestEffort  1.12.0
cluster-example-2  33 MB          0/5000000    Standby (async)   OK      BestEffort  1.12.0
cluster-example-3  33 MB          0/5000060    Standby (async)   OK      BestEffort  1.12.0

クラスター情報

NAMESPACE namespaceの <CLUSTER> クラスターのステータスは、次の方法で確認できます。

kubectl get cluster -n <NAMESPACE> <CLUSTER>

出力:

NAME        AGE        INSTANCES   READY   STATUS                     PRIMARY
<CLUSTER>   10d4h3m    3           3       Cluster in healthy state   <CLUSTER>-1

上記の例は、すべてが* ready *状態で、 <CLUSTER>-1 がプライマリである3つのインスタンスの健全なPostgreSQLクラスターを報告します。

異常な状態の場合、 Cluster リソースのマニフェストを取得することでさらに発見できます。

kubectl get cluster -o yaml -n <NAMESPACE> <CLUSTER>

収集する別の重要なコマンドは、 cnpg プラグインによって提供される status コマンドです。

kubectl cnpg status -n <NAMESPACE> <CLUSTER>

ちなみに

--verbose オプションを追加すると、より多くの情報をプリントできます。

リスタートクラスターのステータスを知ることに加えて、cnpgプラグインを使用して次のことを実行することもできます。レプリカを昇格します。<br />証明書を管理します。<br />ループをリロードロードして設定変更を適用します。<br />詳細については、 cnpg の文書を参照してください。

PostgreSQLコンテナイメージバージョンを取得します。

kubectl describe cluster <CLUSTER_NAME> -n <NAMESPACE> | grep "Image Name"

出力:

Image Name:    ghcr.io/cloudnative-pg/postgresql:14.2-3

注釈

また、 kubectl-cnpg status -n <NAMESPACE> <CLUSTER_NAME> を使用して同じ情報を取得できます。

ポッド情報

以下を使用して、特定のPostgreSQLclusterに属するインスタンスのリストを取得できます。

kubectl get pod -l cnpg.io/cluster=<CLUSTER> -L role -n <NAMESPACE>

出力:

NAME          READY   STATUS    RESTARTS   AGE       ROLE
<CLUSTER>-1   1/1     Running   0          10d4h5m   primary
<CLUSTER>-2   1/1     Running   0          10d4h4m   replica
<CLUSTER>-3   1/1     Running   0          10d4h4m   replica

以下を実行することにより、ポッドが失敗しているかどうか/どのように失敗しているかを確認できます。

kubectl get pod -n <NAMESPACE> -o yaml <CLUSTER>-<N>

以下を使用して、特定のPostgreSQLインスタンスのすべてのログを取得できます。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N>

検索をPostgreSQLプロセスのみに制限する場合は、次を実行できます。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | \
  jq select(.logger=="postgres") | .record.message

次の例も、ユーザフレンドリフォーマットでタイムスタンプを追加します。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | \
  jq -r select(.logger=="postgres") | [(.ts|strflocaltime("%Y-%m-%dT%H:%M:%S %Z")), .record.message] | @csv

PostgreSQLポッドに関する追加情報を収集してフィルタリングする

クラッシュした特定のポッドのログを確認します。

kubectl logs -n <NAMESPACE> --previous <CLUSTER>-<N>

特定のPostgreSQLポッドから致命的なエラーを取得します。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | \
  jq -r .record | select(.error_severity == "FATAL")

出力:

{
  "log_time": "2021-11-08 14:07:44.520 UTC",
  "user_name": "streaming_replica",
  "process_id": "68",
  "connection_from": "10.244.0.10:60616",
  "session_id": "61892f30.44",
  "session_line_num": "1",
  "command_tag": "startup",
  "session_start_time": "2021-11-08 14:07:44 UTC",
  "virtual_transaction_id": "3/75",
  "transaction_id": "0",
  "error_severity": "FATAL",
  "sql_state_code": "28000",
  "message": "role \"streaming_replica\" does not exist",
  "backend_type": "walsender"
}

特定のポッドのログでPostgreSQL DBエラーメッセージをフィルタリングします。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | jq -r .err | select(. != null)

出力:

dial unix /controller/run/.s.PGSQL.5432: connect: no such file or directory

特定のポッドから err ワードにマッチングメッセージを取得します。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | jq -r .msg | grep "err"

出力:

2021-11-08 14:07:39.610 UTC [15] LOG:  ending log output to stderr

特定のポッドからPostgreSQLプロセスからすべてのログを取得します。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | \
  jq -r . | select(.logger == "postgres") | select(.msg != "record") | .msg
```出力:

```shell
2021-11-08 14:07:52.591 UTC [16] LOG:  redirecting log output to logging collector process
2021-11-08 14:07:52.591 UTC [16] HINT:  Future log output will appear in directory "/controller/log".
2021-11-08 14:07:52.591 UTC [16] LOG:  ending log output to stderr
2021-11-08 14:07:52.591 UTC [16] HINT:  Future log output will go to log destination "csvlog".

値を持つフィールドでフィルタリングされたポッドログを取得し、実行中の | で区切って結合します。

kubectl logs -n <NAMESPACE> <CLUSTER>-<N> | \
  jq -r [.level, .ts, .logger, .msg] | join(" | ")

出力:

info | 1636380469.5728037 | wal-archive | Backup not configured, skip WAL archiving
info | 1636383566.0664876 | postgres | record

バックアップ情報

以下を使用して、名前付けクラスター用に作成されたバックアップをリストできます。

kubectl get backup -l cnpg.io/cluster=<CLUSTER>

重要

CloudNativePGのバージョン1.10.0でバックアップラベルが導入されました。そのため、そのバージョン以上で作成されたリソースのみにこのようなlabelが含まれます。

ストレージ情報

次のように、調査またはトラブルシューティング中にクラスターで使用されるStorageClassを再確認してコンテキストを確認すると便利な場合があります。

STORAGECLASS=$(kubectl get pvc <POD> -o jsonpath={.spec.storageClassName})
kubectl get storageclasses $STORAGECLASS -o yaml

多くの場合、クラスターはデフォルトのStorageClassを使用して作成されるため、ここではクラスターポッドの1つからStorageClassを取得しています。

ノード情報

Kubernetesノードは、最終的にPostgreSQLポッドが実行される場所です。それらについてできる限り知ることが戦略的に重要です。

Kubernetesクラスター内のノードのリストを取得するには、次を使用します。

#  look at the worker nodes and their status
kubectl get nodes -o wide

さらに、特定のクラスターのポッドが実行されているノードのリストを収集できます。

kubectl get pod -l cnpg.io/clusterName=<CLUSTER> \
  -L role -n <NAMESPACE> -o wide

後者は、ポッドがどこに分散されているかを理解するために重要です- affinity/anti-affinity rules and/or tolerations を使用している場合は非常に便利です。

条件

多くのネイティブkubernetesobjects like here と同様に、クラスターは status.conditions も公開します。これにより、クラスター全体のヘルス状態に依存する代わりに、特定のイベントが発生するのを「待つ」ことができます。現在利用可能な条件は次のとおりです。

  • LastBackupSucceeded

  • 継続的なアーカイブ

特定の条件を待つ方法

  • バックアップ:

$ kubectl wait --for=condition=LastBackupSucceeded cluster/<CLUSTER-NAME> -n <NAMESPACE>
  • 継続的なアーカイブ:

$ kubectl wait --for=condition=ContinuousArchiving cluster/<CLUSTER-NAME> -n <NAMESPACE>

以下は、失敗した状態を含む cluster.status のスニペットです。

$ kubectl get cluster/<cluster-name> -o yaml
.
.
.
  status:
    conditions:
    - message: unexpected failure invoking barman-cloud-wal-archive: exit status
        2
      reason: Continuous Archiving is Failing
      status: "False"
      type: ContinuousArchiving

    - message: exit status 2
      reason: Backup is failed
      status: "False"
      type: LastBackupSucceeded

いくつかの一般的な問題

ストレージがいっぱいです

クラスター内の1つ以上のポッドが CrashloopBackoff にあり、これがフルディスクである可能性がlogsuggestである場合、おそらくインスタンスの PersistentVolumeClaim のサイズを増やす必要があります。文書の ボリューム拡張 をご覧ください。

ポッドが Pending 状態でスタックしている

クラスターのインスタンスが Pending フェーズでスタックしている場合は、ポッドの Events セクションを確認して、この背後にある理由を把握する必要があります。

kubectl describe pod -n <NAMESPACE> <POD>

これの考えられる原因のいくつかは次のとおりです:

  • nodeSelector にマッチングするノードはありません

  • 許容値は、ノードの汚染とマッチするように正しく構成されていません

  • 使用可能なノードがまったくありません。これは、 cluster-autoscaler がいくつかの制限に達している、または一時的な問題がある

この場合、名前空間のイベントを確認することも役立ちます。

kubectl get events -n <NAMESPACE>
#  list events in chronological order
kubectl get events -n <NAMESPACE> --sort-by=.metadata.creationTimestamp

バックアップが設定されていないときにレプリカが同期しない

メンテナンスの理由により、レプリカがしばらくオフになる場合がありビット(Kubernetesノードが空になった場合を考えてください)。クラスターにバックアップが設定されていない場合、レプリカがバックアップされるときに、プライマリに存在しないWALファイル( :ref:``postgresql` セクション<postgresql セクション>` で説明されているようにWAL管理ポリシーに従って既にリサイクルされている)が必要になり、同期が外れることがあります。

同様に、 pg_rewind が、以前のプライマリに存在しないWALファイルを必要とする場合、 pg_rewind: error: could not open file を報告します。

これらの場合、ポッドは準備ができなくなり、PVCを削除し、演算子にレプリカを再構築させる必要があります。

動的にプロビジョニングされた永続ボリュームに依存していて、PV自分自身を削除することに自信がある場合は、次の方法で削除できます。

PODNAME=<POD>
VOLNAME=$(kubectl get pv -o json | \
  jq -r .items[]|select(.spec.claimRef.name==\"$PODNAME\")|.metadata.name)

kubectl delete pod/$PODNAME pvc/$PODNAME pv/$VOLNAME