新着:プロジェクトのアップデートはTwitterMastodonでご確認いただけます。

ベストプラクティス

このセクションでは、CIS Kubernetes ベンチマークNSA Kubernetes ハードニングガイド、またはBSI Kubernetes セキュリティ推奨事項などの一般的なセキュリティ標準に準拠するように cert-manager を設定する方法について説明します。

また、Datree とその組み込みルールなどのツールによって適用されるものや、Learnk8s の「Kubernetes プロダクションベストプラクティス」チェックリストなどで説明されているものなど、本番環境で cert-manager をデプロイするためのベストプラクティスについても説明します。

概要

HelmチャートまたはYAMLマニフェスト(Deployment、Pod、ServiceAccountなど)内のcert-managerリソースのデフォルト設定は、ベストプラクティスや最大限のセキュリティではなく、後方互換性を重視して設計されています。デフォルトのリソースがKubernetesクラスタのセキュリティポリシーに準拠していない場合があり、その場合は、Helmチャートの値を使用してインストール設定を変更し、デフォルト値を上書きできます。

ネットワーク要件とネットワークポリシー

各cert-manager Podのネットワーク要件の概要を以下に示します。ネットワーク要件の一部は、特定のIssuer/ClusterIssuerの設定や特定の設定オプションによって異なります。

ご自身の cert-managerインストールのネットワーク要件を理解したら、Kubernetesネットワーク(CNI)プラグイン(例:Calico)を使用して、「最小権限」のネットワークポリシーを実装することを検討してください。

ネットワークポリシーにより、信頼できないクライアントがcert-manager Podに接続すること、およびcert-managerが信頼できないサーバーに接続することを防止する必要があります。

この推奨事項の例は、Calicoドキュメントにあります。

Calicoを使用する場合でも、Kubernetesネットワークポリシーを使用する場合でも、Kubernetes Podに対する暗黙的なデフォルト拒否ポリシーを作成することをお勧めします。これにより、不要なトラフィックがデフォルトで拒否されます。

📖 Calicoベストプラクティス:暗黙的なデフォルト拒否ポリシー

任意のKubernetesネットワーク(CNI)プラグインで認識されるため、移植可能なKubernetes組み込みのNetworkPolicyリソースを使用できます。または、CNIソフトウェアによって提供されるカスタムリソースを使用することもできます。

📖 Kubernetes組み込みNetworkPolicy APIについて学び、ポリシーの例を参照してください。

ネットワーク要件

ネットワーク要件の概要を以下に示します。

  1. UDP/TCP: cert-manager(すべて)-> Kubernetes DNS:すべてのcert-managerコンポーネントは、クラスタと外部ドメイン名の両方に対してUDP DNSクエリを実行します。TCPを使用するDNSクエリもあります。

  2. TCP: Kubernetes(APIサーバー)-> cert-manager(webhook):Kubernetes APIサーバーは、cert-manager webhookコンポーネントへのHTTPS接続を確立します。webhookのネットワーク要件を理解するには、cert-managerのwebhookトラブルシューティングガイドを参照してください。

  3. TCP: cert-manager(webhook、controller、cainjector、startupapicheck)-> Kubernetes APIサーバー:cert-managerのwebhook、controller、cainjector、startupapicheckは、cert-managerカスタムリソースおよびKubernetesリソースと対話するために、Kubernetes APIサーバーへのHTTPS接続を確立します。cert-manager webhookは特別なケースであり、SubjectAccessReview APIを使用してKubernetes APIサーバーに接続し、CertificateRequestリソースのApprovedまたはDenied条件を変更しようとするクライアントを検証します。

  4. TCP: cert-manager(controller)-> HashiCorp Vault(認証とリソースAPIエンドポイント)Vault Issuerを使用している場合、cert-manager controllerは1つ以上のVault APIエンドポイントへのHTTPS接続を確立する場合があります。Vaultエンドポイントのターゲットホストとポートは、IssuerまたはClusterIssuerリソースで構成されます。

  5. TCP: cert-manager(controller)-> Venafi TLS Protect(認証とリソースAPIエンドポイント)Venafi Issuerを使用している場合、cert-manager controllerは1つ以上のVenafi APIエンドポイントへのHTTPS接続を確立する場合があります。Venafi APIエンドポイントのターゲットホストとポートは、IssuerまたはClusterIssuerリソースで構成されます。

  6. TCP: cert-manager(controller)-> DNS APIエンドポイント(ACME DNS01の場合)DNS01ソルバーを使用するACME Issuerを使用している場合、cert-manager controllerは、Amazon Route53などのDNS APIエンドポイントと、関連する認証エンドポイントへのHTTPS接続を確立する場合があります。

  7. UDP/TCP: cert-manager(controller)-> 外部DNS:ACME Issuerを使用する場合、cert-manager controllerは、ACMEチャレンジの自己チェックプロセスの一環として、再帰的なDNSサーバーにDNSクエリを送信する場合があります。これは、ACMEサーバーにチェックを実行するよう依頼する前に、DNS01またはHTTP01チャレンジが解決可能であることを確認するためです。

    DNS01の場合、DNS01チャレンジレコードを追加するDNSゾーンを計算するために、権威DNSサーバーへの一連のDNSクエリを実行する場合もあります。DNS01の場合、cert-managerはDNS over HTTPSもサポートしています。

    次のcontrollerフラグを使用して、DNSサーバーのホストとポートを選択できます。--acme-http01-solver-nameservers--dns01-recursive-nameservers、および--dns01-recursive-nameservers-only

  8. TCP: ACME(Let's Encrypt)-> cert-manager(acmesolver):HTTP01用に構成されたACME Issuerを使用する場合、cert-managerは、Issuerの名前空間またはClusterIssuerの場合はcert-managerの名前空間に、acmesolver Pod、Service、およびIngress(またはGateway API)リソースをデプロイします。ACME実装は、選択したIngressロードバランサーを介してこのPodへのHTTP接続を確立するため、ネットワークポリシーでこれを許可する必要があります。

    ℹ️ acmesolver Podは、Kubernetes APIサーバーへのアクセスを必要としません

  9. TCP: Metrics Server -> cert-manager(controller):cert-manager controllerには、TCPポート9402でHTTP接続をリッスンするメトリクスサーバーがあります。選択したメトリクスコレクターからこのサービスへのアクセスを許可するネットワークポリシーを作成してください。

専用のノードプールでcert-managerを分離する

cert-managerはクラスタスコープのオペレーターであり、プラットフォームの制御プレーンの一部として扱う必要があります。cert-manager controllerはKubernetes Secretリソースを作成および変更し、controllerとcainjectorはどちらもメモリにTLS Secretリソースをキャッシュします。これらは、cert-managerコンポーネントを他の特権レベルの低いワークロードから分離することを検討する必要がある2つの理由です。たとえば、信頼できないワークロードまたは悪意のあるワークロードがcert-manager controllerと同じノードで実行され、何らかの方法で基盤となるノードへのrootアクセス権を取得した場合、controllerがメモリにキャッシュしたSecret内の秘密鍵を読み取ることができる可能性があります。

信頼できるプラットフォームオペレーター用に予約されたノードでcert-managerを実行することにより、このリスクを軽減できます。

cert-managerのHelmチャートには、各コンポーネントのPod tolerationsnodeSelectorを構成するためのパラメーターがあります。これらのパラメーターの正確な値は、クラスタによって異なります。

📖 KubernetesドキュメントPodのノードへの割り当てを参照してください。

📖 Kubernetesドキュメント汚染と許容について読んでください。

この例では、taintsを使用してプラットフォーム以外のPodをプラットフォームの制御プレーン用に予約したノードからはじく方法、tolerationsを使用してcert-manager Podがこれらのノードで実行されるようにする方法、およびnodeSelectorを使用してcert-manager Podをこれらのノードに配置する方法を示します。

ノードにラベルを付ける

kubectl label node ... node-restriction.kubernetes.io/reserved-for=platform

ノードに汚染を適用する

kubectl taint node ... node-restriction.kubernetes.io/reserved-for=platform:NoExecute

次に、次のHelmチャート値を使用してcert-managerをインストールします。

nodeSelector:
kubernetes.io/os: linux
node-restriction.kubernetes.io/reserved-for: platform
tolerations:
- key: node-restriction.kubernetes.io/reserved-for
operator: Equal
value: platform
webhook:
nodeSelector:
kubernetes.io/os: linux
node-restriction.kubernetes.io/reserved-for: platform
tolerations:
- key: node-restriction.kubernetes.io/reserved-for
operator: Equal
value: platform
cainjector:
nodeSelector:
kubernetes.io/os: linux
node-restriction.kubernetes.io/reserved-for: platform
tolerations:
- key: node-restriction.kubernetes.io/reserved-for
operator: Equal
value: platform
startupapicheck:
nodeSelector:
kubernetes.io/os: linux
node-restriction.kubernetes.io/reserved-for: platform
tolerations:
- key: node-restriction.kubernetes.io/reserved-for
operator: Equal
value: platform

ℹ️ この例では、Podを配置するためにnodeSelectorを使用していますが、affinity.nodeAffinityを使用することもできます。nodeSelectorは、構文が単純なためここで選択されています。

ℹ️ デフォルトのnodeSelectorkubernetes.io/os: linuxは、混合OSクラスタでcert-manager PodがWindowsノードに配置されるのを回避するため、これも明示的に含める必要があります。

📖 EKSベストプラクティスガイド特定のノードへのテナントワークロードの分離に関するガイドで、これらの手法の詳細な説明を参照してください。

📖 Google Kubernetes Engine専用のノードプールでワークロードを分離する方法について学びます。

📖 RedHat OpenShiftを使用したノードセレクターによる特定のノードへのPodの配置について学びます。

📖 node-restriction.kubernetes.io/プレフィックスとNodeRestrictionアドミッションプラグインの詳細を参照してください。

ℹ️ マルチテナントクラスタでは、テナントがPodに追加できる許容値を制限するために、PodTolerationRestrictionプラグインを有効にすることを検討してください。cert-manager名前空間にデフォルトの許容値を追加するためにそのプラグインを使用することもできます。これにより、Helmチャートで許容値を明示的に設定する必要がなくなります。

ℹ️ 代わりに、Kyverno を使用して、Pod で使用できる許容値を制限することもできます。コントロールプレーンのスケジューリングの制限 を出発点として読んでください。

高可用性

cert-managerには、コントローラー、cainjector、webhookの3つの長時間実行コンポーネントがあります。これらの各コンポーネントにはDeploymentがあり、デフォルトでは各Deploymentにレプリカが1つありますが、これは高可用性を提供しません。cert-managerのHelmチャートには、各DeploymentのreplicaCountを構成するためのパラメーターがあります。本番環境では、次のreplicaCountパラメーターを推奨します。

replicaCount: 2
webhook:
replicaCount: 3
cainjector:
replicaCount: 2

コントローラーとcainjector

コントローラーとcainjectorコンポーネントは、リーダー選挙を使用して、アクティブなレプリカが1つだけになるようにします。これは、複数のレプリカが同じAPIリソースを調整しようとした場合に発生する競合を防ぎます。そのため、これらのコンポーネントでは、水平スケーリングではなく、高可用性を実現するために複数のレプリカを使用できます。

2つのレプリカを使用すると、現在のリーダーが中断に遭遇した場合に、リーダーシップを引き継ぐ準備ができているノードにスタンバイPodがスケジュールされていることが保証されます。たとえば、リーダーPodがノードからドレインされた場合や、リーダーPodが予期しないデッドロックに遭遇した場合などです。

これらのコンポーネントのレプリカを2つ以上使用する正当な理由はほとんどありません。

webhook

デフォルトでは、cert-manager webhook Deploymentにはレプリカが1つありますが、本番環境では3つ以上を使用する必要があります。cert-manager webhookが利用できない場合、cert-managerカスタムリソースに対するすべてのAPI操作が失敗し、cert-managerカスタムリソースを作成、更新、または削除するソフトウェア(cert-manager自体を含む)を中断し、クラスタに他の中断を引き起こす可能性があります。そのため、常に複数のcert-manager webhookレプリカを実行することが特に重要です。

ℹ️ 対照的に、cert-managerコントローラーのレプリカが1つしかない場合、中断のリスクは低くなります。たとえば、単一cert-managerコントローラーマネージャーPodをホストしているノードがドレインされた場合、別のノードで新しいPodが起動されるまで遅延が発生し、その間に作成または変更されたcert-managerリソースは、新しいPodが起動するまで調整されません。しかし、コントローラーマネージャーは非同期的に動作するため、cert-managerカスタムリソースに依存するアプリケーションは、この状況に耐えられるように設計されています。とはいえ、クラスタに十分なリソースがある場合は、各コントローラーのレプリカを2つ以上実行することをお勧めします。

📖 Google Kubernetes Engine(GKE)のドキュメントでWebhookを使用する場合のコントロールプレーンの安定性の確保を読んで、Webhookの中断がクラスタをどのように中断する可能性があるかの例を確認してください。

📖 Cisco Tech BlogのKubernetes Admission Webhookのダークサイドを読んで、Webhookによって引き起こされる可能性のある問題とそれらを回避する方法の詳細について学習してください。

トポロジースプレッド制約

トポロジースプレッド制約を使用することを検討して、ノードまたはデータセンターの中断がcert-managerの動作を低下させないようにしてください。

高可用性のために、レプリカPodが同じノードにスケジュールされないようにする必要があります。そのノードに障害が発生した場合、アクティブなPodとスタンバイPodの両方が終了し、別のノードに十分な空きリソースを持つノードがあるまで、そしてそのPodが準備完了になるまで、そのコントローラーによるリソースの調整は行われなくなります。

クラスタにゾーン間に分散されたノードがある場合は、Podが別々のデータセンター(アベイラビリティゾーン)で実行されることも望ましいです。そうすれば、アクティブなPodをホストするデータセンターに障害が発生した場合、スタンバイPodはすぐにリーダーシップを引き継ぐことができます。

幸いなことに、Kubernetes >= 1.24には組み込みのデフォルトの制約があります。そのため、上記の高可用性スケジューリングは暗黙的に行われます。

ℹ️ クラスタで組み込みのデフォルトの制約を使用していない場合。トポロジースプレッド制約をHelmチャート値を使用してcert-managerコンポーネントのそれぞれに追加できます。

PodDisruptionBudget

高可用性のために、minAvailable=1PodDisruptionBudgetリソースもデプロイする必要があります。

これにより、ノードのドレインなど、任意の中断が、少なくとも別のレプリカが別のノードに正常にスケジュールおよび開始されるまで続行されないことが保証されます。Helmチャートには、長時間実行されるcert-managerコンポーネントのそれぞれについてPodDisruptionBudgetを有効化および構成するためのパラメーターがあります。次のパラメーターをお勧めします。

podDisruptionBudget:
enabled: true
minAvailable: 1
webhook:
podDisruptionBudget:
enabled: true
minAvailable: 1
cainjector:
podDisruptionBudget:
enabled: true
minAvailable: 1

📖 Kubernetesドキュメントでアプリケーションのディスラプション予算の指定について読んでください。

⚠️ これらのPodDisruptionBudget設定は、高可用性デプロイメントにのみ適しています。minAvailable値よりも多くのreplicaCountを各Deploymentに増やす必要があります。そうでない場合、PodDisruptionBudgetによってcert-manager Podのドレインを防ぐことになります。

優先順位クラス名

優先順位クラスを設定する理由は、KubernetesブログのPriorityClassを使用してミッションクリティカルなPodを退避から保護するで次のように要約されています。

Podの優先順位とプリエンプションは、スケジューリングと退避の順序を決定することで、リソース不足の場合にミッションクリティカルなPodが稼働していることを保証するのに役立ちます。

cert-managerがプラットフォームにとってミッションクリティカルな場合は、Kubernetesノードのリソースが不足した場合にプリエンプションから保護するために、cert-manager PodにpriorityClassNameを設定します。priorityClassNameがない場合、cert-manager Podは他のPodのためにリソースを解放するために退避される可能性があり、これにより、cert-managerに依存するアプリケーションに中断が発生する可能性があります。

ほとんどのKubernetesクラスタには、system-cluster-criticalsystem-node-criticalという2つの組み込み優先順位クラス名が付属しており、Kubernetesコアコンポーネントに使用されます。これらは、cert-managerなどの重要なアドオンにも使用できます

すべてのcert-manager PodにpriorityClassName: system-cluster-criticalを設定するには、次のHelmチャート値を使用することをお勧めします。

global:
priorityClassName: system-cluster-critical

一部のクラスタでは、ResourceQuotaアドミッションコントローラー特定の優先順位クラスの使用を特定のネームスペースに制限するように構成されている可能性があります。たとえば、Google Kubernetes Engine(GKE)は、デフォルトでkube-systemネームスペースのPodに対してのみpriorityClassName: system-cluster-criticalを許可します。

📖 Kubernetes PR #93121を読んで、これがどのようにしてなぜ実装されたかを確認してください。

このような場合は、cert-managerネームスペースにResourceQuotaを作成する必要があります。

# cert-manager-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: cert-manager-critical-pods
namespace: cert-manager
spec:
hard:
pods: 1G
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values:
- system-node-critical
- system-cluster-critical
kubectl apply -f cert-manager-resourcequota.yaml

📖 Kubernetesブログの投稿であるPriorityClassを使用してミッションクリティカルなPodを退避から保護するを読んで、Podの優先順位とプリエンプションがリソース不足の場合にミッションクリティカルなPodが稼働していることを保証するのにどのように役立つのかを確認してください。

📖 クリティカルなアドオンPodの保証されたスケジューリングを読んで、完全に機能するクラスタにとってクリティカルなアドオンにsystem-cluster-criticalを使用する理由を学習してください。

📖 デフォルトで優先順位クラスの消費量を制限するを読んで、プラットフォーム管理者が特定の高優先順位クラスの使用を限られた数のネームスペースに制限する理由を学習してください。

📖 system-cluster-critical 優先度クラス名を使用するその他の重要なアドオンの例:NVIDIA GPU OperatorOPA GatekeeperCilium

スケーラビリティ

cert-managerには、コントローラー、cainjector、webhookの3つの長時間実行コンポーネントがあります。Helmチャートには、これらのいずれにもリソース要求と制限が含まれていないため、クラスタに適したリソース要求と制限を指定する必要があります。

コントローラーとcainjector

コントローラーとcainjectorコンポーネントは、リーダー選挙を使用して、アクティブなレプリカが1つだけになるようにします。これにより、複数のレプリカが同じAPIリソースを調整する場合に発生する競合を防ぎます。これらのコンポーネントには水平スケーリングを使用できません。代わりに垂直スケーリングを使用してください。

メモリ

垂直スケーリングを使用して、これらのコンポーネントに十分なメモリリソースを割り当てます。メモリ要件は、非常に多くのAPIリソースがあるクラスタ、または大きなAPIリソースがあるクラスタで高くなります。これは、各コンポーネントが1つ以上のKubernetes APIリソースを調整し、各コンポーネントがメタデータ、場合によってはリソース全体をメモリにキャッシュして、Kubernetes APIサーバーの負荷を軽減するためです。

クラスタにCertificateRequestリソースが大量に含まれている場合(多くの短命の証明書を頻繁にローテーションする場合など)、コントローラーPodのメモリ制限を増やす必要があります。

cainjectorのメモリ消費量を削減するには、cert-manager名前空間のリソースのみを監視するように構成し、Certificateリソースを監視しないように構成します。Helmチャートの値を使用してcainjectorコマンドラインフラグを構成する方法を以下に示します。

cainjector:
extraArgs:
- --namespace=cert-manager
- --enable-certificates-data-source=false

⚠️️ この最適化は、cainjectorがcert-manager webhook専用に使用されている場合にのみ適切です。 cainjectorが他のソフトウェアのWebhookのTLS証明書の管理にも使用されている場合は適切ではありません。たとえば、一部のKubebuilder派生プロジェクトは、cainjectorを使用してWebhookにTLS証明書を挿入する必要がある場合があります。

CPU

垂直スケーリングを使用して、これらのコンポーネントに十分なCPUリソースを割り当てます。CPU要件は、これらのコンポーネントによって調整されるリソースの更新が非常に頻繁に行われるクラスタで高くなります。リソースが変更されるたびに、コンポーネントによって再調整されるようにキューに入れられます。CPUリソースが多いほど、コンポーネントはキューをより高速に処理できます。

Webhook

cert-manager webhookはリーダー選挙を使用しないため、レプリカ数を増やすことで水平方向にスケールできます。Kubernetes APIサーバーは、すべての準備完了レプリカ間の接続をロードバランスするサービスを介してcert-manager webhookに接続します。このため、cert-managerカスタムリソースのインタラクションの頻度が高いクラスタでは、webhookレプリカの数を3以上に増やすことで明確な利点があります。さらに、webhookはキャッシュを使用しないため、メモリ要件が控えめです。このため、webhookをスケールアウトするリソースコストは比較的低くなります。

ライブネスプローブの使用

この推奨事項の例は、Datreeドキュメントにあります。 各コンテナに構成されたライブネスプローブがあることを確認する

ライブネスプローブにより、KubernetesはPodをいつ置き換えるべきかを判断できます。それらは、復元力のあるクラスタアーキテクチャを構成する上で基本です。

cert-manager webhookとコントローラーPodにはライブネスプローブがあります。cainjector Podには、まだライブネスプローブがありません。詳細を以下に示します。

Webhook

cert-manager webhookにはデフォルトで有効になっているライブネスプローブがあり、タイミングと閾値はHelm値を使用して構成できます

コントローラー

📢 cert-managerコントローラーのライブネスプローブは、cert-managerリリース1.12で導入され、リリース1.14でデフォルトで有効になりました。現場で問題が発生した場合は、お問い合わせください

cert-managerコントローラーのライブネスプローブは、ポート9443でリッスンし、独自のthreadで実行されるhealthzサーバーの/livezエンドポイントに接続するHTTPプローブです。/livezエンドポイントは現在、次のサブシステムの結合状態を報告し、各サブシステムには独自の/livezエンドポイントがあります。

  • /livez/leaderElection:リーダー選挙レコードが更新されていない場合、またはリーダー選挙スレッドが親プロセスをクラッシュさせずに終了した場合にエラーを返します。
  • /livez/clockHealth:システムクロックとGoがタイマーのスケジュールに使用している単調クロックとの間にクロックスキューが検出された場合にエラーを返します。

ℹ️ 今後、Kubernetesがロギングがブロックされていないことを確認する方法や各コントローラーのヘルスチェックを行う方法と同様に、/livezエンドポイントによってより多くのサブシステムをチェックできる可能性があります。

📖 個々のヘルスチェックと詳細なステータス情報へのアクセス方法について読んでください(cert-managerはKubernetesと同じhealthzエンドポイントマルチプレクサを使用します)。

Cainjector

cainjector Podには、ライブネスプローブや/livez healthzエンドポイントはありませんが、GitHubの問題に正当な理由があります。シャットダウンを試行した後、ゾンビ状態になったcainjector。この特定の問題も経験した場合は、その問題にコメントを追加し、Helm:作成されたすべてのPodのreadiness、liveness、startupプローブの構成を許可するにコメントを追加してください。cainjectorのライブネスプローブに関する一般的なリクエストがある場合。

背景情報

cert-manager controllerプロセスとcainjectorプロセスはどちらも、Kubernetes リーダー選挙ライブラリを使用して、一度にアクティブにできる各プロセスのレプリカが1つだけになるようにします。Kubernetesコントロールプレーンコンポーネントもこのライブラリを使用します。

リーダー選出コードは、別のスレッド(Goルーチン)内でループして実行されます。最初にリーダー選出手続きで勝利し、その後リーダー選出リースの更新に失敗した場合、終了します。リーダー選出スレッドが終了すると、他のすべてのスレッドは正常にシャットダウンされ、その後プロセスが終了します。同様に、他のメインスレッドのいずれかが予期せず終了した場合、残りのスレッドの順序正しいシャットダウンがトリガーされ、プロセスは終了します。

これは、致命的エラーが発生した場合はコンテナをクラッシュさせるべきであるという原則に従っています。Kubernetesはクラッシュしたコンテナを再起動し、繰り返しクラッシュする場合は、連続する再起動間の時間が徐々に長くなります。

このため、この順序正しいシャットダウンプロセスにバグがある場合、または他のスレッドのいずれかにプロセスをデッドロックさせてシャットダウンさせないバグがある場合にのみ、Livenessプローブが必要となります。

📖 KubernetesドキュメントのLiveness、Readiness、Startupプローブの設定をお読みください。特に、そのドキュメントの注意事項と警告にご注意ください。

📖 Livenessプローブに関するさらに注意すべき情報については、Livenessプローブで自らを窮地に陥れるをお読みください。

Service Accountトークンの自動マウントの制限

この推奨事項は、Kyvernoポリシーカタログで次のように記述されています。

Kubernetesは、各PodにServiceAccountの認証情報を自動的にマウントします。ServiceAccountには、PodがAPIリソースにアクセスできるようにする役割が割り当てられている場合があります。この機能をブロックすることは、最小権限のベストプラクティスの拡張であり、Podが機能するためにAPIサーバーと通信する必要がない場合は従う必要があります。このポリシーは、これらのServiceAccountトークンのマウントをブロックすることを保証します。

cert-managerコンポーネントはAPIサーバーと通信する必要がありますが、それでもautomountServiceAccountToken: falseを設定することをお勧めします。その理由は以下のとおりです。

  1. automountServiceAccountToken: falseを設定すると、Kyverno(またはその他のポリシーシステム)がこのフィールドがtrueに設定されているPodを拒否するように構成されているクラスタにcert-managerをインストールできます。Kubernetesのデフォルト値はtrueです。
  2. automountServiceAccountToken: trueの場合、Pod内のすべてのコンテナ(サイドカーコンテナや、Kubernetesアドミッションコントローラによってcert-manager Podリソースに注入された可能性のあるinitコンテナを含む)にServiceAccountトークンがマウントされます。最小権限の原則から、ServiceAccountトークンをcert-managerコンテナに明示的にマウントする方が優れています。

そのため、automountServiceAccountToken: falseを設定し、ServiceAccountトークン、CA証明書、および通常はKubernetes ServiceAccountコントローラによって自動的に追加されるネームスペースファイルを含む、投影されたVolumeを各cert-manager Deploymentリソースに手動で追加し、各cert-managerコンテナに読み取り専用のVolumeMountを明示的に追加することをお勧めします。

この設定の例は、以下のHelmチャート値ファイルに含まれています。

ベストプラクティスHelmチャート値

以下のHelmチャート値ファイルをダウンロードし、helm installhelm upgrade、またはhelm template--valuesフラグを使用して指定してください。

🔗 values.best-practice.yaml

# Helm chart values which make cert-manager comply with CIS, BSI and NSA
# security benchmarks and other best practices for deploying cert-manager in
# production.
#
# Read the rationale for these values in:
# * https://cert-manager.dokyumento.jp/docs/installation/best-practice/
global:
priorityClassName: system-cluster-critical
replicaCount: 2
podDisruptionBudget:
enabled: true
minAvailable: 1
automountServiceAccountToken: false
serviceAccount:
automountServiceAccountToken: false
volumes:
- name: serviceaccount-token
projected:
defaultMode: 0444
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: serviceaccount-token
readOnly: true
webhook:
replicaCount: 3
podDisruptionBudget:
enabled: true
minAvailable: 1
automountServiceAccountToken: false
serviceAccount:
automountServiceAccountToken: false
volumes:
- name: serviceaccount-token
projected:
defaultMode: 0444
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: serviceaccount-token
readOnly: true
cainjector:
extraArgs:
- --namespace=cert-manager
- --enable-certificates-data-source=false
replicaCount: 2
podDisruptionBudget:
enabled: true
minAvailable: 1
automountServiceAccountToken: false
serviceAccount:
automountServiceAccountToken: false
volumes:
- name: serviceaccount-token
projected:
defaultMode: 0444
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: serviceaccount-token
readOnly: true
startupapicheck:
automountServiceAccountToken: false
serviceAccount:
automountServiceAccountToken: false
volumes:
- name: serviceaccount-token
projected:
defaultMode: 0444
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
name: kube-root-ca.crt
items:
- key: ca.crt
path: ca.crt
- downwardAPI:
items:
- path: namespace
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: serviceaccount-token
readOnly: true

その他

この推奨事項のリストは現在作成中です。他のベストプラクティスの推奨事項がありましたら、このページに貢献してください