如何在DigitalOceanKubernetes上使用Cert-Manager设置Nginx入口

来自菜鸟教程
跳转至:导航、​搜索

介绍

Kubernetes Ingresses 允许您灵活地将流量从 Kubernetes 集群外部路由到集群内部的服务。 这是使用 Ingress Resources 来完成的,它定义了将 HTTP 和 HTTPS 流量路由到 Kubernetes 服务的规则,以及 Ingress Controllers,它通过负载平衡流量并将其路由到适当的来实现规则后端服务。

流行的入口控制器包括 NginxContourHAProxyTraefik。 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 流量并将其路由到端口 5678http-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 的 echo1echo2 服务:

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 PoliciesSource 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.comecho2.example.com 创建指向 DigitalOcean 负载均衡器的外部 IP 的 A 记录。 负载均衡器的外部 IP 是我们在上一步中获取的 ingress-nginx 服务的外部 IP 地址。 如果您使用 DigitalOcean 管理您域的 DNS 记录,请参阅 如何管理 DNS 记录 以了解如何创建 A 记录。

创建必要的 echo1.example.comecho2.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 规范并配置一个或多个 IssuersClusterIssuers 来指定您的首选来自动请求和配置证书颁发机构。 要了解有关 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.comecho2.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.comecho2.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.comecho2.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 入口。