(使用Istio 0.5.1,kubectl 1.9.1 / 1.9.0用于客户端/服务器,minikube 0.25.0)
我试图让Istio EgressRules与Kubernetes Services合作,但遇到了一些麻烦。
我试图以3种方式设置EgressRules:
我想我可以使用kubernetes服务的FQDN作为基于HTTP的EgressRule目标服务(如ext-service.default.svc.cluster.local
),这就是我尝试的ExternalName服务以及没有选择器的服务但是一个相关的Endpoints对象。
对于前者,我创建了以下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服务(即使它用于外部流量)有以下几个原因:
在应用代码中使用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:"在TCP出口规则而不是基于HTTP的出口规则中,目的地由IP或CIDR表示法中的IP块指定。"。
另外,我仍然希望基于HTTP的可观察性来自L7而不是L4,所以我更喜欢基于HTTP的出口。 (使用TCP Egresses,"应用程序发起的HTTPS流量将被Istio视为不透明的TCP")。
任何帮助获得Kubernetes服务作为"目的地服务"一个EgressRule(或帮助理解为什么这不是必要的,如果是这种情况)被赞赏。谢谢!
答案 0 :(得分:1)
解决方案是:
在您的情况下,使用端口和协议定义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重写路由规则以设置主机头:
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,主机标头为ext-service
。由于google.com没有这样的虚拟主机,因此Web服务器不知道转发此类请求的位置。这就是你所经历的:
它将我带到了Google的404页面