最新:在 TwitterMastodon

使用 Venafi 保护 Ingress

本指南将引导您了解如何使用 Venafi Issuer 类型保护 Kubernetes Ingress 资源。

在逐步操作过程中,您将学习如何

  • 使用 eksctl 创建 EKS 集群
  • 将 cert-manager 安装到 EKS 集群中
  • 部署 nginx-ingress 以公开在集群中运行的应用程序
  • 配置 Venafi Cloud Issuer
  • 配置 cert-manager 以保护您的应用程序流量

虽然本指南侧重于将 EKS 作为 Kubernetes 资源供应器,而 Venafi 作为证书颁发者,但此处步骤通常可用于其他颁发者类型。

先决条件

  • 一个 AWS 账户
  • kubectl 已安装
  • 访问公开注册的 DNS 区域
  • 一个 Venafi Cloud 账户和 API 凭据

创建 EKS 集群

如果您已经拥有正在运行的 EKS 集群,则可以跳过此步骤并继续部署 cert-manager。

eksctl 是一个使部署和管理 EKS 集群变得更容易的工具。

各种平台的安装说明可以在 eksctl 安装说明 中找到。

安装完成后,您可以通过运行以下命令创建基本集群

$ eksctl create cluster

此过程可能需要长达 20 分钟才能完成。使用 eksctl 的完整说明可以在 eksctl 使用部分 中找到。

集群创建完毕后,您应该通过运行以下命令来验证您的集群是否正常运行

$ kubectl get pods --all-namespaces
NAME READY STATUS RESTARTS AGE
aws-node-8xpkp 1/1 Running 0 115s
aws-node-tflxs 1/1 Running 0 118s
coredns-694d9447b-66vlp 1/1 Running 0 23s
coredns-694d9447b-w5bg8 1/1 Running 0 23s
kube-proxy-4dvpj 1/1 Running 0 115s
kube-proxy-tpvht 1/1 Running 0 118s

您应该看到类似上面的输出,所有 Pod 都处于运行状态。

安装 cert-manager

在 EKS 上安装 cert-manager 时,没有特殊要求需要注意,因此可以按照常规的 在 Kubernetes 上运行 指南来安装 cert-manager。

请完成安装指南,并在验证 cert-manager 已正确部署后返回此步骤。

安装 ingress-nginx

一个 Kubernetes 入口控制器 被设计为对集群中运行的软件的 HTTP 和 HTTPS 流量的访问点。ingress-nginx 控制器通过提供由您的云提供商的负载均衡器(在本例中为 网络负载均衡器 (NLB))支持的 HTTP 代理服务来实现这一点。

您可以从 ingress-nginx 文档 中获得有关 ingress-nginx 及其工作原理的更多详细信息。

要使用 ELB 部署 ingress-nginx 来公开服务,请运行以下命令

部署 AWS 特定的先决条件清单

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/aws/deploy.yaml

部署“通用” ingress-nginx 清单

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/aws/deploy.yaml

您可能需要等待长达 5 分钟才能使集群和 AWS 账户中的所有必需组件准备好。

您可以运行以下命令来确定 Amazon 分配给您的 NLB 的地址

$ kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx LoadBalancer 10.100.52.175 a8c2870a5a8a311e9a9a10a2e7af57d7-6c2ec8ede48726ab.elb.eu-west-1.amazonaws.com 80:31649/TCP,443:30567/TCP 4m10s

EXTERNAL-IP 字段可能显示 <pending> 一段时间。这表示 NLB 仍在创建中。请重试该命令,直到分配了 EXTERNAL-IP

EXTERNAL-IP 可用后,您应该运行以下命令来验证流量是否已正确路由到 ingress-nginx

$ curl http://a8c2870a5a8a311e9a9a10a2e7af57d7-6c2ec8ede48726ab.elb.eu-west-1.amazonaws.com/
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>openresty/1.15.8.1</center>
</body>
</html>

虽然上述消息通常表示错误(页面未找到),但在这种情况下,它表示流量已正确路由到 ingress-nginx 服务。

注意:尽管 AWS 应用程序负载均衡器 (ALB) 是 AWS 提供的现代负载均衡器,可以从 EKS 中配置,但在撰写本文时,alb-ingress-controller 只能为存储在 AWS 证书管理器 (ACM) 中的证书提供服务。Kubernetes 1.15 版本应解决此控制器的多个错误修复,并允许 TLS 终止支持。

配置您的 DNS 记录

现在我们的 NLB 已经配置好,我们应该将应用程序的 DNS 记录指向 NLB 的地址。

进入您的 DNS 提供商的控制台,设置一个指向您的 NLB 的 CNAME 记录。

为了演示,我们将在本指南中假设您已创建以下 DNS 条目

example.com CNAME a8c2870a5a8a311e9a9a10a2e7af57d7-6c2ec8ede48726ab.elb.eu-west-1.amazonaws.com

在您完成本教程的其余部分时,请将 example.com 替换为您自己的注册域名。

部署演示应用程序

为了演示,我们提供了一个示例部署,它是一个简单的“hello world”网站。

首先,创建一个将包含您的应用程序的新命名空间

$ kubectl create namespace demo
namespace/demo created

将以下 YAML 保存到名为 demo-deployment.yaml 的文件中

apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes
namespace: demo
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
selector:
app: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes
namespace: demo
spec:
replicas: 2
selector:
matchLabels:
app: hello-kubernetes
template:
metadata:
labels:
app: hello-kubernetes
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.5
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 8080

然后运行

kubectl apply -n demo -f demo-deployment.yaml

请注意,我们部署的服务资源类型为 ClusterIP,而不是 LoadBalancer,因为我们将使用之前部署的 ingress-nginx 来公开和保护此服务的流量。

您应该能够在 demo 命名空间中看到两个 Pod 和一个服务

kubectl get po,svc -n demo
NAME READY STATUS RESTARTS AGE
hello-kubernetes-66d45d6dff-m2lnr 1/1 Running 0 7s
hello-kubernetes-66d45d6dff-qt2kb 1/1 Running 0 7s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/hello-kubernetes ClusterIP 10.100.164.58 <none> 80/TCP 7s

请注意,我们还没有将此应用程序公开为可通过互联网访问。我们将在后面的步骤中将演示应用程序公开到互联网。

创建 Venafi Issuer 资源

cert-manager 支持 Venafi TPP 和 Venafi Cloud。

请根据您要从何处检索证书,仅执行以下部分之一。

Venafi TPP

假设您已经正确设置了 Venafi TPP 服务器,则可以创建可用于颁发证书的 Venafi Issuer 资源。

为此,您需要确保已获得 TPP 的用户名密码

为了使 cert-manager 能够验证您的 Venafi TPP 服务器并设置 Issuer 资源,您需要创建一个包含您的用户名和密码的 Kubernetes 密钥

$ kubectl create secret generic \
venafi-tpp-secret \
--namespace=demo \
--from-literal=username='YOUR_TPP_USERNAME_HERE' \
--from-literal=password='YOUR_TPP_PASSWORD_HERE'

然后,我们必须创建一个 Venafi Issuer 资源,它代表 Kubernetes 中的证书颁发机构。

将以下 YAML 保存到名为 venafi-issuer.yaml 的文件中

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: venafi-issuer
namespace: demo
spec:
venafi:
zone: "Default" # Set this to the Venafi policy zone you want to use
tpp:
url: https://venafi-tpp.example.com/vedsdk # Change this to the URL of your TPP instance
caBundle: <base64 encoded string of caBundle PEM file, or empty to use system root CAs>
credentialsRef:
name: venafi-tpp-secret

然后运行

$ kubectl apply -n demo -f venafi-issuer.yaml

运行以下命令时,您应该看到输出中的 Status 部分显示 Issuer 已准备就绪(即已成功验证与 Venafi TPP 服务器的连接)。

$ kubectl describe issuer -n demo venafi-issuer
Status:
Conditions:
Last Transition Time: 2019-07-17T15:46:00Z
Message: Venafi issuer started
Reason: Venafi issuer started
Status: True
Type: Ready
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Ready 14s cert-manager Verified issuer with Venafi server

Venafi Cloud

您可以访问 注册页面 注册 Venafi Cloud 账户。

注册后,您应该通过单击控制面板界面右上角的姓名来获取 API 密钥。

为了使 cert-manager 能够验证您的 Venafi Cloud 账户并设置 Issuer 资源,您需要创建一个包含您的 API 密钥的 Kubernetes 密钥

$ kubectl create secret generic \
venafi-cloud-secret \
--namespace=demo \
--from-literal=apikey=<API_KEY>

然后,我们必须创建一个 Venafi Issuer 资源,它代表 Kubernetes 中的证书颁发机构。

将以下 YAML 保存到名为 venafi-issuer.yaml 的文件中

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: venafi-issuer
namespace: demo
spec:
venafi:
zone: "Default" # Set this to the Venafi policy zone you want to use
cloud:
apiTokenSecretRef:
name: venafi-cloud-secret
key: apikey

然后运行

$ kubectl apply -n demo -f venafi-issuer.yaml

运行以下命令时,您应该看到输出中的 Status 部分显示 Issuer 已准备就绪(即已成功验证与 Venafi Cloud 服务的连接)。

$ kubectl describe issuer -n demo venafi-issuer
...
Status:
Conditions:
Last Transition Time: 2019-07-17T15:46:00Z
Message: Venafi issuer started
Reason: Venafi issuer started
Status: True
Type: Ready
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Ready 14s cert-manager Verified issuer with Venafi server

请求证书

现在 Issuer 已配置好,并且我们已确认其设置正确,我们可以开始请求 Kubernetes 应用程序可使用的证书。

有关如何指定和请求证书资源的完整信息,请参阅请求证书指南。

现在,我们将创建一个适用于我们域名 example.com 的基本 X.509 证书。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com-tls
namespace: demo
spec:
secretName: example-com-tls
dnsNames:
- example.com
commonName: example.com
issuerRef:
name: venafi-issuer

将此 YAML 保存到名为 example-com-tls.yaml 的文件中,然后运行

$ kubectl apply -n demo -f example-com-tls.yaml

只要您确保 Venafi Cloud 帐户的区域(在我们的示例中,我们使用“默认”区域)已配置了 CA 或包含自定义证书,cert-manager 现在就可以采取步骤来填充 example-com-tls 密钥中的证书。它通过使用 API 密钥向 Venafi Cloud 进行身份验证,然后请求与我们创建的证书资源的规范匹配的证书。

您可以运行 kubectl describe 来检查证书的进度

$ kubectl describe certificate -n demo example-com-tls
...
Status:
Conditions:
Last Transition Time: 2019-07-17T17:43:01Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
Not After: 2019-10-15T12:00:00Z
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Issuing 33s cert-manager Requesting new certificate...
Normal GenerateKey 33s cert-manager Generated new private key
Normal Validate 33s cert-manager Validated certificate request against Venafi zone policy
Normal Requesting 33s cert-manager Requesting certificate from Venafi server...
Normal Retrieve 15s cert-manager Retrieved certificate from Venafi server
Normal CertIssued 15s cert-manager Certificate issued successfully

证书签发后,您应该会看到类似于上面的事件。

然后,您应该能够看到证书已成功存储在密钥资源中

$ kubectl get secret -n demo example-com-tls
NAME TYPE DATA AGE
example-com-tls kubernetes.io/tls 3 2m47s
$ kubectl get secret example-com-tls -o 'go-template={{index .data "tls.crt"}}' | \
base64 --decode | \
openssl x509 -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0d:ce:bf:89:04:d4:41:83:f4:4c:32:66:64:fb:60:14
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=DigiCert Inc, CN=DigiCert Test SHA2 Intermediate CA-1
Validity
Not Before: Jul 17 00:00:00 2019 GMT
Not After : Oct 15 12:00:00 2019 GMT
Subject: C=US, ST=California, L=Palo Alto, O=Venafi Cloud, OU=SerialNumber, CN=example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ad:2e:66:02:20:c9:b1:6a:00:63:70:4e:22:3c:
45:63:6e:e7:fd:4c:94:7d:75:50:22:a2:01:72:99:
9c:23:04:90:51:85:4d:47:32:e4:8b:ee:b1:ea:09:
1a:de:97:5d:31:05:a2:73:73:4f:06:a3:b2:59:ee:
bc:30:f7:26:85:3d:b3:56:e4:c2:97:34:b6:ac:6d:
65:7e:a2:4e:b4:ce:f2:0a:0a:4c:d7:32:d7:5a:18:
e8:69:c6:34:28:26:36:ef:c5:bc:ae:ba:ca:d2:46:
3f:d4:61:39:66:8f:19:cc:d6:d6:10:77:af:51:93:
1b:4d:f8:d1:10:19:ab:ac:b3:7b:0b:98:58:29:e6:
a9:ac:9f:7a:dc:63:0d:51:f5:bd:9f:f3:03:2e:b3:
2d:2f:00:87:f4:e1:cd:5a:32:c6:d8:fb:49:c4:e7:
da:3f:0f:8f:bb:66:94:28:5d:99:fe:7c:f0:17:1b:
fd:3e:ed:dd:36:bf:8e:62:60:0c:85:7f:76:74:4b:
37:d9:c2:e8:74:49:04:bf:f1:83:81:cc:4f:9b:f3:
40:97:d4:dc:b6:d3:2d:dc:73:18:93:48:a5:8f:6c:
57:7f:ec:62:c0:bc:c2:b0:e9:0a:51:2d:c4:b6:87:
68:96:87:f8:9a:86:3c:6a:f1:01:ca:57:c4:07:e7:
b0:51
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:D6:4D:F9:39:60:6C:73:C3:22:F5:AD:30:0C:2F:A0:D5:CA:75:4A:2A
X509v3 Subject Key Identifier:
A3:B3:47:2C:41:5E:9C:B2:27:97:57:14:A4:2E:BA:8C:93:E7:01:65
X509v3 Subject Alternative Name:
DNS:example.com
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl3.digicert.com/DigiCertTestSHA2IntermediateCA1.crl
Full Name:
URI:http://crl4.digicert.com/DigiCertTestSHA2IntermediateCA1.crl
X509v3 Certificate Policies:
Policy: 2.16.840.1.114412.1.1
CPS: https://www.digicert.com/CPS
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
CA Issuers - URI:http://cacerts.test.digicert.com/DigiCertTestSHA2IntermediateCA1.crt
X509v3 Basic Constraints: critical
CA:FALSE
Signature Algorithm: sha256WithRSAEncryption
ae:d4:9c:8a:66:19:9e:7d:12:b7:05:c2:b6:33:b3:9c:a5:40:
47:ab:34:8d:1b:0f:51:96:de:e9:46:5a:e4:16:10:43:56:bf:
fa:f8:64:f4:cb:53:39:5b:45:ca:7f:15:d9:59:25:21:23:c4:
4d:dc:a7:f7:83:21:d2:3f:a8:0a:26:f4:ef:fa:1b:2b:7d:97:
7e:28:f3:ca:cd:b2:c4:92:f3:92:27:7f:e0:f1:ac:d6:db:4c:
10:8a:f8:6f:09:bb:b3:4f:19:06:aa:bb:74:1c:e0:51:42:f6:
8c:7d:77:f7:80:a4:03:ab:a9:ae:ae:2b:89:17:af:2f:eb:f7:
3d:61:7c:dd:e1:5d:d2:5a:c5:6a:f6:c8:92:4c:0a:b5:75:d1:
dd:39:f2:a7:a2:10:8c:6d:bf:ca:08:ad:b9:a9:df:e3:59:8f:
64:16:3c:7e:8a:6e:27:fc:49:d7:06:f0:bd:94:15:f2:fd:0f:
94:8a:b8:73:67:73:53:22:df:9d:36:e9:34:f9:2a:68:00:59:
78:6d:2d:8f:a0:0f:13:af:bd:b3:aa:8c:37:c4:22:cf:23:fb:
56:bc:4e:55:ae:3a:0a:e6:3e:b1:1a:22:71:7b:08:b8:00:41:
14:26:f6:9b:9b:72:3f:eb:dc:dd:1b:db:a8:20:fd:54:75:ae:
25:7f:80:e6

在下一步中,我们将配置您的应用程序以实际使用此新的证书资源。

公开和保护您的应用程序

现在我们已经签发了证书,我们可以使用 Kubernetes Ingress 资源公开我们的应用程序。

创建一个名为 application-ingress.yaml 的文件,并将以下内容保存到其中,用您自己的域名替换 example.com

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
namespace: demo
spec:
ingressClassName: nginx
tls:
- hosts:
- example.com
secretName: example-com-tls
rules:
- host: example.com
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: kuard
port:
number: 80

然后,您可以使用以下命令应用此资源

$ kubectl apply -n demo -f application-ingress.yaml

创建后,您应该能够在配置的 URL 上访问您的应用程序,这里是 example.com

在您的网络浏览器中导航到该地址,您应该会看到通过 Venafi 获取的证书用于保护应用程序流量。