- 博客/
Istio 的高级边缘流量控制(二)
Table of Contents
上一节我演示了如何通过 Egress Gateway
引导 Istio 的出口 HTTP
流量,但到 443 端口的 HTTPS
流量没有通过 Egress Gateway,而是直接转到 edition.cnn.com
。Istio 出口流量的 TLS 演示了如何在网格内部直接通过 HTTP 协议访问外部加密服务。本文尝试将这两者结合起来,先将 HTTP 流量路由到 Egress Gateway,然后直接使用 Egress Gateway 发起 TLS
连接。
前提条件与上一篇文章相同。
ServiceEntry#
首先需要为 edition.cnn.com
定义一个 ServiceEntry
以允许网格内服务访问外部服务。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: http-port-for-tls-origination
protocol: HTTP
resolution: DNS
EOF
该 ServiceEntry 会在服务网格内的所有应用的所有 Pod上创建相应的路由规则和与之对应的 Cluster。具体可以参考:控制 Egress 流量。
验证 ServiceEntry
是否生效。发送 HTTPS 请求到 http://edition.cnn.com/politics。
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
HTTP/1.1 301 Moved Permanently
...
location: https://edition.cnn.com/politics
...
command terminated with exit code 35
如果看到输出结果中包含 301 Moved Permanently
,说明 ServiceEntry
配置正确。退出码 35
是由于 Istio 没有执行 TLS。 为了让 Egress gateway 执行 TLS,还要继续执行以下步骤进行配置。
Gateway#
为 edition.cnn.com
的 443
端口创建一个 Egress Gateway(假设没有启用双向 TLS 认证)。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 443
name: http-port-for-tls-origination
protocol: HTTP
hosts:
- edition.cnn.com
EOF
此处 Istio 会将 Gateway
翻译成 Egress Gateway 所在的 Pod 的 Listener
。具体配置如下:
$ istioctl -n istio-system pc listener istio-egressgateway-f8b6469db-fj6zr -o json
[
{
"name": "0.0.0.0_443",
"address": {
"socketAddress": {
"address": "0.0.0.0",
"portValue": 443
}
},
"filterChains": [
{
"filters": [
{
"name": "envoy.http_connection_manager",
"config": {
...
"rds": {
"config_source": {
"ads": {}
},
"route_config_name": "http.443"
},
...
可以看到经过该 Listener 的流量被转交给 RDS http.443
,由于此时我们还没有创建 VirtualService
,所以 RDS http.443
中不会包含任何有意义的路由,它会直接返回 404
状态码。
$ istioctl -n istio-system pc route istio-egressgateway-f8b6469db-fj6zr -o json
[
{
"name": "http.443",
"virtualHosts": [
{
"name": "blackhole:443",
"domains": [
"*"
],
"routes": [
{
"match": {
"prefix": "/"
},
"directResponse": {
"status": 404
},
"perFilterConfig": {
"mixer": {}
}
}
]
}
],
"validateClusters": false
}
]
VirtualService 和 DestinationRule#
创建一个 DestinationRule
和 VirtualService
来引导流量通过 Egress Gateway 与外部服务通信。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: cnn
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 443
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 443
route:
- destination:
host: edition.cnn.com
port:
number: 443
weight: 100
EOF
这里 VirtualService 会分别为网格内的应用和 Egress Gateway 各创建一条路由,以实现通过 Egress Gateway 访问目的地址 edition.cnn.com:443
。具体的 Envoy 配置解析与上一篇文章类似。
但此时我们仍然不能访问外部服务,因为 Egress Gateway 通过 443
端口发起连接的时候,使用的仍然是 HTTP
协议。所以我们需要让 Egress Gateway 在出口流量上执行 TLS 发起,使用 HTTPS
协议来访问外部服务。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: originate-tls-for-edition-cnn-com
spec:
host: edition.cnn.com
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 443
tls:
mode: SIMPLE # initiates HTTPS for connections to edition.cnn.com
EOF
现在所有的配置都已经完成,只要是访问 edition.cnn.com:80
的流量都会被 Egress Gateway 路由到 Cluster outbound|443||edition.cnn.com
,最后将流量转发到服务 https://edition.cnn.com:443
。
完整的流量转发流程如下图所示:
重新发送 HTTP 请求到 http://edition.cnn.com/politics。
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
HTTP/1.1 200 OK
...
content-length: 150793
...
输出应该与 Istio 出口流量的 TLS 中的输出相同:没有 301 Moved Permanently
信息。
HTTP
流量重定向到 Egress Gateway,并通过 Egress Gateway 发起 TLS 连接;到 443 端口的 HTTP
流量仍然直接通过应用的 sidecar 代理发起 TLS 连接。清理#
删除之前创建的 Istio 配置项:
$ kubectl delete gateway istio-egressgateway
$ kubectl delete serviceentry cnn
$ kubectl delete virtualservice direct-cnn-through-egress-gateway
$ kubectl delete destinationrule originate-tls-for-edition-cnn-com
$ kubectl delete destinationrule egressgateway-for-cnn