3.2.1.3 Ingress/Egress

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

附上:数据库

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

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

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

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

一. Ingress(入口网关)

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

>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 路由规则进行配置,与内部服务请求彻底相同。curl

让咱们看看如何为 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就能够没有任何访问限制了

发表评论

后才能评论