前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Istio 大入门 — Egress Gateway

Istio 大入门 — Egress Gateway

作者头像
崔秀龙
发布2019-07-23 15:05:16
3.4K0
发布2019-07-23 15:05:16
举报
文章被收录于专栏:伪架构师伪架构师

Istio 还是早期版本的时候,我曾经有个蒙事的混蛋设想:在网格里面搭建一个反向代理,用于代理网格甚至是集群之外的存量应用,让这些改不得甚至动不得又正在赚钱的应用,以网格内成员的身份对网格中的微服务提供服务。后来知道了,Istio 的 Egress Gateway 实现了这一混蛋想法。

原理

根据官方文档的解释:

Gateway 描述了一个负载均衡器,用于承载网格边缘的进入和发出连接。这一规范中描述了一系列开放端口,以及这些端口所使用的协议、负载均衡的 SNI 配置等内容。

之前的 Service Entry 一文中讲到了 ServiceEntry 对象,让网格内部的应用在访问外部应用时,可以使用 VirtualService 进行部分控制。但是如果我们进一步尝试策略的话,会发现常用的 Denier 等适配器都是无效的(这点并没有经过官方验证)。这里就需要使用刚才说的 Egress Gateway 了。

根据官方示例介绍,这种方式的基本访问流程是:

  1. 建立 Service Entry 对象,注册外部服务。
  2. 建立 Egress Gateway 注册出口。
  3. 创建 DestinationRule,定义一个到 istio-egressgateway.istio-system.svc.cluster.local 服务 的目标规则。
  4. 创建 VirtualService 对象,这一对象对主机名 edition.cnn.com 生效:
    • 如果流量发生在 mesh gateway,则把请求转发给 istio-egressgateway.istio-system 服务。
    • 如果流量发生在 egress gateway,则把请求转发到外部。

开始之前

跟前文一样,需要部署两个版本的 sleep 服务。源码见后。

代码语言:javascript
复制
$ istioctl kube-inject -f sleep-v1v2.yaml | kubectl apply -f -
service/sleep created
deployment.extensions/sleep-v1 created
deployment.extensions/sleep-v2 created

接下来把两个版本的 Pod 分别保存到环境变量之中。

代码语言:javascript
复制
$ export SLEEP_V1=$(kubectl get pod -l app=sleep,version=v1 -o jsonpath={.items..metadata.name})
$ export SLEEP_V2=$(kubectl get pod -l app=sleep,version=v2 -o jsonpath={.items..metadata.name})
$ env | grep SLEEP
SLEEP_V2=sleep-v2-69f4fc6c68-s9d96
SLEEP_V1=sleep-v1-d5b4f795f-fcrxs

再建立一个 ServiceEntry,完成准备工作。

代码语言:javascript
复制
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
 name: httpbin-ext
spec:
 hosts:
   - httpbin.org
 ports:
   - number: 80
     name: http
     protocol: HTTP
 resolution: DNS

设立别名并确认可访问性:

代码语言:javascript
复制
$ alias S1_HTTPBIN="kubectl exec -it $SLEEP_V1 -c sleep -- curl http://httpbin.org/ip"
$ alias S2_HTTPBIN="kubectl exec -it $SLEEP_V2 -c sleep -- curl http://httpbin.org/ip"
$ S1_HTTPBIN
{
 "origin": "13.67.109.88"
}

成功返回。

创建 Gateway 和 DestinationRule

建立 Gateway

这里为域名 “httpbin.org” 创建一个网关,selector 字段表明这里使用的是 Egress gateway。

代码语言:javascript
复制
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: httpbin-gateway
spec:
 selector:
   istio: egressgateway
 servers:
   - port:
       number: 80
       name: http
       protocol: HTTP
     hosts:
       - httpbin.org

为服务 istio-egressgateway 创建一个目标规则

代码语言:javascript
复制
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: dest-rule-httpbin
spec:
 host: istio-egressgateway.istio-system.svc.cluster.local
 subsets:
   - name: ext

上面的 host 字段使用了 istio-egressgateway 的 FQDN,指向 istio-system 命名空间。

创建 VirtualService

代码语言:javascript
复制
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: vs-httpbin
spec:
 hosts:
   - httpbin.org # 这一对象对域名 “httpbin.org” 生效。
 gateways: # 本对象所针对的 Gateway。
   - httpbin-gateway # 前面为 “httpbin.org” 注册的 Egress gateway。
   - mesh # 内置 Gateway,代表网格中的所有 Sidecar
 http:
   - match: # 这一条规则匹配的是 “mesh” Gateway 的流量
       - gateways:
           - mesh
         port: 80
     route: # 如果是 “mesh” gateway 的流量,则转发到 egress 网关服务。
       - destination:
           host: istio-egressgateway.istio-system.svc.cluster.local
           subset: ext
           port:
             number: 80
         weight: 100
   - match:
       - gateways: # 这一条规则匹配的是外发流量
           - httpbin-gateway
         port: 80
     route: # 通过 Service Entry 流向目标的外网流量
       - destination:
           host: httpbin.org
           port:
             number: 80
         weight: 100

这一对象创建之后,我们再次尝试访问 “http://httpbin.org/ip” :

代码语言:javascript
复制
$ S1_HTTPBIN
{
 "origin": "10.240.0.41, 13.67.109.88"
}

可以看到访问成功,并且返回地址中因为转发的原因,代入了 Pod IP。

如果查看 Egress gateway controller 的日志,也会看到这一访问的踪迹:

代码语言:javascript
复制
$ kubetail  egress -n istio-system
Will tail 1 logs...
istio-egressgateway-55449548bd-99mvl
[istio-egressgateway-55449548bd-99mvl] [2018-08-25T15:07:29.272Z] "GET /ip HTTP/2" 200 - 0 44 477 473 "10.240.0.41" "curl/7.35.0" "e9cc4d93-7617-9f97-b29e-3411c3b66543" "httpbin.org" "52.73.140.127:80"

加入策略限制

经过上面一番折腾之后,应用对外部网站的请求就有了一段完全在网格内的部分,接下来就可尝试使用策略了。

Denier

首先我们尝试编写一个 Denier 策略,只允许 “v2” 版本对 “httpbin.org” 的访问:

注意:跨命名空间的策略,必须在 “istio-system” 命名空间中创建。

代码语言:javascript
复制
---
apiVersion: config.istio.io/v1alpha2
kind: denier
metadata:
 name: denysleepv1
 namespace: istio-system
spec:
 status:
   code: 7
   message: Not allowed
---
apiVersion: config.istio.io/v1alpha2
kind: checknothing
metadata:
 name: denysleepv1request
 namespace: istio-system
spec: null
---
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
 name: deneysleepv1
 namespace: istio-system
spec:
 match: >-
   source.labels["app"]=="sleep" && source.labels["version"]=="v1" &&
   request.host=="httpbin.org"
 actions:
   - handler: denysleepv1.denier
     instances:
       - denysleepv1request.checknothing

创建这一策略之后进行验证:

代码语言:javascript
复制
 $ kubectl apply -f denier.yaml -n istio-system
denier.config.istio.io/denysleepv1 created
checknothing.config.istio.io/denysleepv1request created
rule.config.istio.io/deneysleepv1 created
$ S1_HTTPBIN
PERMISSION_DENIED:denysleepv1.denier.istio-system:Not allowed
$ S2_HTTPBIN
{
 "origin": "10.240.0.21, 13.67.109.88"
}

由上面的测试可以看到,策略应用之后。来自 “v1” 的请求被禁止。如果进一步测试还可以发现,“v1” 服务对其他的访问还是可以照常进行。

补充:1.0.1 中,ServiceEntry 应该在 istio-system 中创建。

频率限制

再次失败,等 Issue。

源码

sleep.yaml

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
 name: sleep
 labels:
   app: sleep
spec:
 selector:
   app: sleep
 ports:
   - name: ssh
     port: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: sleep-v1
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: sleep
       version: v1
   spec:
     containers:
     - name: sleep
       image: dustise/sleep:latest
       imagePullPolicy: IfNotPresent
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: sleep-v2
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: sleep
       version: v2
   spec:
     containers:
     - name: sleep
       image: dustise/sleep:latest
       imagePullPolicy: IfNotPresent
---
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 伪架构师 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理
  • 开始之前
  • 创建 Gateway 和 DestinationRule
    • 建立 Gateway
      • 为服务 istio-egressgateway 创建一个目标规则
      • 创建 VirtualService
      • 加入策略限制
      • Denier
      • 频率限制
      • 源码
        • sleep.yaml
        相关产品与服务
        负载均衡
        负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档