icon

Sealos,在云桌面中运行分布式应用程序,像使用个人电脑一样使用云

icon
icon

扫码加入微信群,和云原生大佬们一起探讨云原生和不可描述的事情!

扫码加入微信群

Please enable Javascript to view the contents

Istio 的高级边缘流量控制(二)

通过 Egress gateway 发起 TLS 连接

 ·  ☕ 3 分钟  ·  ✍️ 米开朗基杨 · 👀... 阅读
像使用个人电脑一样使用 Sealos 走,看看去!

上一节我演示了如何通过 Egress Gateway 引导 Istio 的出口 HTTP 流量,但到 443 端口的 HTTPS 流量没有通过 Egress Gateway,而是直接转到 edition.cnn.com 。 Istio 出口流量的 TLS 演示了如何在网格内部直接通过 HTTP 协议访问外部加密服务。本文尝试将这两者结合起来,先将 HTTP 流量路由到 Egress Gateway,然后直接使用 Egress Gateway 发起 TLS 连接。

前提条件与 上一篇文章相同。

1. 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,还要继续执行以下步骤进行配置。

2. 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
    }
]

3. 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://edition.cnn.com

重新发送 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 信息。

注意,这里我们只将到 80 端口的 HTTP 流量重定向到 Egress Gateway,并通过 Egress Gateway 发起 TLS 连接;到 443 端口的 HTTP 流量仍然直接通过应用的 sidecar 代理发起 TLS 连接。

4. 清理


删除之前创建的 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

5. 参考


-------他日江湖相逢 再当杯酒言欢-------
分享
您的鼓励是我最大的动力
alipay QR Code
wechat QR Code

米开朗基杨
❉ 作者: 米开朗基杨 ❉
云原生搬砖师

公众号二维码

目录

点击屏幕右上角的 ···
在弹出的窗口中选择 在浏览器中打开