多个web服务接入共享ingressgateway
[TOC]
多个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去实现
关键点说明:
-
Gateway的servers的port要特别注意处理好,number和name不能随便定义,name有固定格式,number是要在ingressgateway真实配置好的
-
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路由到了不同的后端服务