多个web服务接入共享ingressgateway

背景

共享ingressgateway

首先,对ingressgateway而言,目前业界一致的做法就是共享ingressgateway,这个对于前期来看,也是足够了,只是需要保证ingressgateway不能单点,并且ingressgateway可以部署多个进行负载均衡。

因此,一个ingressgateway就需要支撑不同的业务接入,对于ingressgateway来说,Gateway资源配置为同一个端口,同一种协议,然后只要对应的VirtualService中配置不同的hosts,最后通过VirtualService的hosts路由到不同的服务就能解决。

外部统一的入口访问,指定不同hosts,然后VirtualService会有不同的路由规则,不冲突~

统一域名访问

另外一块在于统一的域名姿势访问,在K8S内部,创建Service的时候会默认给kube-DNS里面添加一条记录,然后可以通过服务名在Pod里面访问其他服务。

但是如果希望能够自定义域名,保持接入容器、接入istio和没有接入istio都有着同样的访问姿势的话,就需要能够自定义域名,当然,这个自定义域名必须首先能够解析,kube-DNS可以配置私有DNS和上游域名服务器,并且我们自己在K8S集群中针对这块DNS有做相关优化

现有K8S集群中,创建service的时候给定的这个默认的自定义域名,会写到机房的bind9中,也同时会写到我们外部的DNS解析服务器中,这样,这个域名就可以在集群内和集群外都能够解析访问。这个域最终会解析到LVS上,然后LVX下面就是ingress,也就是七层的负载均衡器,然后通过七层进行路由。

如果是其他特殊的自定义域名,那么需要运维手动配置,也是通过dnsPod和bind9,然后最后还是解析LVS上,然后进行7层路由

接入Istio后,要想还是保持原有统一域名的访问方式,那么这个自定义域名,同样需要解析,并且解析到LVS,LVS下面就是istio的ingress  gateway,然后通过host进行路由。因此client请求http处理的时候,需要携带Host用来进行路由。

这一点上,和K8S现有的域名管理姿势保持一致,只是自定义域名解析的LVS不同,一个LB的LVS,一个istio ingressgateway的LVS。

然后再一点就是在istio中,需要通过是VirtualService来配置路由,路由的区分是要通过hosts来区分

方案&实操

在MAC 本机上进行验证

ingressgateway

kubectl get svc -n istio-system  |grep istio-ingressgateway  istio-ingressgateway       NodePort    10.233.13.102   <none>        80:31380/TCP,443:31390/TCP,8081:31381/TCP,31499:31499/TCP,31400:31400/TCP,15011:32636/TCP,8060:32041/TCP,15030:31210/TCP,15031:32538/TCP   25d 复制代码

对于服务一:

hello-web 服务

1,服务一的部署配置如下:

apiVersion: v1 kind: Service metadata:   name: hello-web   labels:     app: hello-web spec:   ports:   - name: http-web     port: 12345   selector:     app: hello-web --- apiVersion: extensions/v1beta1 kind: Deployment metadata:   name: hello-web-v1 spec:   replicas: 1   template:     metadata:       labels:         app: hello-web         version: v1     spec:       containers:       - name: hello-web         image: wudebao5220150/webserver:1.0.0         imagePullPolicy: IfNotPresent         ports:         - containerPort: 12345 --- 复制代码

kubectl apply -f <(istioctl kube-inject -f hello-web.yaml)

2,网关和路由的配置如下:

apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:   name: hello-web-gateway spec:   selector:     istio: ingressgateway # use Istio default gateway implementation   servers:   - port:       number: 80       name: http       protocol: HTTP     hosts:     - "*.hello-web.com" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:   name: hello-web spec:   hosts:   - "www.hello-web.com"   gateways:   - hello-web-gateway   http:   - match:     - uri:         exact: /hello     route:     - destination:         port:           number: 12345         host: hello-web 复制代码

kubectl apply  -f hello-web-gateway.yaml

hosts为www.hello-web.com的请求,会路由到指定的http的match上。这里是入口,入口之后的路由,通过hosts进行区分,然后具体到下游Cluster的详尽规则由http的match去实现

对于服务二:

wudebao-web 服务

1,服务二的部署配置如下:

apiVersion: v1 kind: Service metadata:   name: wudebao-web   labels:     app: wudebao-web spec:   ports:   - name: http-web     port: 54321   selector:     app: wudebao-web --- apiVersion: extensions/v1beta1 kind: Deployment metadata:   name: wudebao-web spec:   replicas: 1   template:     metadata:       labels:         app: wudebao-web         version: v1     spec:       containers:       - name: wudebao-web         image: wudebao5220150/webserver-v2:1.0.0         imagePullPolicy: IfNotPresent         ports:         - containerPort: 54321 复制代码

kubectl apply -f <(istioctl kube-inject -f wudebao-web.yaml)

2,网关和路由的配置如下:

apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:   name: wudebao-web-gateway spec:   selector:     istio: ingressgateway # use Istio default gateway implementation   servers:   - port:       number: 80       name: http       protocol: HTTP     hosts:     - "*.wudebao-web.com" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:   name: wudebao-web spec:   hosts:   - "www.wudebao-web.com"   gateways:   - wudebao-web-gateway   http:   - match:     - uri:         exact: /wudebao     route:     - destination:         port:           number: 54321         host: wudebao-web 复制代码

kubectl apply -f wudebao-web-gateway.yaml

hosts为www.wwudebao-web.com的请求,会路由到指定的http的match上。这里是入口,入口之后的路由,通过hosts进行区分,然后具体到下游Cluster的详尽规则由http的match去实现

关键点说明:

  1. Gateway的servers的port要特别注意处理好,number和name不能随便定义,name有固定格式,number是要在ingressgateway真实配置好的

  2. VirtualService的spec下的hosts,需要指定,可以任意指定就比如可以是真实域名

  • 这个host设置为和访问的域名一样,然后client进行http请求的时候带上host,然后就可以通过host路由
  • 同时需要能够保证k8s能够解析这个自定义域名

VirtualService的route的destination的host,是真正要路由到cluster的服务

  • 一般可以直接采用服务名,如果是同一个namespace下
  • 最好FQDN,写上完全限定域名

如果只是ingressgateway,服务可以不用Sidecar,外部请求能够访问,但是不能应用到istio的一些针对服务的路由策略和规则

  • 因此,部署的时候,还是得Sidecar注入envoy代理才行

最终访问:

IP:Port一样,Host和URI不同,通过Host路由到不同的Service上:

 curl 172.31.36.68:31380/hello -H "Host: www.hello-web.com"  -v curl 172.31.36.68:31380/wudebao -H "Host: www.wudebao-web.com"  -v 复制代码

这样同时满足多个web服务的接入请求,不同host路由到了不同的后端服务