如何使用 cert-manager、Traefik 和 Let's Encrypt 在 Kubernetes 中确保网站安全

作者选择了 多样性在技术基金作为 写给捐款计划的一部分接受捐款。

介绍

Kubernetes是一个受欢迎的方式来托管网站和其他服务,这些服务受益于其可靠性和可扩展性。随着越来越多的网站与敏感数据(如个人信息或密码)互动,浏览器开始要求所有网站使用 TLS来确保他们的流量。然而,管理托管基于TLS的网站所需的所有移动部分可能很难,从获得TLS证书到及时更新这些证书并配置您的服务器使用它们。

幸运的是,您可以在您的 Kubernetes 集群中运行服务,以便为您管理许多此类复杂性。您可以使用 Traefik Proxy(发音为流量)作为网络代理,使用 cert-manager作为获取和管理安全证书的服务。 使用这些服务与 Let's Encrypt,免费和自动安全证书的提供商,减少了管理您的证书的负担,通常只需要进行初始设置。

在本教程中,您将在您的 Kubernetes 集群中设置 cert-manager、Traefik 和 Let's Encrypt,以及示例网站服务,以自动获得、更新和使用安全证书。

如果您正在寻找一个管理的Kubernetes托管服务,请查看我们的简单的,用于增长的管理的Kubernetes服务(https://www.digitalocean.com/products/kubernetes)。

前提条件

步骤 1 — 在您的集群中设置 cert-manager

传统上,在为网站设置安全证书时,您需要生成 证书签名请求并支付一个受信任的 证书机构为您生成证书。

然而,随着 Let's Encrypt在2014年创建,现在可以通过自动化流程获得免费证书,这些证书仅有效几个月而不是一年,因此使用自动系统更新这些证书是必需的。

在本节中,您将设置 cert-manager 以在自己的cert-manager名称空间中在您的集群中运行。

首先,使用「kubectl」与 cert-manager 的发布文件安装 cert-manager(https://cert-manager.io/docs/installation/):

1kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml

默认情况下,cert-manager 将安装在其自己的名称空间中,名为 cert-manager. 随着文件的应用,将在您的集群中创建一系列资源,这些资源将出现在您的输出中(部分输出因长度而删除):

 1[secondary_label Output]
 2namespace/cert-manager created
 3customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
 4customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
 5
 6# some output excluded
 7
 8deployment.apps/cert-manager-cainjector created
 9deployment.apps/cert-manager created
10deployment.apps/cert-manager-webhook created
11mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
12validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created

在本节中,您安装了 cert-manager 来管理您的安全证书. 现在,您需要设置一种方式来告诉 cert-manager 您希望您的证书如何发行。

步骤 2 – 配置 Let’s Encrypt 证书发行器

使用安全的证书为您的网站是告诉您的用户他们可以信任他们正在浏览的网站来自您的服务器的一种方式。 要做到这一点,证书机构必须验证您拥有该证书的域。 让我们加密使用一个名为 ACME的标准来做到这一点,该标准使用 挑战来证明您拥有您正在生成证书的域。 cert-manager 支持各种提供商的 DNS 和 HTTP 挑战,但在本教程中,您将使用 DNS-01 挑战与 DigitalOcean 的 DNS 提供商。

在本节中,您将为您的集群创建一个 ClusterIssuer,以告知 cert-manager 如何从 Let's Encrypt 发行证书,以及使用哪些凭证来完成 Let's Encrypt 所需的 DNS 挑战。

<$>[注] **注:**本教程假定您正在使用DigitalOcean为您的DNS提供商,并将ClusterIssuer配置为此假设。

有关 cert-manager 支持的其他提供商的更多信息,请参阅 cert-manager 文档中的 ACME 介绍

在为您的集群创建ClusterIssuer之前,您需要为您的集群配置创建一个目录。 使用mkdir命令创建一个目录,然后cd输入该目录:

1mkdir tutorial-cluster-config
2cd tutorial-cluster-config

一旦您创建了目录,您将需要为您创建的DNS访问的 个人访问代币作为本教程的先决条件的一部分。

要将您的访问令牌保存在 Kubernetes 中的秘密中,您需要将其加密到 base-64

1echo -n 'dop_v1_4321...' | base64

此命令将将您的访问代码从echo发送到base64命令中,以便加密它。

1[secondary_label Output]
2ZG9wX3YxX3RoaXNpc25vdGFyZWFsdG9rZW5idXRpbXB1dHRpbmdhYnVuY2hvZnN0dWZmaW5oZXJlc29sZW5ndGhzbWF0Y2g=

此输出是您的 base-64 加密访问代码. 复制此,因为您将下次使用它。

使用nano或您最喜欢的编辑器,创建并打开名为lets-encrypt-do-dns.yaml的新文件:

1nano lets-encrypt-do-dns.yaml

添加以下代码来创建一个Kubernetes秘密,请确保在访问代码字段中使用您的 base-64 加密访问代码:

1[label tutorial-cluster-config/lets-encrypt-do-dns.yaml]
2apiVersion: v1
3kind: Secret
4metadata:
5  namespace: cert-manager
6  name: lets-encrypt-do-dns
7data:
8  access-token: ZG9wX3Y...

这个秘密将被称为let-encrypt-do-dns,并存储在cert-manager的名称空间中。在数据部分中,您将包含您之前创建的 base-64 加密的访问代码

接下来,保存您的文件并使用kubectl应用将其应用到集群中:

1kubectl apply -f lets-encrypt-do-dns.yaml

在输出中,您将收到一个消息,即您的秘密已在集群中创建:

1[secondary_label Output]
2secret/lets-encrypt-do-dns created

现在,创建一个名为lets-encrypt-issuer.yaml的新文件,以包含 cert-manager 的ClusterIssuer,您将使用它来发行您的 Let's Encrypt 证书:

1nano lets-encrypt-issuer.yaml

添加以下行,在spec.acme.email字段中输入您的电子邮件地址(这是 Let's Encrypt 将与其提供的证书关联的地址):

 1[label tutorial-cluster-config/lets-encrypt-issuer.yaml]
 2apiVersion: cert-manager.io/v1
 3kind: ClusterIssuer
 4metadata:
 5  name: letsencrypt-issuer
 6spec:
 7  acme:
 8    email: your_email_address
 9    server: https://acme-v02.api.letsencrypt.org/directory
10    privateKeySecretRef:
11      name: letsencrypt-issuer-account-key
12    solvers:
13      - selector: {}
14        dns01:
15          digitalocean:
16            tokenSecretRef:
17              name: lets-encrypt-do-dns
18              key: access-token

在前两行中,apiVersionkind表示这个Kubernetes资源是Cert-manager的ClusterIssuer。接下来,你将其命名为letsencrypt-issuer

接下来,在spec部分中,您定义了acme挑战部分,以告知Cert-managerClusterIssuer应该使用ACME使用letsencrypt-issuer发行证书。email是您的电子邮件地址,让Let’s Encrypt发送任何与证书相关的通信,如更新提醒,如果存在问题,而Cert-manager不会及时更新它们。服务器字段指定了请求ACME挑战的联系人URL,并设置为生产Let’s Encrypt URL。在服务器字段之后,您将包含PrivateKeySecretRefret字段,其中包含Cert-manager将使用的秘密名称来存储其生成的私密密钥。

spec.acme部分中最重要的部分之一是解决方案部分。在本节中,您将为letsencrypt-issuer配置所需的ACME挑战解决方案。在这种情况下,您将包括一个单一的解决方案,即dns01解决方案。解决方案配置的第一部分,即选择器,配置为{},意思是任何东西。如果您希望在集群中使用其他证书的不同解决方案,您可以在同一发行器中设置额外的选择器。

dns01部分中,您添加了一个digitalocean部分,表示发行人应该使用DigitalOcean作为DNS-01解决方案。如果您使用的是不同的云提供商,这就是您要配置的位置(https://cert-manager.io/docs/configuration/acme/dns01/)。在这个部分中,您添加了一个tokenSecretRef来引用您之前创建的Secretlet-encrypt-do-dns``access-token字段。

一旦您保存了发行文件,请使用kubectl应用将其应用到集群中:

1kubectl apply -f lets-encrypt-issuer.yaml

输出将确认名为letsencrypt-issuerClusterIssuer已被创建:

1[secondary_label Output]
2clusterissuer.cert-manager.io/letsencrypt-issuer created

在本节中,您设置了 cert-manager,并将其配置为从 Let's Encrypt 发行证书,但是没有任何证书被请求,没有任何服务为您的网站,并且您在集群中没有运行网站服务。

步骤 3 — 使用 Traefik 的负载平衡器

Traefik是一个开源的 代理服务,旨在与Kubernetes集成网站流量和来自集群的其他网络流量。随着网络流量的增长,您可能需要增加集群中运行的Treefik实例的数量,以便在不同的Kubernetes节点中分散资源使用。

在本节中,您将安装 Traefik 到您的集群中,并准备将其用于 cert-manager 管理的证书和您将在步骤 5 中添加的网站,您还将设置负载平衡器,它将从集群外向您的 Traefik 服务发送入口网络流量,并为您准备处理多个 Traefik 实例,如果您选择运行它们。

首先,创建一个名称空间叫做traefik,在那里你会安装Traefik。 要做到这一点,打开名为traefik-ns.yaml的文件:

1nano traefik-ns.yaml

输入KubernetesNamespace资源:

1[label tutorial-cluster-config/traefik-ns.yaml]
2apiVersion: v1
3kind: Namespace
4metadata:
5  name: traefik

保存文件后,使用kubectl应用将其应用到您的集群:

1kubectl apply -f traefik-ns.yaml

一旦命令运行,集群的输出将确认已创建了名称空间:

1[secondary_label Output]
2namespace/traefik created

创建traefik名称空间后,您将安装 Traefik 服务本身。 为此,您将使用名为 Helm的实用程序。 Helm 是 Kubernetes 的包管理器,使安装 Kubernetes 服务与在您的计算机上安装应用程序相似。

首先,您需要将traefik Helm 存储库添加到可用的存储库中,这将允许 Helm 找到traefik包:

1helm repo add traefik https://helm.traefik.io/traefik

一旦命令完成,您将收到确认traefik存储库已被添加到您的计算机的Helm存储库:

1[secondary_label Output]
2"traefik" has been added to your repositories

接下来,更新您的图表存储库:

1helm repo update

输出将确认traefik图表存储库已更新:

1[secondary_label Output]
2Hang tight while we grab the latest from your chart repositories...
3...Successfully got an update from the "traefik" chart repository
4Update Complete. ⎈Happy Helming!⎈

最后,将traefik 安装到您在集群中创建的traefik 名称空间中:

1helm install --namespace=traefik traefik traefik/traefik

在这个命令中有很多traefik,所以让我们来谈谈一下每一个做什么。你的命令中的第一个traefik,用--namespace=traefik,告诉赫尔姆在你之前创建的traefik命名空间中安装Traefik。接下来,突出的traefik是你想要在集群中给这个 Traefik 安装的名称。这样,如果你在同一个集群中有多个 Traefik 安装,你可以给它们不同的名称,如traefik-website1traefik-website2。因为你现在在集群中只有一个 Traefik 安装,你可以使用traefik这个名称。第三个traefik/是你先前添加和想要安装的存储库。最后,最后一个traefik是你

一旦运行命令,类似以下的输出将打印到屏幕上:

1NAME: traefik
2LAST DEPLOYED: Sun Oct 2 16:32:57 2022
3NAMESPACE: traefik
4STATUS: deployed
5REVISION: 1
6TEST SUITE: None

一旦安装了 Helm 图表,Traefik 将开始在您的集群上下载。 若要查看 Traefik 是否已启动并运行,请运行kubectl get all以查看在traefik名称空间中创建的所有 Traefik 资源:

1kubectl get -n traefik all

您的输出将与下面的输出相似:

 1[secondary_label Output]
 2NAME READY STATUS RESTARTS AGE
 3pod/traefik-858bb8459f-k4ztp 1/1 Running 0 94s
 4
 5NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)                      AGE
 6service/traefik LoadBalancer 10.245.77.251   <pending>     80:31981/TCP,443:30188/TCP 94s
 7
 8NAME READY UP-TO-DATE AVAILABLE AGE
 9deployment.apps/traefik 1/1 1 1 94s
10
11NAME DESIRED CURRENT READY AGE
12replicaset.apps/traefik-858bb8459f 1 1 1 94s

根据您的群集和运行之前的命令时,某些名称和年龄可能有所不同. 如果您在服务/traefikEXTERNAL-IP下看到<pending>,请继续运行kubectl get -n traefik all命令,直到列出IP地址。EXTERNAL-IP是负载平衡器在互联网上可用的IP地址。列出IP地址后,请将该IP地址列为您的traefik_ip_address

在本节中,您已在您的集群中安装了 Traefik,并且有一个外部IP,您可以将您的网站流量导向到。

步骤 4 – 使用您的域名访问 Traefik

现在你已经在你的集群中设置了 Traefik 并通过负载平衡器在互联网上访问,你需要更新你的域的 DNS 以指向你的 Traefik 负载平衡器。 继续前,请确保你的域是 添加到你的 DigitalOcean 帐户。 cert-manager 需要能够更新你的域的 DNS 设置,使用你之前设置的访问代码。 你会使用 doctl 来设置你的域的 DNS 记录,以指向 Traefik 负载平衡器。

<$>[注] **注: **本节假定您正在使用DigitalOcean作为您的DNS主机. 如果您正在使用DigitalOcean以外的DNS主机,您仍然会创建相同的DNS记录类型,具有相同的值,但您需要参阅您的DNS主机的文档,以了解如何添加它们。

首先,为您的域名创建一个名为tutorial-proxy.your_domain的DNSA记录,指向您的traefik_ip_address:

1doctl compute domain records create your_domain --record-name tutorial-proxy --record-type A --record-data traefik_ip_address

一个DNSA记录会告诉DNS将给定的主机名称指向特定IP地址,在这种情况下,tutorial-proxy.your_domain会指向traefik_ip_address.因此,如果有人在tutorial-proxy.your_domain上请求网站,DNS服务器会将其指向traefik_ip_address

运行命令后,您将收到确认您的记录已创建:

1[secondary_label Output]
2ID Type Name Data Priority Port TTL Weight
312345678 A tutorial-proxy traefik_ip_address 0 0 1800 0

现在,创建一个CNAME类型的DNS记录,名为tutorial-service.your_domain,并将其导向到tutorial-proxy.your_domain。因为你可能在某个时候在你的群集中运行多个服务,使用一个A记录将每个域指向你的Treefik代理可以是很多工作,如果你需要更改你的代理的IP地址。使用一个CNAME告诉DNS使用它指向的域的地址。

若要创建CNAME记录,请再次使用doctl命令,请确保在--record-data中包含追溯期(.):

1doctl compute domain records create your_domain --record-name tutorial-service --record-type CNAME --record-data tutorial-proxy.your_domain.

这将创建你的tutorial-service.your_domain``CNAMEDNS记录,指向tutorial-proxy.your_domain。现在,当有人请求tutorial-service.your_domain,DNS服务器将告诉他们连接到tutorial-proxy.your_domain指向的IP地址。

运行命令后,您将看到类似于以下的输出:

1[secondary_label Output]
2ID Type Name Data Priority Port TTL Weight
312345679 CNAME tutorial-service tutorial-proxy.your_domain 0 0 1800 0

由于DigitalOcean是您的主要DNS服务器,您可以直接查询服务器,以确定是否正确设置,而不是等待互联网上的其他DNS服务器更新。

<$>[注] 注: 如果您使用的是 DigitalOcean 以外的 DNS 主机,请在此命令中将 ns1.digitalocean.com 替换为您的 DNS 主机在您的域上设置的 DNS 服务器之一。

1dig @ns1.digitalocean.com +noall +answer +domain=your_domain tutorial-proxy tutorial-service

dig是一个实用程序,直接连接到DNS服务器挖掘到DNS记录找到你正在寻找的一个。在这种情况下,你提供@ns1.digitalocean.com告诉dig你想查询ns1.digitalocean.com服务器的DNS记录。+noall +answer选项告诉dig只输出更短的响应。

接下来,使用+domain=your_domain告诉dig.your_domain添加到命令中提供的任何主机名称的末尾。 最后,tutorial-proxytutorial-service是要搜索的主机名称。

您应该收到类似于以下的输出,对 your_domaintraefik_ip_address 具有自己的值:

1[secondary_label Output]
2tutorial-proxy.your_domain.	1662	IN	A	traefik_ip_address
3tutorial-service.your_domain. 1800	IN	CNAME	tutorial-proxy.your_domain.
4tutorial-proxy.your_domain.	1800	IN	A	traefik_ip_address

输出的第一行显示,‘tutorial-proxy.your_domain’是一个指向‘traefik_ip_address’的‘A’(‘IN A’)记录。第二行确认,‘tutorial-service.your_domain’是一个指向‘tutorial-proxy.your_domain’的‘CNAME’(‘IN CNAME’)记录。最后一行是‘dig’查询,以便找到你的‘CNAME’记录指向的地址。

在本节中,您已将A类型的 DNS 记录和CNAME类型的 DNS 记录添加到您的域名中,以便网络客户端(如浏览器)知道要去哪里连接到您的 Traefik 服务。

步骤五:创建您的网站

在之前的部分中,您设置了 cert-manager 和 Traefik 来处理您的网站的安全证书,并将网络流量路由到您的 Web 服务。

为了模拟网站,您将使用nginx Docker 图像设置一个部署,它只会显示 Nginx 欢迎!页面,但这足以确保一切都正确连接并按预期工作。

首先,创建一个名为tutorial-service.yaml的文件:

1nano tutorial-service.yaml

添加以下代码,创建一个名称空间,称为教程和一个名为教程服务部署:

 1[label tutorial-cluster-config/tutorial-service.yaml]
 2apiVersion: v1
 3kind: Namespace
 4metadata:
 5  name: tutorial
 6---
 7apiVersion: apps/v1
 8kind: Deployment
 9metadata:
10  namespace: tutorial
11  name: tutorial-service
12spec:
13  replicas: 3
14  selector:
15    matchLabels:
16      app.kubernetes.io/name: tutorial-service
17      app.kubernetes.io/part-of: tutorial
18  template:
19    metadata:
20      labels:
21        app.kubernetes.io/name: tutorial-service
22        app.kubernetes.io/part-of: tutorial
23    spec:
24      containers:
25        - name: service
26          image: nginx
27          ports:
28            - containerPort: 80

类似于您之前创建的traefik命名空间,此文件中的第一个资源将在您的集群中创建一个名为教程的新命名空间。

下一个部分,即选择器,告诉Kubernetes如何找到与此部署相关的任何点子。在这种情况下,它会找到具有匹配标签的任何点子。在模板部分中,您将定义您希望每个点子看起来是什么样子。在元数据部分中提供将在选择器中匹配的标签,而在spec中,您将指定您希望在服务号的点子中使用nginx图像并在端口80上听到网络连接的一个容器。

一旦您保存了更改,请将其应用到集群:

1kubectl apply -f tutorial-service.yaml

输出将确认已创建了教程名称空间和教程服务部署:

1[secondary_label Output]
2namespace/tutorial created
3deployment.apps/tutorial-service created

要检查部署是否正在运行,您可以使用kubectl get pods命令列出在教程名称空间中运行的 pods:

1kubectl get -n tutorial pods

类似于以下的输出将打印:

1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3tutorial-service-568b4f8477-hpstl 1/1 Running 0 2m15s
4tutorial-service-568b4f8477-mcpqd 1/1 Running 0 2m15s
5tutorial-service-568b4f8477-mg8mb 1/1 Running 0 2m15s

你应该找到一个列表的三个 pods 与状态运行和随机名称之后的教程-服务-

现在你的网页服务正在运行,你需要一种方式来通过所有三个子段发送流量. 在Kubernetes中,你使用一个服务来完成这项工作。

要创建你的服务,请重新打开你的tutorial-service.yaml文件,并在末尾添加一个服务:

 1[label tutorial-cluster-config/tutorial-service.yaml]
 2...
 3        - name: service
 4          image: nginx
 5          ports:
 6            - containerPort: 80
 7---
 8apiVersion: v1
 9kind: Service
10metadata:
11  namespace: tutorial
12  name: tutorial-service
13spec:
14  selector:
15    app.kubernetes.io/name: tutorial-service
16    app.kubernetes.io/part-of: tutorial
17  ports:
18    - protocol: TCP
19      port: 80
20      targetPort: 80

部署类似,您的服务有一个选择器部分,列出用于查找您要发送流量的潜艇的标签。这些标签与您在部署中的模板部分中包含的潜艇标签相匹配。

保存更改后,将服务应用于集群:

1kubectl apply -f tutorial-service.yaml

这次在输出中,名称空间和部署列为未更改(因为您没有对它们进行任何更改),并且教程服务创建:

1[secondary_label Output]
2namespace/tutorial unchanged
3deployment.apps/tutorial-service unchanged
4service/tutorial-service created

创建教程服务后,您可以通过使用kubectl port-forward命令来测试您是否可以访问该服务,以便在本地计算机上提供该服务:

1kubectl port-forward -n tutorial service/tutorial-service 8888:80

此命令将发送到本地计算机的端口8888的任何流量转发到群集中的辅导服务端口80。在您的Kubernetes群集中,您设置了辅导服务``服务,以便在端口80上收听连接,您需要一种方式来从本地计算机发送流量到群集中的那个服务。在命令中,您指定要在辅导名空间辅导服务服务/辅导服务,然后提供组合的端口88:88:80。第一个列出的端口是您的本地计算机会收听的端口,而第二个端口(在群集中:之后)是服务/辅导服务上的端口,那里将发送流量。当您在本地计算机上发送流量到

当您运行命令时,您将收到类似于以下的输出:

1[secondary_label Output]
2Forwarding from 127.0.0.1:8888 -> 80
3Forwarding from [::1]:8888 -> 80

请注意,该命令不会返回,并将继续运行以传输流量。

若要对您的服务提出请求,请在您的计算机上打开第二台终端,并在端口8888上的计算机使用弯曲命令:

1[environment second]
2curl http://localhost:8888/

此命令通过您的转发端口(‘8888’)将HTTP请求发送到集群的教程服务,并返回包含 Nginx欢迎页面的HTML响应:

 1[environment second]
 2[secondary_label Output]
 3<!DOCTYPE html>
 4<html>
 5<head>
 6<title>Welcome to nginx!</title>
 7<style>
 8html { color-scheme: light dark; }
 9body { width: 35em; margin: 0 auto;
10font-family: Tahoma, Verdana, Arial, sans-serif; }
11</style>
12</head>
13<body>
14<h1>Welcome to nginx!</h1>
15<p>If you see this page, the nginx web server is successfully installed and
16working. Further configuration is required.</p>
17
18<p>For online documentation and support please refer to
19<a href="http://nginx.org/">nginx.org</a>.<br/>
20Commercial support is available at
21<a href="http://nginx.com/">nginx.com</a>.</p>
22
23<p><em>Thank you for using nginx.</em></p>
24</body>
25</html>

在您的原始终端中,您现在可以按CONTROL+C来停止port-forward命令,您还会看到一些额外的输出,当您连接curl时:

1[secondary_label Output]
2Forwarding from 127.0.0.1:8888 -> 80
3Forwarding from [::1]:8888 -> 80
4Handling connection for 8888

在本节中,您使用部署服务在集群中设置了一个nginx网络服务,然后使用kubectl port-forwardcurl命令来确保nginx正常运行。

步骤6 – 让您的网站服务可用和安全

即使你有所有单独的服务在你的集群中运行,但它们都相对独立运行. cert-manager 只是坐在那里,Traefik 不知道它应该服务的任何网站,你的 Nginx 网站只有在您向集群转移时才可用。

首先,重新打开tutorial-service.yaml:

1nano tutorial-service.yaml

在您之前添加的教程服务``服务之后,在文件的末尾添加一个Ingress,请确保更新配置以自己的域名,并在开始时包含---,以便将您的Ingress资源从上面的服务资源分开:

 1[label tutorial-cluster-config/tutorial-service.yaml]
 2...
 3---
 4apiVersion: networking.k8s.io/v1
 5kind: Ingress
 6metadata:
 7  name: tutorial-service-ingress
 8  namespace: tutorial
 9  annotations:
10    traefik.ingress.kubernetes.io/router.entrypoints: websecure
11    traefik.ingress.kubernetes.io/router.tls: "true"
12    cert-manager.io/cluster-issuer: letsencrypt-issuer
13spec:
14  rules:
15    - host: tutorial-service.your_domain
16      http:
17        paths:
18          - path: /
19            pathType: Prefix
20            backend:
21              service:
22                name: tutorial-service
23                port:
24                  number: 80
25  tls:
26    - secretName: tutorial-service-cert
27      hosts:
28        - tutorial-service.your_domain

这些行包括规则和注释,以说明一切如何匹配在一起. 该Ingress资源包括引用Treefik,Cert-Manager和您的教程服务

traefik.ingress.kubernetes.io/router.entrypoints的注释告诉Traefik,此Ingress的流量应该通过websecure的入口点可用。

下一个注释,‘traefik.ingress.kubernetes.io/router.tls’,设置为‘true’,告诉 Traefik只响应HTTPS流量,而不是HTTP流量。

最后一个注释,cert-manager.io/cluster-issuer被设置为letsencrypt-issuer,以告知Cert-manager您想要在发行此Ingress的安全证书时使用的发行商。

Ingressspec.rules部分中,你包括一个路由流量发送到Ingress的规则。它说,对于名为tutorial-service.your_domain主机,使用http用于给定路径。唯一包含的路径是根/路径,具有PathTypePrefix,这意味着发送的任何流量都应该发送到提供的后端

Ingressspec.tls 部分提供了 cert 管理员需要请求和发行您的安全证书的信息,以及 Traefik 需要使用这些证书的信息。 secretName 是 Kubernetes 的 Secret,在那里 cert 管理员会放置发行的安全证书,而 Secret Traefik 会用来加载发行的证书。 hosts 部分列出了 cert 管理员会请求证书的主机名称。 在这种情况下,它只会是 tutorial-service.your_domain 主机名称,但如果您希望该网站响应多个主机名称,您还可以包括其他您拥有的。

保存您创建的Ingress后,使用kubectl应用再次将新资源应用到您的集群:

1kubectl apply -f tutorial-service.yaml

Ingress将被创建,其他资源将保持不变:

1[secondary_label Output]
2namespace/tutorial unchanged
3deployment.apps/tutorial-service unchanged
4service/tutorial-service unchanged
5ingress.networking.k8s.io/tutorial-service-ingress created

一旦Ingress被创建,Traefik将开始自我配置,Cert-manager将开始挑战/响应过程,以获得证书发行。

1kubectl get -n tutorial certificates

您将收到类似于以下的输出:

1[secondary_label Output]
2NAME READY SECRET AGE
3tutorial-service-cert False tutorial-service-cert 12m

如果READY字段是False,则证书尚未发行,您可以继续运行相同的命令,以确保它转换为True

<$>[注] 注: 如果您的证书在 10-15 分钟后没有发出,可以帮助 cert-manager 查看日志消息,看看是否有问题要求该证书。

1kubectl logs -n cert-manager deployment/cert-manager --tail=10 -f

美元

一旦您的证书准备好了,您可以使用curl对您的集群进行 HTTPS 请求:

1curl https://tutorial-service.your_domain

<$>[注] 注: 根据您更新 DNS 记录的时间和 DNS 记录在互联网的 DNS 服务器中传播的时间,您可能会看到一个错误,即您的域名无法找到或错误地点。

1curl https://tutorial-service.your_domain --resolve 'tutorial-service.your_domain:443:traefik_ip_address'

這個命令告訴「curl」命令使用「--resolve」選項,以代替「traefik_ip_address」在「443」端口上的「tutorial-service.your_domain」的任何 DNS 解析度。

在您的输出中,您将从先前的端口转发中获得相同的Nginx欢迎!页面,但这次它可以通过互联网访问:

 1[secondary_label Output]
 2<!DOCTYPE html>
 3<html>
 4<head>
 5<title>Welcome to nginx!</title>
 6<style>
 7html { color-scheme: light dark; }
 8body { width: 35em; margin: 0 auto;
 9font-family: Tahoma, Verdana, Arial, sans-serif; }
10</style>
11</head>
12<body>
13<h1>Welcome to nginx!</h1>
14<p>If you see this page, the nginx web server is successfully installed and
15working. Further configuration is required.</p>
16
17<p>For online documentation and support please refer to
18<a href="http://nginx.org/">nginx.org</a>.<br/>
19Commercial support is available at
20<a href="http://nginx.com/">nginx.com</a>.</p>
21
22<p><em>Thank you for using nginx.</em></p>
23</body>
24</html>

但是,如果您尝试请求您的网站的 HTTP 版本,您将不会收到回复:

1curl http://tutorial-service.your_domain

404错误会加载:

1[secondary_label Output]
2404 page not found

由于您在Ingress中配置了您的网站以不响应HTTP流量,所以Traefik从来没有在该地址设置一个网站,并且会返回一个404错误,这可能会使用户感到困惑,如果他们知道他们应该看到一个网站,所以许多管理员会将他们的服务器配置为自动重定向HTTP流量到HTTPS网站。

1helm upgrade --namespace=traefik traefik traefik/traefik --set 'ports.web.redirectTo=websecure'

选项 `--set 'ports.web.redirectTo=websecure' 告诉 Traefik 重新配置以自动进行重定向。

您应该看到一个类似于下面的消息,即traefik安装已被升级:

1[secondary_label Output]
2Release "traefik" has been upgraded. Happy Helming!
3NAME: traefik
4LAST DEPLOYED: Sun Oct 2 19:17:34 2022
5NAMESPACE: traefik
6STATUS: deployed
7REVISION: 2
8TEST SUITE: None

现在,如果您向您的 HTTP 位置提出请求,您将收到输出,表示该网站已被移动:

1curl http://tutorial-service.your_domain

这个答案预计:

1[secondary_label Output]
2Moved Permanently

由于您希望您的所有流量都转到您的 HTTPS 网站,所以 Traefik 现在正在以您的名义从 HTTP 网站返回自动重定向到 HTTPS 网站。 网页浏览器将自动执行此重定向,但‘curl’需要一个额外的选项,‘-L’,告诉它遵循重定向。 更新您的‘curl’命令以‘-L’选项来遵循重定向:

1curl -L http://tutorial-service.your_domain

输出将包含来自您的 HTTPS 网站的 Nginx 欢迎页面:

 1[secondary_label Output]
 2<!DOCTYPE html>
 3<html>
 4<head>
 5<title>Welcome to nginx!</title>
 6<style>
 7html { color-scheme: light dark; }
 8body { width: 35em; margin: 0 auto;
 9font-family: Tahoma, Verdana, Arial, sans-serif; }
10</style>
11</head>
12<body>
13<h1>Welcome to nginx!</h1>
14<p>If you see this page, the nginx web server is successfully installed and
15working. Further configuration is required.</p>
16
17<p>For online documentation and support please refer to
18<a href="http://nginx.org/">nginx.org</a>.<br/>
19Commercial support is available at
20<a href="http://nginx.com/">nginx.com</a>.</p>
21
22<p><em>Thank you for using nginx.</em></p>
23</body>
24</html>

此输出确认重定向按预期工作。

在本节中,您将Cert-manager、Traefik 和您的 Nginx 网站连接在一起,使用 Kubernetes 的Ingress资源,您还更新了您的 Traefik 配置以将 HTTP 流量重定向到 HTTPS 网站,以确保用户可以找到您的网站。

结论

在本教程中,您在您的 Kubernetes 集群中安装了几个不同的服务,以便更容易运行具有安全证书的网站。您安装了 cert-manager 服务,以处理 Let's Encrypt 发行的 TLS 证书的生命周期。您安装了 Traefik,以使您的网站在您的集群之外可用,并使用 Let's Encrypt 发行的 TLS 证书。最后,您在您的集群中创建了一个 Nginx 网站,以测试您的 cert-manager 和 Traefik 配置。

现在,您已经在集群中配置了 cert-manager 和 Traefik,您还可以设置更多的网站,具有不同的Ingress资源,以便使用单个 cert-manager 和 Traefik 安装来服务同一集群的多个网站。

您可以阅读 Traefik Proxy 文档 有关 Traefik 在您的集群中可以提供的不同功能的更多信息。

要继续配置您的 Kubernetes 集群,请参阅我们的其他 Kubernetes 教程

Published At
Categories with 技术
comments powered by Disqus