概述
网关是一个运行在网格边缘的负载均衡器,它主要用于接收外部请求并转发给网格内的服务。
对于一个网关而言,需要配置对外的端口、协议以及并将其与网格内部的服务映射起来。
在 Istio 中包含两种类型的网关:
- Ingress 网关: 控制网格外部访问网格内部服务的流量;
- Egress 网关: 控制网格内部服务调用网格外部服务的流量。
实战
在本文在,我们将会演示 Istio 中创建一个入口网关,并将进入网格的流量分发到不同的地址。
具体来说,希望你通过本文的学习可以掌握:
- 通过Gateway控制入口流量;
- 掌握 Gateway 的配置方法。
StepByStep
Step1:检查当前的 gateway 列表
kubectl get gw -n istio-demo
# NAME AGE
# bookinfo-gateway 9h
可以看到,目前应该仅有一个我们在之前 QuickStart 中创建的对应的网关。
如果有其他的网关,那么建议先进行删除。
Step2:创建detail服务网关
我们可以准备如下一个 detail-gateway.yaml 的配置文件:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: detail-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: detail-vs
spec:
hosts:
- "*"
gateways:
- detail-gateway
http:
- match:
- uri:
prefix: /details
- uri:
exact: /health
route:
- destination:
host: details
port:
number: 9080
然后运行 kubectl 使得上述配置生效:
kubectl apply -f samples/bookinfo/networking/detail-gateway.yaml -n istio-demo
# gateway.networking.istio.io/detail-gateway created
# virtualservice.networking.istio.io/detail-vs created
Step3:测试一下
下面,我们来测试一下看看吧。
在 QuickStart 中,我们已经演示和如何查询 Ingress 的IP和Port了,如果你不太记得了,没关系,可以用如下命令来快速查询:
# 获取 ingress 的 HostIP
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
# 获取 ingress 的 HTTP Port
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
# 获取 ingress 的 HTTPS Port
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
# 具体的访问地址
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo "$GATEWAY_URL"
我们可以先访问 /health 接口看一下:
curl http://$GATEWAY_URL/health
# {"status":"Details is healthy"}
可以看到,/health 请求已经访问到了对应的服务。
再来看看 /details/21 接口呢?
curl http://$GATEWAY_URL/details/21
{
"id": 21,
"author": "William Shakespeare",
"year": 1595,
"type": "paperback",
"pages": 200,
"publisher": "PublisherA",
"language": "English",
"ISBN-10": "1234567890",
"ISBN-13": "123-1234567890"
}
同样,以 /details 开头的 url 访问也正常访问到了对应的 details 服务。
原理说明
配置分析
下面,我们来对刚才创建的 Gateway 配置和 VirtualService 的配置进行说明。
我们先来看 Gateway 资源对象的配置:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: detail-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
其中:
- selector 指定了具体在哪个Gateway部署对象上生效。
- servers 中包含了 hosts 和 ports 相关的配置,其中,端口本质上可以任意配置,只是由于端口映射等关系,导致通常只有几个端口可以正常使用。
可以看到,在 Gateway 的配置中,我们仅仅会定义网关的入口点,但是不涉及到具体的路由策略。
通过,我们还需要创建一个 VirtualService 来描述对应的路由规则:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: detail-vs
spec:
hosts:
- "*"
gateways:
- detail-gateway
http:
- match:
- uri:
prefix: /details
- uri:
exact: /health
route:
- destination:
host: details
port:
number: 9080
其中:
- gateways 指名了它是针对指定 Gateway 入口的流量进行路由的。
- http 块的部分就比较简单了,和前一篇文章中讲到的内容是一致的,本文中就不再赘述了。
资源配置项
了解了我们上述的配置信息,我们再来完整的看一下 Gateway 支持了哪些配置项以及它们的作用:
可以看到:
- Gateway 中包含 servers(配置入口点) 和 selector(选择网关Pod的标签)
- 在 Server 中描述了具体的入口点的端口、协议等信息。
- Gateway 本身不负责流量的路由;而是通过创建一个 VirtualService 来关联 Gateway 进行 Gateway 入口的流量路由。
使用场景
最后,我们来讨论一下 Ingress 有哪些使用场景呢?
- 首先,它可以将网格内的服务暴露给外界来访问;
- 其次,可以进行访问安全相关的配置,例如 HTTPS, mTLS 等;
- 最后,我们还可以通过 Ingress 来提供应用的统一入口和 API 聚合。
思考与实战
配置一个网关,只让特定域名的请求访问服务
我们在上文的了解中可以看到,在 Server 配置框中,有一个 hosts 字段可以用于过滤仅针对特定域名的访问时允许请求访问。
因此,我们可以修改 Gateway 的配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: detail-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- istio-gateway.com
下面,我们再来试试看?
kubectl apply -f samples/bookinfo/networking/detail-gateway.yaml -n istio-demo
# gateway.networking.istio.io/detail-gateway configured
# virtualservice.networking.istio.io/detail-vs unchanged
再次通过机器IP直接访问 /health 看看效果呢?
已经变为了404 Not Found了!
下面,我们来修改一下本机的 /etc/hosts 文件,增加一条将机器IP映射到 istio-gateway.com 域名的配置。
xxx.xxx.xxx.xxx istio-gateway.com
其中,xxx表示你的K8s机器IP地址。
下面,我们再来通过 istio-gateway.com:$port/health 来访问看看吧!
棒!已经可以了!