多个web服务接入共享ingressgateway

2,293 阅读5分钟

[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去实现

关键点说明:

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

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

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

    • 一般可以直接采用服务名,如果是同一个namespace下
    • 最好FQDN,写上完全限定域名
  4. 如果只是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路由到了不同的后端服务

【"欢迎关注我的微信公众号:Linux 服务端系统研发,后面会大力通过微信公众号发送优质文章"】

我的微信公众号