原文连接:Istio 服务网格中的网关html
在一个典型的网格中,一般有一个或多个用于终结外部 TLS 连接,将流量引入网格的负载均衡器(咱们称之为 gateway)。 而后流量经过边车网关(sidecar gateway)流经内部服务。 应用程序使用外部服务的状况也很常见(例如访问 Google Maps API),一些状况下,这些外部服务可能被直接调用;但在某些部署中,网格中全部访问外部服务的流量可能被要求强制经过专用的出口网关(Egress gateway)。 下图描绘了网关在网格中的使用状况。node
其中 Gateway
是一个独立于平台的抽象,用于对流入专用中间设备的流量进行建模。下图描述了跨多个配置资源的控制流程。api
Gateway 用于为 HTTP / TCP 流量配置负载均衡器,并无论该负载均衡器将在哪里运行。 网格中能够存在任意数量的 Gateway,而且多个不一样的 Gateway 实现能够共存。 实际上,经过在配置中指定一组工做负载(Pod)标签,能够将 Gateway 配置绑定到特定的工做负载,从而容许用户经过编写简单的 Gateway Controller 来重用现成的网络设备。浏览器
对于入口流量管理,您可能会问: 为何不直接使用 Kubernetes Ingress API ? 缘由是 Ingress API 没法表达 Istio 的路由需求。 Ingress 试图在不一样的 HTTP 代理之间取一个公共的交集,所以只能支持最基本的 HTTP 路由,最终致使须要将代理的其余高级功能放入到注解(annotation)中,而注解的方式在多个代理之间是不兼容的,没法移植。bash
Istio Gateway
经过将 L4-L6 配置与 L7 配置分离的方式克服了 Ingress
的这些缺点。 Gateway
只用于配置 L4-L6 功能(例如,对外公开的端口,TLS 配置),全部主流的L7代理均以统一的方式实现了这些功能。 而后,经过在 Gateway
上绑定 VirtualService
的方式,可使用标准的 Istio 规则来控制进入 Gateway
的 HTTP 和 TCP 流量。网络
例如,下面这个简单的 Gateway
配置了一个 Load Balancer,以容许访问 host bookinfo.com
的 https 外部流量进入网格中:负载均衡
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- bookinfo.com
复制代码
要为进入上面的 Gateway 的流量配置相应的路由,必须为同一个 host 定义一个 VirtualService(参考上一篇博文),并使用配置中的 gateways
字段绑定到前面定义的 Gateway
上:curl
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
gateways:
- bookinfo-gateway # <---- bind to gateway
http:
- match:
- uri:
prefix: /reviews
route:
...
复制代码
Gateway 能够用于建模边缘代理或纯粹的内部代理,如第一张图所示。 不管在哪一个位置,全部网关均可以用相同的方式进行配置和控制。ide
下面经过一个示例来演示如何配置 Istio 以使用 Istio Gateway 在服务网格外部公开服务。post
让咱们看看如何为 Gateway 在 HTTP 80 端口上配置流量。
建立一个 Istio Gateway
$ cat <<EOF | istioctl create -f - 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 进入的流量配置路由
$ cat <<EOF | istioctl create -f - 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
复制代码
在这里,咱们 为服务建立了一个 VirtualService 配置 httpbin
,其中包含两条路由规则,容许路径 /status
和 路径的流量 /delay
。
该网关列表指定,只有经过咱们的要求 httpbin-gateway
是容许的。全部其余外部请求将被拒绝,并返回 404 响应。
请注意,在此配置中,来自网格中其余服务的内部请求不受这些规则约束,而是简单地默认为循环路由。要将这些(或其余规则)应用于内部调用,咱们能够将特殊值 mesh
添加到 gateways
的列表中。
使用 curl 访问 httpbin 服务。
首先获取 Ingress Gateway 的 IP 和 端口,参考上一篇文章:Istio 流量管理
$ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/status/200
HTTP/1.1 200 OK
server: envoy
date: Thu, 02 Aug 2018 04:18:41 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: 9
复制代码
请注意,咱们使用该 -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://$INGRESS_HOST:$INGRESS_PORT/headers
HTTP/1.1 404 Not Found
date: Thu, 02 Aug 2018 04:21:39 GMT
server: envoy
transfer-encoding: chunked
复制代码
若是你想在浏览器中输入 httpbin 服务的 URL 来访问是行不通的,由于咱们没有办法像使用 curl 同样告诉浏览器伪装访问 httpbin.example.com
,只能经过向 /etc/hosts
文件中添加 hosts 来解决这个问题。
可是麻烦又来了,目前这种情况下即便你添加了 hosts,也仍然没法访问,由于 Istio Gateway 使用的是 NodePort 模式,暴露出来的不是 80 端口和 443 端口,而咱们要想经过域名来访问服务,必需要求 Gateway 暴露出来的端口是 80 和 443。
因此咱们只能曲线救国了,经过修改 Ingress Gateway 的 Deployment
,将 80 端口和 443 端口配置为 hostPort
模式,而后再经过 Node 亲和性将 Gateway
调度到某个固定的主机上。
$ kubectl -n istio-system edit deployment istio-ingressgateway
复制代码
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: istio-ingressgateway
namespace: istio-system
...
spec:
...
template:
...
spec:
affinity:
nodeAffinity:
...
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 192.168.123.248 # 好比你想调度到这台主机上
containers:
- name: ISTIO_META_POD_NAME
...
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
...
复制代码
修改完以后保存退出,等待 Gateway 的 Pod 从新调度,而后在你的浏览器所在的本地电脑上添加一条 hosts:
192.168.123.248 httpbin.example.com
复制代码
从新配置 VirtualService
:
$ cat <<EOF | istioctl replace -f - 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
- uri:
prefix: /headers
route:
- destination:
port:
number: 8000
host: httpbin
EOF
复制代码
接下来就能够在浏览器中输入 URL:http://httpbin.example.com/headers
来访问服务啦!
删除 Gateway、VirtualService 和 httpbin 服务:
$ istioctl delete gateway httpbin-gateway
$ istioctl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml
复制代码