如何在DigitalOceanKubernetes上使用Cert-Manager设置Nginx入口
介绍
Kubernetes Ingresses 允许您灵活地将流量从 Kubernetes 集群外部路由到集群内部的服务。 这是使用 Ingress Resources 来完成的,它定义了将 HTTP 和 HTTPS 流量路由到 Kubernetes 服务的规则,以及 Ingress Controllers,它通过负载平衡流量并将其路由到适当的来实现规则后端服务。
流行的入口控制器包括 Nginx、Contour、HAProxy 和 Traefik。 Ingress 为设置多个 LoadBalancer 服务提供了一种更高效、更灵活的替代方案,每个服务都使用自己的专用负载均衡器。
在本指南中,我们将设置 Kubernetes 维护的 Nginx 入口控制器 ,并创建一些入口资源以将流量路由到几个虚拟后端服务。 设置好 Ingress 后,我们将 cert-manager 安装到我们的集群中,以管理和配置 TLS 证书,用于加密到 Ingress 的 HTTP 流量。 本指南 not 使用 Helm 包管理器。 有关使用 Helm 推出 Nginx 入口控制器的指南,请参阅 如何使用 Helm 在 DigitalOcean Kubernetes 上设置 Nginx 入口。
先决条件
在开始阅读本指南之前,您应该准备好以下内容:
- 启用了 基于角色的访问控制 (RBAC) 的 Kubernetes 1.15+ 集群。 此设置将使用 DigitalOcean Kubernetes 集群,但您可以使用 另一种方法 自由创建集群。
kubectl命令行工具安装在您的本地机器上并配置为连接到您的集群。 您可以在官方文档中阅读更多关于安装kubectl的信息。 如果您使用的是 DigitalOcean Kubernetes 集群,请参考 如何连接到 DigitalOcean Kubernetes 集群 了解如何使用kubectl连接到您的集群。- 您可以指向 Ingress 使用的 DigitalOcean 负载均衡器的域名和 DNS A 记录。 如果您使用 DigitalOcean 管理您域的 DNS 记录,请参阅 如何管理 DNS 记录 以了解如何创建
A记录。 - 安装在本地计算机上的
wget命令行实用程序。 您可以使用操作系统内置的包管理器安装wget。
设置好这些组件后,您就可以开始阅读本指南了。
第 1 步 — 设置虚拟后端服务
在部署 Ingress Controller 之前,我们将首先创建并推出两个虚拟 echo 服务,我们将使用 Ingress 将外部流量路由到这些服务。 echo 服务将运行 hashicorp/http-echo Web 服务器容器,该容器返回一个页面,其中包含在 Web 服务器启动时传入的文本字符串。 要了解有关 http-echo 的更多信息,请参阅其 GitHub Repo,要了解有关 Kubernetes 服务的更多信息,请参阅 Kubernetes 官方文档中的 Services。
在您的本地计算机上,使用 nano 或您喜欢的编辑器创建并编辑一个名为 echo1.yaml 的文件:
nano echo1.yaml
粘贴以下服务和部署清单:
echo1.yaml
apiVersion: v1
kind: Service
metadata:
name: echo1
spec:
ports:
- port: 80
targetPort: 5678
selector:
app: echo1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo1
spec:
selector:
matchLabels:
app: echo1
replicas: 2
template:
metadata:
labels:
app: echo1
spec:
containers:
- name: echo1
image: hashicorp/http-echo
args:
- "-text=echo1"
ports:
- containerPort: 5678
在这个文件中,我们定义了一个名为 echo1 的服务,它使用 app: echo1 标签选择器将流量路由到 Pod。 它接受端口 80 上的 TCP 流量并将其路由到端口 5678、http-echo 的默认端口。
然后我们定义一个 Deployment,也称为 echo1,它使用 app: echo1 Label Selector 管理 Pod。 我们指定 Deployment 应该有 2 个 Pod 副本,并且 Pod 应该启动一个名为 echo1 的容器来运行 hashicorp/http-echo 映像。 我们传入 text 参数并将其设置为 echo1,以便 http-echo Web 服务器返回 echo1。 最后,我们在 Pod 容器上打开端口 5678。
对虚拟服务和部署清单感到满意后,保存并关闭文件。
然后,使用带有 -f 标志的 kubectl apply 创建 Kubernetes 资源,指定刚刚保存的文件作为参数:
kubectl apply -f echo1.yaml
您应该看到以下输出:
Outputservice/echo1 created deployment.apps/echo1 created
通过确认它有一个 ClusterIP(服务暴露在其上的内部 IP)来验证服务是否正确启动:
kubectl get svc echo1
您应该看到以下输出:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo1 ClusterIP 10.245.222.129 <none> 80/TCP 60s
这表明 echo1 服务现在在端口 80 上的 10.245.222.129 内部可用。 它将流量转发到它选择的 Pod 上的 containerPort 5678。
现在 echo1 服务已启动并运行,请对 echo2 服务重复此过程。
创建并打开一个名为 echo2.yaml 的文件:
echo2.yaml
apiVersion: v1
kind: Service
metadata:
name: echo2
spec:
ports:
- port: 80
targetPort: 5678
selector:
app: echo2
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo2
spec:
selector:
matchLabels:
app: echo2
replicas: 1
template:
metadata:
labels:
app: echo2
spec:
containers:
- name: echo2
image: hashicorp/http-echo
args:
- "-text=echo2"
ports:
- containerPort: 5678
在这里,我们基本上使用与上面相同的服务和部署清单,但命名并重新标记服务和部署 echo2。 另外,为了提供一些多样性,我们只创建了 1 个 Pod 副本。 我们确保将 text 参数设置为 echo2,以便 Web 服务器返回文本 echo2。
保存并关闭文件,使用 kubectl 创建 Kubernetes 资源:
kubectl apply -f echo2.yaml
您应该看到以下输出:
Outputservice/echo2 created deployment.apps/echo2 created
再次验证服务是否已启动并正在运行:
kubectl get svc
您应该会看到分配有 ClusterIP 的 echo1 和 echo2 服务:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo1 ClusterIP 10.245.222.129 <none> 80/TCP 6m6s echo2 ClusterIP 10.245.128.224 <none> 80/TCP 6m3s kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 4d21h
现在我们的虚拟回显 Web 服务已经启动并运行,我们可以继续推出 Nginx 入口控制器。
第 2 步 — 设置 Kubernetes Nginx 入口控制器
在这一步中,我们将推出 Kubernetes 维护的 Nginx 入口控制器 的 v1.1.1。 注意有几个 Nginx Ingress Controller; Kubernetes 社区维护本指南中使用的社区和 Nginx Inc.。 维护 kubernetes-ingress。 本教程中的说明基于官方 Kubernetes Nginx Ingress Controller 安装指南中的说明。
Nginx Ingress Controller 由一个 Pod 组成,该 Pod 运行 Nginx Web 服务器并监视 Kubernetes 控制平面以获取新的和更新的 Ingress Resource 对象。 入口资源本质上是后端服务的流量路由规则列表。 例如,Ingress 规则可以指定到达路径 /web1 的 HTTP 流量应定向到 web1 后端 Web 服务器。 使用 Ingress Resources,您还可以执行基于主机的路由:例如,将命中 web1.your_domain.com 的请求路由到后端 Kubernetes Service web1。
在这种情况下,因为我们将 Ingress Controller 部署到 DigitalOcean Kubernetes 集群,所以 Controller 将创建一个 LoadBalancer 服务,该服务提供一个 DigitalOcean 负载均衡器,所有外部流量都将定向到该负载均衡器。 此负载均衡器会将外部流量路由到运行 Nginx 的 Ingress Controller Pod,然后将流量转发到适当的后端服务。
我们将从创建 Nginx Ingress Controller Kubernetes 资源开始。 这些包括包含控制器配置的 ConfigMap、基于角色的访问控制 (RBAC) 角色以授予控制器对 Kubernetes API 的访问权限,以及使用 Nginx 入口控制器映像的 v1.1.1 的实际入口控制器部署。 要查看这些所需资源的完整列表,请参阅 Kubernetes Nginx Ingress Controller 的 GitHub 存储库中的 manifest。
注意:在本教程中,我们按照DigitalOcean Provider的官方安装说明进行操作。 您应该根据您的 Kubernetes 提供商选择适当的清单文件。
要创建资源,请使用 kubectl apply 和 -f 标志来指定托管在 GitHub 上的清单文件:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/do/deploy.yaml
我们在这里使用 apply 以便将来我们可以对 Ingress Controller 对象进行增量 apply 更改,而不是完全覆盖它们。 要了解有关 apply 的更多信息,请参阅 Kubernetes 官方文档中的 管理资源。
您应该看到以下输出:
Outputnamespace/ingress-nginx created serviceaccount/ingress-nginx created configmap/ingress-nginx-controller created clusterrole.rbac.authorization.k8s.io/ingress-nginx created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created role.rbac.authorization.k8s.io/ingress-nginx created rolebinding.rbac.authorization.k8s.io/ingress-nginx created service/ingress-nginx-controller-admission created service/ingress-nginx-controller created deployment.apps/ingress-nginx-controller created validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created job.batch/ingress-nginx-admission-create created job.batch/ingress-nginx-admission-patch created role.rbac.authorization.k8s.io/ingress-nginx-admission created rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created serviceaccount/ingress-nginx-admission created
此输出还可作为从 deploy.yaml 清单创建的所有 Ingress Controller 对象的方便摘要。
确认 Ingress Controller Pod 已启动:
kubectl get pods -n ingress-nginx \ -l app.kubernetes.io/name=ingress-nginx --watch
OutputNAME READY STATUS RESTARTS AGE ingress-nginx-admission-create-l2jhk 0/1 Completed 0 13m ingress-nginx-admission-patch-hsrzf 0/1 Completed 0 13m ingress-nginx-controller-c96557986-m47rq 1/1 Running 0 13m
点击 CTRL+C 返回提示。
现在,通过使用 kubectl 获取服务详细信息来确认 DigitalOcean 负载均衡器已成功创建:
kubectl get svc --namespace=ingress-nginx
几分钟后,您应该会看到一个外部 IP 地址,对应于 DigitalOcean 负载均衡器的 IP 地址:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller LoadBalancer 10.245.201.120 203.0.113.0 80:31818/TCP,443:31146/TCP 14m ingress-nginx-controller-admission ClusterIP 10.245.239.119 <none> 443/TCP 14m
记下负载均衡器的外部 IP 地址,因为您将在后面的步骤中需要它。
注意: 默认情况下,Nginx Ingress LoadBalancer Service 将 service.spec.externalTrafficPolicy 设置为值 Local,它将所有负载均衡器流量路由到运行 Nginx Ingress Pod 的节点。 其他节点将故意使负载均衡器健康检查失败,以使 Ingress 流量不会被路由到它们。 外部流量策略超出了本教程的范围,但要了解更多信息,您可以参考官方的 A Deep Dive into Kubernetes External Traffic Policies 和 Source IP for Services with Type=LoadBalancer Kubernetes 文档。
此负载均衡器在 HTTP 和 HTTPS 端口 80 和 443 上接收流量,并将其转发到 Ingress Controller Pod。 然后入口控制器将流量路由到适当的后端服务。
我们现在可以将我们的 DNS 记录指向这个外部负载均衡器,并创建一些入口资源来实现流量路由规则。
第三步——创建入口资源
让我们首先创建一个最小的 Ingress Resource 来将指向给定子域的流量路由到相应的后端服务。
在本指南中,我们将使用测试域 example.com。 您应该将其替换为您拥有的域名。
我们将首先创建一个简单的规则,将指向 echo1.example.com 的流量路由到 echo1 后端服务,并将指向 echo2.example.com 的流量路由到echo2 后端服务。
首先在您喜欢的编辑器中打开一个名为 echo_ingress.yaml 的文件:
nano echo_ingress.yaml
粘贴以下入口定义:
echo_ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ingress
spec:
rules:
- host: echo1.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: echo1
port:
number: 80
- host: echo2.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: echo2
port:
number: 80
编辑完 Ingress 规则后,保存并关闭文件。
在这里,我们指定要创建一个名为 echo-ingress 的 Ingress Resource,并根据 Host 标头路由流量。 HTTP 请求主机头指定目标服务器的域名。 要了解有关主机请求标头的更多信息,请参阅 Mozilla 开发人员网络 定义页面 。 主机 echo1.example.com 的请求将被定向到步骤 1 中设置的 echo1 后端,主机 echo2.example.com 的请求将被定向到 echo2 后端。
您现在可以使用 kubectl 创建 Ingress:
kubectl apply -f echo_ingress.yaml
您将看到以下确认 Ingress 创建的输出:
Outputingress.networking.k8s.io/echo-ingress created
要测试 Ingress,请导航到您的 DNS 管理服务并为 echo1.example.com 和 echo2.example.com 创建指向 DigitalOcean 负载均衡器的外部 IP 的 A 记录。 负载均衡器的外部 IP 是我们在上一步中获取的 ingress-nginx 服务的外部 IP 地址。 如果您使用 DigitalOcean 管理您域的 DNS 记录,请参阅 如何管理 DNS 记录 以了解如何创建 A 记录。
创建必要的 echo1.example.com 和 echo2.example.com DNS 记录后,您可以使用 curl 命令行实用程序测试您创建的入口控制器和资源。
从您的本地计算机,curl echo1 服务:
curl echo1.example.com
您应该从 echo1 服务获得以下响应:
Outputecho1
这确认您对 echo1.example.com 的请求正通过 Nginx 入口正确路由到 echo1 后端服务。
现在,对 echo2 服务执行相同的测试:
curl echo2.example.com
您应该从 echo2 服务获得以下响应:
Outputecho2
这确认您对 echo2.example.com 的请求正通过 Nginx 入口正确路由到 echo2 后端服务。
至此,您已经成功设置了一个最小的 Nginx Ingress 来执行基于虚拟主机的路由。 在下一步中,我们将安装 cert-manager 为我们的 Ingress 提供 TLS 证书并启用更安全的 HTTPS 协议。
第 4 步 — 安装和配置 Cert-Manager
在这一步中,我们将 cert-manager 的 v1.7.1 安装到我们的集群中。 cert-manager 是一个 Kubernetes 插件,它提供来自 Let's Encrypt 和其他证书颁发机构 (CA) 的 TLS 证书并管理它们的生命周期。 证书可以通过注解 Ingress 资源、将 tls 部分附加到 Ingress 规范并配置一个或多个 Issuers 或 ClusterIssuers 来指定您的首选来自动请求和配置证书颁发机构。 要了解有关 Issuer 和 ClusterIssuer 对象的更多信息,请参阅 Issuers 上的官方 cert-manager 文档。
按照官方 安装说明 安装 cert-manager 及其 自定义资源定义 (CRD),例如 Issuers 和 ClusterIssuers。 请注意,将创建一个名为 cert-manager 的命名空间,其中将创建 cert-manager 对象:
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.7.1/cert-manager.yaml
您应该看到以下输出:
Outputcustomresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created . . . deployment.apps/cert-manager-webhook created mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
要验证我们的安装,请检查 cert-manager 命名空间以运行 pod:
kubectl get pods --namespace cert-manager
OutputNAME READY STATUS RESTARTS AGE cert-manager-578cd6d964-hr5v2 1/1 Running 0 99s cert-manager-cainjector-5ffff9dd7c-f46gf 1/1 Running 0 100s cert-manager-webhook-556b9d7dfd-wd5l6 1/1 Running 0 99s
这表明 cert-manager 安装成功。
在我们开始为我们的 echo1.example.com 和 echo2.example.com 域颁发证书之前,我们需要创建一个颁发者,它指定可以从中获取签名 x509 证书的证书颁发机构。 在本指南中,我们将使用 Let's Encrypt 证书颁发机构,它提供免费的 TLS 证书,并提供用于测试证书配置的暂存服务器和用于推出可验证 TLS 证书的生产服务器。
让我们创建一个测试 ClusterIssuer 以确保证书供应机制正常运行。 ClusterIssuer 不是命名空间范围的,可以由任何命名空间中的 Certificate 资源使用。
在您喜欢的文本编辑器中打开一个名为 staging_issuer.yaml 的文件:
nano staging_issuer.yaml
粘贴以下 ClusterIssuer 清单:
staging_issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
namespace: cert-manager
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: your_email_address_here
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
在这里,我们指定要创建一个名为 letsencrypt-staging 的 ClusterIssuer,并使用 Let's Encrypt 登台服务器。 我们稍后将使用生产服务器来推出我们的证书,但生产服务器会限制针对它的请求,因此出于测试目的,您应该使用暂存 URL。
然后我们指定一个电子邮件地址来注册证书,并创建一个名为 letsencrypt-staging 的 Kubernetes Secret 来存储 ACME 帐户的私钥。 我们还使用 HTTP-01 挑战机制。 要了解有关这些参数的更多信息,请参阅 Issuers 上的官方 cert-manager 文档。
使用 kubectl 推出 ClusterIssuer:
kubectl create -f staging_issuer.yaml
您应该看到以下输出:
Outputclusterissuer.cert-manager.io/letsencrypt-staging created
我们现在将重复此过程以创建生产 ClusterIssuer。 请注意,只有在对上一步中配置的 Ingress 资源进行注释和更新后,才会创建证书。
在您喜欢的编辑器中打开一个名为 prod_issuer.yaml 的文件:
nano prod_issuer.yaml
粘贴以下清单:
prod_issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: cert-manager
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: your_email_address_here
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
请注意不同的 ACME 服务器 URL 和 letsencrypt-prod 密钥名称。
完成编辑后,保存并关闭文件。
使用 kubectl 推出此发行者:
kubectl create -f prod_issuer.yaml
您应该看到以下输出:
Outputclusterissuer.cert-manager.io/letsencrypt-prod created
现在我们已经创建了 Let's Encrypt staging 和 prod ClusterIssuers,我们准备修改上面创建的 Ingress Resource 并为 echo1.example.com 和 echo2.example.com 路径启用 TLS 加密。
如果您使用的是 DigitalOcean Kubernetes,您首先需要实现 一种解决方法,以便 Pod 可以使用 Ingress 与其他 Pod 通信。 如果你没有使用 DigitalOcean Kubernetes,你可以跳到 Step 6。
第 5 步 — 通过负载均衡器启用 Pod 通信(可选)
在从 Let's Encrypt 提供证书之前,cert-manager 首先执行自检以确保 Let's Encrypt 可以访问验证您的域的 cert-manager Pod。 要在 DigitalOcean Kubernetes 上通过此检查,您需要通过 Nginx Ingress 负载均衡器启用 Pod-Pod 通信。
为此,我们将创建一个指向云负载均衡器外部 IP 的 DNS A 记录,并使用此子域注释 Nginx Ingress Service 清单。
首先导航到您的 DNS 管理服务并为 workaround.example.com 创建一个指向 DigitalOcean 负载均衡器的外部 IP 的 A 记录。 负载均衡器的外部 IP 是我们在步骤 2 中获取的 ingress-nginx 服务的外部 IP 地址。 如果您使用 DigitalOcean 管理您域的 DNS 记录,请参阅 如何管理 DNS 记录 了解如何创建 A 记录。 在这里,我们使用子域 workaround,但您可以自由使用您喜欢的任何子域。
现在您已经创建了指向 Ingress 负载均衡器的 DNS 记录,请使用 do-loadbalancer-hostname 注释来注释 Ingress LoadBalancer 服务。 在您喜欢的编辑器中打开一个名为 ingress_nginx_svc.yaml 的文件,然后粘贴到以下 LoadBalancer 清单中:
ingress_nginx_svc.yaml
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: 'true'
service.beta.kubernetes.io/do-loadbalancer-hostname: "workaround.example.com"
labels:
helm.sh/chart: ingress-nginx-4.0.6
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.1.1
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
此服务清单是从您在步骤 2 中安装的完整 Nginx Ingress 清单文件 中提取的。 一定要复制你安装的Nginx Ingress版本对应的Service manifest; 在本教程中,这是 1.1.1。 还要确保将 do-loadbalancer-hostname 注释设置为 workaround.example.com 域。
完成后,保存并关闭文件。
使用 kubectl apply 修改正在运行的 ingress-nginx-controller 服务:
kubectl apply -f ingress_nginx_svc.yaml
您应该看到以下输出:
Outputservice/ingress-nginx-controller configured
这确认您已注释 ingress-nginx-controller 服务,并且集群中的 Pod 现在可以使用此 ingress-nginx-controller 负载均衡器相互通信。
第 6 步 — 颁发登台和生产 Let's Encrypt 证书
要为我们的域颁发暂存 TLS 证书,我们将使用在步骤 4 中创建的 ClusterIssuer 注释 echo_ingress.yaml。 这将使用 ingress-shim 为 Ingress 清单中指定的域自动创建和颁发证书。
在您喜欢的编辑器中打开 echo_ingress.yaml:
nano echo_ingress.yaml
将以下内容添加到 Ingress 资源清单:
echo_ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-staging"
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- echo1.example.com
- echo2.example.com
secretName: echo-tls
rules:
- host: echo1.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: echo1
port:
number: 80
- host: echo2.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: echo2
port:
number: 80
这里我们添加一个注解,将 cert-manager ClusterIssuer 设置为 letsencrypt-staging,即第 4 步创建的测试证书 ClusterIssuer。 我们还添加了一个描述入口类型的注释,在本例中为 nginx。
我们还添加了一个 tls 块来指定我们要为其获取证书的主机,并指定一个 secretName。 此密钥将包含 TLS 私钥和颁发的证书。 请务必将 example.com 替换为您为其创建 DNS 记录的域。
完成更改后,保存并关闭文件。
我们现在将使用 kubectl apply 将此更新推送到现有的 Ingress 对象:
kubectl apply -f echo_ingress.yaml
您应该看到以下输出:
Outputingress.networking.k8s.io/echo-ingress configured
您可以使用 kubectl describe 来跟踪您刚刚应用的 Ingress 更改的状态:
kubectl describe ingress
OutputEvents: Type Reason Age From Message ---- ------ ---- ---- ------- Normal UPDATE 6s (x3 over 80m) nginx-ingress-controller Ingress default/echo-ingress Normal CreateCertificate 6s cert-manager Successfully created Certificate "echo-tls"
成功创建证书后,您可以在其上运行 describe 以进一步确认其成功创建:
kubectl describe certificate
您应该在 Events 部分看到以下输出:
OutputEvents: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Requested 64s cert-manager Created new CertificateRequest resource "echo-tls-vscfw" Normal Issuing 40s cert-manager The certificate has been successfully issued
这确认 TLS 证书已成功颁发,并且 HTTPS 加密现在对配置的两个域处于活动状态。
我们现在准备向后端 echo 服务器发送请求,以测试 HTTPS 是否正常运行。
运行以下 wget 命令向 echo1.example.com 发送请求并将响应头打印到 STDOUT:
wget --save-headers -O- echo1.example.com
您应该看到以下输出:
Output. . . HTTP request sent, awaiting response... 308 Permanent Redirect . . . ERROR: cannot verify echo1.example.com's certificate, issued by ‘ERROR: cannot verify echo1.example.com's certificate, issued by ‘CN=(STAGING) Artificial Apricot R3,O=(STAGING) Let's Encrypt,C=US’: Unable to locally verify the issuer's authority. To connect to echo1.example.com insecurely, use `--no-check-certificate'.
这表明 HTTPS 已成功启用,但证书无法验证,因为它是 Let's Encrypt 登台服务器颁发的假临时证书。
现在我们已经使用这个临时假证书测试了一切正常,我们可以为两个主机 echo1.example.com 和 echo2.example.com 推出生产证书。 为此,我们将使用 letsencrypt-prod ClusterIssuer。
更新 echo_ingress.yaml 以使用 letsencrypt-prod:
nano echo_ingress.yaml
对文件进行以下更改:
echo_ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- echo1.example.com
- echo2.example.com
secretName: echo-tls
rules:
- host: echo1.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: echo1
port:
number: 80
- host: echo2.example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: echo2
port:
number: 80
在这里,我们将 ClusterIssuer 名称更新为 letsencrypt-prod。
对更改感到满意后,保存并关闭文件。
使用 kubectl apply 展开更改:
kubectl apply -f echo_ingress.yaml
Outputingress.networking.k8s.io/echo-ingress configured
等待几分钟,让 Let's Encrypt 生产服务器颁发证书。 您可以使用 certificate 对象上的 kubectl describe 跟踪其进度:
kubectl describe certificate echo-tls
看到以下输出后,证书已成功颁发:
Output Normal Issuing 28s cert-manager Issuing certificate as Secret was previously issued by ClusterIssuer.cert-manager.io/letsencrypt-staging Normal Reused 28s cert-manager Reusing private key stored in existing Secret resource "echo-tls" Normal Requested 28s cert-manager Created new CertificateRequest resource "echo-tls-49gmn" Normal Issuing 2s (x2 over 4m52s) cert-manager The certificate has been successfully issued
我们现在将使用 curl 执行测试,以验证 HTTPS 是否正常工作:
curl echo1.example.com
您应该看到以下内容:
Output<html> <head><title>308 Permanent Redirect</title></head> <body> <center><h1>308 Permanent Redirect</h1></center> <hr><center>nginx/1.15.9</center> </body> </html>
这表明 HTTP 请求被重定向以使用 HTTPS。
在 https://echo1.example.com 上运行 curl:
curl https://echo1.example.com
您现在应该看到以下输出:
Outputecho1
您可以使用详细的 -v 标志运行前面的命令,以深入了解证书握手并验证证书信息。
至此,您已经使用 Let's Encrypt 证书为您的 Nginx Ingress 成功配置了 HTTPS。
结论
在本指南中,您将设置一个 Nginx 入口来负载平衡并将外部请求路由到 Kubernetes 集群内的后端服务。 您还通过安装 cert-manager 证书配置程序并为两个主机路径设置 Let's Encrypt 证书来保护 Ingress。
Nginx Ingress Controller 有很多替代品。 要了解更多信息,请参阅 Kubernetes 官方文档中的 Ingress 控制器。
有关使用 Helm Kubernetes 包管理器推出 Nginx 入口控制器的指南,请参阅 如何使用 Helm 在 DigitalOcean Kubernetes 上设置 Nginx 入口。