【发布时间】:2021-01-10 05:24:55
【问题描述】:
我在 AWS EKS 中托管的 Kubernetes 集群中部署了 Istio。这创建了一个名为 istio-ingressgateway 的 LoadBalancer 类型的 Kubernetes 服务,外部主机名为 [redacted]-redacted.us-west-2.elb.amazonaws.com,并自动预置了一个 AWS ELB,类型为 classic。那太棒了。 (注意:在 AWS 控制台中,我没有看到此 elb 主机名的托管区域,看起来我无法配置别名或其他东西)
我已经能够通过定义一个打开端口 80 到host:"*" 的 istio 网关,并定义一个路由端口 80 的 istio 虚拟服务,将运行在集群外的 gRPC 客户端连接到运行在集群中的 gRPC 服务器到我的目的地(某些 kubernetes 服务的某个端口)。到目前为止一切顺利。
现在我想为集群中的第二个 gRPC 端点执行此操作。据我所知,我的选择是:通过在入口上打开第二个端口(比如 81)来路由(我现在选择不这样做)。或者通过定义[redacted]-redacted.us-west-2.elb.amazonaws.com 的子域进行路由,或者通过实现“虚拟主机”进行路由,即客户端在标头中发送host:"svc1" 的同一域上的两个服务。
这就是我卡住的地方。不知道怎么给这个ELB域名定义子域,也不知道能不能用TLS做虚拟主机,如果能,还能不能用Istio的“直通”tls模式以免网关上的 TLS 终止。
1- 使用子域: 在我的开发人员机器上尝试getent hosts svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com 时,它不会映射到 IP,而如果删除 svc1 前缀 DNS 会返回 3 个 IP(猜测 3 个可用性us-west-2 中的区域)。所以我不能在没有工作的情况下为域添加前缀 svc1。
我能否为由经典 AWS ELB 创建的域定义子域 svc1 和 svc2,通过部署 Istio 自动预置,如果可以,如何?我可以使用 kubectl/istioctl 来配置 Istio,还是需要使用 AWS CLI 来执行此操作?这可以在不注册域的情况下完成吗,我可以接受用户不友好的 elb.amazonaws.com 主机名吗?
2- 虚拟主机: 或者,我可以在 gRPC 元数据中添加 host=svc1。我尝试将 ctx := metadata.AppendToOutgoingContext(context.Background(), "Host", "svc1") 添加到我的 Go 客户端,但没有成功。
一些指导会很棒。
更新 1,以及一种纯文本解决方案
我正在阅读List of HTTP header fields 上的“主机”标头不应在 HTTP2 中使用。鉴于这是 gRPC,它是 HTTP2,因此我不应该在我的 gRPC 客户端请求中将其添加为自定义标头。做虚拟主机时的解决方案,在gRPC客户端中不是发送“host”头,而是发送“:Authority”头,该值必须对应于istio的gateway+virtualservice中指定的主机。这对我有用。在我的 Go 客户端中,我必须添加 dialOptions = append(dialOptions, grpc.WithAuthority("[my-service-1]"))。
根据GoDoc grpc.WithAuthority,该解决方案不适用于 TLS。所以我仍然需要找到如何在使用 TLS 时从相同的外部 IP 和端口路由 2 个服务。
更新 1.1:
在虚拟主机中,当使用 TLS 时,SNI 可以在 CLIENT HELLO 消息中传递,而不是像明文那样作为 gRPC 标头。根据您的语言,确切的 API 会有所不同,但在 Go 中,我可以通过在 tls.Config 中设置 ServerName 字段来传递主机名。然后,您可以在您的 istio 网关配置中对该主机名进行门控,并根据您的 istio 虚拟服务中的该值进行路由。
更新 2: 我尝试在 AWS Route53 上创建子域,但失败了。首先,我为域创建一个公共托管区域:[redacted]-redacted.us-west-2.elb.amazonaws.com。接下来,在该托管区域中,我创建一个 A 记录,名称为=svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com,route=Alias to Classic Load Balancer,region=us-west-2 , load balancer=dualstack.[redacted]-redacted.us-west-2.elb.amazonaws.com.
我稍后测试了 svc1.[redacted]-redacted.us-west-2.elb.amazonaws.com 存在dig 的记录,它没有返回答案。但是 dig 确实返回了 [redacted]-redacted.us-west-2.elb.amazonaws.com 的 3 个 A 记录(不带 svc1 前缀),带有 3 个负载均衡器的 IP。
【问题讨论】:
-
我的网关 yaml 很简单,它只是打开了 80 端口。我的虚拟服务 yaml 在同一个网关上定义了 2 个虚拟服务,第一个用于 host=svc1,路由到 service1,第二个用于 host =svc2,带有到 service2 的路由。这行得通。但它需要客户端发送“:Authority=svcX”标头,这在使用 TLS 时无法解决。我想知道如何更新它以使用 TLS。在我看来,拥有 ELB 主机名的 2 个子域会更“干净”。这样我可以更轻松地升级到使用 TLS。但我不知道如何子域 ELB 主机名。
-
我有类似的情况,但使用 https。两个服务接受路径
/上的流量,而我只能使用端口443。我通过使用两个带有子域abc.example.com和def.example.com指向负载均衡器外部IP 的DNS 条目解决了这个问题。网关接受这两个条目作为主机。对于每个子域,我都有一个VirtualService转发到/上的正确服务。如果你愿意,我可以发布我的配置作为答案。 -
谢谢@ChristophRaab。我很想学习如何为域“[redacted]-[redacted].us-west-2.elb.amazonaws.com”创建 2 个子域“abc”和“def”,而无需创建自定义域名“ example.com”,或者被告知这是不可能的,我必须创建一个自定义域名来定义“abc”和“def”子域。
-
抱歉,但我不知道如何仅使用 istio 执行此操作,除非可能创建两个入口网关。我来自 Azure,在那里我使用私有 DNS 区域解决了子域部分,以在我的网络中解析 DNS,但没有注册公共域。 AWS 也应该有一些东西。
标签: amazon-web-services grpc kubernetes-ingress amazon-elb istio