五、跨语言微服务框架 - Istio Ingress和Egress详解(解决Istio无法外网访问问题)

image

在微服务中另外一个重点就是网关,网关理论包含入口网关和出口网关,传统意义上的网关很难做到出口网络控制,但是对于Istio是一件非常轻松的事情(因为所有的出口流量都会经过Istio),入口网关控制解析路由数据流向,出口网关控制对外访问的限制,在Istio中使用了 Ingress和Egress 来实现网关的功能.

附上:

喵了个咪的博客:w-blog.cn

Istio官方地址:https://preliminary.istio.io/zh

Istio中文文档:https://preliminary.istio.io/zh/docs/

PS : 此处基于当前最新istio版本1.0.3版本进行搭建和演示

一. Ingress(入口网关)

Istio的网关运行配置路由规则以及流量如何进入到集群中,我们使用httpbin来作为实验项目

>kubectl apply -n istio-test -f istio-1.0.3/samples/httpbin/httpbin.yaml

  1. 确定入口 IP 和端口

执行以下命令以确定您的 Kubernetes 集群是否在支持外部负载均衡器的环境中运行。

> kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                                                                                                                   AGE
istio-ingressgateway   LoadBalancer   10.43.92.244   172.16.0.203   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30921/TCP,8060:30126/TCP,853:30117/TCP,15030:31865/TCP,15031:30683/TCP   22h

如果环境不再一套内网中使用了负载均衡,需要使用映射的对应的IP和端口,笔者是内网所以对应的访问可以通过其中的任意一个节点即可

  1. 使用 Istio 网关配置 Ingress

Ingress Gateway描述了在网格边缘操作的负载平衡器,用于接收传入的 HTTP/TCP 连接。它配置暴露的端口,协议等,但与 Kubernetes Ingress Resources 不同,它不包括任何流量路由配置。流入流量的流量路由使用 Istio 路由规则进行配置,与内部服务请求完全相同。

让我们看看如何为 Gateway 在 HTTP 80 端口上配置流量。

kubectl apply -n istio-test -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
EOF

为通过 Gateway 进入的流量配置路由:

kubectl apply -n istio-test -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

在这里,我们 为服务创建了一个虚拟服务配置 httpbin ,其中包含两条路由规则,允许路径 /status 和 路径的流量 /delay。

该网关列表指定,只有通过我们的要求 httpbin-gateway 是允许的。所有其他外部请求将被拒绝,并返回 404 响应。

请注意,在此配置中,来自网格中其他服务的内部请求不受这些规则约束,而是简单地默认为循环路由。要将这些(或其他规则)应用于内部调用,我们可以将特殊值 mesh 添加到 gateways 的列表中。

  1. 使用 curl 访问 httpbin 服务:
curl -I -HHost:httpbin.example.com http://172.16.0.203:31380/status/200
HTTP/1.1 200 OK
server: envoy
date: Thu, 08 Nov 2018 02:35:52 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 46

请注意,这里使用该 -H 标志将 Host HTTP Header 设置为 “httpbin.example.com”。这以操作是必需的,因为上面的 Ingress Gateway 被配置为处理 “httpbin.example.com”,但在测试环境中没有该主机的 DNS 绑定,只是将请求发送到 Ingress IP。

  1. 访问任何未明确公开的其他 URL,应该会看到一个 HTTP 404 错误:
curl -I -HHost:httpbin.example.com http://172.16.0.203:31380/headers
HTTP/1.1 404 Not Found
date: Thu, 08 Nov 2018 02:36:32 GMT
server: envoy
transfer-encoding: chunked

二. Egress(出口网关)

入口网关大家都很好理解不就是一个NGINX域名解析路由控制嘛,你这个出口网关有啥用啊? 在日益精细化运维管理的今天对于出口流量的控制越来越重要, 可以访问什么不可以访问什么对每一个程序来说应该都是确定的,这样的限制可以避免异常流量外部攻击等.

缺省情况下,Istio 服务网格内的 Pod,由于其 iptables 将所有外发流量都透明的转发给了 Sidecar,所以这些集群内的服务无法访问集群之外的 URL,而只能处理集群内部的目标。

这就导致了文章开头所说的问题Istio无法外网访问,如果大家的数据库不在集群内就会发现根本连不上

我们还是使用sleep来作为我们的例子

> kubectl apply -n istio-test -f istio-1.0.3/samples/sleep/sleep.yaml
> export SOURCE_POD=$(kubectl get -n istio-test pod -l app=sleep -o jsonpath={.items..metadata.name})
# 尝试访问(访问任何外部地址都会出现404)
> kubectl exec -n istio-test -it $SOURCE_POD -c sleep bash
crul -I baidu.com
bash: crul: command not found
root@sleep-76df4f989c-9hvvd:/# curl -I baidu.com
HTTP/1.1 404 Not Found
date: Thu, 08 Nov 2018 03:37:16 GMT
server: envoy
transfer-encoding: chunked

  1. 配置外部服务
kubectl apply -n istio-test -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: baidu-ext
spec:
  hosts:
  - baidu.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  location: MESH_EXTERNAL
EOF

创建一个 ServiceEntry 以及 VirtualService,允许访问外部 HTTPS 服务。注意:包括 HTTPS 在内的 TLS 协议,在 ServiceEntry 之外,还需要创建 TLS VirtualService

> kubectl exec -n istio-test -it $SOURCE_POD -c sleep bash
> curl -I baidu.com
HTTP/1.1 200 OK
date: Thu, 08 Nov 2018 03:37:57 GMT
server: envoy
last-modified: Tue, 12 Jan 2010 13:48:00 GMT
etag: "51-47cf7e6ee8400"
accept-ranges: bytes
content-length: 81
cache-control: max-age=86400
expires: Fri, 09 Nov 2018 03:37:57 GMT
content-type: text/html
x-envoy-upstream-service-time: 67

  1. 配置外部 HTTPS 服务

上面只配置了http可以访问,如果使用https会出现以下情况

> curl -I https://baidu.com
curl: (35) Unknown SSL protocol error in connection to baidu.com:443 

创建一个 ServiceEntry 和一个 VirtualService 以允许访问外部 HTTPS 服务。请注意, 对于 TLS 协议(包括 HTTPS),除了 ServiceEntry 之外,还需要 VirtualService。 VirtualService 必须在 match 子句中包含 tls 规则和 sni_hosts 以启用 SNI 路由。

kubectl apply -n istio-test -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: baidu
spec:
  hosts:
  - baidu.com
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
  location: MESH_EXTERNAL
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: baidu
spec:
  hosts:
  - baidu.com
  tls:
  - match:
    - port: 443
      sni_hosts:
      - baidu.com
    route:
    - destination:
        host: baidu.com
        port:
          number: 443
      weight: 100
EOF

> curl -I https://baidu.com
HTTP/1.1 302 Moved Temporarily
Server: bfe/1.0.8.18
Date: Thu, 08 Nov 2018 03:41:05 GMT
Content-Type: text/html
Content-Length: 161
Connection: keep-alive
Location: http://www.baidu.com/

  1. 为外部服务设置路由规则

通过 ServiceEntry 访问外部服务的流量,和网格内流量类似,都可以进行 Istio 路由规则 的配置。下面我们使用 istioctl 为 httpbin.org 服务设置一个超时规则。

在测试 Pod 内部,使用 curl 调用 httpbin.org 这一外部服务的 /delay 端点:

> kubectl apply -n istio-test -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-ext
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  location: MESH_EXTERNAL
EOF
> time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5
200

real    0m5.752s
user    0m0.013s
sys     0m0.022s

使用 kubectl 为 httpbin.org 外部服务的访问设置一个 3 秒钟的超时

kubectl apply -n istio-test -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin-ext
spec:
  hosts:
    - httpbin.org
  http:
  - timeout: 3s
    route:
      - destination:
          host: httpbin.org
        weight: 100
EOF

这一次会在 3 秒钟之后收到一个内容为 504 (Gateway Timeout) 的响应。虽然 httpbin.org 还在等待他的 5 秒钟,Istio 却在 3 秒钟的时候切断了请求。

time curl -o /dev/null -s -w "%{http_code}\n" http
504

real    0m3.046s
user    0m0.010s
sys     0m0.010s

  1. 直接调用外部服务

确认限制可以带来更多的控制避免出错,但是很多时候还是会带来很多麻烦,那么如果不希望Istio进行限制可以随意的访问需要怎么办呢?当然是可以的,可以配置Istio对于哪些范围,首先我们需要确定内部集群IP范围:

  • 使用minikube 范围是 10.0.0.1/24
  • 使用rancher 范围是 10.43.0.1/24

方案一(HELM):

注意这里应该使用和之前部署 Istio 的时候同样的 Helm 命令,尤其是 --namespace 参数。在安装 Istio 原有命令的基础之上,加入 --set global.proxy.includeIPRanges="10.0.0.1/24" -x templates/sidecar-injector-configmap.yaml 即可。

helm template install/kubernetes/helm/istio <安装 Istio 时所使用的参数> --set global.proxy.includeIPRanges="10.0.0.1/24" -x templates/sidecar-injector-configmap.yaml | kubectl apply -f -

然后重新部署sleep就可以了

方案二(改编排):

应为笔者不是使用helm进行的istio安装,直接使用的官方demo来安装的,我们可以先找到includeOutboundIPRanges然后修改后面的*改成对应的IP段

PS : 不同版本生成的yaml是不一样的需要注意

istio-1.0.1版本

- "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges"  ]]"
[[ else -]]
- "10.43.0.1/24"
[[ end -]]

istio1.0.3版本

- "[[ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges`  "10.43.0.1/24"  ]]"

然后重新部署Istio就可以没有任何访问限制了

作者:文振熙
链接:https://www.jianshu.com/p/03bf0f54b301
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容