新着:プロジェクトの最新情報についてはTwitterMastodonでご確認ください。

cert-manager のスケーリング

クラスタ用に cert-manager を最適化する方法を学習します。

概要

HelmチャートとYAMLマニフェストのデフォルト設定は、一般的な用途を目的としています。Kubernetesクラスタのサイズと使用方法に合わせて、設定を変更することをお勧めします。

適切なメモリリクエストとリミットを設定する

証明書リソースが主要なユースケースである場合(ワークロードがTLSシークレットをマウントする必要がある場合や、gateway-shimを使用する場合など)、cert-managerコントローラのメモリ消費量は、TLSキーペアを含むこれらのシークレットリソースの合計サイズにほぼ比例します。なぜなら、cert-managerコントローラはこれらのシークレットリソースの全内容をメモリにキャッシュするためです。大きなTLSキー(例:RSA 4096)を使用すると、小さなTLSキー(例:ECDSA)を使用する場合よりもメモリ使用量が多くなります。

Helmチャートの設定やその他のワークロードに使用されるクラスタ内の他のシークレットは、cert-managerがこれらのシークレットのメタデータのみをキャッシュするため、メモリ消費量を大幅に増加させることはありません。

CertificateRequestリソースが主要なユースケースである場合(csi-driverやistio-csrを使用する場合など)、TLSシークレットとキャッシュする必要があるリソースが少なくなるため、cert-managerコントローラのメモリ消費量ははるかに少なくなります。

📖 Kubernetesメモリ制限に関する誰もが知っておくべきことを読んで、メモリリクエストの適切なサイズ設定方法を学びましょう。

Kubernetes APIリクエストに対するクライアント側レート制限を無効にする

デフォルトでは、cert-managerはKubernetes APIサーバーへのリクエストレートを1秒あたり20クエリに制限します。これは歴史的に、cert-managerがKubernetes APIサーバーを圧倒することを防ぐことを目的としていましたが、最新のKubernetesバージョンではAPI優先順位と公平性が実装されているため、クライアント側のスロットリングは不要になりました。以下のHelm値を使用して、クライアント側レートリミッターのしきい値を増やすことができます。

# helm-values.yaml
config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
kubernetesAPIQPS: 10000
kubernetesAPIBurst: 10000

ℹ️ これは技術的にはクライアント側のレート制限を無効にするわけではなく、QPSとBurstの値を十分に高く設定して、それらの値に到達しないようにします。

🔗 cert-manager#6890: クライアント側のレート制限を無効にすることを許可する を参照してください。クライアント側のレート制限を無効にするためのcert-manager設定オプションに関する提案です。

🔗 kubernetes#111880: AP&Fが有効な場合、クライアント側のレート制限を無効にするを参照してください。kubernetes.io/client-goモジュールが有効な場合、サーバー側のレート制限を自動的に使用するようにする提案です。

🔗 クライアント側のレート制限を無効にする他のプロジェクトについてはこちらを参照してください:Flux

📖 kubernetesAPIQPSkubernetesAPIBurst設定オプションの説明については、コントローラ設定のAPIドキュメントを参照してください。

大きなRSAキーの使用を制限する

大きなRSAキーを持つ証明書は、cert-managerがより多くのCPUリソースを使用する原因となります。CPUリソースが不足している場合、調整キューの長さが長くなり、すべての証明書の調整が遅延します。多数のRSA 4096証明書を作成する権限を持つユーザーは、誤って、または悪意を持って、クラスタ上の他のユーザーのサービス拒否を引き起こす可能性があります。

📖 大きなRSAキーの使用を防ぐ方法については、承認ポリシーの適用方法を参照してください。

📖 Kyvernoなどのツールを使用して、証明書のデフォルト設定を自動的に設定する方法を学びましょう。

すべての証明書リソースでrevisionHistoryLimit: 1を設定する

デフォルトでは、cert-managerは作成したすべてのCertificateRequestリソースを保持します(revisionHistoryLimit)。

証明書の履歴に保持されるCertificateRequestリビジョンの最大数。各リビジョンは、作成時、更新時、または仕様の変更時に、この証明書によって作成された単一のCertificateRequestを表します。リビジョンの数がこの数を超えると、最も古いリビジョンから削除されます。設定する場合は、revisionHistoryLimit1以上の値にする必要があります。設定しない場合(nil)、リビジョンはガベージコレクションされません。デフォルト値はnilです。

負荷の高いクラスタでは、これらは最終的にKubernetes APIサーバーを圧倒します。これらすべてをキャッシュするために必要なメモリとCPU、およびそれらを保存するために必要なストレージが原因です。

Kyvernoなどのツールを使用して、すべての名前空間のCertificate.spec.revisionHistoryLimitをオーバーライドします。

📖 revisionHistoryLimitフィールドをデフォルト値ではなくオーバーライドするように、チュートリアル:証明書のデフォルト設定を自動的に設定する方法のKyvernoポリシーを調整します。

📖 アノテーション付きIngressリソースを使用する場合のrevisionHistoryLimitの設定方法については、こちらを参照してください。

🔗 cert-manager#3958: 証明書のリビジョン履歴制限の適切なデフォルト値を参照してください。デフォルトのrevisionHistoryLimitを変更する提案であり、この特定の推奨事項を無効にする可能性があります。

サーバーサイド適用を有効にする

デフォルトでは、cert-managerは更新リクエストを使用してCertificateRequestSecretなどのリソースを作成および変更しますが、負荷の高いクラスタでは、cert-managerの各制御ループがさまざまなリソースのステータスを更新しようとするため、頻繁に競合が発生します。

ログに次のようなエラーが表示されます。

I0419 14:11:51.325377 1 controller.go:162] "リソースに対する楽観的ロックのためアイテムを再キューイング" logger="cert-manager.certificates-trigger" key="team-864-p6ts6/app-7" error="certificates.cert-manager.io \"app-7\" に対して操作を実行できません。オブジェクトが変更されています。最新のバージョンに変更を適用して、再試行してください"

このエラーは、更新の試行が再試行されるため比較的無害ですが、各エラーが指数関数的なバックオフメカニズムをトリガーするため、調整速度が低下し、再試行間の遅延が増加します。

解決策は、サーバーサイド適用機能を有効にすることです。これにより、cert-managerはAPIリソースを変更する必要があるたびにサーバーサイド適用を使用したHTTP PATCHを使用するようになります。これにより、各cert-managerコントローラが所有するフィールドのみを設定するため、すべての競合が回避されます。

以下のHelmチャート値を使用して、サーバーサイド適用機能ゲートを有効にできます。

# helm-values.yaml
config:
apiVersion: controller.config.cert-manager.io/v1alpha1
kind: ControllerConfiguration
featureGates:
ServerSideApply: true

📖 cert-managerのようなソフトウェアに対するサーバーサイド適用の利点については、コントローラでのサーバーサイド適用の使用方法を参照してください。