Google Kubernetes Engine:为服务类型启用 HTTPS

Posted

技术标签:

【中文标题】Google Kubernetes Engine:为服务类型启用 HTTPS【英文标题】:Google Kubernetes Engine: Enable HTTPS for Service type 【发布时间】:2018-07-06 04:13:07 【问题描述】:

我在 GKE 上有一个应用程序,我希望只能通过 HTTPS 访问,因此我获得了一个签名证书来使用 TLS 保护应用程序。

我查看了很多关于如何做到这一点的教程,但它们都提到了使用 Ingress 并使用 LetsEncrypt 和 KubeLego 自动请求证书。但我希望继续使用外部负载均衡器(谷歌为我提供的计算引擎实例),但我只想通过 https 访问我的应用程序。

如何应用我的 server.crt 和 server.key 文件来启用 https.Do I apply it to the Load balancers 或 kubernetes 集群。

【问题讨论】:

可能你想看看这个开源项目。 github.com/appscode/voyager 【参考方案1】:

解决办法:

在运行时获取您的证书,很多人使用 LetsEncrypt,因为它非常简单,但您可以将证书存储在真正安全的存储中,例如您的云平台的密钥管理存储,或者运行您自己的 Hashicorp Vault(我推荐 Hashicorp Vault,它非常好!)然后在运行时安全地检索您的秘密。


您注意到每个教程或指南都建议动态获取它们。

但它们都指使用 Ingress 并使用 LetsEncrypt 和 KubeLego 自动请求证书。

原因如下:

https://kubernetes.io/docs/concepts/configuration/secret/#risks

风险

在 API 服务器中,秘密数据以明文形式存储在 etcd 中;所以: 管理员应将 etcd 的访问权限限制为管理员用户 API server 中的秘密数据保存在 etcd 使用的磁盘上;管理员可能希望在不再使用时擦除/粉碎 etcd 使用的磁盘

可以创建使用密钥的 pod 的用户也可以看到该密钥的值。即使 apiserver 策略不允许该用户读取机密对象,用户也可以运行一个暴露机密的 pod。

如果运行了多个 etcd 副本,那么秘密将在它们之间共享。默认情况下,etcd 不使用 SSL/TLS 保护对等通信,尽管可以配置。

目前,在任何节点上拥有 root 权限的任何人都可以通过模拟 kubelet 从 apiserver 读取任何秘密。这是一个计划中的功能,只向实际需要它们的节点发送秘密,以限制根漏洞对单个节点的影响。

因此,每个人都正确地建议您不要使用 K8s SECRETS 来存储您的宝贵证书,因为它不适合这项工作。

【讨论】:

这确实是另一种方式。但需要明确的是,从 Kubernetes 1.7 开始,可以启用静态加密来加密机密:kubernetes.io/docs/tasks/administer-cluster/encrypt-data【参考方案2】:

在通过 HTTPS 公开您的应用程序时,Ingress 可能是您的最佳选择。 Ingress 资源指定了一个后端服务,因此您将继续将您的应用程序公开为 Kubernetes 服务,只需将类型设置为 ClusterIP。这将为您的集群生成一个“内部”服务,并且一旦您设置它就可以通过 Ingress 进行外部访问。

现在,特别是在 Google Kubernetes Engine (GKE) 中,您集群中定义的任何入口资源都将由 Google Cloud Load Balancer 提供服务,因此我认为您不必担心部署自己的入口控制器(例如 nginx入口控制器)。

就 TLS 而言,如果您有证书,您可以使用自己的证书。证书必须通过 Kubernetes Secret 上传到集群。定义该密钥后,您可以在 Ingress 定义中引用该密钥。 (https://kubernetes.io/docs/concepts/services-networking/ingress/#tls)

您可以使用以下命令创建密钥:

kubectl create secret tls my-app-certs --key /tmp/tls.key --cert /tmp/tls.crt

一旦你有了你的秘密,你就可以在你的入口资源中引用它:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  tls:
  - secretName: my-app-certs
  backend:
    serviceName: s1
    servicePort: 80

一旦您创建了入口资源,GKE 将配置负载平衡器并为您提供一个可供您使用的可公开访问的 IP:

kubectl get ingress my-app-ingress

以下是一个很好的教程,可引导您了解 GKE 上的 Ingress: https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer

【讨论】:

非常感谢,我已经这样做了,并使用了默认的 nginx 服务进行测试,但我希望它在地址栏中表明该站点是安全的,但事实并非如此。此过程是否表明该站点是安全的? @Ogbe 通过这种沟通方式很难弄清楚。你是如何获得证书的?您的浏览器是否信任它?是否正在送达证书? DNS 名称是否与证书中的名称(或 SAN 中的名称)匹配? 注意:Kubernetes 机密存储在 etcd 上的 PLAINTEXT 中,任何有权访问 APIserver 的节点都可以访问任何机密,即使未分配。适当照顾! kubernetes.io/docs/concepts/configuration/secret/#risks 从 Kubernetes 1.7 开始,可以启用静态加密来加密机密:kubernetes.io/docs/tasks/administer-cluster/encrypt-data 我向这个答案授予了赏金,我已经能够安装 ssl 证书,但我需要将所有 http 请求路由到 https,将 ssl_redirect 注释设置为 true 并允许 https 注释为 false 没有帮助实现这一目标【参考方案3】:

Ingress 是最简单的方法。您不需要使用 LetsEncrypt,您可以指定自己的证书。

入口控制器只是一个 NGINX 代理。如果您不想使用入口(为什么?),您必须自己创建此代理服务。这基本上是这项服务的入口。

【讨论】:

使用入口是否意味着我必须创建一个新的负载均衡器? 为每个 LoadBalancer 类型的服务(每个外部暴露的服务)创建一个负载均衡器。这个想法是只有一个入口,所有其他服务都应该是内部的。

以上是关于Google Kubernetes Engine:为服务类型启用 HTTPS的主要内容,如果未能解决你的问题,请参考以下文章

Google Kubernetes Engine(GKE)使用初探 | Linux 中国

Google Kubernetes Engine:为服务类型启用 HTTPS

使用 Config Connector 对 Google Kubernetes Engine 集群进行地形改造

如何使用工作负载身份通过 Google Cloud .NET SDK 访问 Google Kubernetes Engine 中的 ESP?

Vertex AI 自定义预测与 Google Kubernetes Engine

Google Cloud、Kubernetes 和 Cloud SQL 代理:默认 Compute Engine 服务帐户问题