在 Google Kubernetes Engine (GKE) 上部署 cert-manager 并使用 Let's Encrypt 为 Ingress 创建 SSL 证书
上次验证:2022 年 7 月 15 日
在本教程中,您将学习如何在 Google Kubernetes Engine (GKE) 上部署和配置 cert-manager。您将学习如何配置 cert-manager 以从 Let's Encrypt 获取签名的 SSL 证书,使用 HTTP-01 挑战。最后,您将学习如何使用证书通过公共域名提供 HTTPS 网站。
Google Cloud:Google 提供的一套云计算服务。
Kubernetes:运行在您的服务器上。自动执行容器化应用程序的部署、扩展和管理。
cert-manager:运行在 Kubernetes 中。获取 TLS/SSL 证书,并确保证书有效且最新。
Let's Encrypt:互联网服务。允许您生成免费的短期 SSL 证书。
首先,您将创建一个 Kubernetes (GKE) 集群并部署一个示例 Web 服务器。然后,您将为您的网站创建一个公共 IP 地址和一个公共域名。您将设置 Ingress 和 Google Cloud 负载均衡器,以便互联网客户端可以使用 HTTP 连接到 Web 服务器。最后,您将使用 cert-manager 从 Let's Encrypt 获取 SSL 证书,并配置负载均衡器以使用该证书。在本教程结束时,您将能够使用 https://
URL 从互联网连接到您的网站。
先决条件
💻 Google Cloud 帐户
您需要一个 Google Cloud 帐户。注册需要信用卡或银行账户信息。请访问 Google Cloud 入门 页面并按照说明进行操作。
💵 如果您以前从未使用过 Google Cloud,您可能有资格获得 Google Cloud 免费计划,该计划为您提供 90 天的试用期,其中包括 300 美元的免费云结算额度,用于探索和评估 Google Cloud。
💻 域名
您需要一个域名,并能够在该域名中创建 DNS 记录。我们将从 Google Domains 获取一个 12 美元的域名。Google Domains 是众多“域名注册商”之一。NameCheap 和 GoDaddy 是另外两个知名的注册商。
💵 如果您不想购买域名,也可以将本教程改编为使用 IP 地址来提供您的网站和 SSL 证书。
💻 软件
您还需要在笔记本电脑上安装以下软件
- gcloud:用于创建和管理 Google Cloud 资源的一套工具。
- kubectl:Kubernetes 命令行工具,允许您配置 Kubernetes 集群。
- curl:用于使用 HTTP 和 HTTPS 连接到 Web 服务器的命令行工具。
ℹ️ 尝试运行
gcloud components install kubectl
以快速安装kubectl
。
0. 使用 Google Cloud 项目配置 gcloud
如果您没有 Google Cloud 帐户,以下命令将为您创建一个帐户
gcloud init
您需要对以下问题回答“yes”
Do you want to configure a default Compute Region and Zone? (Y/n)? Y
运行命令后,您将看到项目名称、默认区域和默认区域。
示例输出
* Commands that require authentication will use [email protected] by default* Commands will reference project `your-project` by default* Compute Engine commands will use region `europe-west1` by default* Compute Engine commands will use zone `europe-west1-b` by default
在本教程中,我们将使用变量 PROJECT
来引用在运行 gcloud init
时选择的项目名称。在您在命令中看到 $PROJECT
的任何地方,您都需要 (1) 在执行命令之前手动替换变量,或者 (2) 在 shell 会话中导出变量。这适用于您在本教程中列出的命令中遇到的所有环境变量。
我们将使用选项 (2),因此我们需要使用 gcloud init
打印的信息导出环境变量,然后才能继续。
export PROJECT=your-project # Your Google Cloud project ID.export REGION=europe-west1 # Your Google Cloud region.
1. 创建 Kubernetes 集群
首先,让我们在 Google Cloud 中创建一个 Kubernetes 集群。您需要为您的集群选择一个名称。在这里,我们将使用“test-cluster-1”。让我们将其保存在一个环境变量中
export CLUSTER=test-cluster-1
现在,使用以下命令创建集群
gcloud container clusters create $CLUSTER --preemptible --num-nodes=1
为 kubectl
设置 Google Kubernetes Engine 身份验证插件
gcloud components install gke-gcloud-auth-pluginexport USE_GKE_GCLOUD_AUTH_PLUGIN=Truegcloud container clusters get-credentials $CLUSTER
现在检查您是否可以连接到集群
kubectl get nodes -o wide
⏲ 创建集群需要 4-5 分钟。
💵 为了最大程度地降低您的云账单,此命令使用 抢占式虚拟机 创建了一个 1 节点集群,它比普通虚拟机更便宜。
2. 部署一个示例 Web 服务器
我们将部署一个非常简单的 Web 服务器,它使用“hello world!”响应 HTTP 请求。
kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0
我们还需要创建一个 Kubernetes 服务,以便可以将连接路由到 Web 服务器 Pod
kubectl expose deployment web --port=8080
ℹ️ 这些 kubectl 命令式命令 用于可读性和简洁性。您可以随意使用 YAML 清单和
kubectl apply -f
代替。ℹ️ 由
kubectl expose
创建的服务将是ClusterIP
类型(默认值),这只能在集群内由组件访问。稍后,我们将创建一个 Ingress,这是我们将服务提供给集群外部客户端的方式。🔰 阅读有关 使用服务公开您的应用程序 的更多信息。
3. 创建一个静态外部 IP 地址
本教程是关于使用 HTTP01 挑战机制创建带有 Let's Encrypt SSL 证书的公共面向 HTTPS 的网站,因此我们需要一个公共 IP 地址,以便 Let's Encrypt 和其他互联网客户端都可以连接到您的网站。
在 Google Cloud 中创建公共 IP 地址很容易,稍后我们将将其与您的网站域名和 Google Cloud 负载均衡器相关联,该负载均衡器将接受来自互联网客户端的 HTTP(S) 连接,并将请求代理到您的集群中运行的 Web 服务器。
按如下方式创建一个全局静态 IP 地址
gcloud compute addresses create web-ip --global
您应该会看到列出的新 IP 地址
gcloud compute addresses list
⚠️ 您必须创建一个
global
IP 地址,因为这是我们在本教程中将使用的 外部 HTTP(S) 负载均衡器 的先决条件。💵 全局静态 IP 地址仅在高级网络服务层中可用,比短暂和标准公共 IP 地址更昂贵。
🔰 阅读有关 Google Cloud 中的网络服务层 的更多信息。
🔰 阅读有关 在 Google Cloud 中保留静态外部 IP 地址 的更多信息。
最后,我们将 IP 地址保存到环境变量中以供以后使用。使用以下命令显示 IP 地址
gcloud compute addresses describe web-ip --format='value(address)' --global
然后,复制输出并将其保存到环境变量中
export IP_ADDRESS=198.51.100.1 # Replace with your IP address
4. 为您的网站创建域名
您需要一个网站域名,Let's Encrypt 会在签署您的 SSL 证书之前检查您的域名,因此域名需要从互联网访问。
我们将使用信用卡购买一个廉价域名。请访问 https://domains.google.com,并在搜索框中输入内容。例如,我们搜索了 hello-app.com
,因为我们将要部署的示例容器称为 hello-app
。最重要的是,我们确保按价格对域名进行排序
我们不选择 hello-app.com
,因为它要花费 2,800 美元;相反,我们选择最上面的那个:heyapp.net
。它看起来不错!然后我们点击购物车按钮。在下一个屏幕上,您需要禁用自动续订,因为我们不想每年为这个域名付费
现在您知道您的域名,请将其保存在一个环境变量中
export DOMAIN_NAME=heyapp.net
接下来,您需要创建一个新的指向我们在上面创建的 IP 地址的 A
记录。返回 https://domains.google.com/registrar,打开您的域名(这里为 heyapp.net
)并点击左侧菜单的“DNS”。您将看到“自定义记录”。您需要添加一个新的类型为 A
的记录,并将上一步中的 IP 地址放入“数据”中。您必须将“主机名”保留为空,因为我们正在配置顶级域名
🔰 了解更多关于 Cloudflare DNS 教程中的什么是 DNS A 记录?.
ℹ️ 为您的网站创建域名不是必需的。您可以使用 IP 地址连接到它,之后可以为 IP 地址创建 SSL 证书而不是域名。如果由于某种原因您无法创建域名,那么您可以随意跳过此部分,并根据以下说明使用 IP 地址代替。
ℹ️ 每个 Google Cloud 地址都有一个自动生成的逆向 DNS 名称,例如
51.159.120.34.bc.googleusercontent.com
,但父域名googleusercontent.com
拥有 CAA 记录,它会阻止 Let's Encrypt 为子域名签署证书。请参阅 Let's Encrypt 文档中的 证书颁发机构授权 (CAA).
5. 创建 Ingress
您还不能访问您的网站。您的 Web 服务器正在 Kubernetes 集群中运行,但还没有路由或代理供互联网客户端连接到它!现在我们将创建一个 Kubernetes Ingress 对象,在 Google Cloud 中,这将触发创建各种服务,这些服务共同允许互联网客户端连接到运行在 Kubernetes 集群中的 Web 服务器。
最初,我们将创建一个 HTTP(而不是 HTTPS)Ingress,以便我们在添加 SSL 层之前测试基本连接。
将以下 YAML 复制到名为 ingress.yaml
的文件中并应用它
# ingress.yamlapiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: web-ingressannotations:# This tells Google Cloud to create an External Load Balancer to realize this Ingresskubernetes.io/ingress.class: gce# This enables HTTP connections from Internet clientskubernetes.io/ingress.allow-http: "true"# This tells Google Cloud to associate the External Load Balancer with the static IP which we created earlierkubernetes.io/ingress.global-static-ip-name: web-ipspec:defaultBackend:service:name: webport:number: 8080
kubectl apply -f ingress.yaml
这将触发创建与您之前创建的 IP 地址关联的 Google HTTP(S) 负载均衡器。您可以观察创建的资源和进度
kubectl describe ingress web-ingress
在 4-5 分钟内,所有负载均衡器组件都应该准备就绪,您应该能够连接到 DNS 名称并查看之前部署的 hello-world Web 服务器的响应
curl http://$DOMAIN_NAME
示例输出
Hello, world!Version: 1.0.0Hostname: web-79d88c97d6-t8hj2
此时,我们有一个 Google 负载均衡器,它将 HTTP 流量转发到运行在集群中的 Pod 中的 hello-world Web 服务器。
⏲ 负载均衡器组件的创建和配置以及互联网客户端路由到您的 Web 服务器可能需要 4-5 分钟。如果时间更长,请参阅 故障排除 部分。
🔰 阅读有关如何使用 通过 Ingress 注释为 HTTP(S) 负载均衡器使用静态 IP 地址 的信息。
🔰 阅读 GKE 的外部 Ingress 注释摘要.
🔰 阅读关于 在 GKE 上使用外部 HTTP(S) 负载均衡故障排除 Ingress 的信息。
ℹ️ GKE Ingress 提供两种 Ingress 类别。
gce
类部署外部负载均衡器,而gce-internal
类部署内部负载均衡器。没有指定类的 Ingress 资源默认使用gce
。⚠️ 与 Kubernetes Ingress 文档相反,您必须使用
kubernetes.io/ingress.class
注释而不是Ingress.Spec.IngressClassName
字段。请参阅 ingress-gce #1301 和 ingress-gce #1337.
6. 安装 cert-manager
所以最后我们准备开始为我们的网站创建 SSL 证书。您需要做的第一件事是安装 cert-manager,我们将使用 kubectl
以简单的方式安装它,如下所示
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.1/cert-manager.yaml
这将在一个名为 cert-manager
的新命名空间中创建三个 Deployment,以及一些服务和 Pod。它还安装了各种集群范围的辅助资源,例如 RBAC 角色和自定义资源定义。
您可以查看已安装的一些资源,如下所示
kubectl -n cert-manager get all
您可以使用 kubectl explain
探索自定义资源定义(cert-manager 的 API),如下所示
kubectl explain Certificatekubectl explain CertificateRequestkubectl explain Issuer
🔰 阅读有关 其他安装 cert-manager 的方法 的信息。
🔰 阅读有关 证书和颁发者 的更多信息。
7. 为 Let's Encrypt 暂存创建颁发者
颁发者是一个自定义资源,它告诉 cert-manager 如何签署证书。在本例中,颁发者将被配置为连接到 Let's Encrypt 暂存服务器,这使我们能够在不使用域名的 Let's Encrypt 证书配额的情况下测试所有内容。
ℹ️ Let's Encrypt 使用自动证书管理环境 (ACME) 协议,这就是以下配置在名为
acme
的键下的原因。
将以下内容保存到名为 issuer-lets-encrypt-staging.yaml
的文件中,将 email
字段更改为您的电子邮件地址并应用它
# issuer-lets-encrypt-staging.yamlapiVersion: cert-manager.io/v1kind: Issuermetadata:name: letsencrypt-stagingspec:acme:server: https://acme-staging-v02.api.letsencrypt.org/directoryemail: <email-address> # ❗ Replace this with your email addressprivateKeySecretRef:name: letsencrypt-stagingsolvers:- http01:ingress:name: web-ingress
kubectl apply -f issuer-lets-encrypt-staging.yaml
ℹ️ 电子邮件地址仅供 Let's Encrypt 在证书过期前 30 天提醒您续订证书。只有在使用 cert-manager 续订证书时出现问题,您才会收到此电子邮件。
您可以检查颁发者的状态
kubectl describe issuers.cert-manager.io letsencrypt-staging
示例输出
Status:Acme:Last Registered Email: [email protected]Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/60706744Conditions:Last Transition Time: 2022-07-13T16:13:25ZMessage: The ACME account was registered with the ACME serverObserved Generation: 1Reason: ACMEAccountRegisteredStatus: TrueType: Ready
ℹ️ Let's Encrypt 生产颁发者具有 非常严格的速率限制。当您进行实验和学习时,很容易达到这些限制。由于这种风险,我们将从 Let's Encrypt 暂存颁发者开始,一旦我们确认它正常工作,我们将切换到生产颁发者。
⚠️ 在下一步中,您将看到有关不受信任证书的警告,因为我们从暂存颁发者开始,但这完全正常。
🔰 阅读有关 配置 ACME 颁发者 的更多信息。
8. 重新配置 Ingress 以使用 SSL
之前我们创建了一个 Ingress,并看到我们可以使用 HTTP 连接到我们的 Web 服务器。现在我们将重新配置该 Ingress 以使用 HTTPS。
首先是一个快速解决方案,用于解决 Google Cloud Ingress 控制器出现的问题。在重新配置 Ingress **之前**,为您的 SSL 证书创建一个空的 Secret 并应用它
# secret.yamlapiVersion: v1kind: Secretmetadata:name: web-ssltype: kubernetes.io/tlsstringData:tls.key: ""tls.crt: ""
kubectl apply -f secret.yaml
ℹ️ 这是一个解决循环依赖问题的解决方法,其中 ingress-gce 控制器除非先找到最终将包含 SSL 证书的 Secret,否则不会更新其转发规则。但 Let's Encrypt 只有在获取特殊
.../.well-known/acme-challenge/...
URL(cert-manager 将其添加到 Ingress,然后必须由 ingress-gce 控制器将其转换为 Google Cloud 转发规则)后才会签署 SSL 证书。🔰 阅读有关 Kubernetes Secret 及其使用方法 的更多信息。
现在对 Ingress 进行以下更改并应用它们
--- a/ingress.yaml+++ b/ingress.yaml@@ -7,7 +7,12 @@ metadata:kubernetes.io/ingress.class: gcekubernetes.io/ingress.allow-http: "true"kubernetes.io/ingress.global-static-ip-name: web-ip+ cert-manager.io/issuer: letsencrypt-stagingspec:+ tls:+ - secretName: web-ssl+ hosts:+ - $DOMAIN_NAMEdefaultBackend:service:name: web
kubectl apply -f ingress.yaml
这将触发一系列复杂的运算,最终完成可能需要几分钟。其中一些步骤需要 2-3 分钟,有些步骤最初会失败。它们最终都应该成功,因为 cert-manager 和 ingress-gce(Google Cloud Ingress 控制器)将定期重新协调。
最终,当所有部分都到位后,您应该能够使用 curl 检查到您网站的 HTTPS 连接
curl -v --insecure https://$DOMAIN_NAME
您应该看到 HTTPS 连接已建立,但 SSL 证书不受信任;这就是为什么您在此阶段使用 --insecure
标志的原因
示例输出
* Server certificate:* subject: CN=www.example.com* start date: Jul 14 08:52:29 2022 GMT* expire date: Oct 12 08:52:28 2022 GMT* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
⏲ 您需要等待 5-10 分钟才能签署 SSL 证书,然后由 Google Cloud 负载均衡器加载它。如果时间更长,请参阅 故障排除 部分。
ℹ️ 添加注释
cert-manager.io/issuer: letsencrypt-staging
将 Ingress 标记为 cert-manageringress-shim
的关注对象,并导致它创建新的证书,并引用我们之前创建的颁发者。🔰 阅读 保护 Ingress 资源 以了解更多信息。
🔰 阅读有关如何 在 GKE 中为 Ingress 指定证书 的信息。
9. 创建生产就绪的 SSL 证书
现在 Let's Encrypt 暂存服务器的所有功能都已正常运行,我们可以切换到生产服务器并获取受信任的 SSL 证书。
创建一个 Let's Encrypt 生产颁发者并应用它
# issuer-lets-encrypt-production.yamlapiVersion: cert-manager.io/v1kind: Issuermetadata:name: letsencrypt-productionspec:acme:server: https://acme-v02.api.letsencrypt.org/directoryemail: <email-address> # ❗ Replace this with your email addressprivateKeySecretRef:name: letsencrypt-productionsolvers:- http01:ingress:name: web-ingress
kubectl apply -f issuer-lets-encrypt-production.yaml
然后更新 Ingress 注释以使用生产颁发者
kubectl annotate ingress web-ingress cert-manager.io/issuer=letsencrypt-production --overwrite
这将触发 cert-manager 获取由 Let's Encrypt 生产 CA 签署的新 SSL 证书,并将其存储到 web-ssl
Secret 中。大约 10 分钟内,此新证书将同步到 Google Cloud 负载均衡器,您将能够使用安全的 HTTPS 连接到该网站
curl -v https://$DOMAIN_NAME
示例输出
...* Server certificate:* subject: CN=www.example.com* start date: Jul 14 09:44:29 2022 GMT* expire date: Oct 12 09:44:28 2022 GMT* subjectAltName: host "www.example.com" matched cert's "www.example.com"* issuer: C=US; O=Let's Encrypt; CN=R3* SSL certificate verify ok....Hello, world!Version: 1.0.0Hostname: web-79d88c97d6-t8hj2
您还应该能够在 Web 浏览器中访问 https://$DOMAIN_NAME
,没有任何错误或警告。
本教程到此结束。您现在了解了 cert-manager 如何与 Kubernetes Ingress 和云 Ingress 控制器集成。您已经学习了如何使用 cert-manager 获取免费的 Let's Encrypt SSL 证书。您还了解了如何将这些证书用于基于云的负载均衡器,以终止来自互联网客户端的 SSL 连接并将 HTTPS 请求转发到 Kubernetes 集群中运行的 Web 服务器。
💵 阅读 清理 部分,了解如何删除本教程中创建的所有资源,并降低您的云账单。
🔰 如果您在执行本教程中描述的步骤时遇到困难,请阅读 故障排除 部分。
清理
完成本教程后,您可以通过以下步骤清理集群、域名和静态 IP:
# Delete the cluster and all the Google Cloud resources related to the Ingress that it containsgcloud container clusters delete $CLUSTER# Delete the domain namegcloud dns record-sets delete $DOMAIN_NAME --zone $ZONE --type A# Delete the static IP addressgcloud compute addresses delete web-ip --global
故障排除
在本教程中,当您创建或更新 Ingress 对象时,会触发一系列复杂的操作,这些操作可能需要几分钟才能完成。其中一些步骤需要 2-3 分钟,一些步骤最初会失败,但随后会在 cert-manager 或 Google Ingress 控制器重新协调后成功。简而言之,您应该在创建或更改 Ingress 后等待 5-10 分钟,并且您应该预期在运行 kubectl describe ingress web-ingress
时会看到一些错误和警告。
以下是 cert-manager 和 ingress-gce(Google Cloud Ingress 控制器)执行的操作摘要:
- cert-manager 连接到 Let's Encrypt 并发送 SSL 证书签名请求。
- Let's Encrypt 会以“挑战”的形式进行响应,这是一个唯一的令牌,cert-manager 必须将其放置在目标网站的知名位置。这证明您是该网站和域名的管理员。
- cert-manager 部署一个包含临时 Web 服务器的 Pod,该服务器提供 Let's Encrypt 挑战令牌。
- cert-manager 重新配置 Ingress,添加一个
rule
,将来自 Let's Encrypt 的请求路由到该临时 Web 服务器。 - Google Cloud Ingress 控制器使用该新规则重新配置外部 HTTP 负载均衡器。
- Let's Encrypt 现在连接并接收预期的挑战令牌,然后对 SSL 证书进行签名,并将其返回给 cert-manager。
- cert-manager 将签名的 SSL 证书存储在名为
web-ssl
的 Kubernetes Secret 中。 - Google Cloud Ingress 控制器将签名的证书和关联的私钥上传到 Google Cloud 证书。
- Google Cloud Ingress 控制器重新配置外部负载均衡器,使其提供上传的 SSL 证书。
检查 Ingress 和相关事件
使用 kubectl describe
查看 Ingress 配置和所有相关事件。检查 IP 地址是否正确,以及 TLS 和 Host 条目是否与您为网站选择的域名匹配。请注意,ingress-gce
为其管理的每个 Google Cloud 组件创建一个事件。并且请注意,它会添加包含对这些组件 ID 的引用的注释。cert-manager 还会在协调 Ingress 对象时创建事件,包括其为 Ingress 创建的证书对象的详细信息。
$ kubectl describe ingress web-ingressName: web-ingressLabels: <none>Namespace: defaultAddress: 34.120.159.51Ingress Class: <none>Default backend: web:8080 (10.52.0.13:8080)TLS:web-ssl terminates www.example.comRules:Host Path Backends---- ---- --------* * web:8080 (10.52.0.13:8080)Annotations: cert-manager.io/issuer: letsencrypt-stagingingress.kubernetes.io/backends: {"k8s1-01784147-default-web-8080-1647ccd2":"HEALTHY"}ingress.kubernetes.io/forwarding-rule: k8s2-fr-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/https-forwarding-rule: k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/https-target-proxy: k8s2-ts-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/ssl-cert: k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174ingress.kubernetes.io/target-proxy: k8s2-tp-1lt9dzcy-default-web-ingress-yteotwe4ingress.kubernetes.io/url-map: k8s2-um-1lt9dzcy-default-web-ingress-yteotwe4kubernetes.io/ingress.allow-http: truekubernetes.io/ingress.class: gcekubernetes.io/ingress.global-static-ip-name: web-ipEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal CreateCertificate 28m cert-manager-ingress-shim Successfully created Certificate "web-ssl"Normal Sync 28m loadbalancer-controller UrlMap "k8s2-um-1lt9dzcy-default-web-ingress-yteotwe4" updatedWarning Sync 24m (x16 over 28m) loadbalancer-controller Error syncing to GCP: error running load balancer syncing routine: loadbalancer 1lt9dzcy-default-web-ingress-yteotwe4 does not exist: googleapi: Error 404: The resource 'projects/your-project/global/sslCertificates/k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-e3b0c44298fc1c14' was not found, notFoundNormal Sync 34s (x16 over 65m) loadbalancer-controller Scheduled for sync
使用 cmctl 显示证书及其关联资源的状态
ℹ️ 如果您尚未安装
cmctl
,请 安装cmctl
。
当您创建证书时,cert-manager 会创建一组临时资源,每个资源都包含有关证书签名过程状态的信息。您可以在 证书生命周期 部分中详细了解这些资源。使用 cmctl status
命令查看所有这些资源以及所有相关事件和错误消息的详细信息。
您可能会看到一些临时错误,例如:
$ cmctl status certificate web-sslName: web-sslNamespace: defaultCreated at: 2022-07-14T17:30:06+01:00Conditions:Ready: False, Reason: MissingData, Message: Issuing certificate as Secret does not contain a private keyIssuing: True, Reason: MissingData, Message: Issuing certificate as Secret does not contain a private keyDNS Names:- www.example.comEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal Issuing 4m37s cert-manager-certificates-trigger Issuing certificate as Secret does not contain a private keyNormal Generated 4m37s cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "web-ssl-8gsqc"Normal Requested 4m37s cert-manager-certificates-request-manager Created new CertificateRequest resource "web-ssl-dblrj"Issuer:Name: letsencrypt-stagingKind: IssuerConditions:Ready: True, Reason: ACMEAccountRegistered, Message: The ACME account was registered with the ACME serverEvents: <none>error: 'tls.crt' of Secret "web-ssl" is not setNot Before: <none>Not After: <none>Renewal Time: <none>CertificateRequest:Name: web-ssl-dblrjNamespace: defaultConditions:Approved: True, Reason: cert-manager.io, Message: Certificate request has been approved by cert-manager.ioReady: False, Reason: Pending, Message: Waiting on certificate issuance from order default/web-ssl-dblrj-327645514: "pending"Events:Type Reason Age From Message---- ------ ---- ---- -------Normal cert-manager.io 4m37s cert-manager-certificaterequests-approver Certificate request has been approved by cert-manager.ioNormal OrderCreated 4m37s cert-manager-certificaterequests-issuer-acme Created Order resource default/web-ssl-dblrj-327645514Normal OrderPending 4m37s cert-manager-certificaterequests-issuer-acme Waiting on certificate issuance from order default/web-ssl-dblrj-327645514: ""Order:Name: web-ssl-dblrj-327645514State: pending, Reason:Authorizations:URL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/3008789144, Identifier: www.example.com, Initial State: pending, Wildcard: falseChallenges:- Name: web-ssl-dblrj-327645514-2671694319, Type: HTTP-01, Token: TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro, Key: TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro.f4bppCOm-jXasFGMKjpBE5aQlhiQBeTPIs0Lx822xao, State: pending, Reason: Waiting for HTTP-01 challenge propagation: did not get expected response when querying endpoint, expected "TKspp86xMjQzTvMVXWkezEA2sE2GSWjnld5Lt4X13ro.f4bppCOm-jXasFGMKjpBE5aQlhiQBeTPIs0Lx822xao" but got: Hello, world!Version: 1... (truncated), Processing: true, Presented: true
这是因为 cert-manager 正在执行预检检查,以查看临时挑战 Web 服务器是否可以在预期 URL 上访问。最初它将无法访问,因为 cert-manager 需要一些时间来部署临时 Web 服务器,而 Ingress 控制器也需要一些时间来设置新的 HTTP 路由规则。最终您将看到证书已准备好并已签名。
$ cmctl status certificate web-sslName: web-sslNamespace: defaultCreated at: 2022-07-14T17:30:06+01:00Conditions:Ready: True, Reason: Ready, Message: Certificate is up to date and has not expiredDNS Names:- www.example.comEvents:Type Reason Age From Message---- ------ ---- ---- -------Normal Issuing 31m cert-manager-certificates-trigger Issuing certificate as Secret does not contain a private keyNormal Generated 31m cert-manager-certificates-key-manager Stored new private key in temporary Secret resource "web-ssl-8gsqc"Normal Requested 31m cert-manager-certificates-request-manager Created new CertificateRequest resource "web-ssl-dblrj"Normal Issuing 26m cert-manager-certificates-issuing The certificate has been successfully issuedIssuer:Name: letsencrypt-stagingKind: IssuerConditions:Ready: True, Reason: ACMEAccountRegistered, Message: The ACME account was registered with the ACME serverEvents: <none>Secret:Name: web-sslIssuer Country: USIssuer Organisation: (STAGING) Let's EncryptIssuer Common Name: (STAGING) Artificial Apricot R3Key Usage: Digital Signature, Key EnciphermentExtended Key Usages: Server Authentication, Client AuthenticationPublic Key Algorithm: RSASignature Algorithm: SHA256-RSASubject Key ID: a51e3621f5c1138947810f27dce425b33c88cb16Authority Key ID: de727a48df31c3a650df9f8523df57374b5d2e65Serial Number: fa8bb0b603ca2cdbfdfb2872d05ee52cda10Events: <none>Not Before: 2022-07-14T16:34:52+01:00Not After: 2022-10-12T16:34:51+01:00Renewal Time: 2022-09-12T16:34:51+01:00
检查 SSL 证书是否已复制到 Google Cloud
在 cert-manager 接收签名的证书后,它会将其存储在 web-ssl
Secret 中,这反过来会触发 Google Cloud Ingress 控制器将 SSL 证书复制到 Google Cloud。您可以使用以下 gcloud
命令查看证书:
$ gcloud compute ssl-certificates listNAME TYPE CREATION_TIMESTAMP EXPIRE_TIME MANAGED_STATUSk8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174 SELF_MANAGED 2022-07-14T09:37:06.920-07:00 2022-10-12T08:34:51.000-07:00
您还可以查看其内容并检查其属性,如下所示:
$ gcloud compute ssl-certificates describe k8s2-cr-1lt9dzcy-4gjeakdb9n7k6ls7-a257650b5fefd174 --format='value(certificate)' \| openssl x509 -in - -noout -text...Certificate:Data:Version: 3 (0x2)Serial Number:04:9f:47:f1:cb:25:37:9b:86:a3:ef:bf:2e:77:3b:45:fc:1aSignature Algorithm: sha256WithRSAEncryptionIssuer: C = US, O = Let's Encrypt, CN = R3ValidityNot Before: Jul 14 17:11:15 2022 GMTNot After : Oct 12 17:11:14 2022 GMTSubject: CN = www.example.com
检查 Google Cloud 转发规则
在将 TLS 部分添加到 Ingress 对象后,您最终应该会看到一个用于 SSL 连接的转发规则:
$ gcloud compute forwarding-rules describe k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4 --globalIPAddress: 34.120.159.51IPProtocol: TCPcreationTimestamp: '2022-07-14T09:37:12.362-07:00'description: '{"kubernetes.io/ingress-name": "default/web-ingress"}'fingerprint: oBTg7dRaIqI=id: '2303318464959215831'kind: compute#forwardingRulelabelFingerprint: 42WmSpB8rSM=loadBalancingScheme: EXTERNALname: k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4networkTier: PREMIUMportRange: 443-443selfLink: https://www.googleapis.com/compute/v1/projects/your-project/global/forwardingRules/k8s2-fs-1lt9dzcy-default-web-ingress-yteotwe4target: https://www.googleapis.com/compute/v1/projects/your-project/global/targetHttpsProxies/k8s2-ts-1lt9dzcy-default-web-ingress-yteotwe4