Cert Manager 申请SSL证书流程及相关概念-二

中英文对照表

英文 英文 - K8S CRD 中文 备注
certificates Certificate 证书 certificates.cert-manager.io/v1
certificate issuers Issuer 证书颁发者 issuers.cert-manager.io
ClusterIssuer 集群证书颁发者 clusterissuers.cert-manager.io
certificate request CertificateRequest 证书申请 certificaterequests.cert-manager.io
order Order (证书)订单 orders.acme.cert-manager.io
challenge Challenge (证书)挑战 challenges.acme.cert-manager.io
SelfSigned 自签名 cert-manager Issuer 的一种
CA 证书颁发机构 Certificate Authority 的缩写;
cert-manager Issuer 的一种
Vault 金库 cert-manager Issuer 的一种,即 Hashicorp Vault
Venafi Venafi 在线证书办理服务,目前用的不多。
External 外部 cert-manager Issuer 的一种
ACME 自动证书管理环境 Automated Certificate Management Environment 的缩写;
cert-manager Issuer, 包括 HTTP01 和 DNS01

书接上回, 接下来看一下 cert-manager 的证书申请和续期流程.

申请 SSL 证书流程

这张图显示了使用 ACME/Let's Encrypt Issuer 的名为cert-1的证书的生命周期:

证书生命周期

HTTP01 方式

cert-manager 可以用来从使用 ACME 协议的 CA 获得证书。ACME 协议支持各种 challenge 机制,用来证明一个域名的所有权,以便为该域名签发有效的证书。

其中一个 challenge 机制是 HTTP01 challenge。通过 HTTP01 challenge,你可以通过确保一个特定的文件存在于该域中来证明该域的所有权。如果你能够在给定的路径下发布给定的文件,就可以认为你控制了该域。

首先,配置 HTTP01 Issuer, 见上文

http://acme-v02.api.letsencrypt.org/directory 就是 Let's Encrypt 的生产环境。对应的,Staging 环境 的 URL 为:http://acme-staging-v02.api.letsencrypt.org/directory

Staging 环境不会签发可信的证书,但用来确保在转移到生产环境之前,验证过程是正常工作的。Let's Encrypt 的生产环境施加了更严格的 速率限制,所以为了减少你触及这些限制的机会,强烈建议开始时先使用暂存环境。

ACME 协议的第一阶段是由客户向 ACME 服务器注册。这个阶段包括生成一个非对称密钥对,然后将其与发件人中指定的电子邮件地址联系起来 (?这里我没有填写邮箱)。请确保将这个电子邮件地址改为你自己的一个有效地址。它通常用于在你的证书即将更新时发送到期通知。生成的私钥被存储在一个名为`letsencrypt-staging'的 Secret 中。示例如下:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  creationTimestamp: '2022-03-08T14:34:05Z'
  generation: 1
  labels:
    app: rancher
    app.kubernetes.io/managed-by: Helm
    chart: rancher-2.6.4
    heritage: Helm
    release: rancher
  name: tls-rancher-ingress
  namespace: cattle-system
status:
  conditions:
    - lastTransitionTime: '2022-03-08T14:39:35Z'
      message: Certificate is up to date and has not expired
      observedGeneration: 1
      reason: Ready
      status: 'True'
      type: Ready
  notAfter: '2022-08-05T12:40:37Z'
  notBefore: '2022-05-07T12:40:38Z'
  renewalTime: '2022-07-06T12:40:37Z'
  revision: 2
spec:
  dnsNames:
    - rancher.ewhisper.cn
  issuerRef:
    group: cert-manager.io
    kind: Issuer
    name: rancher
  secretName: tls-rancher-ingress
  usages:
    - digital signature
    - key encipherment

我们必须提供一个或多个 Solvers 来处理 ACME challenge。在这种情况下,我们想使用 HTTP 验证,所以我们指定了一个http01 Issuer - rancher。我们可以选择映射不同的域来使用不同的 Solver 配置。

一旦我们创建了上述发行者,我们就可以用它来获取证书。

证书资源描述了我们所需的证书以及可以用来获取证书的可能方法。如果成功获得证书,产生的密钥对将被存储在与证书相同命名空间的名为tls-rancher-ingress的 Secret 中。

该证书的 dnsname 为rancher.ewhisper.cn.

?Notes

如果上面的 yaml 删除 dnsNames, 替换为 commonName: ewhisper.cn,Subject Alternative Name(SAN) 将是ewhisper.cnwww.ewhisper.cn

在我们的证书中,我们引用了上面的rancher Issuer。发行人必须与证书处于同一命名空间。如果你想引用ClusterIssuer,这是一个集群范围内的 Issuer,你必须添加kind:ClusterIssuerissuerRef 节中。

acme节定义了 ACME challenge 的配置。这里我们定义了 HTTP01 challenge 的配置,它将被用来验证域名所有权。为了验证 http01 节中提到的每个域的所有权,cert-manager 将创建一个 Pod、SVC 和 Ingress,暴露一个满足 HTTP01 challenge 的 HTTP 端点。

http01节中的ingressingressClass字段可以用来控制 cert-manager 与 Ingress 资源的交互方式。

  • 如果指定了 ingress 字段,那么在与证书相同的 NameSpace 中,具有相同名称的 Ingress 资源必须已经存在,它将被修改,只是为了添加适当的规则以解决 challenge 。这个字段对 ingress 控制器以及其他一些为每个 ingress 资源分配一个公共 IP 地址的控制器很有用。如果没有人工干预,创建一个新的 Ingress 资源将导致任何 challenge 失败。
  • 如果指定了 ingressClass 字段,将创建一个具有随机生成的名称的新入口资源,以解决 challenge 。这个新资源将有一个注释,其 key 是kubernetes.io/ingress.class 值设置为 ingressClass 的 field. 这适用于 NGINX ingress controller 等。
  • 如果两者都没有指定,新的 Ingress 资源将以随机生成的名称被创建,但它们不会有 ingressClass 注释的设置。
  • 如果两者都被指定,那么 ingress 字段将被优先考虑。

一旦域名所有权得到验证,任何受影响的 cert-manager 资源将被清理或删除。

? 注意

你有责任将每个域名指向你的入口控制器的正确 IP 地址。(就是配置 DNS 记录的活还是需要你自己来做。)

在创建上述证书后,我们可以使用kubectl describe检查它是否已经成功获得。

$ kubectl describe certificate example-com
Events:
  Type    Reason          Age      From          Message
  ----    ------          ----     ----          -------
  Normal  CreateOrder     57m      cert-manager  Created new ACME order, attempting validation...
  Normal  DomainVerified  55m      cert-manager  Domain "example.com" verified with "http-01" validation
  Normal  DomainVerified  55m      cert-manager  Domain "www.example.com" verified with "http-01" validation
  Normal  IssueCert       55m      cert-manager  Issuing certificate...
  Normal  CertObtained    55m      cert-manager  Obtained certificate from ACME server
  Normal  CertIssued      55m      cert-manager  Certificate issued successfully

你也可以用kubectl get secret tls-rancher-ingress -o yaml来检查发行是否成功。你应该看到一个 base64 编码的 TLS 密钥对。

一旦我们获得了证书,cert-manager 将定期检查它的有效性,并在它接近到期时尝试更新。当证书上的 Not After 字段小于当前时间加 30 天时,cert-manager 认为证书接近到期。

证书更新

我的证书之前已经申请到了,前几天更新的过程日志记录如下(可以对照上文的证书生命周期来看):

I0507 13:39:31.141402       1 trigger_controller.go:181] cert-manager/certificates-trigger "msg"="Certificate must be re-issued" "key"="cattle-system/tls-rancher-ingress" "message"="Renewing certificate as renewal was scheduled at 2022-05-07 13:39:31 +0000 UTC" "reason"="Renewing"
I0507 13:39:31.143437       1 conditions.go:201] Setting lastTransitionTime for Certificate "tls-rancher-ingress" condition "Issuing" to 2022-05-07 13:39:31.142484989 +0000 UTC m=+186628.212145824
I0507 13:39:31.807902       1 controller.go:161] cert-manager/certificates-key-manager "msg"="re-queuing item due to optimistic locking on resource" "key"="cattle-system/tls-rancher-ingress" "error"="Operation cannot be fulfilled on certificates.cert-manager.io \"tls-rancher-ingress\": the object has been modified; please apply your changes to the latest version and try again"
I0507 13:39:31.928746       1 conditions.go:261] Setting lastTransitionTime for CertificateRequest "tls-rancher-ingress-5j9mm" condition "Approved" to 2022-05-07 13:39:31.927475704 +0000 UTC m=+186628.997136533
I0507 13:39:32.181390       1 conditions.go:261] Setting lastTransitionTime for CertificateRequest "tls-rancher-ingress-5j9mm" condition "Ready" to 2022-05-07 13:39:32.181379458 +0000 UTC m=+186629.251040270
I0507 13:39:32.263457       1 controller.go:161] cert-manager/certificaterequests-issuer-acme "msg"="re-queuing item due to optimistic locking on resource" "key"="cattle-system/tls-rancher-ingress-5j9mm" "error"="Operation cannot be fulfilled on certificaterequests.cert-manager.io \"tls-rancher-ingress-5j9mm\": the object has been modified; please apply your changes to the latest version and try again"
I0507 13:39:41.306332       1 pod.go:71] cert-manager/challenges/http01/ensurePod "msg"="creating HTTP01 challenge solver pod" "dnsName"="rancher.ewhisper.cn" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:39:41.621639       1 pod.go:59] cert-manager/challenges/http01/selfCheck/http01/ensurePod "msg"="found one existing HTTP01 solver pod" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Pod" "related_resource_name"="cm-acme-http-solver-pglxk" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:39:41.621784       1 service.go:43] cert-manager/challenges/http01/selfCheck/http01/ensureService "msg"="found one existing HTTP01 solver Service for challenge resource" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Service" "related_resource_name"="cm-acme-http-solver-xsqkb" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
E0507 13:39:41.837584       1 sync.go:186] cert-manager/challenges "msg"="propagation check failed" "error"="wrong status code '404', expected '200'" "dnsName"="rancher.ewhisper.cn" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:39:42.027681       1 pod.go:59] cert-manager/challenges/http01/selfCheck/http01/ensurePod "msg"="found one existing HTTP01 solver pod" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Pod" "related_resource_name"="cm-acme-http-solver-pglxk" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:39:42.027757       1 service.go:43] cert-manager/challenges/http01/selfCheck/http01/ensureService "msg"="found one existing HTTP01 solver Service for challenge resource" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Service" "related_resource_name"="cm-acme-http-solver-xsqkb" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:39:42.027811       1 ingress.go:110] cert-manager/challenges/http01/selfCheck/http01/ensureIngress "msg"="multiple challenge solver ingresses found for challenge. cleaning up all existing ingresses." "dnsName"="rancher.ewhisper.cn" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
E0507 13:39:42.076190       1 controller.go:102] ingress 'cattle-system/cm-acme-http-solver-knwm8' in work queue no longer exists
E0507 13:39:42.100492       1 controller.go:102] ingress 'cattle-system/cm-acme-http-solver-59gvf' in work queue no longer exists
E0507 13:39:42.101020       1 sync.go:186] cert-manager/challenges "msg"="propagation check failed" "error"="multiple existing challenge solver ingresses found and cleaned up. retrying challenge sync" "dnsName"="rancher.ewhisper.cn" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
...
E0507 13:40:22.187779       1 sync.go:386] cert-manager/challenges/acceptChallenge "msg"="error waiting for authorization" "error"="context deadline exceeded" "dnsName"="rancher.ewhisper.cn" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
E0507 13:40:22.188198       1 controller.go:163] cert-manager/challenges "msg"="re-queuing item due to error processing" "error"="context deadline exceeded" "key"="cattle-system/tls-rancher-ingress-5j9mm-2528720963-983401508" 
I0507 13:40:27.188948       1 pod.go:59] cert-manager/challenges/http01/selfCheck/http01/ensurePod "msg"="found one existing HTTP01 solver pod" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Pod" "related_resource_name"="cm-acme-http-solver-pglxk" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:40:27.190011       1 service.go:43] cert-manager/challenges/http01/selfCheck/http01/ensureService "msg"="found one existing HTTP01 solver Service for challenge resource" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Service" "related_resource_name"="cm-acme-http-solver-xsqkb" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
I0507 13:40:27.190749       1 ingress.go:98] cert-manager/challenges/http01/selfCheck/http01/ensureIngress "msg"="found one existing HTTP01 solver ingress" "dnsName"="rancher.ewhisper.cn" "related_resource_kind"="Ingress" "related_resource_name"="cm-acme-http-solver-cmp2c" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508" "resource_namespace"="cattle-system" "resource_version"="v1" "type"="HTTP-01" 
E0507 13:40:38.478817       1 controller.go:102] ingress 'cattle-system/cm-acme-http-solver-cmp2c' in work queue no longer exists
I0507 13:40:39.806118       1 acme.go:209] cert-manager/certificaterequests-issuer-acme/sign "msg"="certificate issued" "related_resource_kind"="Order" "related_resource_name"="tls-rancher-ingress-5j9mm-2528720963" "related_resource_namespace"="cattle-system" "related_resource_version"="v1" "resource_kind"="CertificateRequest" "resource_name"="tls-rancher-ingress-5j9mm" "resource_namespace"="cattle-system" "resource_version"="v1" 
I0507 13:40:39.809106       1 conditions.go:250] Found status change for CertificateRequest "tls-rancher-ingress-5j9mm" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2022-05-07 13:40:39.809091738 +0000 UTC m=+186696.878752561
I0507 13:40:40.068059       1 controller.go:161] cert-manager/certificates-issuing "msg"="re-queuing item due to optimistic locking on resource" "key"="cattle-system/tls-rancher-ingress" "error"="Operation cannot be fulfilled on certificates.cert-manager.io \"tls-rancher-ingress\": the object has been modified; please apply your changes to the latest version and try again"
I0507 13:40:40.168307       1 controller.go:161] cert-manager/certificates-key-manager "msg"="re-queuing item due to optimistic locking on resource" "key"="cattle-system/tls-rancher-ingress" "error"="Operation cannot be fulfilled on certificates.cert-manager.io \"tls-rancher-ingress\": the object has been modified; please apply your changes to the latest version and try again"
E0507 13:40:41.298717       1 sync.go:70] cert-manager/orders "msg"="failed to update status" "error"=null "resource_kind"="Order" "resource_name"="tls-rancher-ingress-5j9mm-2528720963" "resource_namespace"="cattle-system" "resource_version"="v1" 
I0507 13:40:41.299059       1 controller.go:161] cert-manager/orders "msg"="re-queuing item due to optimistic locking on resource" "key"="cattle-system/tls-rancher-ingress-5j9mm-2528720963" "error"="Operation cannot be fulfilled on orders.acme.cert-manager.io \"tls-rancher-ingress-5j9mm-2528720963\": the object has been modified; please apply your changes to the latest version and try again"
E0507 13:40:41.331531       1 controller.go:211] cert-manager/challenges "msg"="challenge in work queue no longer exists" "error"="challenge.acme.cert-manager.io \"tls-rancher-ingress-5j9mm-2528720963-983401508\" not found"  
  1. cert-manager/certificates-trigger 触发证书 renew(Certificate 里有一个 renewalTime 字段记录该时间)

  2. tls-rancher-ingress 证书的状态变为 "Issuing"

  3. 创建了一个新的 CertificateRequest - tls-rancher-ingress-5j9mm, 状态变为 "Approved", 具体内容如下:

    apiVersion: cert-manager.io/v1
    kind: CertificateRequest
    metadata:
      annotations:
        cert-manager.io/certificate-name: tls-rancher-ingress
        cert-manager.io/certificate-revision: '2'
        cert-manager.io/private-key-secret-name: tls-rancher-ingress-nttqs
      creationTimestamp: '2022-05-07T13:39:31Z'
      generateName: tls-rancher-ingress-
      generation: 1
      name: tls-rancher-ingress-5j9mm
      namespace: cattle-system
      ownerReferences:
        - apiVersion: cert-manager.io/v1
          blockOwnerDeletion: true
          controller: true
          kind: Certificate
          name: tls-rancher-ingress
      resourceVersion: '20868343'
    status:
      certificate: >-
        ...
      conditions:
        - lastTransitionTime: '2022-05-07T13:39:31Z'
          message: Certificate request has been approved by cert-manager.io
          reason: cert-manager.io
          status: 'True'
          type: Approved
        - lastTransitionTime: '2022-05-07T13:40:39Z'
          message: Certificate fetched from issuer successfully
          reason: Issued
          status: 'True'
          type: Ready
    spec:
      extra:
        authentication.kubernetes.io/pod-name:
          - cert-manager-6d6bb4f487-525q9
        authentication.kubernetes.io/pod-uid:
          - 857565c8-b05c-4114-8e94-14960476f90e
      groups:
        - system:serviceaccounts
        - system:serviceaccounts:cert-manager
        - system:authenticated
      issuerRef:
        group: cert-manager.io
        kind: Issuer
        name: rancher
      request: >-
        <-----BEGIN CERTIFICATE REQUEST-----... 的 base64 编码>
      usages:
        - digital signature
        - key encipherment
      username: system:serviceaccount:cert-manager:cert-manager
    
  4. CertificateRequest - tls-rancher-ingress-5j9mm, 的状态变为 "Ready"

  5. 创建 HTTP01 challenge solver pod - "resource_kind"="Challenge" "resource_name"="tls-rancher-ingress-5j9mm-2528720963-983401508"

  6. 前几次 challenge 失败,404: "msg"="propagation check failed" "error"="wrong status code '404', expected '200'"

  7. 经过多次,最终成功:

    1. "msg"="certificate issued" "related_resource_kind"="Order" (开始renew 后, 创建完 CertificateRequest 就开始创建 Order)
    2. Found status change for CertificateRequest "tls-rancher-ingress-5j9mm" condition "Ready": "False" -> "True"; setting lastTransitionTime to 2022-05-07 13:40:39.809091738 +0000 UTC m=+186696.878752561

成功后,Challenge 被删除,Order 的状态变为 valid, 如下:

apiVersion: acme.cert-manager.io/v1
kind: Order
metadata:
  annotations:
    cert-manager.io/certificate-name: tls-rancher-ingress
    cert-manager.io/certificate-revision: '2'
    cert-manager.io/private-key-secret-name: tls-rancher-ingress-nttqs
  creationTimestamp: '2022-05-07T13:39:32Z'
  name: tls-rancher-ingress-5j9mm-2528720963
  namespace: cattle-system
status:
  authorizations:
    - challenges:
        - token: WkoIW-...
          type: http-01
          url: >-
            http://acme-v02.api.letsencrypt.org/acme/chall-v3/.../...
        - token: WkoIW-...
          type: dns-01
          url: >-
            http://acme-v02.api.letsencrypt.org/acme/chall-v3/.../...
        - token: WkoIW-...
          type: tls-alpn-01
          url: >-
            http://acme-v02.api.letsencrypt.org/acme/chall-v3/.../...
      identifier: rancher.ewhisper.cn
      initialState: pending
      url: http://acme-v02.api.letsencrypt.org/acme/authz-v3/...
      wildcard: false
  certificate: >-
    ...
  finalizeURL: http://acme-v02.api.letsencrypt.org/acme/finalize/.../...
  state: valid
  url: http://acme-v02.api.letsencrypt.org/acme/order/.../...
spec:
  dnsNames:
    - rancher.ewhisper.cn
  issuerRef:
    group: cert-manager.io
    kind: Issuer
    name: rancher
  request: >-
    ...

最终 Certificate 的状态也发生更新,新的证书更新进对应的 Secret 中。如下:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: tls-rancher-ingress
  namespace: cattle-system
status:
  notAfter: '2022-08-05T12:40:37Z'
  notBefore: '2022-05-07T12:40:38Z'
  renewalTime: '2022-07-06T12:40:37Z'
  revision: 2
...

DNS01 方式

cert-manager 可以用来从使用 ACME 协议的 CA 获得证书。ACME 协议支持各种 challenge 机制,用来证明一个域名的所有权,以便为该域名签发有效的证书。

其中一个 challenge 机制是 DNS01。通过 DNS01 challenge ,你可以通过证明你控制了一个域名的 DNS 记录来证明它的所有权。这是通过创建一个具有特定内容的 TXT 记录来实现的,该记录证明你对该域名的 DNS 记录有控制权。

之前的 Issuer 定义了启用 DNS 验证的一些必要信息。指定的还是 Let's Encrypt 的生产环境:http://acme-v02.api.letsencrypt.org/directory

dns01 字段包含一个 DNS01 提供者的列表,可用于解决 DNS challenge。这里我只定义了一个 webhook 实现的提供者 - dnspod。

只要我们创建了上述发行者,我们就可以用它来获得证书:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: ewhisper-crt
  namespace: cert-manager
spec:
  dnsNames:
  - ewhisper.cn
  - '*.ewhisper.cn'
  issuerRef:
    group: cert-manager.io
    kind: ClusterIssuer
    name: dnspod
  secretName: ewhisper-crt-secret

证书 CRD 描述了我们所需的证书以及可以用来获取证书的可能方法。你可以像其他域名一样获得通配符域名的证书。请确保在你的 YAML 资源中用星号包裹通配符域名,以避免格式问题。这里我在同一个证书上同时指定ewhisper.cn*.ewhisper.cn,那么执行验证的时间会稍微长一些,因为每个域名必须一个一个地被验证。

? Thinking:

我的通配符证书,在 2022.4.30 开始更新,然后直到 2022.5.8 才更新成功,不知道是不是因为这个原因。

如果成功获得证书,产生的密钥对将被存储在与证书相同命名空间的名为ewhisper-crt-secret的 Secret 中。

该证书的通用名称为*.ewhisper.cn

在我们的证书中,我们引用了上面的dnspod ClusterIssuer, 这种情况下 Issuer 可以与证书不处于同一命名空间。

acme 节定义了我们的 ACME challenge 的配置。这里我们定义了 DNS challenge 的配置,它将被用来验证域名所有权。对于dns01节中提到的每个域名,cert-manager 将使用被引用的 Issue 的提供者的证书来创建一个名为_acme-challenge的 TXT 记录。这条记录将由 ACME 服务器验证,以便签发证书。一旦域名所有权被验证,任何受 cert-manager 影响的记录都将被清理掉。

DNS 服务器我用的是 DNSPod, 这里创建 TXT 的记录如下:

2022-05-08 19:05:39: (<my-public-ip>) 删除记录 TXT 记录 默认 线路 _acme-challenge 值 mfaEFIBPUFzh1ub7Ek05v-bN-fwsdfwdfwdfwedw (1117684179) Uin:<my-uin> Real Client IP:<my-public-ip> API FROM:YUNAPI
2022-05-08 19:04:27: (<my-public-ip>) 添加 TXT 记录 默认 线路 _acme-challenge 值 mfaEFIBPUFzh1ub7Ek05v-bN-fwsdfwdfwdfwedw (1117684179) Uin:<my-uin> Real Client IP:<my-public-ip> API FROM:YUNAPI
2022-05-08 19:04:26: (<my-public-ip>) 删除记录 TXT 记录 默认 线路 _acme-challenge 值 cVxv2s9P_UvThEB2DLcZxfwdfwdfwdwds8Ogv_k (1117683586) Uin:<my-uin> Real Client IP:<my-public-ip> API FROM:YUNAPI
2022-05-08 19:03:12: (<my-public-ip>) 添加 TXT 记录 默认 线路 _acme-challenge 值 cVxv2s9P_UvThEB2DLcZxfwdfwdfwdwds8Ogv_k (1117683586) Uin:<my-uin> Real Client IP:<my-public-ip> API FROM:YUNAPI
2022-05-08 18:04:21: (<my-public-ip>) 删除记录 TXT 记录 默认 线路 _acme-challenge 值 QYLKuSmlK6aWmD64hhExOwdfwdfwdfwdcwdk5bfRCLAI (1117656075) Uin:<my-uin> Real Client IP:<my-public-ip> API FROM:YUNAPI
2022-05-08 18:03:07: (<my-public-ip>) 添加 TXT 记录 默认 线路 _acme-challenge 值 QYLKuSmlK6aWmD64hhExOwdfwdfwdfwdcwdk5bfRCLAI (1117656075) Uin:<my-uin> Real Client IP:<my-public-ip> API FROM:YUNAPI

其他方面就和 HTTP01 是类似的,这里不再做过多的说明。

在这里,用的是 <imroc.cc> 开发的 cert-manager 插件 - cert-manager-webhook-dnspod.

参考的是 这篇文章配置的 dnspod 的 cert-manager webhook

结合上面的流程, 下面来了解一下 cert-manager 的相关概念

系列文章

  • cert-manager TAG

?️ 参考文档

  • cert-manager - cert-manager Documentation
  • 使用 cert-manager 为 dnspod 的域名签发免费证书 | kubernetes 学习笔记 (imroc.cc)
本文转载于网络 如有侵权请联系删除

相关文章

  • 全链路测试不是银弹

    微服务概述微服务应用是一系列自治服务的集合,每个服务只负责完成一块功能,这些服务共同合作来就可以完成某些更加复杂的操作。与单体的复杂系统不同,开发者需要开发和管理一系列相对简单的服务,而这些服务可能以一些复杂的方式交互。这些服务之间的相互协作是通过一系列与具体技术无关的消息协议来完成的,这些协议可能是点到点形式的,也可能是异步形式的。这种想法听起来很简单,但是它确实能够显著降低复杂系统开发过程中的摩擦和冲突。传统的软件工程实践倡导设计良好的系统都应该具备高内聚、低耦合的特点。具备这些特性的系统更加易于维护,并且在面对变更时,也更加容易适应和扩展。内聚度是用来衡量某个模块中的各个元素属于一个整体的紧密程度的指标,耦合度则是衡量一个元素对另一个元素的内部运行逻辑的了解程度的指标。在讨论内聚度时,罗伯特·C.马丁(RobertC.Martin)的单一职责原则是一种非常有用的方式:将那些因相同原因而修改的内容聚合到一起,将那些因不同原因而修改的内容进行拆分。在单体应用中,开发者会在类、模块、类库的层面来设计功能属性;而在微服务应用中,开发者的目标则变成了可独立部署的功能单元——要为这些功能单元

  • Lambda-让人又爱又恨的“->"

    写在前边聊到Java8新特性,你第一反应想到的肯定是Lambda表达式和函数式接口的出现。要说他到底有没有在一定程度上“优化”了代码的简洁性呢?抑或是ta在一定程度上给程序员增加了阅读和debug的难度,让不少程序员头疼。这期来接着“聊聊Java”,新特性篇只又爱又恨的Lambda。Lambda表达式实质属于函数式编程的概念,可返回一个接口的实现 线程中的应用传统方式创建一个一次性的类//一次性的类,用在newThread中充当Runnable对的实现类 classrunnableimplementsRunnable{ @Override publicvoidrun(){ System.out.println("我在路上"); } } publicclasslambdaTest{ publicstaticvoidmain(String[]args){ runnablerunnable=newrunnable(); Threadthread1=newThread(runnable); } } 复制代码复制(稍微优化)匿名内部类Threadthread1=newTh

  • 互联网架构,如何进行容量设计?

    一,需求缘起互联网公司,这样的场景是否似曾相识:场景一:pm要做一个很大的运营活动,技术老大杀过来,问了两个问题:(1)机器能抗住么?(2)如果扛不住,需要加多少台机器?场景二:系统设计阶段,技术老大杀过来,又问了两个问题:(1)数据库需要分库么?(2)如果需要分库,需要分几个库?技术上来说,这些都是系统容量预估的问题,容量设计是架构师必备的技能之一。常见的容量评估包括数据量、并发量、带宽、CPU/MEM/DISK等,今天分享的内容,就以【并发量】为例,看看如何回答好这两个问题。二,容量评估的步骤与方法【步骤一:评估总访问量】如何知道总访问量?对于一个运营活动的访问量评估,或者一个系统上线后PV的评估,有什么好的方法?答案是:询问业务方,询问运营同学,询问产品同学,看对运营活动或者产品上线后的预期是什么。举例:58要做一个APP-push的运营活动,计划在30分钟内完成5000w用户的push推送,预计push消息点击率10%,求push落地页系统的总访问量?回答:5000w*10%=500w【步骤二:评估平均访问量QPS】如何知道平均访问量QPS?答案是:有了总量,除以总时间即可,如

  • Excel催化剂开源第37波-音视频文件元数据提取(分辨率,时长,采样率等)

    上一篇提到图片元信息Exif的提取,当然还有一类音视频文件,也同样存储着许多宝贵的元数据,那就开源到底呗,虽然自己找寻过程也是蛮艰辛坎坷的,大家看后有收获,只求多多传播下,让前人的工作可以更有价值。此篇对应的Excel催化剂功能实现:第83波-遍历文件夹内文件信息特别是图像、音视频等特有信息https://www.jianshu.com/p/ad98adc64f0b音视频元数据的提取,用到了MediaToolkit类库,较其他复杂的方案来说,这个对我这种业余开发者最友好,最后很幸运地相遇了它。MediaToolkit类库直接上代码,同样只需三两行代码就可以拿到核心信息。``` privatevoidAddMediaInfo(DataRowdr,stringfilePath) { try { using(varengine=newEngine()) { varinputFile=newMediaToolkit.Model.MediaFile{Filename=filePath}; engine.GetMetadata(inputFile); varvideoData=inputFile.

  • Android 优化Handler防止内存泄露

    Android优化Handler防止内存泄露Demo描述:Handler可能导致的内存泄露及其优化1关于常见的Handler的用法但是可能导致内存泄露2优化方式请参考BetterHandler和BetterRunnable的实现packagecc.cc; importjava.lang.ref.WeakReference; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.Message; importandroid.app.Activity; /** *Demo描述: *Handler可能导致的内存泄露及其优化 * *1关于常见的Handler的用法但是可能导致内存泄露 *请参考方法initHandler() *2优化方式请参考BetterHandler和BetterRunnable的实现 * * * */ publicclassMainActivityextendsActivity{ privateHandlermHandler; @Override protectedvoidonCreate(B

  • 零基础入门量子计算:从一个神奇的概念进入量子世界

    导读:量子比特是量子计算的基本单位,量子比特可以用电子的自旋或光子的偏振来表示。本文将从量子特有的自旋概念开始,带你进入神奇的量子世界。限于篇幅,本文将略过光子的偏振相关内容,如果你对这部分内容感兴趣,可阅读《人人可懂的量子计算》一书第1.6节。作者:克里斯·伯恩哈特(ChrisBernhardt)来源:大数据DT(ID:hzdashuju)所有的计算都包括三个过程,首先输入数据,然后根据一定的规则对输入进行操作,最后输出结果。对于经典计算来说,比特是数据的基本单位。对于量子计算来说,这个基本单位是量子比特(quantumbit)——通常缩写为qubit。一个经典比特对应于两个选项中的一个。任何处于两种状态之一的事物都可以表示成一个比特。稍后我们将看到各种各样的例子,其中包括逻辑语句的真假,开关打开或关闭,甚至台球的存在或不存在。就像一个比特一样,一个量子比特包括这两种状态,但与比特不同的是,它也可以是这两种状态的组合。这是什么意思?两种状态的组合到底是什么?能代表量子比特的物理对象是什么?开关在量子计算中的类似物是什么?量子比特可以用电子的自旋或光子的偏振来表示。尽管这是真的,但似乎

  • Android-Q 对 startActivity() 做了限制,怎么适配?

    本文转载自公众号:「承香墨影」 一.Q禁用后台启动Activity前几天写了篇文章,描述了AndroidQ中,后台禁止启动Activity对现有国内App中启动页设计的影响。当时由于主题所限,没有聊到技术细节。今天就延续这个话题,再聊聊AndroidQ限制后台启动Activity的具体细节。有人可能会觉得P还没用上,Q还远着。如果只是对于普通用户来说,确实是这样,大多数情况新系统对应的就是新设备,手机的换代速度是远低于系统升级的。但是对于我们开发者来说,老旧的系统版本可以战略性的放弃,但是新系统肯定要率先支持的。就算你不想这么做,各大硬件厂商,也会推动你去做,毕竟最新的设备都是搭载的最新的系统,App不稳定,肯定是影响用户体验的。AndroidQ在今年Q3季度,就准备发布正式版了,了解AndroidQ的新特性,也是我们开发者马上马就要面临的事情了。言归正传,继续聊AndroidQ下,禁止后台启动Activity。二.限制影响的范围以最新的AndroidQBeta4来举例,当你的App处于后台时,一旦尝试开启新的页面,会发生什么呢?首先你的新页面肯定是打不开的,在现有的Beta版本上,系

  • 《Print Friendly & PDF》让你拥有最佳的打印阅读体验

    主流浏览器默认的打印效果都不理想,Chrome也不例外以掘金的一篇热门文章为例https://juejin.im/post/5cc089eae51d456e7d189f9d Chrome默认打印效果 使用《PrintFriendly&PDF》生成打印效果 Chrome默认生成为41页,通过《PrintFriendly&PDF》生成的PDF为36页(PrintFriendly&PDF自动移除了与文章内容无关的相关推荐内容) 如果有些内容不想打印,可以直接通过《PrintFriendly&PDF》删掉 如果你想减少打印页数,可以通过PrintFriendly&PDF改变字号来实现 如果你不想打印,只是将网页内容保存为pdf,《PrintFriendly&PDF》也是支持的~ 小结:PrintFriendly&PDF是一款文件打印chrome插件,会在打印之前删除垃圾广告,导航和无用浮窗从而实现页面优化,让你拥有最佳的打印阅读体验,如果你经常需要打印网页,可以通过PrintFriendly&PDF让你的打印工作变得省时

  • 如何在FreeBSD 10.1上使用Sendmail通过外部SMTP服务发送电子邮件

    介绍设置新的Web服务器时最常见的需求之一是发送电子邮件。最安全,最简单的方法是将服务器连接到SendGrid或AmazonSES等邮件服务。使用外部服务将帮助您避免陷阱,例如您的服务器IP被反垃圾邮件服务列入黑名单。在本教程中,我们将讨论如何将FreeBSD的内置Sendmail服务连接到SendGrid以从服务器发送电子邮件。您还可以轻松调整其他外部邮件服务的设置。如果你是FreeBSD的新手,我们所做的一些事情可能看起来有些可怕,但是你很快就可以轻松地卷起袖子来重新编译像FreeBSD专业版这样的系统工具。目标在本教程中,我们将:使用SASL支持重新编译Sendmail,以便服务器可以使用外部服务进行身份验证使用适当的设置配置Sendmail邮件服务器测试出站电子邮件以确保邮件从您的服务器发出准备在开始本指南之前,您需要以下内容:一台已经设置好可以使用sudo命令的非root账号的reeBSD10.1服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。熟悉如何从命令行编辑文本文件您应该安装自己喜

  • 聊天机器人中的深度学习技术(引言)

    原文链接:DEEPLEARNINGFORCHATBOTS,PART1–INTRODUCTION 译者:刘翔宇审核:赵屹华 责编:周建丁(zhoujd@csdn.net)聊天机器人,又被称为会话代理或者对话系统,它是一个热门的话题。微软在聊天机器人上下了很大的成本,Facebook(M),苹果公司(Siri),谷歌,微信,和Slack也是如此。聊天机器人在初创公司中掀起了一种新浪潮,他们试图通过建立类似于Operator或x.ai这样的应用程序,类似于Chatfuel这样的平台以及类似Howdy’sBotkit这样的机器人库来改变消费者与服务的交互。最近微软发布了自己的机器人开发者框架。许多公司都希望开发出有人类水准能够进行自然对话的机器人,并且许多公司都声称使用自然语言处理和深度学习技术来实现。但是随着AI被大肆炒作,很难将事实与虚幻区分开来。在本系列中,我会介绍用于构建会话代理所用到的一些深度学习技术,首先我将阐述我们目前所处的阶段,哪些可能实现,以及又有哪些,至少在短期内几乎不可能实现。这篇文章将作为一个介绍,我们会在接下来的文章中深入讲解实现细节。模型分类法基于检索(Retrie

  • 2016年推动云计算全面爆发的三大关键性趋势

    运维、容器以及相关培训将成为未来一年内的主要工作重点——这也意味着其应当成为大家的核心投资对象。新年即将来临,现在是时候展望未来一年的全新趋势了,这样我们才能更具前瞻性地抓住机遇、实现发展目标。下面一起来看将在2016年年内出现的三大关键性云计算发展趋势。趋势一:云运维逐步崛起云运维代表的是我们在打理公有或私有云内各操作系统时的一切相关工作。其专注于安全、管理、监控以及治理等诸多方面,同时也需要以主动方式关注系统的长期运行状态。要实现这一目标,意味着我们需要利用预测分析手段评估性能何时会成为负载处理瓶颈,或者当前运行模式是否有可能引发安全事故等问题。趋势二:容器技术持续爆炸式增长对于容器这一技术概念,大家想必已经不会感到陌生了。容器方案之所以能够在短时间内获得爆棚的人气,主要是因为它们为业界指明了在云环境下构建新型分布式应用程序的可行途径,同时能够对现有应用进行“容器化”转换。好消息是,容器确实没有辜负人们的厚望,Docker与CoreOS等相关项目更是发展得红红火火。坏消息是:目前容器技术仍然存在组件缺失,例如网络与安全服务,这意味着其在全面进入企业生产环境之前还需要得到进一步改进。

  • 证监会批复上市:三年营收 211 亿、净利润 11.5 亿、研发投入 32.75 亿;拟募资 22 亿

    2022年9月15日,证监会发布《关于同意锐捷网络股份有限公司首次公开发行股票注册的批复》。2020年12月18日,锐捷网络申请创业板上市。拟募资22亿:主要财务数据:近三年营收分别为91.89亿、66.98亿、52.2亿;净利润为4.75亿、3.1亿、3.68亿。主营业务营收构成:网络设备收入构成:1、交换机收入构成:2、无线产品收入构成: 网络安全产品收入构成:云桌面收入构成:销售模式: 报告期各期,纳入锐捷网络渠道商管理体系的一级渠道商各细分类型数量如下:报告期各期,渠道商管理体系内退出一级渠道商数量、新增一级渠道商数量及合计新增一级渠道商的销售收入占当期渠道销售模式收入比例如下:神州数码、联强国际和伟仕佳杰三家总代理商向锐捷网络采购额及营业收入如下表所示:按产品是否定制分类: 前五大客户: 渠道销售模式主要客户(总代理商): 渠道销售模式主要客户(行业代理商): 渠道销售模式主要客户(SMB经销商):直销主要客户:(整体状况)前五大供应商:(整机设备)前五大供应商:(原材料)前五大供应商:(交换机)前五大供应商:(云桌面解决方案)前五大供应商:合作的供应链管理公司主要为信利康。

  • Linq之旅:Linq入门详解(Linq to Objects)

      示例代码下载:Linq之旅:Linq入门详解(LinqtoObjects)         本博文详细介绍.NET3.5中引入的重要功能:LanguageIntegratedQuery(LINQ,语言集成查询)。通过LINQ,我们可以使用相同API操作不同的数据源。接下来就让我们看看LINQ是什么以及如何使用?    再此之前,需要先了解的相关技术 1.       隐式类型、匿名类型、对象初始化器 1)       隐式类型,使用var关键字创建,C#编译器会根据用于初始化局部变量的初始值推断出变量的数据类型。(不过我个人认为,能用具体类型的地方尽量不要用var关键字,因为这样会让你遗忘“被封装类库”方法的返回值类型--有损可读性) 隐式类型使用限制: a)       隐式

  • CMDB的数据获取实现方式

    CMDB项目: 1.什么是自动化运维?为什么需要自动化运维? 自动化运维可以实现以下四点: 1.项目上线:​ 流程:​ 产品经理调研(画出原型图)--->定需求--->三方会谈(产品经理,研发,老大们)--->定日期--->测试项目--->最终上线--->应用运维​ 目前:是把代码打包给运维,运维解压上线问题:随着机器数量的线性增加,运维的工作量也是线性增加,重复而且是无意义的劳动解决:1.写一个shell脚本,进行部署2.搞一个自动化代码上线系统必要条件:服务器的各种信息(主机名,cpu,硬盘大小等)2.监控系统:检测服务器的各信息,(硬盘是否满,cpu的使用率,内存使用率,网站服务运行是否正常)问题:之前写简单的脚本,检测服务器的信息,比较麻烦解决:想将服务器的各种信息,以图表的形式展示在web界面上(可视化)必要条件:服务器的各种信息(主机名,cpu,硬盘大小等)3.自动装机系统:问题:人工去装机,一台一台的装解决:搞一个装机系统,cobbler软件必要条件:服务器的各种信息(主机名,cpu等)4.Excel表格审计管理资产复制

  • 章抠图粘贴到新的文件中

    1.拍照红章 2.PS打开红章图片——>选择——>颜色范围——>红色——>复制。 打开新的文件图片——>粘贴。   3.章参考参数: 字体长城长宋体 大小32,标准,字距-10,环边距25。 中心图案尺寸比例55%,边线宽4。   仅供参考。

  • HTML基础要点归纳

    一、开发环境   常用的HTML编辑器有SublimeText、Hbuild、Dreamweare、以及vscode、pycharm等都可以。我目前在用的就是Sublimetext3和Hbuild两款。 二、HTML文档结构 1<!--<!DOCTYPEhtml>是文档声明--> 2<!DOCTYPEhtml> 3<!--<html></html>称为根标签--> 4<htmllang="en"> 5 6<head> 7<!--头部信息相关内容--> 8<metacharset="UTF-8"> 9<title>Document</title> 10</head> 11 12<body> 13<!--页面主体相关内容--> 14</body> 15</html>复制 三、head标签放什么? (1)文档的头部描述了文档的各种属性和信息,标题、编码、URL之类的。以下标签是可以放在h

  • Python matplotlib绘图设置图例

    一、语法简介 plt.legend(loc=2,edgecolor='red',facecolor='green',shadow='True',fontsize=10) #edgecolor图例边框线颜色facecolor图例背景色shadow是否添加阴影title图例标题fontsize设置字体大小 ''' 设置图例位置loc参数简介 best0根据图标区域自动选择最合适的位置 upperright1右上角 upperleft2左上角 lowerleft3左下角 lowerright4右下角 right5右侧 centerleft6左侧中心 centerright7右侧中心 lowercenter8底部中心 uppercenter9顶部中心 center10正中心位置 '''复制 二、完整代码 importmatplotlib.pyplotasplt importnumpyasnp plt.rcParams['font.sans-serif']=['STZhongsong']#指定默认字体:解决plot不能显示中文问题 plt.rcParams['axes.unicode_m

  • Windows Server 2008 Workstation Converter优化设置

    http://www.win2008workstation.com/windows-server-2008-workstation-converter/ Ifyoudon’twanttoconfigurealloptionstoconvertWindowsServer2008toaWorkstationmanually,sawonowmadeitpossibletouseatoolforthis.Hehasdoneagreatjobbycreatingthisconvertertoautomateallstepsofthemanual! GettheWindowsServer2008WorkstationConverter DownloadServ08Convert12.zip(13.2MB) Support&Suggestions Atthispage(http://converter.win2008workstation.com/)usingcomments. AttheForumsinthe‘WindowsServer2008WorkstationConverter

  • python起简易http server

    python-mSimpleHTTPServer9111

  • 执行插件超过2分钟超时错误,如何办?

    我们都知道,默认情况下Dynamics365执行的插件有2分钟的限制,若达到2分钟还没有执行完毕,会触发异常,类似如下: System.TimeoutException:Couldn’tcompleteexecutionofthecustomactivity***plug-inwithinthe2-minutetimelimit. 那我改到工作流行不行?如果改到自定义工作流活动,同样也有类似的限制,一个自定义工作流活动的执行时间不能超过2分钟,若超过了,会触发异常,和插件的异常是一样的。 如果碰到这种情况怎么办? 若是工作流中有多个循环的话,考虑将这个循环拆出来,每个循环的逻辑用一个异步工作流来做,这个异步工作流设置为仅仅支持手工触发,记得,一定要设置成支持手工触发。 然后这个循环体里面的就用调用工作流来代替,类似如下的代码,这样在很多情况下就可以绕过这个2分钟的限制。 varfetchXml=@"<fetchversion='1.0'mapping='logical'distinct='false'no-lock='true'> <entityname='work

  • 关于电路中常说的上拉,下拉,浮空

    引言 最开始学习嵌入式的时候,经常在野火的视频中听到上拉之类的名词,一直不清楚该名词,直到看了数字设计和计算机架构这本书,与该部分相关的位置为1.7节 tip:该部分会涉及到数字电路的一点点知识 说明:博客中的图片都来自于《数字设计和计算机架构》 前置知识 集成电路中常见的基本元器件是MOS管,而MOS又可以分为pMOS和nMOS: 特性: nMOS对低电平导通性较好 pMOS对高电平导通性较好 能够同时提供两种MOS管的器件被广泛使用,称为CMOS CMOS实现非门: 正题 那么这个和上拉的关系在于什么? 其实可以将上面的非门抽象为下图: 恍然大悟!!! 其实,上拉也就是导通pMOS,下拉也就是导通nMOS,这也就是上拉和下拉的由来 那么浮空呢? 其实就是这样一种情况:既不导通pMOS,也不导通nMOS 那再想想如果pMOS和nMOS都导通会怎么样? 该部分的电路就会短路!!!严重的毁坏MOS管 结语 在《数字设计和计算机架构》这本书中有这样的建议: 在具有正常功能的逻辑门中,上拉或下拉网络必然有一个导通且另一个截止。 使用传导互补规则满足该条件:nMOS使用串联时,pMOS使

相关推荐

推荐阅读