Webhook 使用時のコントロール プレーンの安定性を確保する

アドミッション Webhook(Kubernetes の Webhook)はアドミッション コントローラの一種で、Kubernetes クラスタでこれを使用して、リクエストが永続化される前に、コントロール プレーンへのリクエストを検証または変更できます。サードパーティ アプリケーションでは、システムに不可欠なリソースと名前空間で動作する Webhook を使用するのが一般的です。Webhook が正しく構成されていなければ、コントロール プレーンのパフォーマンスと信頼性に影響する可能性があります。たとえば、サードパーティ アプリケーションによって作成された Webhook が正しく構成されていなければ、GKE でマネージド kube-system Namespace でのリソースの作成や変更ができなくなり、クラスタの機能が低下する可能性があります。

Google Kubernetes Engine(GKE)はクラスタをモニタリングし、Recommender サービスを利用して、プラットフォームの使用を最適化できるようにガイダンスを提供します。クラスタの安定性とパフォーマンスを維持するために、次のシナリオに関する GKE の推奨事項をご覧ください。

  • 動作しているが利用可能なエンドポイントがない Webhook。
  • システムの重要なリソースと Namespace で動作するため、安全でないとみなされている Webhook。

このガイダンスを使用すると、構成ミスの可能性がある Webhook を確認し、必要に応じて更新する手順を確認できます。

Recommender から取得した分析情報と推奨事項を管理する方法については、分析情報と推奨事項で GKE の使用を最適化するをご覧ください。

クラスタに影響を与える可能性のある Webhook の構成ミスを特定する

クラスタのパフォーマンスと安定性に影響する可能性がある Webhook を識別する分析情報を取得するには、分析情報と推奨事項を表示するの手順に沿って操作します。分析情報は次の方法で取得できます。

  • Cloud de Confiance コンソールを使用する。
  • Google Cloud CLI または Recommender API を使用して、サブタイプ K8S_ADMISSION_WEBHOOK_UNSAFEK8S_ADMISSION_WEBHOOK_UNAVAILABLE でフィルタリングする。

分析情報で Webhook を特定したら、検出された Webhook のトラブルシューティングの手順に沿って操作します。

GKE が構成ミスのある Webhook を検出した場合

クラスタが次のいずれかの条件に該当する場合、GKE は分析情報と推奨事項を生成します。

検出された Webhook のトラブルシューティング

以下の各セクションでは、構成ミスの可能性があるとして GKE によって検出された Webhook のトラブルシューティングの手順について説明します。

指示に従って Webhook を正しく構成すると、推奨事項は 24 時間以内に解決され、コンソールに表示されなくなります。

推奨事項を実施しない場合は、拒否することができます。

利用可能なエンドポイントがないと Webhook が報告する

Webhook が使用可能なエンドポイントがないと報告している場合、Webhook エンドポイントの背後にある Service には、実行されていない 1 つ以上の Pod があります。Webhook エンドポイントを利用できるようにするには、この Webhook エンドポイントの背後にある Service の Pod を見つけてトラブルシューティングを行います。

  1. 分析情報と推奨事項を表示し、トラブルシューティングする分析情報を一度に 1 つ選択します。GKE はクラスタごとに 1 つの分析情報を生成します。この分析情報には、調査が必要な損傷したエンドポイントがある Webhook が 1 つ以上表示されます。これらの Webhook のそれぞれについて、Service の名前、損傷したエンドポイント、最後にエンドポイントが呼び出された時刻も表示されます。

  2. Webhook に関連する Service の処理元の Pod を見つけます。

    コンソール

    分析情報のサイドバー パネルから、正しく構成されていない Webhook の表が表示されます。Service の名前をクリックします。

    kubectl

    次のコマンドを実行して Service の説明を取得します。

    kubectl describe svc SERVICE_NAME -n SERVICE_NAMESPACE
    

    SERVICE_NAMESERVICE_NAMESPACE をそれぞれサービスの名前と名前空間に置き換えます。

    Webhook に Service 名が表示されない場合は、構成にリストされている名前と Service の実際の名前の不一致が原因で、エンドポイントが使用できない可能性があります。エンドポイントの可用性を修正するには、正しい Service オブジェクトと一致するように Webhook 構成の Service 名を更新します。

  3. この Service の処理元の Pod を検査します。

    コンソール

    [Service の詳細] の [処理元の Pod] で、この Service の背後にある Pod のリストを確認します。

    kubectl

    Deployment または Pod を一覧表示して、実行されていない Pod を特定します。

    kubectl get deployment -n SERVICE_NAMESPACE
    

    または、次のコマンドを実行します。

    kubectl get pods -n SERVICE_NAMESPACE -o wide
    

    実行されていない Pod がある場合は、Pod のログを調べて、その Pod が実行されていない理由を確認します。Pod に関する一般的な問題に対する手順については、デプロイされたワークロードに関する問題のトラブルシューティングをご覧ください。

安全でないとみなされる Webhook

Webhook がシステム管理の名前空間内のリソース、または特定のタイプのリソースをインターセプトしている場合、GKE はこれを安全でないものとみなし、これらのリソースのインターセプトを避けるために Webhook を更新することをおすすめします。

  1. 分析情報と推奨事項を表示する手順に沿って、トラブルシューティングする分析情報を 1 つずつ選択します。GKE はクラスタごとに 1 つの分析情報のみを生成します。この分析情報には、1 つ以上の Webhook 構成が一覧表示されます。各構成には 1 つ以上の Webhook が含まれます。表示された Webhook 構成ごとに、構成にフラグが付けられた理由が分析情報に表示されます。
  2. Webhook の構成を確認します。

    コンソール

    分析情報のサイドバー パネルから、表が表示されます。各行には、Webhook 構成の名前と、この構成にフラグが付けられた理由が表示されます。

    各構成を調べるには、名前をクリックして GKE のオブジェクト ブラウザ ダッシュボードでこの構成に移動します。

    kubectl

    次の kubectl コマンドを実行して Webhook 構成を取得します。CONFIGURATION_NAME は、Webhook 構成の名前に置き換えます。

    kubectl get validatingwebhookconfigurations CONFIGURATION_NAME -o yaml
    

    このコマンドが何も返さない場合は、validatingwebhookconfigurationsmutatingwebhookconfigurations に置き換えてコマンドを再実行します。

    webhooks セクションに 1 つ以上の Webhook が表示されます。

  3. Webhook にフラグが付けられた理由に応じて、構成を編集します。

    kube-system Namespace と kube-node-lease Namespace を除外する

    scope* の場合、Webhook にフラグが付けられます。または、スコープが Namespaced で、次のいずれかの条件に当てはまる場合、Webhook にフラグが付けられます。

    • 次の例のように、operator 条件は NotIn であり、valueskube-systemkube-node-lease を省略している場合:

      webhooks:
      - admissionReviewVersions:
        ...
        namespaceSelector:
          matchExpressions:
          - key: kubernetes.io/metadata.name
            operator: NotIn
            values:
            - blue-system
        objectSelector: {}
        rules:
        - apiGroups:
          ...
          scope: '*'
        sideEffects: None
        timeoutSeconds: 3
      

      Webhook が特定の名前空間でのみ動作するように、scope* ではなく Namespaced に設定されていることを確認します。また、operatorNotIn の場合は、kube-systemkube-node-leasevalues に含めます(この例では、blue-system を使用)。

    • 次の例のように、operator 条件は In であり、values には kube-systemkube-node-lease が含まれている場合:

      namespaceSelector:
          matchExpressions:
          - key: kubernetes.io/metadata.name
            operator: In
            values:
            - blue-system
            - kube-system
            - kube-node-lease
      

      Webhook が特定の名前空間でのみ動作するように、scope* ではなく Namespaced に設定されていることを確認します。operatorIn の場合は、valueskube-systemkube-node-lease を含めないでください。この例では、operatorIn であるため、values には blue-system のみを含める必要があります。

    一致したリソースを除外する

    次の例のように、nodestokenreviewssubjectaccessreviews、または certificatesigningrequests がリソースの下に表示されている場合も、Webhook にフラグが付けられます。

    - admissionReviewVersions:
    ...
      resources:
      - 'pods'
      - 'nodes'
      - 'tokenreviews'
      - 'subjectaccessreviews'
      - 'certificatesigningrequests'
      scope: '*'
    sideEffects: None
    timeoutSeconds: 3
    

    リソース セクションから nodestokenreviewssubjectaccessreviewscertificatesigningrequests を削除します。podsresources に保持できます。

システムに不可欠なコンポーネントをブロックする Webhook

ClusterRolesClusterRoleBindings を作成または更新するリクエストをインターセプトする Webhook は、これらの重要なシステム リソースを調整するコントロール プレーンの機能を妨げる可能性があります。たとえば、クラスタのアップグレード中に、kube-apiserver がシステム ロールの更新を必要とする場合があります。使用できない Webhook または構成ミスのある Webhook がこの更新をブロックすると、kube-apiserver が正常な状態にならず、クラスタのアップグレードがブロックされます。

GKE は、Webhook が ClusterRolesClusterRoleBindings をインターセプトするかどうかを検出しないため、このシナリオでは分析情報は生成されません。

次の例は、ClusterRoles をインターセプトする問題のある Webhook 構成を示しています。

-   admissionReviewVersions:
  ...
  resources:
  -   'clusterroles'
  -   'clusterrolebindings'
  scope: '*'
sideEffects: None
timeoutSeconds: 3

この状況を回避するには、Webhook が system: prefix 設定の ClusterRolesClusterRoleBindings のリクエストをインターセプトしないようにします。

アドミッションのデッドロック

Webhook がフェイルクローズするように構成されている場合、クラスタが自動的に復旧できない状況が発生する可能性があります。たとえば、クラスタ内のすべてのノードが削除されると、Webhook も停止します。新しいノードを追加するにはアドミッション検証が必要なため、リクエストを承認するには Webhook を使用可能にする必要があります。 これにより、クラスタのコントロール プレーンが復旧できなくなる循環依存が発生します。

GKE はアドミッションのデッドロック シナリオを検出しないため、このシナリオでは分析情報は生成されません。ただし、Webhook Pod が停止している場合はアドミッションのデッドロックが発生する可能性があります。この場合、GKE は Webhook に使用可能なエンドポイントがないことを検出し、K8S_ADMISSION_WEBHOOK_UNAVAILABLE 分析情報を生成します。

この問題を軽減するには、ValidatingWebhookConfiguration を削除して循環依存を解消し、クラスタを復旧できるようにします。

クラスタ コントロール プレーンの可用性

Webhook がフェイルクローズするように構成されている場合、Kubernetes コントロール プレーンの可用性は Webhook の可用性に依存します。コントロール プレーンの可用性を向上させるには、次のことを検討してください。

GKE は、Webhook が原因で発生するクラスタ コントロール プレーンの可用性の問題を検出しないため、このシナリオでは分析情報は生成されません。

  • Webhook のスコープを制限する: Webhook が機密性の高い プロセスを妨げないように、Webhook による検証から重要なリソースを除外できます。名前空間または特定の種類のリソースを除外できます。ただし、わかりにくい依存関係に注意してください。たとえば、ConfigMap は Kubernetes でのリーダー選出に不可欠なリソースになる可能性があります。

  • Webhook デプロイを強化する: 複数の Pod で Webhook を実行すると、復元力と稼働時間を向上させることができます。ノードセレクタを使用して、Pod を異なる障害ドメインに分散させることができます。

次のステップ