本页面介绍如何保护和优化 Google Kubernetes Engine (GKE) Ingress 的流量。您可以在客户端和负载均衡器之间配置 SSL 证书,并确保负载均衡器与后端应用之间的流量安全。在继续之前,请确保您熟悉 GKE 如何通过 HTTPS 保护 Ingress。
本页面适用于为组织设计和架构网络以及安装、配置和支持网络设备的网络专家。如需详细了解我们在Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。
保护并优化客户端与负载均衡器之间的流量
如需接受来自客户端的 HTTPS 请求,负载均衡器必须具有证书,以便向客户端证明其身份。负载均衡器还必须具有私钥才能完成 HTTPS 握手。如需详细了解如何为 HTTP(S) 负载均衡器提供 SSL 证书,请参阅在客户端与负载均衡器之间配置 TLS。
使用 Google 管理的证书
如需配置一个或多个由 Google 管理的 SSL 证书并将其与 Ingress 关联,您需要执行以下操作:
- 在 Ingress 所在的命名空间中创建一个或多个
ManagedCertificate对象。您可以为负载均衡器指定最多 15 个证书 - 通过将
networking.gke.io/managed-certificates注解添加到 Ingress,将ManagedCertificate对象与 Ingress 相关联。此注解一个是英文逗号分隔的ManagedCertificate对象列表。
限制
本部分介绍了 Google 管理的证书的限制。如果您需要自行管理的证书,或者您已经拥有要在 Ingress 上配置的 SSL 证书,请参阅在客户端和负载均衡器之间设置 HTTPS (TLS)。
由 Google 管理的证书不如由您获得和管理的证书灵活。Google 管理的证书最多支持 100 个非通配符网域。与自行管理的证书不同,Google 管理的证书不支持通配符网域。
Ingress 所支持证书的数量和类型由 Google 管理的 SSL 证书的限制定义。
不支持对由 Google 管理的证书进行更新。 如需了解详情,请参阅手动更新由 Google 管理的证书。
如果证书直接由证书授权机构撤消,Google 不会自动轮替证书。您必须删除 ManagedCertificate,然后创建一个新证书。
GKE Ingress 不支持由 Certificate Manager 管理的证书。如需使用由 Certificate Manager 管理的证书,请使用 Gateway API。
前提条件
您必须拥有域名。域名长度不得超过 63 个字符。您可以使用任何域名注册商来获取域名。
如果您使用 GKE Standard 集群,则必须启用
HttpLoadBalancing插件。您的 Ingress 清单必须包含
kubernetes.io/ingress.class: "gce"注解。ingressClassName字段不受支持。您必须在同一项目和命名空间中应用
Ingress和ManagedCertificate资源。创建预留的(静态)外部 IP 地址。 预留静态 IP 地址可以确保该地址始终属于您,即使您删除 Ingress 也是如此。如果您不预留 IP 地址,则 IP 地址可能会更改,这样您需要重新配置您的网域的 DNS 记录。请使用 Google Cloud CLI 或 Google Cloud 控制台创建预留的 IP 地址。
gcloud
如需创建预留 IP 地址,请运行以下命令:
gcloud compute addresses create ADDRESS_NAME --global将
ADDRESS_NAME替换为您要创建的预留 IP 地址的名称。如需查找您创建的静态 IP 地址,请运行以下命令:
gcloud compute addresses describe ADDRESS_NAME --global输出内容类似如下:
address: 203.0.113.32 ...控制台
如需创建预留的 IP 地址,请执行以下步骤:
进入 Google Cloud 控制台中的外部 IP 地址页面。
为此 IP 地址指定名称(例如
example-ip-address)。指定您需要 IPv4 还是 IPv6 地址。
选择类型对应的全球选项。
点击预留。 IP 地址在外部地址列中列出。
Config Connector
注意:此步骤需要使用 Config Connector。按照安装说明在您的集群上安装配置连接器。
如需部署此清单,请将它以compute-address.yaml的形式下载到您的机器上,然后运行以下命令:kubectl apply -f compute-address.yaml
设置由 Google 管理的证书
创建一个
ManagedCertificate对象。 此资源会指定 SSL 证书的网域。不支持通配符网域。以下清单描述了一个
ManagedCertificate对象。将此清单保存为managed-cert.yaml。apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: FIRST_CERT_NAME spec: domains: - FIRST_DOMAIN --- apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: SECOND_CERT_NAME spec: domains: - SECOND_DOMAIN替换以下内容:
FIRST_CERT_NAME:第一个ManagedCertificate对象的名称。FIRST_DOMAIN:您拥有的第一个网域。SECOND_CERT_NAME:第二个ManagedCertificate对象的名称。SECOND_DOMAIN:您拥有的第二个网域。
ManagedCertificate对象的名称不同于其创建的实际证书的名称。您只需知道ManagedCertificate对象的名称,以在 Ingress 中使用它们。将清单应用到您的集群:
kubectl apply -f managed-cert.yaml按照说明创建 Deployment 和 Service,以便在互联网上公开应用。
若要让此
ManagedCertificate对象变为Active,请使用networking.gke.io/managed-certificates注解将其关联到您的 Ingress,如以下示例所示。ManagedCertificate不必为Active即可将其关联到 Ingress。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-gmc-ingress annotations: networking.gke.io/managed-certificates: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002 ``` Replace <code><var>FIRST_DOMAIN</var></code> and <code><var>SECOND_DOMAIN</var></code> with your domain names. This manifest describes an Ingress that lists pre-shared certificate resources in an annotation. Note: It might take several hours for Google Cloud to provision the load balancer and the managed certificates, and for the load balancer to begin using the new certificates. For more information, see [Deploy a Google-managed certificate with load balancer authorization](/certificate-manager/docs/deploy-google-managed-lb-auth#wait_until_the_certificate_has_been_activated).等待 Google 管理的证书完成预配。此过程最多可能需要 60 分钟。您可以使用以下命令检查证书的状态:
kubectl describe managedcertificate managed-cert输出类似于以下内容:
Name: managed-cert Namespace: default Labels: <none> Annotations: <none> API Version: networking.gke.io/v1 Kind: ManagedCertificate (...) Spec: Domains: FQDN_1 FQDN_2 Status: CertificateStatus: Active (...)Status.CertificateStatus字段的值指示证书是否已预配。如果Status.CertificateStatus不是Active,则表示证书尚未预配。使用
https://前缀访问您的网域,验证 SSL 是否正常工作。您的浏览器会指示连接是否安全,您可以查看证书详细信息。
从自行管理的证书迁移到由 Google 管理的证书
将 Ingress 从使用自行管理的 SSL 证书迁移到 Google 管理的 SSL 证书时,在 Google 管理的 SSL 证书处于活跃状态之前,请不要删除任何自行管理的 SSL 证书。成功预配由 Google 管理的 SSL 证书后,它们会自动处于活跃状态。 由 Google 管理的 SSL 证书生效时,您可以删除自行管理的 SSL 证书。
使用以下说明从自行管理的 SSL 证书迁移到 Google 管理的 SSL 证书。
- 将由 Google 管理的新证书添加到 Ingress,如上一部分中所述。
等待由 Google 管理的证书资源的状态变为
Active。 使用以下命令检查证书的状态:kubectl describe managedcertificate managed-cert状态为
Active时,更新 Ingress,以移除对自行管理证书的引用。
移除由 Google 管理的证书
如需从集群中移除由 Google 管理的证书,您必须删除 ManagedCertificate 对象并移除引用它的 Ingress 注解。
删除
ManagedCertificate对象:kubectl delete -f managed-cert.yaml输出内容类似如下:
managedcertificate.networking.gke.io "managed-cert" deleted从 Ingress 中移除注释:
kubectl annotate ingress managed-cert-ingress networking.gke.io/managed-certificates-请注意命令末尾的减号
-。释放您为负载均衡器预留的静态 IP 地址。
您可以使用 Google Cloud CLI、 Google Cloud 控制台或 Config Connector 释放预留的 IP 地址。
gcloud
使用以下命令释放预留的 IP 地址:
gcloud compute addresses delete ADDRESS_NAME --global将
ADDRESS_NAME替换为该 IP 地址的名称。控制台
如需释放预留的 IP 地址,请执行以下步骤:
进入 Google Cloud 控制台中的外部 IP 地址页面。
选中要释放的 IP 地址旁边的复选框。
点击释放 IP 地址。
Config Connector
注意:此步骤需要使用 Config Connector。按照安装说明在您的集群上安装配置连接器。
如需部署此清单,请将它以
compute-address.yaml的形式下载到您的机器上,然后运行以下命令:kubectl delete -f compute-address.yaml
创建证书和密钥
如需使用预共享证书或 Kubernetes Secret,您首先需要一个或多个证书以及相应的私钥。每个证书的公用名 (CN) 必须与您拥有的域名一致。如果您的两个证书文件的公用名都有适当的值,可跳转至下一部分。
创建第一个密钥:
openssl genrsa -out test-ingress-1.key 2048创建第一个证书签名请求:
openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \ -subj "/CN=FIRST_DOMAIN"将
FIRST_DOMAIN替换为您拥有的域名,例如example.com。创建第一个证书:
openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \ -out test-ingress-1.crt创建第二个密钥:
openssl genrsa -out test-ingress-2.key 2048创建第二个证书签名请求:
openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \ -subj "/CN=SECOND_DOMAIN"将
SECOND_DOMAIN替换为您拥有的另一个域名,例如examplepetstore.com。创建第二个证书:
openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \ -out test-ingress-2.crt
如需详细了解证书和密钥,请参阅 SSL 证书概览。
您现在有了 2 个证书文件和 2 个密钥文件。
其余任务使用以下占位符来引用您的网域、证书和密钥:
FIRST_CERT_FILE:第一个证书文件的路径。FIRST_KEY_FILE:与第一个证书对应的密钥文件的路径。FIRST_DOMAIN:您拥有的一个域名。FIRST_SECRET_NAME:包含第一个证书和密钥的 Secret 的名称。SECOND_CERT_FILE:第二个证书文件的路径。SECOND_KEY_FILE:与第二个证书对应的密钥文件的路径。SECOND_DOMAIN:您拥有的另一个域名。SECOND_SECRET_NAME:包含第二个证书和密钥的 Secret 的名称。
使用预共享证书
您可以使用上传到 Google Cloud 项目的自行管理的 SSL 证书。这些证书称为预共享证书。您可以为 Ingress 指定一个或多个预共享证书。
如需使用多个预共享证书,请按以下步骤操作:
为每个证书和密钥对在 Google Cloud中创建一个公开可见的 SSL 证书资源。
gcloud compute ssl-certificates create FIRST_CERT_NAME \ --certificate=FIRST_CERT_FILE \ --private-key=FIRST_KEY_FILE ``` ```sh gcloud compute ssl-certificates create SECOND_CERT_NAME \ --certificate=SECOND_CERT_FILE \ --private-key=SECOND_KEY_FILE ``` Replace the following:FIRST_CERT_NAME、SECOND_CERT_NAME:第一个和第二个证书的名称。FIRST_CERT_FILE、SECOND_CERT_FILE:您的第一个和第二个证书文件。FIRST_KEY_FILE:和SECOND_KEY_FILE:您的第一个和第二个密钥文件。
在 Ingress 清单中,添加
ingress.gcp.kubernetes.io/pre-shared-cert注解。该注解的值是以英文逗号分隔的证书名称列表。此外,在spec.rules部分中,添加host字段以指定服务的网域。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-psc-ingress annotations: ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002 ``` Replace <code><var>FIRST_DOMAIN</var></code> and <code><var>SECOND_DOMAIN</var></code> with your domain names. This manifest describes an Ingress that lists pre-shared certificate resources in an annotation.
使用 Kubernetes Secret
如需为 HTTP(S) 负载均衡器提供您自己创建的证书和密钥,请创建一个或多个 Kubernetes Secret 对象。每个 Secret 都包含一个证书和密钥。您将 Secret 添加到 Ingress 清单的 tls 字段中。负载均衡器使用服务器名称指示 (SNI),根据 TLS 握手中的域名确定要向客户端提供哪个证书。
如需使用多个证书,请按以下步骤操作:
为每个证书和密钥对创建一个 Secret:
kubectl create secret tls FIRST_SECRET_NAME \ --cert=FIRST_CERT_FILE \ --key=FIRST_KEY_FILE ``` ```sh kubectl create secret tls SECOND_SECRET_NAME \ --cert=SECOND_CERT_FILE \ --key=SECOND_KEY_FILE ```在 Ingress 清单的
spec.tls部分中,列出您创建的 Secret。此外,在spec.rules部分中,添加host字段以指定服务的网域。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-mc-ingress spec: tls: - secretName: FIRST_SECRET_NAME - secretName: SECOND_SECRET_NAME rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002将
FIRST_DOMAIN和SECOND_DOMAIN替换为您拥有的域名,例如example.com和examplepetstore.com。
系统会定期获取对 Secret 的更改,因此如果您修改了 Secret 内的数据,则最多需要 10 分钟就能将这些更改应用于负载平衡器。
要为您的 GKE 集群保护 HTTPS 加密的 Ingress,请参阅保护 Ingress 示例。
停用 HTTP
如果您希望客户端和负载均衡器之间的所有流量都使用 HTTPS,则可以通过在 Ingress 清单中添加 kubernetes.io/ingress.allow-http 注解来停用 HTTP。请将注释的值设置为 "false"。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress-2
annotations:
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- secretName: SECRET_NAME
...
此清单包含 SECRET_NAME,即您创建的 Secret 的名称。
客户端和负载平衡器之间的 HTTP/2
客户端可以使用 HTTP/2 向负载平衡器发送请求。无需配置。
保护和优化负载均衡器与应用之间的流量
您可以配置负载均衡器与应用 Pod 之间用于通信的协议,以确保端到端安全性或优化内部流量性能。虽然负载均衡器默认对后端连接使用未加密的 HTTP/1.1,但您可以启用 HTTPS 或 HTTP/2 来满足应用的特定要求。
负载均衡器和应用之间的 HTTPS
如果在 GKE Pod 中运行的应用能够接收 HTTPS 请求,您可以将负载均衡器配置成使用 HTTPS 将请求转发给应用。如需了解详情,请参阅负载均衡器和应用之间的 HTTPS (TLS)。
如需配置负载均衡器和应用之间使用的协议,请在 Service 清单中使用 cloud.google.com/app-protocols 注释。
除非您使用容器原生负载均衡,否则此 Service 清单必须包含 type: NodePort。如果您使用容器原生负载均衡,请使用 type: ClusterIP。
以下 Service 清单指定了两个端口。注释表明,如果 HTTP(S) 负载均衡器以 Service 的端口 80 作为目标,则应该使用 HTTP。如果负载均衡器以 Service 的端口 443 作为目标,则应该使用 HTTPS。
Service 清单必须在端口注解中包含一个 name 值。您只能通过引用 Service 已分配的 name 端口(而不是通过其 targetPort 值)来修改 Service 端口。
apiVersion: v1
kind: Service
metadata:
name: my-service-3
annotations:
cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
spec:
type: NodePort
selector:
app: metrics
department: sales
ports:
- name: my-https-port
port: 443
targetPort: 8443
- name: my-http-port
port: 80
targetPort: 50001
在负载均衡器和应用之间使用 HTTP/2
如果在 GKE Pod 中运行的应用能够接收 HTTP/2 请求,则可以将负载均衡器配置为在将请求转发给应用时使用 HTTP/2。
如需启用 HTTP/2,您必须在 Kubernetes Service 清单中使用 cloud.google.com/app-protocols 注解。此注解用于指定负载均衡器用于与应用通信的协议。为了确保负载平衡器可以向后端发出正确的 HTTP/2 请求,后端必须通过 SSL 进行配置。
以下是为 HTTP/2 配置的 Service 清单示例:
apiVersion: v1
kind: Service
metadata:
name: my-http2-service
annotations:
cloud.google.com/app-protocols: '{"my-port":"HTTP2"}'
spec:
type: NodePort
selector:
app: my-app
ports:
- name: my-port
protocol: TCP
port: 443
targetPort: 8443
请注意以下几点:
cloud.google.com/app-protocols注解设置为'{"my-port":"HTTP2"}',这会指示负载均衡器对发送到名为my-port的端口的流量使用 HTTP/2。- 端口设置为
443,并将流量定向到targetPort8443上的 Pod。