如何在 GKE 上为 Kubernetes Ingress 强制 SSL

Posted

技术标签:

【中文标题】如何在 GKE 上为 Kubernetes Ingress 强制 SSL【英文标题】:How to force SSL for Kubernetes Ingress on GKE 【发布时间】:2016-08-28 08:19:09 【问题描述】:

有没有办法强制对入口负载平衡器上的传入连接进行 SSL 升级?或者,如果这不可能,我可以禁用端口:80 吗?我还没有找到一个很好的文档页面来概述 YAML 文件中的此类选项。提前非常感谢!

【问题讨论】:

“传入连接的 SSL 升级”是什么意思。你能详细说明一下吗?另外,您能否详细说明您要做什么? 我想将连接到 http 端口 80 重定向到 https 端口 443,最好是在 Kubernetes Ingress 负载均衡器上——如果可能的话。如果不是,最好的策略是什么 - 负载平衡 80 和 443,并在 LB 后面放置一个 haproxy 来进行转发? 【参考方案1】:

https://github.com/kubernetes/ingress-gce#frontend-https

您可以通过注解 kubernetes.io/ingress.allow-http: "false" 阻止 HTTP 或通过指定自定义后端将 HTTP 重定向到 HTTPS。不幸的是,GCE 还没有直接为您处理 L7 层的重定向或重写。 (见https://github.com/kubernetes/ingress-gce#ingress-cannot-redirect-http-to-https)

更新:GCP now handles redirection rules for load balancers,包括 HTTP 到 HTTPS。似乎还没有通过 Kubernetes YAML 创建这些的方法。

【讨论】:

这就是为什么如果我在我的 nginx HTTP 服务器块中将 301 返回到 HTTPS 会导致 301 循环的原因。 是否有任何可用资源可以详细说明如何实际使用自定义后端来执行重定向?或者可以在这部分扩展您的答案?我的应用程序没有在 Apache/nginx 上运行,所以添加这样的服务意味着一个额外的难题,我不知道如何正确路由。 我找到了满足自己需求的解决方案(并弄清楚如何插入额外的 Pod),将其发布在 ***.com/a/49750913/2745865 通过这篇文章digitalocean.com/community/questions/… 我了解如何使用 nginx 将 HTTP 重定向到 HTTPS。但 nginx conf 要求提供 ssl 证书文件位置。就我而言,我使用的是 GCP 托管证书。我不知道 nginx conf 文件将与 GCP 托管证书有什么关系。 现在有一种方法可以通过 FrontendConfig 在 k8s yaml 中支持重定向:cloud.google.com/kubernetes-engine/docs/how-to/…【参考方案2】:

注释已更改:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
...

这里是注解改动PR: https://github.com/kubernetes/contrib/pull/1462/files

【讨论】:

最近检查过,注释保持不变,但最新版本现在是 apiVersion:networking.k8s.io/v1beta1【参考方案3】:

如果您没有绑定到 GCLB 入口控制器,您可以查看Nginx Ingress Controller。该控制器在多个方面与内置控制器不同。首先,您需要自己部署和管理一个。但如果您愿意这样做,您将获得不依赖 GCE LB(20 美元/月)并获得对 IPv6/websockets 的支持的好处。

documentation 声明:

默认情况下,如果为该入口启用了 TLS,控制器会重定向 (301) 到 HTTPS。如果你想全局禁用该行为,你 可以在 NGINX 配置映射中使用ssl-redirect: "false"

最近发布的0.9.0-beta.3 附带了一个额外的注释,用于显式执行此重定向:

使用注解 ingress.kubernetes.io/force-ssl-redirect 强制重定向到 SSL

【讨论】:

对于 nginx 入口控制器,我尝试了 nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 及其工作。完整的注释列表请访问github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/… 感觉还是最好的答案 更新注释文档链接:github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/… GCE 负载均衡器支持 WebSockets,并且至少从 2018 年 5 月开始就支持 WebSockets - 你可以调整这个答案吗?【参考方案4】:

在 Kubernetes 中重定向到 HTTPS 有点复杂。根据我的经验,您可能希望使用诸如 Ambassador 或 ingress-nginx 之类的入口控制器来控制到您的服务的路由,而不是让您的负载均衡器直接路由到您的服务。

假设您使用的是入口控制器,那么:

如果您在外部负载均衡器上终止 TLS,并且 LB 以 L7 模式(即 HTTP/HTTPS)运行,那么您的入口控制器需要使用 X-Forwarded-Proto,并相应地发出重定向。 如果您要在外部负载均衡器上终止 TLS,并且 LB 在 TCP/L4 模式下运行,那么您的入口控制器需要使用 PROXY 协议进行重定向。 您还可以直接在入口控制器中终止 TLS,在这种情况下,它具有执行重定向所需的所有信息。

这里是 tutorial,关于如何在大使中执行此操作。

【讨论】:

【参考方案5】:

Google 已响应我们的请求,并正在其负载平衡器上测试 HTTP->HTTPS SSL 重定向。 Their latest answer 说它应该在 2020 年 1 月结束之前的某个时间进入 Alpha。

他们的评论:

感谢您在此问题上的耐心等待。该功能目前正在测试中,我们预计将在 1 月底之前进入 Alpha 阶段。随着 Alpha 版发布的临近​​,我们的 PM 团队将发布更多详细信息。

希望我们能在不久的将来为这个非常常见的功能找到一个简单的解决方案。


更新(2020 年 4 月)

HTTP(S) 重写现在是 Generally Available 功能。它的边缘仍然有点粗糙,不幸的是,它不适用于 GCE Ingress Controller 开箱即用。但时间会证明一切,希望会出现原生解决方案。

【讨论】:

从字面上看,5 年后。 没关系:Unfortunately that will push our Alpha date out a number of weeks. @Michal 终于出来了:issuetracker.google.com/issues/35904733#comment95 但是,我敢肯定,我们可以在 Kubernetes YAML 中使用一个配置来自动设置它还需要更长的时间...... 谢谢@Cyral 我会更新乔希的答案。如果不满意,请随时回滚。 现在可以在 GCE Ingress Controller 中使用吗?【参考方案6】:

您可以disable HTTP on your cluster(请注意,您需要重新创建集群才能将此更改应用于负载均衡器),然后通过在同一 IP 地址上创建额外的负载均衡器来set HTTP-to-HTTPS redirect。

我在同一个问题上花了几个小时,最后做了我刚才描述的事情。效果很好。

【讨论】:

【参考方案7】:

为此工作了很长时间。以防有人不清楚上面的帖子。您将使用注释重建您的入口 -- kubernetes.io/ingress.allow-http: "false" -- 然后删除您的入口并重新部署。注释将使入口只为 443 创建一个 LB,而不是 443 和 80。

然后你做一个计算 HTTP LB,而不是 GKE。

GUI 说明: 创建负载均衡器并选择 HTTP(S) 负载均衡 -- 开始配置。

选择 - 从 Internet 到我的虚拟机并继续

为 LB 选择一个名称

将后端配置留空。

在主机和路径规则下,选择高级主机和路径规则并将操作设置为 将客户端重定向到不同的主机/路径。 将主机重定向字段留空。 选择前缀重定向并将路径值留空。 选择重定向响应代码为 308。 勾选启用 HTTPS 重定向框。

对于前端配置,保留 http 和端口 80,对于 ip 地址选择静态 用于您的 GKE 入口的 IP 地址。

创建这个 LB。

您现在将所有 http 流量都转到这里,并且 308 重定向到您的 GKE 的 https 入口。超级简单的配置设置,效果很好。

注意:如果您只是尝试删除 GKE 生成的端口 80 LB(不进行注释更改并重建入口),然后添加新的重定向计算 LB,它确实有效,但您将开始看到错误消息您的 Ingress 说错误 400 字段“resource.ipAddress”的无效值正在使用中,会导致冲突,无效。它正在尝试启动端口 80 LB,但不能,因为您已经在端口 80 上有一个使用相同 IP 的 LB。它确实有效,但错误很烦人,GKE 一直在尝试构建它(我认为)。

【讨论】:

谢谢!这也正是我们需要做的。 我认为这对应于谷歌官方文档中的“创建 HTTP LB2”步骤:cloud.google.com/load-balancing/docs/https/…【参考方案8】:

快速更新。 Here

现在可以使用 FrontEndConfig 来配置入口。希望对您有所帮助。

例子:

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: my-frontend-config
spec:
  redirectToHttps:
    enabled: true
    responseCodeName: 301

您需要确保您的负载平衡器支持 HTTP 和 HTTPS

【讨论】:

首先,感谢您的回复。请考虑将解决方案直接包含在您的答案中。如果本文的网址发生变化,您的回答将变得毫无用处。【参考方案9】:

已通过对已接受答案的评论正确回答了此问题。但是由于评论被埋没了,所以我错过了好几次。

从 GKE 版本 1.18.10-gke.600 开始,您可以添加 k8s 前端配置以从 http 重定向到 https。

https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#https_redirect

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: ssl-redirect
spec:
  redirectToHttps:
    enabled: true

# add below to ingress
# metadata:
#   annotations:
#     networking.gke.io/v1beta1.FrontendConfig: ssl-redirect

【讨论】:

这太完美了!

以上是关于如何在 GKE 上为 Kubernetes Ingress 强制 SSL的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Terraform 将 GKE 凭证传递给 Kubernetes 提供者?

如何在 GKE 中通过入口启用 Cors

Kubernetes 的动态通配符子域入口

如何在 GKE 自动驾驶仪中基于自定义指标实现水平自动缩放

在具有私有 GKE 集群的 Terraform 上使用 Kubernetes 提供程序

将文件放置在 GKE 上的 Kubernetes 持久卷存储中