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
- 肯定入口 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和端口,笔者是内网因此对应的访问能够经过其中的任意一个节点便可运维
- 使用 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 的列表中。
- 使用 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。
- 访问任何未明确公开的其余 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
- 配置外部服务
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
- 配置外部 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/
- 为外部服务设置路由规则
经过 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
- 直接调用外部服务
确认限制能够带来更多的控制避免出错,可是不少时候仍是会带来不少麻烦,那么若是不但愿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就能够没有任何访问限制了