Istio 出口与 Kubernetes 服务
Istio Egresses with Kubernetes Services
(使用 Istio 0.5.1,kubectl 1.9.1/1.9.0 client/server,minikube 0.25.0)
我正在尝试让 Istio EgressRules 与 Kubernetes 服务一起工作,但遇到了一些问题。
我尝试通过 3 种方式设置 EgressRules:
- 指向另一个域的 ExternalName 服务(例如
www.google.com)
- 没有选择器但有关联的服务
端点对象(用于具有 IP 地址但没有 DNS 的服务
姓名)
- (用于比较)没有 Kubernetes 服务,只有 EgressRule
我想我可以将 kubernetes 服务的 FQDN 用作基于 HTTP 的 EgressRule 目标服务(如 ext-service.default.svc.cluster.local
),这就是我对 ExternalName 服务以及具有没有选择器,只有关联的端点对象。
对于前者,我创建了以下 yaml
文件:
kind: Service
apiVersion: v1
metadata:
name: ext-service
spec:
type: ExternalName
externalName: www.google.com
---
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
name: ext-egress-rule
spec:
destination:
service: ext-service.default.svc.cluster.local
ports:
- port: 443
protocol: https
对于后者,我创建了这个 yaml
文件(我只是 ping google 并获取了 IP 地址):
kind: Endpoints
apiVersion: v1
metadata:
name: ext-service
subsets:
- addresses:
- ip: 216.58.198.78
ports:
- port: 443
---
kind: Service
apiVersion: v1
metadata:
name: ext-service
spec:
ports:
- protocol: TCP
port: 443
targetPort: 443
---
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
name: ext-service-egress-rule
spec:
destination:
service: ext-service.default.svc.cluster.local
ports:
- port: 443
protocol: https
在这两种情况下,在应用程序代码中,我访问:
http://ext-service.default.svc.cluster.local:443
我的假设是流量会像这样流动:
[[ app -> envoy proxy -> (tls origination) -> kubernetes service ]] -> external service
其中 [[ ... ]]
是服务网格(以及 Kubernetes 集群)的边界
结果:
ExternalName
服务 几乎 按预期工作,但它把我带到了 Google 的 404 页面(有时响应似乎是空的,不确定如何具体复制一个或另一个)
带有 Endpoint 对象的服务没有工作,而是打印了这条消息(当通过 Golang 发出请求时,但我认为这不重要):
这有时也会给出空响应。
出于以下几个原因,我想使用 Kubernetes 服务(即使它用于外部流量):
- 您不能将 IP 地址用于 EgressRule 的目标服务。来自 Egress Rules configuration:"The destination of an egress rule ... can be either a fully qualified or wildcard domain name".
- 对于没有域名的外部服务(一些没有 DNS 名称的本地 legacy/monolith 服务),我希望应用程序能够访问它们而不是通过 IP 地址,而是通过 kube-dns(或与 Istio 相关的类似)名称。
- (与之前相关)我喜欢 Kubernetes 服务提供的额外抽象层,因此我可以在不更改 EgressRule 的情况下更改底层目标(除非我弄错了,这不是架构师的正确方法这个)。 EgressRule 是否旨在完全取代外部流量的 Kubernetes 服务而不创建额外的 Kubernetes 服务?
在应用程序代码中使用 https://
不是一个选项,因为那样的话请求将不得不禁用 TLS 验证,因为 kube-dns 名称与证书上的任何名称都不匹配。它也不会被观察到。
如果我使用以下 EgressRule(没有任何 Kubernetes 服务),通过 http://www.google.com:443
访问 Google 工作正常,得到我期望的确切 html 表示:
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
name: google-egress-rule
spec:
destination:
service: www.google.com
ports:
- port: 443
protocol: https
我看到有一个 TCP EgressRule,但我宁愿不必为每个 IP 块指定规则。来自 TCP Egress:"In TCP egress rules as opposed to HTTP-based egress rules, the destinations are specified by IPs or by blocks of IPs in CIDR notation.".
另外,我仍然喜欢来自 L7 而不是 L4 的基于 HTTP 的可观察性,所以我更喜欢基于 HTTP 的出口。 (使用 TCP 出口,"The HTTPS traffic originated by the application will be treated by Istio as opaque TCP")。
感谢任何帮助将 Kubernetes 服务作为 EgressRule 的 "destination service"(或者帮助理解为什么在这种情况下不需要这样做)。谢谢!
解决方法是:
- 定义一个 Kubernetes ExternalName 服务指向 www.google.com
- 不要定义任何 EgressRules
- 创建 RouteRule 以设置主机 header。
在您的情况下,使用端口和协议定义一个 ExternalName 服务:
kind: Service
apiVersion: v1
metadata:
name: ext-service
spec:
type: ExternalName
externalName: www.google.com
ports:
- port: 80
# important to set protocol name
name: http
---
定义 HTTP 重写路由规则以设置主机 header:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: externalgoogle-rewrite-rule
#namespace: default
spec:
destination:
name: ext-service
rewrite:
authority: www.google.com
---
然后用curl
访问它,例如:curl ext-service
没有路由规则,请求将到达 google.com,主机 header 为 ext-service
。由于 google.com 没有这样的虚拟主机,Web 服务器不知道将这样的请求转发到哪里。这是你经历过的:
it brought me to Google's 404 page
(使用 Istio 0.5.1,kubectl 1.9.1/1.9.0 client/server,minikube 0.25.0)
我正在尝试让 Istio EgressRules 与 Kubernetes 服务一起工作,但遇到了一些问题。
我尝试通过 3 种方式设置 EgressRules:
- 指向另一个域的 ExternalName 服务(例如 www.google.com)
- 没有选择器但有关联的服务 端点对象(用于具有 IP 地址但没有 DNS 的服务 姓名)
- (用于比较)没有 Kubernetes 服务,只有 EgressRule
我想我可以将 kubernetes 服务的 FQDN 用作基于 HTTP 的 EgressRule 目标服务(如 ext-service.default.svc.cluster.local
),这就是我对 ExternalName 服务以及具有没有选择器,只有关联的端点对象。
对于前者,我创建了以下 yaml
文件:
kind: Service
apiVersion: v1
metadata:
name: ext-service
spec:
type: ExternalName
externalName: www.google.com
---
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
name: ext-egress-rule
spec:
destination:
service: ext-service.default.svc.cluster.local
ports:
- port: 443
protocol: https
对于后者,我创建了这个 yaml
文件(我只是 ping google 并获取了 IP 地址):
kind: Endpoints
apiVersion: v1
metadata:
name: ext-service
subsets:
- addresses:
- ip: 216.58.198.78
ports:
- port: 443
---
kind: Service
apiVersion: v1
metadata:
name: ext-service
spec:
ports:
- protocol: TCP
port: 443
targetPort: 443
---
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
name: ext-service-egress-rule
spec:
destination:
service: ext-service.default.svc.cluster.local
ports:
- port: 443
protocol: https
在这两种情况下,在应用程序代码中,我访问:
http://ext-service.default.svc.cluster.local:443
我的假设是流量会像这样流动:
[[ app -> envoy proxy -> (tls origination) -> kubernetes service ]] -> external service
其中 [[ ... ]]
是服务网格(以及 Kubernetes 集群)的边界
结果:
ExternalName
服务 几乎 按预期工作,但它把我带到了 Google 的 404 页面(有时响应似乎是空的,不确定如何具体复制一个或另一个)带有 Endpoint 对象的服务没有工作,而是打印了这条消息(当通过 Golang 发出请求时,但我认为这不重要):
这有时也会给出空响应。
出于以下几个原因,我想使用 Kubernetes 服务(即使它用于外部流量):
- 您不能将 IP 地址用于 EgressRule 的目标服务。来自 Egress Rules configuration:"The destination of an egress rule ... can be either a fully qualified or wildcard domain name".
- 对于没有域名的外部服务(一些没有 DNS 名称的本地 legacy/monolith 服务),我希望应用程序能够访问它们而不是通过 IP 地址,而是通过 kube-dns(或与 Istio 相关的类似)名称。
- (与之前相关)我喜欢 Kubernetes 服务提供的额外抽象层,因此我可以在不更改 EgressRule 的情况下更改底层目标(除非我弄错了,这不是架构师的正确方法这个)。 EgressRule 是否旨在完全取代外部流量的 Kubernetes 服务而不创建额外的 Kubernetes 服务?
在应用程序代码中使用 https://
不是一个选项,因为那样的话请求将不得不禁用 TLS 验证,因为 kube-dns 名称与证书上的任何名称都不匹配。它也不会被观察到。
如果我使用以下 EgressRule(没有任何 Kubernetes 服务),通过 http://www.google.com:443
访问 Google 工作正常,得到我期望的确切 html 表示:
apiVersion: config.istio.io/v1alpha2
kind: EgressRule
metadata:
name: google-egress-rule
spec:
destination:
service: www.google.com
ports:
- port: 443
protocol: https
我看到有一个 TCP EgressRule,但我宁愿不必为每个 IP 块指定规则。来自 TCP Egress:"In TCP egress rules as opposed to HTTP-based egress rules, the destinations are specified by IPs or by blocks of IPs in CIDR notation.".
另外,我仍然喜欢来自 L7 而不是 L4 的基于 HTTP 的可观察性,所以我更喜欢基于 HTTP 的出口。 (使用 TCP 出口,"The HTTPS traffic originated by the application will be treated by Istio as opaque TCP")。
感谢任何帮助将 Kubernetes 服务作为 EgressRule 的 "destination service"(或者帮助理解为什么在这种情况下不需要这样做)。谢谢!
解决方法是:
- 定义一个 Kubernetes ExternalName 服务指向 www.google.com
- 不要定义任何 EgressRules
- 创建 RouteRule 以设置主机 header。
在您的情况下,使用端口和协议定义一个 ExternalName 服务:
kind: Service
apiVersion: v1
metadata:
name: ext-service
spec:
type: ExternalName
externalName: www.google.com
ports:
- port: 80
# important to set protocol name
name: http
---
定义 HTTP 重写路由规则以设置主机 header:
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: externalgoogle-rewrite-rule
#namespace: default
spec:
destination:
name: ext-service
rewrite:
authority: www.google.com
---
然后用curl
访问它,例如:curl ext-service
没有路由规则,请求将到达 google.com,主机 header 为 ext-service
。由于 google.com 没有这样的虚拟主机,Web 服务器不知道将这样的请求转发到哪里。这是你经历过的:
it brought me to Google's 404 page