証明書のデフォルト値を自動的に設定する方法を学ぶ
最終検証日:2024年1月19日
目的
ユーザーがCertificate
リソースでできるだけ少ないYAMLを指定するクラスターをセットアップします。これは、Kyvernoを利用して、ユーザーが指定しないCertificate
フィールドにカスタムの「デフォルト」値を適用することで実現します。
デフォルト値を持つことにはいくつかの利点があります。
Certificate
の利用者は、YAMLリソースを最小限に抑えることができます。Certificate
の利用者は、必要に応じてフィールドを上書きする柔軟性を維持できます。- クラスター運用者は、cert-managerの組み込みのデフォルトに依存するのではなく、デフォルトを何にするかを決定できます。
ユースケース
クラスター全体にカスタムのデフォルトを設定することで、プラットフォームチームは以下のようなユースケースに取り組むことができます。
-
CertificateRequest
リソースがクリーンアップされるようにする。ClusterPolicy
を使用して、Certificate.Spec.RevisionHistoryLimit
フィールドのカスタムのデフォルト値を設定します。 -
ユーザーが
Certificate
リソースに対して安全なデフォルトキー設定を選択できるようにする。ClusterPolicy
を使用して、Certificate.Spec.PrivateKey
フィールドのカスタムのデフォルト値を設定します。 -
クラスター内のユーザーの
Issuer
をデフォルトにする。ClusterPolicy
を使用して、Certificate.spec.issuerRef
フィールドのカスタムのデフォルトを設定します。 -
証明書が設定される
Secret
の名前付けのデフォルトパターンを設定する。ClusterPolicy
を使用して、必須フィールドであるspec.secretName
のカスタムのデフォルト値を設定します。 -
アプリケーション開発者が、最小限の設定で安全なX.509 TLS証明書を作成できるようにすることで、彼らの生活を楽にする。
ClusterPolicy
を使用して、他のすべての必須Certificate.spec
フィールドを設定します。1つのアイデンティティ仕様フィールドのみが必要になります。それは次のいずれかです。commonName
またはliteralSubject
dnsNames
uris
emailAddresses
ipAddresses
otherNames
プロセス
3つの異なるシナリオに対して、徐々に高度化しながらデフォルトを設定します。
- オプションの
Certificate
リソースフィールドのデフォルトを設定します。 - 必須の
Certificate
リソースフィールドのデフォルトを設定します。 Ingress
アノテーションを使用して証明書をリクエストする場合の、Certificate
リソースフィールドのデフォルトを設定します。
セットアップ
前提条件
💻 ソフトウェア
- kubectl: Kubernetesクラスターを構成するためのKubernetesコマンドラインツール。
- helm: Kubernetesのパッケージマネージャー。
- kind(オプション):Dockerまたはその他のコンテナランタイムで実行されるローカルのKubernetes環境を作成するため。
ローカルKubernetes環境
⚠️ 他のKubernetes環境をお持ちの場合は、このステップをスキップできます。
-
このチュートリアルでは、
kind
を使用してクラスター環境を作成します。kind create cluster --name defaults⏲ マシンによって異なりますが、クラスターの作成には1分もかかりません。
⚠️ このクラスターは学習目的でのみ適しています。本番環境での使用には適していません。
ソフトウェアのインストール
クラスター環境が整ったら、helm
を使用して必要なKubernetesパッケージをインストールします。
-
helmチャートのバージョンの環境変数を設定します。
export CERT_MANAGER_CHART_VERSION="v1.16.1" \KYVERNO_CHART_VERSION="3.1.4" \INGRESS_NGINX_CHART_VERSION="4.9.0" -
cert-managerをインストールします。
helm upgrade --install cert-manager cert-manager \--namespace cert-manager \--version $CERT_MANAGER_CHART_VERSION \--set crds.enabled=true \--set startupapicheck.enabled=false \--create-namespace \--repo https://charts.jetstack.io/ -
Kyvernoをインストールします。
helm upgrade --install kyverno kyverno \--namespace kyverno-system \--version $KYVERNO_CHART_VERSION \--create-namespace \--repo https://kyverno.github.io/kyverno/ -
ingress-nginxをインストールします。
helm upgrade --install ingress-nginx ingress-nginx \--namespace ingress-nginx \--version $INGRESS_NGINX_CHART_VERSION \--create-namespace \--repo https://kubernetes.github.io/ingress-nginx
完全なインストール手順については、次のリンクを参照してください。
デフォルトの設定
メインのチュートリアルはここから始まり、3つのシナリオのそれぞれに取り組む前に、いくつかの背景を説明します。
必須と非必須
Certificate
リソースには、多くの「必須」フィールドを含むspec
セクションがあります。これは、Certificate
リソースを作成するときにこれらのフィールドが存在する必要があることを意味します。また、各Certificate
リソースで明示的に定義する必要がない他の多くのフィールドもあります。これは基本的に、これらのフィールドの1つの値が必須ではないか、または他の場所でデフォルトが定義されていることを意味します。その「他の場所」は、cert-managerコードベースである可能性もあれば、X.509証明書を作成して返す発行者である可能性もあります。これらの値を操作してカスタムにし、Certificate
ユーザーの生活を楽にする方法を見ていきましょう。
このチュートリアルでは、いくつかのClusterPolicy
リソースとCertificate
リソースをセットアップします。Certificate
スペックに存在しないClusterIssuer
を参照しますが、このチュートリアルでは、実際に証明書をリクエストしないため、ClusterIssuer
は必須ではありません。つまり、誰でも自分のドメインがなくてもこのチュートリアルに従うことができます。
⚠️ 開始を容易にするために、クラスター スコープの
ClusterPolicy
リソースを使用しています。 将来的には、Policy
リソースを使用することで、デフォルトを名前空間レベルにスコープ設定できますが、このチュートリアルでは取り上げません。
1 - オプションフィールドのデフォルト設定
このセクションでは、すべてのCertificate
リソースに対して3つのフィールドを自動的に設定するルールを作成します。ここにある3つのフィールドはいずれも必須フィールドではありませんが、プラットフォームと発行者の設定によっては設定する必要がある場合があります。これらのルールは次のようになります。
- デフォルト値を設定:
revisionHistoryLimit: 2
。 spec.privateKey.rotationPolicy
のデフォルト値をAlways
に設定します。spec.privateKey
フィールドすべてのデフォルト値を設定します。
ℹ️ これらのルールが、ユースケースのうち最初の2つにどのように対応しているかを確認してください。
-
まず、
ClusterPolicy
を見てみましょう。apiVersion: kyverno.io/v1kind: ClusterPolicymetadata:name: mutate-certificatesspec:failurePolicy: Failrules:# Set a sane default for the history field if not already present- name: set-revisionHistoryLimitmatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:# +(...) This is the clever syntax for if not already set+(revisionHistoryLimit): 2# Set rotation to always if not already set- name: set-privateKey-rotationPolicymatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:privateKey:+(rotationPolicy): Always# Set private key details for algorithm and size- name: set-privateKey-detailsmatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:privateKey:+(algorithm): ECDSA+(size): 521+(encoding): PKCS1 -
ポリシーをクラスターに適用し、準備ができていることを確認します。
kubectl apply -f cpol-mutate-certificates-0.yamlkubectl get cpolClusterPolicy
の準備ができると、出力は次のようになります。NAME ADMISSION BACKGROUND VALIDATE ACTION READY AGE MESSAGEmutate-certificates true true Audit True 0s Ready -
次に、"test-revision"
Certificate
を調べます。apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: test-revisionnamespace: defaultspec:dnsNames:- example.comissuerRef:group: cert-manager.iokind: ClusterIssuername: not-my-corp-issuersecretName: test-revision-cert証明書のDNS名、保存場所(
secretName
)、証明書のリクエストに使用するイシュアー(issuerRef
)のみを指定した、現在可能な限り最小限の設定になっていることがわかります。 -
次のコマンドを使用して、証明書をドライラン適用し、元のリソースと比較(
diff
)して、ClusterPolicy
からのデフォルト値がどのように適用されるかを確認します。kubectl apply -f cert-test-revision.yaml --dry-run=server -o yaml | diff -uZ cert-test-revision.yaml -このコマンドは、この例のような出力を返すはずです。
--- cert-test-revision.yaml 2024-01-08 12:14:59.225074232 +0000+++ - 2024-01-12 17:37:51.076593214 +0000@@ -1,8 +1,14 @@apiVersion: cert-manager.io/v1kind: Certificatemetadata:+ annotations:+ kubectl.kubernetes.io/last-applied-configuration: |+ {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-revision","namespace":"default"},"spec":{"dnsNames":["example.com"],"issuerRef":{"group":"cert-manager.io","kind":"ClusterIssuer","name":"not-my-corp-issuer"},"secretName":"test-revision-cert"}}+ creationTimestamp: "2024-01-12T17:37:51Z"+ generation: 1name: test-revisionnamespace: default+ uid: 9f9a4f0a-4aa7-427d-ae4b-c1716fed8246spec:dnsNames:- example.com@@ -10,4 +16,10 @@group: cert-manager.iokind: ClusterIssuername: not-my-corp-issuer+ privateKey:+ algorithm: ECDSA+ encoding: PKCS1+ rotationPolicy: Always+ size: 521+ revisionHistoryLimit: 2secretName: test-revision-certprivateKey
およびrevisionHistoryLimit
フィールドのデフォルト設定が正常に完了しました! -
エンドユーザーとして必要なものを設定できることを検証するために、これらのデフォルト設定されたすべてのフィールドを上書きしてみましょう。これをテストするために、"test-revision-override"
Certificate
を使用します。apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: test-revision-overridenamespace: defaultspec:dnsNames:- example.comissuerRef:group: cert-manager.iokind: ClusterIssuername: not-my-corp-issuerprivateKey:algorithm: RSAencoding: PKCS8rotationPolicy: Neversize: 4096revisionHistoryLimit: 44secretName: test-revision-override-cert🔗
cert-test-revision-override.yaml
以前と同様に、ドライラン適用し、出力を入力ファイルと比較(
diff
)します。kubectl apply -f cert-test-revision-override.yaml --dry-run=server -o yaml | diff -uZ cert-test-revision-override.yaml -出力では、
Certificate
自体の仕様に変更がないことがわかります。Certificate
には、ClusterPolicy
ルールが影響を与えるすべてのフィールドがすでに定義されていました。--- cert-test-revision-override.yaml 2024-01-05 14:45:14.972562067 +0000+++ - 2024-01-12 17:39:57.217028745 +0000@@ -1,8 +1,14 @@apiVersion: cert-manager.io/v1kind: Certificatemetadata:+ annotations:+ kubectl.kubernetes.io/last-applied-configuration: |+ {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-revision-override","namespace":"default"},"spec":{"dnsNames":["example.com"],"issuerRef":{"group":"cert-manager.io","kind":"ClusterIssuer","name":"not-my-corp-issuer"},"privateKey":{"algorithm":"RSA","encoding":"PKCS8","rotationPolicy":"Never","size":4096},"revisionHistoryLimit":44,"secretName":"test-revision-override-cert"}}+ creationTimestamp: "2024-01-12T17:39:57Z"+ generation: 1name: test-revision-overridenamespace: default+ uid: 83a6ddbc-6903-479e-802d-e11149985338spec:dnsNames:- example.com
2 - 必須フィールドのデフォルト設定
⚠️ このセクションは、すぐに使用するには cert-manager v1.14.x 以降が必要です。詳細については、付録セクションを参照してください。
ここで、Kyverno ClusterPolicy
を設定して、Certificate
フィールドのいずれかにデフォルト値を適用できます。これには、必須フィールドも含まれます。この例の ClusterPolicy
では、次の2つのことを行います。
- 関連する
issuerRef
フィールドをデフォルトで "our-corp-issuer"ClusterIssuer
を使用するように設定します。 - デフォルトの
secretName
を、"-cert" が付加されたCertificate
オブジェクトの名前に設定します。
ℹ️ これらのルールが、3番目と4番目の ユースケースにどのように対応しているかを確認してください。
-
次に、両方のフィールドをデフォルト値で設定する
ClusterPolicy
リソースを示します。apiVersion: kyverno.io/v1kind: ClusterPolicymetadata:name: mutate-certificatesspec:failurePolicy: Failrules:# Set a sane default for the history field if not already present- name: set-revisionHistoryLimitmatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:# +(...) This is the clever syntax for if not already set+(revisionHistoryLimit): 2# Set rotation to always if not already set- name: set-privateKey-rotationPolicymatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:privateKey:+(rotationPolicy): Always# Set private key details for algorithm and size- name: set-privateKey-detailsmatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:privateKey:+(algorithm): ECDSA+(size): 521+(encoding): PKCS1# Set a secretName when one is not provided- name: set-default-secret-namematch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:# You can read more about this syntax in the Kyverno documentation:# https://kyverno.io/docs/writing-policies/variables/#variables-from-admission-review-requests+(secretName): "{{request.object.metadata.name}}-cert"# Set a default for issuerRef fields- name: set-default-issuer-refmatch:any:- resources:kinds:- Certificatemutate:patchStrategicMerge:spec:+(issuerRef):name: our-corp-issuerkind: ClusterIssuergroup: cert-manager.io🔗
cpol-mutate-certificates-1.yaml
この
ClusterPolicy
は、以前適用したポリシーの拡張です。 -
このポリシーを適用します。
kubectl apply -f cpol-mutate-certificates-1.yaml既存の
ClusterPolicy
が変更されたことがわかります。clusterpolicy.kyverno.io/mutate-certificates configuredClusterPolicy
を取得して、"Ready" であることを検証します。kubectl get cpolこのコマンドは、この例のような出力を返すはずです。
NAME ADMISSION BACKGROUND VALIDATE ACTION READY AGE MESSAGEmutate-certificates true true Audit True 6m21s Ready -
ポリシー内のすべてのルールが有効であることを検証するように設計された "test-minimal"
Certificate
を見てみましょう。apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: test-minimalnamespace: defaultspec:dnsNames:- example.com -
ドライラン適用し、
diff
して、すべてのデフォルトがこの最小限のCertificate
に適用されていることを検証します。kubectl apply -f cert-test-minimal.yaml --dry-run=server -o yaml | diff -uZ cert-test-minimal.yaml -このコマンドは、この例のような出力を返すはずです。
--- cert-test-minimal.yaml 2024-01-05 14:45:07.140668401 +0000+++ - 2024-01-12 17:44:08.110290752 +0000@@ -1,8 +1,25 @@apiVersion: cert-manager.io/v1kind: Certificatemetadata:+ annotations:+ kubectl.kubernetes.io/last-applied-configuration: |+ {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-minimal","namespace":"default"},"spec":{"dnsNames":["example.com"]}}+ creationTimestamp: "2024-01-12T17:44:08Z"+ generation: 1name: test-minimalnamespace: default+ uid: 792d29c7-8cf3-4f3a-9f12-4fba396e0d6espec:dnsNames:- example.com+ issuerRef:+ group: cert-manager.io+ kind: ClusterIssuer+ name: our-corp-issuer+ privateKey:+ algorithm: ECDSA+ encoding: PKCS1+ rotationPolicy: Always+ size: 521+ revisionHistoryLimit: 2+ secretName: test-minimal-certspec.issuerRef
およびspec.secretName
フィールドの値が自動的に入力されていることがわかります。これは、KyvernoClusterPolicy
が、指定されたCertificate
リソースに適用されたことを示しています。 -
設定を強制していないことを完全に確実にするために、デフォルトルールがある
Certificate
の各プロパティを明示的に設定しましょう。"test-revision-override"Certificate
を使用します。apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: test-revision-overridenamespace: defaultspec:dnsNames:- example.comissuerRef:group: cert-manager.iokind: ClusterIssuername: not-my-corp-issuerprivateKey:algorithm: RSAencoding: PKCS8rotationPolicy: Neversize: 4096revisionHistoryLimit: 44secretName: test-revision-override-cert -
ドライラン適用し、このファイルと比較(
diff
)します。kubectl apply -f cert-test-revision-override.yaml --dry-run=server -o yaml | diff -uZ cert-test-revision-override.yaml -このコマンドは、この例のような出力を返すはずです。
--- cert-test-revision-override.yaml 2024-01-05 14:45:14.972562067 +0000+++ - 2024-01-12 17:45:48.261997150 +0000@@ -1,8 +1,14 @@apiVersion: cert-manager.io/v1kind: Certificatemetadata:+ annotations:+ kubectl.kubernetes.io/last-applied-configuration: |+ {"apiVersion":"cert-manager.io/v1","kind":"Certificate","metadata":{"annotations":{},"name":"test-revision-override","namespace":"default"},"spec":{"dnsNames":["example.com"],"issuerRef":{"group":"cert-manager.io","kind":"ClusterIssuer","name":"not-my-corp-issuer"},"privateKey":{"algorithm":"RSA","encoding":"PKCS8","rotationPolicy":"Never","size":4096},"revisionHistoryLimit":44,"secretName":"test-revision-override-cert"}}+ creationTimestamp: "2024-01-12T17:45:48Z"+ generation: 1name: test-revision-overridenamespace: default+ uid: d0ad7abe-c703-45f7-acf9-634b3a263cfaspec:dnsNames:- example.comこのコマンドから、
Certificate
の仕様フィールドが変更されていないことがわかります。メタデータセクションのみが変更されており、これはポリシーが適用されたが、値がすでに指定されているため、デフォルトを設定しなかったことを示しています。これにより、必要に応じてクラスターのデフォルトを上書きできる柔軟性が維持されていることがわかります。
3 - Ingressアノテーションによるデフォルト設定
多くの cert-manager ユーザーは Certificate
リソースを直接作成するのではなく、ingress-shim 機能を使用しています。cert-manager は、サポートされているアノテーションと Ingress
仕様に基づいて Certificate
リソースを作成します。このユースケースでも ClusterPolicy
を使用してデフォルトを適用する方法を見てみましょう。
-
この例の
Ingress
リソースには、cert-manager.io/cluster-issuer
アノテーションがあります。このアノテーションは、cert-manager にissuerRef
フィールドがour-corp-issuer
という名前のClusterIssuer
を指すCertificate
を作成するように指示します。apiVersion: networking.k8s.io/v1kind: Ingressmetadata:annotations:cert-manager.io/cluster-issuer: "our-corp-issuer"name: defaults-examplenamespace: defaultspec:ingressClassName: nginxrules:- host: app.example.comhttp:paths:- backend:service:name: appport:number: 80path: /pathType: ImplementationSpecifictls:- hosts:- app.example.comsecretName: defaults-example-certificate-tls -
このアノテーションと関連する
ingress.spec.tls
構成がすべて必要なので、リソースを適用します。kubectl apply -f ingress.yaml -
ここで、
Certificate
リソースが自動的に生成されたことを検証します。kubectl get cert defaults-example-certificate-tls -o yamlこのコマンドは、この例のような出力を返すはずです。
apiVersion: cert-manager.io/v1kind: Certificatemetadata:creationTimestamp: "2024-01-12T17:47:04Z"generation: 1name: defaults-example-certificate-tlsnamespace: defaultownerReferences:- apiVersion: networking.k8s.io/v1blockOwnerDeletion: truecontroller: truekind: Ingressname: defaults-exampleuid: bea33a55-a9ed-4664-a56a-a679eb8272c3resourceVersion: "584260"uid: 43ced989-723b-4eac-bad0-f8bead6976dfspec:dnsNames:- app.example.comissuerRef:group: cert-manager.iokind: ClusterIssuername: our-corp-issuerprivateKey:algorithm: ECDSAencoding: PKCS1rotationPolicy: Alwayssize: 521revisionHistoryLimit: 2secretName: defaults-example-certificate-tlsusages:- digital signature- key enciphermentstatus:conditions:- lastTransitionTime: "2024-01-12T17:47:04Z"message: Issuing certificate as Secret does not existobservedGeneration: 1reason: DoesNotExiststatus: "True"type: Issuing- lastTransitionTime: "2024-01-12T17:47:04Z"message: Issuing certificate as Secret does not existobservedGeneration: 1reason: DoesNotExiststatus: "False"type: ReadynextPrivateKeySecretName: defaults-example-certificate-tls-nbjws -
オプションで、Kyverno アドミッションコントローラーコンテナーのログを表示して、"mutate-certificates"
ClusterPolicy
が適用されていることを検証できます。kubectl logs -n kyverno-system $(kubectl get pod -n kyverno-system -l app.kubernetes.io/component=admission-controller -o jsonpath='{.items[0].metadata.name}') -c kyverno --tail 3このコマンドは、この例のような出力を返すはずです。
I0112 17:47:04.425863 1 mutation.go:113] webhooks/resource/mutate "msg"="mutation rules from policy applied successfully" "clusterroles"=["cert-manager-controller-approve:cert-manager-io","cert-manager-controller-certificates","cert-manager-controller-certificatesigningrequests","cert-manager-controller-challenges","cert-manager-controller-clusterissuers","cert-manager-controller-ingress-shim","cert-manager-controller-issuers","cert-manager-controller-orders","system:basic-user","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"cert-manager.io","version":"v1","kind":"Certificate"} "gvr"={"group":"cert-manager.io","version":"v1","resource":"certificates"} "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"] "uid"="6f93bd8d-29ca-4eab-8e96-065ea82a1bf2" "user"={"username":"system:serviceaccount:cert-manager:cert-manager","uid":"21cbad67-9d2e-44ee-bb02-7fef9aa2e502","groups":["system:serviceaccounts","system:serviceaccounts:cert-manager","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["cert-manager-648cd49b44-z6g8s"],"authentication.kubernetes.io/pod-uid":["4bd741fa-a8ec-48a1-82d5-26c5b7acce5e"]}}I0112 17:47:04.458402 1 mutation.go:113] webhooks/resource/mutate "msg"="mutation rules from policy applied successfully" "clusterroles"=["cert-manager-controller-approve:cert-manager-io","cert-manager-controller-certificates","cert-manager-controller-certificatesigningrequests","cert-manager-controller-challenges","cert-manager-controller-clusterissuers","cert-manager-controller-ingress-shim","cert-manager-controller-issuers","cert-manager-controller-orders","system:basic-user","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"cert-manager.io","version":"v1","kind":"Certificate"} "gvr"={"group":"cert-manager.io","version":"v1","resource":"certificates"} "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"] "uid"="ec61a3c9-df0a-4daf-8bc3-227dc80348a9" "user"={"username":"system:serviceaccount:cert-manager:cert-manager","uid":"21cbad67-9d2e-44ee-bb02-7fef9aa2e502","groups":["system:serviceaccounts","system:serviceaccounts:cert-manager","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["cert-manager-648cd49b44-z6g8s"],"authentication.kubernetes.io/pod-uid":["4bd741fa-a8ec-48a1-82d5-26c5b7acce5e"]}}I0112 17:47:09.477776 1 mutation.go:113] webhooks/resource/mutate "msg"="mutation rules from policy applied successfully" "clusterroles"=["cert-manager-controller-approve:cert-manager-io","cert-manager-controller-certificates","cert-manager-controller-certificatesigningrequests","cert-manager-controller-challenges","cert-manager-controller-clusterissuers","cert-manager-controller-ingress-shim","cert-manager-controller-issuers","cert-manager-controller-orders","system:basic-user","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"cert-manager.io","version":"v1","kind":"Certificate"} "gvr"={"group":"cert-manager.io","version":"v1","resource":"certificates"} "kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"] "uid"="c4384662-cb2a-49a0-8e83-e590942ec48d" "user"={"username":"system:serviceaccount:cert-manager:cert-manager","uid":"21cbad67-9d2e-44ee-bb02-7fef9aa2e502","groups":["system:serviceaccounts","system:serviceaccounts:cert-manager","system:authenticated"],"extra":{"authentication.kubernetes.io/pod-name":["cert-manager-648cd49b44-z6g8s"],"authentication.kubernetes.io/pod-uid":["4bd741fa-a8ec-48a1-82d5-26c5b7acce5e"]}}最後の行を例として使用すると、次のことがわかります。
"kind"="Certificate" "name"="defaults-example-certificate-tls" "namespace"="default" "operation"="UPDATE" "policy"="mutate-certificates" "resource.gvk"={"Group":"cert-manager.io","Version":"v1","Kind":"Certificate"} "roles"=["kube-system:cert-manager:leaderelection"] "rules"=["set-revisionHistoryLimit","set-privateKey-rotationPolicy","set-privateKey-details"]policy
キーは、ポリシーが適用されていることを示しています。rules
セクションでは、5つのルールのうち3つが生成された "defaults-example-certificate-tls"Certificate
リソースに適用されていることを識別できます。
Ingress
リソースを使用する場合は、証明書をロードする secretName
を常に指定する必要があります。これは Ingress
仕様の必須部分であるため、このユースケースではデフォルト設定は不要です。
ユーザーがIngress
リソースで指定する必要がある追加のYAMLは、アノテーションだけです。
cert-manager.io/cluster-issuer: "our-corp-issuer"
このアノテーションは、cert-managerがこのIngress
に対して動作するためのトリガーとして機能すると同時に、Certificate.spec.issuerRef
フィールドの設定値としても機能します。この1行だけで、ユーザーがCertificate
リソースを完全に作成する必要がなくなります。これにより、このIngress
の背後でアプリケーションを保護するために必要なYAMLの総量が削減されます。
まとめ
これは、クラスターのCertificate
リソースのデフォルトをいかに簡単に設定できるかを示す、かなり単純な例です。ClusterPolicy
が設定を「強制」するのではなく、デフォルトオプションを設定および拡張するために使用できることを示しました。Certificate
のユーザーは、必要に応じて任意の値を上書きする柔軟性を維持しながら、YAMLを削減できます。
5つのルールのみを持つ単純なClusterPolicy
が、Certificate
リソースを作成するユーザーエクスペリエンスをどのように変更できるかを示しました。
apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: test-revision-overridenamespace: defaultspec:dnsNames:- example.comissuerRef:group: cert-manager.iokind: ClusterIssuername: not-my-corp-issuerprivateKey:algorithm: RSAencoding: PKCS8rotationPolicy: Neversize: 4096revisionHistoryLimit: 44secretName: test-revision-override-cert
🔗 cert-test-revision-override.yaml
代わりに、ユーザーにとって重要な設定のみを指定する必要がある場合。
apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: test-minimalnamespace: defaultspec:dnsNames:- example.com
このポリシーにより、目標を達成し、ユーザーが最小限のCertificate
リソースを送信できるようにしました。これにより、仕様に含まれる単一のフィールド、dnsNames
エントリのみを使用した5番目のユースケースが完了しました。指定された他のすべてのフィールドは、通常プラットフォーム管理者によって設定されるClusterPolicy
を持つKyvernoを使用して自動的にデフォルト設定されました。
クリーンアップ
このチュートリアルのためにkindクラスターを作成した場合は、単に実行できます。
kind delete cluster --name defaults
それ以外の場合は、このチュートリアルでデプロイされたすべてのリソースを削除するには
# Assuming you are running from this directly or saved all the files to yamls/kubectl delete -f ingress.yamlkubectl delete -f cpol-mutate-certificates-1.yamlhelm uninstall kyverno -n kyverno-systemhelm uninstall cert-manager -n cert-managerhelm uninstall ingress-nginx -n ingress-nginx
付録
cert-managerのバージョンの要件
cert-managerのミューティングWebhookの動作は、v1.14.x以降から変更されました。変更の詳細については、PR #6311を参照してください。手動での修正手順は、PR #6311のこのコメントにあります。
プリセット機能リクエスト
「デフォルト」または「プリセット」の設定に関する背景情報をさらに読むには、issue 2239を参照してください。このチュートリアルは、その問題の調査から生まれました。
cert-managerチームは、要求されたソリューションは、他の、より一般的なオープンソースポリシーツールを使用することで実現できると判断しました。Kyvernoはその一例に過ぎず、Gatekeeperを代替ツールとして使用しても同様の結果を得ることができます。