前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Istio 的高级边缘流量控制(一)

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

作者头像
米开朗基杨
发布2019-08-29 12:05:19
1.6K0
发布2019-08-29 12:05:19
举报
文章被收录于专栏:云原生实验室

在上一篇文章 Istio 出口流量的 TLS 中,我演示了如何在网格内部直接通过 HTTP 协议访问外部加密服务,并揭示了其背后 Envoy 的配置逻辑。

本文将会通过 Egress Gateway 来引导 Istio 的出口流量,与 Istio 出口流量的 TLS 任务中描述的功能的相同,唯一的区别就是,这里会使用 Egress Gateway 来完成这一任务。

Istio 0.8 引入了 ingress 和 Egress gateway 的概念。 Ingress Gateway 允许定义进入服务网格的流量入口,所有入站流量都通过该入口;Egress Gateway 与之相对,它定义了网格的流量出口。 Egress Gateway 允许将 Istio 的流量治理功能(例如,监控和路由规则)应用于 Egress 流量。

1. 用例

设想一个具有严格安全要求的组织。根据这些要求,服务网格的所有出口流量必须流经一组专用节点。这些节点与运行其他应用的节点分开,通过策略来控制出口流量。相比其他节点而言,对这些专用节点的监控也更加详细。

另一个用例是设想一个集群,它的应用程序所在的节点没有外网 IP,因此在其上运行的网格内服务无法访问外网服务。通过定义 Egress Gateway,并将公共 IP 分配给 Egress Gateway 节点,然后通过它引导所有出口流量,就可以控制网格内服务访问外网服务了。

2. 前提条件

  • 按照安装指南中的说明设置 Istio 。
  • 启动 sleep 示例,它将作为外部调用的测试源。

如果您已启用自动注入 sidecar, 请按如下命令部署 sleep 应用程序:

代码语言:javascript
复制
$ kubectl apply -f samples/sleep/sleep.yaml

否则,您必须在部署 sleep 应用程序之前手动注入 sidecar:

代码语言:javascript
复制
$ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml)

请注意,任何可以 execcurl 的 pod 都可以执行以下步骤。

  • 创建一个 shell 变量来保存源 pod 的名称,以便将请求发送到外部服务, 如果您使用 sleep 示例,请按如下命令运行:
代码语言:javascript
复制
$ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})

3. 定义 Egress Gateway 来引导 Istio 的出口 HTTP 流量

首先创建一个 ServiceEntry 以允许网格内服务访问外部服务。

1. 为 edition.cnn.com 定义一个 ServiceEntry

2. 验证 ServiceEntry 是否生效。发送 HTTPS 请求到 http://edition.cnn.com/politics。

代码语言:javascript
复制
$ 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
...

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
...

此处的返回结果应该与 Istio 出口流量的 TLS 中没有配置 TLS 发起的情况下的返回结果相同。

3. 为 edition.cnn.com 的 80 端口创建一个 Egress Gateway(假设没有启用双向 TLS 认证)。

此处 Istio 会将 Gateway 翻译成 Egress Gateway 所在的 Pod 的 Listener。具体配置如下:

代码语言:javascript
复制
$ istioctl -n istio-system pc listeners istio-egressgateway-f8b6469db-4csb2 -o json
代码语言:javascript
复制
[
    {
        "name": "0.0.0.0_80",
        "address": {
            "socketAddress": {
                "address": "0.0.0.0",
                "portValue": 80
            }
        },
        "filterChains": [
            {
                "filters": [
                    {
                        "name": "envoy.http_connection_manager",
                        "config": {
                            ...
                            "rds": {
                                "config_source": {
                                    "ads": {}
                                },
                                "route_config_name": "http.80"
                            },
                            ...

可以看到流量经过该 Listener 之后被转交给 RDS http.80,由于此时我们还没有创建 VirtualService,所以 RDS http.80 中不会包含任何有意义的路由,它会直接返回 404 状态码。

代码语言:javascript
复制
$ istioctl -n istio-system pc route istio-egressgateway-f8b6469db-4csb2 -o json
代码语言:javascript
复制
[
    {
        "name": "http.80",
        "virtualHosts": [
            {
                "name": "blackhole:80",
                "domains": [
                    "*"
                ],
                "routes": [
                    {
                        "match": {
                            "prefix": "/"
                        },
                        "directResponse": {
                            "status": 404
                        },
                        "perFilterConfig": {
                            "mixer": {}
                        }
                    }
                ]
            }
        ],
        "validateClusters": false
    }
]

此处的 validateClusters 用来决定集群管理器是否对路由表中指向的 Cluster 进行验证。如果该参数设置为 true且路由指向了不存在的集群,则不会加载该路由表;如果该参数设置为 false 且路由指向了不存在的集群,则会继续加载该路由表,最后找不到路由会返回 404。如果通过静态配置文件 route_config 定义路由表,则该选项默认值为 true;如果通过 RDS 接口动态加载路由器,则该选项默认值为 false

如果你启用了双向 TLS 认证,需要加上额外的 TLS 配置,这里我不展开详述,可以参考官方文档。

4. 创建一个 DestinationRuleVirtualService 来引导流量通过 Egress Gateway 与外部服务通信。

这里其实创建了两条路由,我们一个一个来看:

  • ① : gateway 选择了 mesh,表示该路由创建在网格内的应用中:
代码语言:javascript
复制
$ istioctl pc route sleep-5bc866558c-5nl8k --name 80 -o json|grep "edition.cnn.com" -A 11 -B 1
代码语言:javascript
复制
{
    "name": "edition.cnn.com:80",
    "domains": [
        "edition.cnn.com",
        "edition.cnn.com:80"
    ],
    "routes": [
        {
            "match": {
                "prefix": "/"
            },
            "route": {
                "cluster": "outbound|80|cnn|istio-egressgateway.istio-system.svc.cluster.local",
                "timeout": "0.000s",
                "maxGrpcTimeout": "0.000s"
            },

如果不指定 gateway,gateway 默认值就是 mesh

该 VirtualService 的作用就是将目的地址是 edition.cnn.com:80 的流量重定向到 Egress Gateway

这里我们将流量打向了 subset 为 cnn 的 Cluster,但现在不存在这个 Cluster,所以还需要通过 DestinationRule 定义一个 Cluster:

查看创建好的 Cluster:

代码语言:javascript
复制
$ istioctl pc cluster sleep-5bc866558c-5nl8k --fqdn istio-egressgateway.istio-system.svc.cluster.local --subset cnn --port 80 -o json
代码语言:javascript
复制
[
    {
        "name": "outbound|80|cnn|istio-egressgateway.istio-system.svc.cluster.local",
        "type": "EDS",
        "edsClusterConfig": {
            "edsConfig": {
                "ads": {}
            },
            "serviceName": "outbound|80|cnn|istio-egressgateway.istio-system.svc.cluster.local"
        },
        "connectTimeout": "1.000s",
        "circuitBreakers": {
            "thresholds": [
                {}
            ]
        },
        "http2ProtocolOptions": {
            "maxConcurrentStreams": 1073741824
        }
    }
]
  • ② : gateway 选择了 istio-egressgateway,表示该路由创建在 Egress Gateway 中:
代码语言:javascript
复制
$ istioctl -n istio-system pc route istio-egressgateway-f8b6469db-fj6zr -o json
代码语言:javascript
复制
[
    {
        "name": "http.80",
        "virtualHosts": [
            {
                "name": "edition.cnn.com:80",
                "domains": [
                    "edition.cnn.com",
                    "edition.cnn.com:80"
                ],
                "routes": [
                    {
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "outbound|80||edition.cnn.com",
                            "timeout": "0.000s",
                            "maxGrpcTimeout": "0.000s"
                        },
                        ...

该 VirtualService 的作用是通过 Egress Gateway 访问目的地址 edition.cnn.com:80这里 Egress Gateway 将流量路由到 Cluster outbound|80||edition.cnn.com,最后将流量转发到服务 edition.cnn.com:80。完整的流量转发流程如下图所示:

通过 Egress Gateway 引导 Istio 的出口 HTTP 流量

5. 重新发送 HTTP 请求到 http://edition.cnn.com/politics。

代码语言:javascript
复制
$ 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
...

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
...

输出应与步骤 2 中的输出相同。

6. 查看 istio-egressgateway pod 中与我们的请求相对应的日志。

代码语言:javascript
复制
$ kubectl logs $(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') istio-proxy -n istio-system | tail

你会在输出结果中看到与请求相关的日志:

代码语言:javascript
复制
[2018-06-14T11:46:23.596Z] "GET /politics HTTP/1.1" 301 - 0 0 3 1 "172.30.146.87" "curl/7.35.0" "ab7be694-e367-94c5-83d1-086eca996dae" "edition.cnn.com" "151.101.193.67:80"

这里我们只将到 80 端口的 HTTP 流量重定向到 Egress Gateway,到 443 端口的 HTTPS 流量直接转到 edition.cnn.com

4. 清理

删除 Gateway、VirtualService、DestinationRule 和 ServiceEntry。

代码语言:javascript
复制
$ kubectl delete gateway istio-egressgateway
$ kubectl delete serviceentry cnn
$ kubectl delete virtualservice direct-cnn-through-egress-gateway
$ kubectl delete destinationrule egressgateway-for-cnn

5. 参考

  • 配置 Egress gateway
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-11-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云原生实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 用例
  • 2. 前提条件
  • 3. 定义 Egress Gateway 来引导 Istio 的出口 HTTP 流量
  • 4. 清理
  • 5. 参考
相关产品与服务
SSL 证书
腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档