最新:在推特Mastodon

了解如何自动设置证书默认值

上次验证:2024 年 1 月 19 日

目标

我们将设置一个集群,用户在 Certificate 资源中需要指定的 YAML 代码尽可能少。这将通过利用 Kyverno 来实现,Kyverno 会将自定义的“默认”值应用于用户未指定的 Certificate 字段。

拥有默认值有一些好处

  • Certificate 的使用者可以最大程度地减少其 YAML 资源。
  • Certificate 的使用者保留了在需要时覆盖字段的灵活性。
  • 集群操作员可以决定默认值是什么,而不是依赖 cert-manager 的内置默认值。

用例

通过在我们的集群中设置自定义默认值,我们使平台团队能够解决诸如以下用例:

  • 确保 CertificateRequest 资源得到清理。

    使用 ClusterPolicyCertificate.Spec.RevisionHistoryLimit 字段设置自定义默认值。

  • 帮助用户为其 Certificate 资源选择安全的默认密钥设置。

    使用 ClusterPolicyCertificate.Spec.PrivateKey 字段设置自定义默认值。

  • 为集群内的用户默认 Issuer

    使用 ClusterPolicyCertificate.spec.issuerRef 字段设置自定义默认值。

  • 为存放证书的 Secret 的命名设置默认模式。

    使用 ClusterPolicyspec.secretName 必填字段设置自定义默认值。

  • 通过允许应用程序开发人员以最少的配置创建安全的 X.509 TLS 证书,使他们的生活更轻松。

    使用 ClusterPolicy 设置所有其他必需的 Certificate.spec 字段。只需一个身份规范字段,即以下之一:

    • commonNameliteralSubject
    • dnsNames
    • uris
    • emailAddresses
    • ipAddresses
    • otherNames

流程

我们将为三种不同的场景设置默认值,每次都更高级一点

  1. 为可选的 Certificate 资源字段设置默认值。
  2. 为必需的 Certificate 资源字段设置默认值。
  3. 使用 Ingress 注释请求证书时,为 Certificate 资源字段设置默认值。

设置

先决条件

💻 软件

  1. kubectl:Kubernetes 命令行工具,允许您配置 Kubernetes 集群。
  2. helm:Kubernetes 的包管理器。
  3. kind(**可选**):用于创建在 Docker 或其他容器运行时中运行的本地 Kubernetes 环境。

本地 Kubernetes 环境

⚠️ 如果您有其他 Kubernetes 环境,则可以跳过此步骤。

  1. 使用 kind 为本教程创建集群环境。

    kind create cluster --name defaults

    ⏲ 创建集群可能需要不到一分钟,具体取决于您的机器。

    ⚠️ 此集群仅适合学习目的。它不适合生产使用。

软件安装

在您拥有集群环境后,使用 helm 安装所需的 Kubernetes 包。

  1. 为 helm 图表版本设置一些环境变量

    export CERT_MANAGER_CHART_VERSION="v1.16.1" \
    KYVERNO_CHART_VERSION="3.1.4" \
    INGRESS_NGINX_CHART_VERSION="4.9.0"
  2. 安装 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/
  3. 安装 Kyverno

    helm upgrade --install kyverno kyverno \
    --namespace kyverno-system \
    --version $KYVERNO_CHART_VERSION \
    --create-namespace \
    --repo https://kyverno.github.io/kyverno/
  4. 安装 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

有关完整安装说明,请参阅以下链接

设置默认值

本教程从这里开始,先介绍一些背景知识,然后再分别介绍这三种场景。

必需与非必需

Certificate 资源有一个 spec 部分,其中包含许多“必需”字段。这意味着创建 Certificate 资源时必须存在这些字段。还有一些其他字段不需要在每个 Certificate 资源上明确定义。这实际上意味着这些字段之一的值不是必需的,或者在其他地方定义了默认值。该其他地方可能在 cert-manager 代码库中,也可能是在创建和返回 X.509 证书的发行者中。让我们探讨如何操作这些值以使其成为自定义值,并使 Certificate 用户的生活更轻松。

在本教程中,我们将设置一些 ClusterPolicy 资源和 Certificate 资源。我们将引用 Certificate spec 中不存在的 ClusterIssuer,但对于本教程而言,ClusterIssuer 不是必需的,因为我们实际上不会请求证书。这意味着即使没有自己的域名,任何人都可以学习本教程。

⚠️ 为了便于入门,我们使用集群范围的 ClusterPolicy 资源。将来,您可以通过使用命名空间级别的 Policy 资源将默认值范围限定到命名空间级别,但这在本教程中不会介绍。

1 - 默认可选字段

在本节中,我们将创建一些规则,这些规则会自动为所有 Certificate 资源设置三个字段。这里没有三个字段是必需字段,但根据平台和发行者的偏好,可能需要设置这些字段。这些规则将

ℹ️ 请注意,这些规则如何解决我们的 用例 中的前两个。

  1. 首先看一下 ClusterPolicy

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
    name: mutate-certificates
    spec:
    failurePolicy: Fail
    rules:
    # Set a sane default for the history field if not already present
    - name: set-revisionHistoryLimit
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    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-rotationPolicy
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(rotationPolicy): Always
    # Set private key details for algorithm and size
    - name: set-privateKey-details
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(algorithm): ECDSA
    +(size): 521
    +(encoding): PKCS1

    🔗 cpol-mutate-certificates-0.yaml

  2. 将策略应用于集群并检查其是否已准备就绪

    kubectl apply -f cpol-mutate-certificates-0.yaml
    kubectl get cpol

    ClusterPolicy 准备就绪时,输出应如下所示

    NAME ADMISSION BACKGROUND VALIDATE ACTION READY AGE MESSAGE
    mutate-certificates true true Audit True 0s Ready
  3. 现在检查“test-revision” Certificate

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    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

    🔗 cert-test-revision.yaml

    您可以看到,我们设置了目前最小的配置,仅指定了证书的 DNS 名称、证书保存位置 (secretName) 和用于请求证书的发行者 (issuerRef)。

  4. 使用以下命令对证书执行dry-run apply,然后与原始资源进行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/v1
    kind: Certificate
    metadata:
    + 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: 1
    name: test-revision
    namespace: default
    + uid: 9f9a4f0a-4aa7-427d-ae4b-c1716fed8246
    spec:
    dnsNames:
    - example.com
    @@ -10,4 +16,10 @@
    group: cert-manager.io
    kind: ClusterIssuer
    name: not-my-corp-issuer
    + privateKey:
    + algorithm: ECDSA
    + encoding: PKCS1
    + rotationPolicy: Always
    + size: 521
    + revisionHistoryLimit: 2
    secretName: test-revision-cert

    我们已成功将privateKeyrevisionHistoryLimit字段设为默认值!

  5. 让我们覆盖所有这些默认字段,以验证我们作为最终用户仍然可以设置我们想要的。为了测试这一点,让我们使用“test-revision-override”Certificate

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    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

    🔗 cert-test-revision-override.yaml

    与之前一样,对输出执行dry-run apply并与输入文件进行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/v1
    kind: Certificate
    metadata:
    + 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: 1
    name: test-revision-override
    namespace: default
    + uid: 83a6ddbc-6903-479e-802d-e11149985338
    spec:
    dnsNames:
    - example.com

2 - 设置必需字段的默认值

⚠️ 此部分需要 cert-manager v1.14.x 或更高版本才能正常运行。有关详细信息,请参见附录部分。

现在,我们可以设置一个 Kyverno ClusterPolicy,以将默认值应用于任何Certificate字段。这包括必需字段。在我们的示例ClusterPolicy中,我们将执行两件事。

  • 将相关issuerRef字段设为默认值,以使用“our-corp-issuer”ClusterIssuer
  • 应用一个默认secretName,该名称为Certificate对象的名称后缀为“-cert”。

ℹ️ 注意这些规则如何解决第三和第四个用例

  1. 以下是用于设置这两个字段默认值的ClusterPolicy资源。

    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
    name: mutate-certificates
    spec:
    failurePolicy: Fail
    rules:
    # Set a sane default for the history field if not already present
    - name: set-revisionHistoryLimit
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    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-rotationPolicy
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(rotationPolicy): Always
    # Set private key details for algorithm and size
    - name: set-privateKey-details
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    privateKey:
    +(algorithm): ECDSA
    +(size): 521
    +(encoding): PKCS1
    # Set a secretName when one is not provided
    - name: set-default-secret-name
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    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-ref
    match:
    any:
    - resources:
    kinds:
    - Certificate
    mutate:
    patchStrategicMerge:
    spec:
    +(issuerRef):
    name: our-corp-issuer
    kind: ClusterIssuer
    group: cert-manager.io

    🔗 cpol-mutate-certificates-1.yaml

    ClusterPolicy是我们之前应用的策略的扩展。

  2. 应用此策略。

    kubectl apply -f cpol-mutate-certificates-1.yaml

    您应该会看到我们现有的ClusterPolicy已更改。

    clusterpolicy.kyverno.io/mutate-certificates configured

    获取ClusterPolicy,以验证其是否处于“就绪”状态。

    kubectl get cpol

    此命令应返回类似于以下示例的输出。

    NAME ADMISSION BACKGROUND VALIDATE ACTION READY AGE MESSAGE
    mutate-certificates true true Audit True 6m21s Ready
  3. 查看“test-minimal”Certificate,该证书旨在验证策略中的所有规则是否都处于运行状态。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    name: test-minimal
    namespace: default
    spec:
    dnsNames:
    - example.com

    🔗 cert-test-minimal.yaml

  4. 对该最小Certificate执行dry-run apply并进行diff,以验证所有默认值是否都已应用。

    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/v1
    kind: Certificate
    metadata:
    + 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: 1
    name: test-minimal
    namespace: default
    + uid: 792d29c7-8cf3-4f3a-9f12-4fba396e0d6e
    spec:
    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-cert

    请查看我们如何自动填充了spec.issuerRefspec.secretName字段值。这表明 Kyverno ClusterPolicy已应用于提供的Certificate资源。

  5. 为了确保我们没有强制执行任何设置,让我们显式设置具有默认规则的Certificate的每个属性。我们将使用“test-revision-override”Certificate

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    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

    🔗 cert-test-revision-override.yaml

  6. 对该文件执行dry-run apply并进行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/v1
    kind: Certificate
    metadata:
    + 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: 1
    name: test-revision-override
    namespace: default
    + uid: d0ad7abe-c703-45f7-acf9-634b3a263cfa
    spec:
    dnsNames:
    - example.com

    从此命令中,您可以看到没有一个Certificate规范字段被更改。只有元数据部分发生了更改,这告诉我们策略已应用,但没有设置任何默认值,因为已经提供了值。这表明,您可以在需要时保留覆盖群集默认值的灵活性。

3 - 通过 Ingress 注释设置默认值

许多 cert-manager 用户不会直接创建Certificate资源,而是使用ingress-shim功能。cert-manager 根据支持的注释Ingress规范创建Certificate资源。让我们看看如何在这种情况中仍然使用ClusterPolicy应用默认值。

  1. 此示例Ingress资源具有cert-manager.io/cluster-issuer注释,该注释指示 cert-manager 创建一个Certificate,该证书具有一个指向名为our-corp-issuerClusterIssuerissuerRef字段。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    cert-manager.io/cluster-issuer: "our-corp-issuer"
    name: defaults-example
    namespace: default
    spec:
    ingressClassName: nginx
    rules:
    - host: app.example.com
    http:
    paths:
    - backend:
    service:
    name: app
    port:
    number: 80
    path: /
    pathType: ImplementationSpecific
    tls:
    - hosts:
    - app.example.com
    secretName: defaults-example-certificate-tls

    🔗 ingress.yaml

  2. 此注释和相关的ingress.spec.tls配置是我们应用该资源所需的全部内容。

    kubectl apply -f ingress.yaml
  3. 现在验证是否已自动生成Certificate资源。

    kubectl get cert defaults-example-certificate-tls -o yaml

    此命令应返回类似于以下示例的输出。

    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
    creationTimestamp: "2024-01-12T17:47:04Z"
    generation: 1
    name: defaults-example-certificate-tls
    namespace: default
    ownerReferences:
    - apiVersion: networking.k8s.io/v1
    blockOwnerDeletion: true
    controller: true
    kind: Ingress
    name: defaults-example
    uid: bea33a55-a9ed-4664-a56a-a679eb8272c3
    resourceVersion: "584260"
    uid: 43ced989-723b-4eac-bad0-f8bead6976df
    spec:
    dnsNames:
    - app.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: defaults-example-certificate-tls
    usages:
    - digital signature
    - key encipherment
    status:
    conditions:
    - lastTransitionTime: "2024-01-12T17:47:04Z"
    message: Issuing certificate as Secret does not exist
    observedGeneration: 1
    reason: DoesNotExist
    status: "True"
    type: Issuing
    - lastTransitionTime: "2024-01-12T17:47:04Z"
    message: Issuing certificate as Secret does not exist
    observedGeneration: 1
    reason: DoesNotExist
    status: "False"
    type: Ready
    nextPrivateKeySecretName: defaults-example-certificate-tls-nbjws
  4. 您可以通过查看 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部分,您可以识别出我们的五个规则中有三个已应用于生成的“defaults-example-certificate-tls”Certificate资源。

当使用Ingress资源时,您始终需要指定要从中加载证书的secretName。在这种情况下不需要设置默认值,因为这是Ingress规范的必需部分。

用户在Ingress资源上需要指定的唯一其他 YAML 是注释。

cert-manager.io/cluster-issuer: "our-corp-issuer"

此注释既是 cert-manager 对此Ingress采取行动的触发器,也是Certificate.spec.issuerRef字段的配置值。这一行代码取代了用户创建Certificate资源的必要性。这减少了为在此Ingress后面保护应用程序所需的总 YAML 量。

摘要

这是一个关于为群集Certificate资源设置默认值的简单示例。我们已经展示了ClusterPolicy不必“强制”设置,而可以用于设置和扩展默认选项。Certificate用户可以减少 YAML,同时保留在需要时覆盖任何值的灵活性。

我们已经展示了如何使用一个只有 5 个规则的简单ClusterPolicy,将创建Certificate资源的用户体验从

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
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

🔗 cert-test-revision-override.yaml

更改为仅需要指定对他们重要的配置,例如

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: test-minimal
namespace: default
spec:
dnsNames:
- example.com

🔗 cert-test-minimal.yaml

通过这项策略,我们实现了目标,并让用户能够提交最小化的证书资源。 这完成了我们的第五个用例, 规范中只包含一个字段,即dnsNames条目。 每个其他指定的字段都使用 Kyverno 和ClusterPolicy自动设置为默认值, 这些通常由平台管理员设置。

清理

如果您为本教程创建了集群,则可以简单地运行

kind delete cluster --name defaults

否则,要删除在本教程中部署的所有资源

# Assuming you are running from this directly or saved all the files to yamls/
kubectl delete -f ingress.yaml
kubectl delete -f cpol-mutate-certificates-1.yaml
helm uninstall kyverno -n kyverno-system
helm uninstall cert-manager -n cert-manager
helm uninstall ingress-nginx -n ingress-nginx

附录

cert-manager 版本要求

cert-manager 的变异 Webhook 的行为从 v1.14.x 开始发生了改变。 要了解有关更改的更完整解释和详细信息,请参阅PR #6311。 关于手动修复的说明可以在PR #6311 上的此评论中找到。

预设功能请求

要了解更多关于设置“默认值”或“预设”的背景信息,您可以参考问题 2239。 本教程是在对该问题的调查中产生的。

cert-manager 团队认为,可以通过使用其他更通用的开源策略工具来实现所请求的解决方案。 Kyverno 只是一个示例,类似的效果也可以使用Gatekeeper作为替代工具来实现。