[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路由到了不同的後端服務