缺省狀態下,Istio服務網格內的Pod,由於其iptables將所有外發流量都透明的轉發給了sidecar,所以這些集羣內的服務無法訪問集羣之外的 URL,而只能處理集羣內部的目標。
控制出口流量描述瞭如何通過ServiceEntry將外部服務暴露給集羣內的客戶端
本文則通過一個官方的用例解釋如何通過Egress Gateway
配置Istio的出口流量,這個例子主要適用於兩種場景:
- 離開服務網格的所有流量必須流經一組專用節點,這一組節點會有特殊的監控和審查
- 集羣中不是所有節點都有public IP,定義egress網關,通過它引導所有出口流量並將public IP分配給egress網關節點,允許應用節點以受控方式訪問外部服務
環境準備
創建Kubernetes集羣
阿里雲容器服務Kubernetes 1.11.2目前已經上線,可以通過容器服務管理控制檯非常方便地快速創建 Kubernetes 集羣。具體過程可以參考這裏
部署istio
阿里雲容器服務在應用目錄
目前支持istio快速部署,具體過程可以參考這裏
部署用例
kubectl apply -f <(istioctl kube-inject -f https://raw.githubusercontent.com/istio/istio/release-1.0/samples/sleep/sleep.yaml)
定義需要向外發送請求的pod
export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
創建ServiceEntry
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: cnn
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
驗證配置生效
kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
如下返回表示配置生效
HTTP/1.1 301 Moved Permanently
...
location: https://edition.cnn.com/politics
...
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
...
創建Gateway
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-egressgateway
spec:
selector:
istio: egressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- edition.cnn.com
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: egressgateway-for-cnn
spec:
host: istio-egressgateway.istio-system.svc.cluster.local
subsets:
- name: cnn
EOF
創建VirtualService
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: direct-cnn-through-egress-gateway
spec:
hosts:
- edition.cnn.com
gateways:
- istio-egressgateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
- match:
- gateways:
- istio-egressgateway
port: 80
route:
- destination:
host: edition.cnn.com
port:
number: 80
weight: 100
EOF
再次發送請求
kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
此時返回應該仍然是成功的,但是我們查看istio-egressgateway
的日誌
kubectl logs $(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') egressgateway -n istio-system | tail
應該會有一條類似這樣的記錄
[2018-06-14T11:46:23.596Z] "GET /politics HTTP/2" 301 - 0 0 3 1 "172.30.146.87" "curl/7.35.0" "ab7be694-e367-94c5-83d1-086eca996dae" "edition.cnn.com" "151.101.193.67:80"
說明出口流量已經匯入egress gateway
,然後由他引導至集羣外部
配置解釋
在本例中創建了四種資源,真正定義將出口流量轉發給egress gateway
的是VirtualService
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
subset: cnn
port:
number: 80
weight: 100
這一段配置中的match
的gateways
表示這一條路由規則是作用在mesh
上的,也就是整個網格中所有的sidecar上,port
表示所有訪問80端口的流量纔會應用這條規則,因爲本例中只提供了80端口的服務,所以這一項是可以省略掉的
destination
表示會把所有路由後的流量導入istio-egressgateway.istio-system.svc.cluster.local
service的cnn
sbuset下的80端口,這裏需要注意的是,istio-egressgateway
是在Istio部署時定義的service,已經開放了80,443端口,在真實使用中如果要用到別的端口,需要在istio-egressgateway
的定義中做對應的修改
同理,VirtualService
中的另一部分規則作用在istio-egressgateway
上,會把出口流量引導至集羣外部
總結
本文通過示例演示了Istio如何對網格內的出口流量做統一的引導。
歡迎大家使用阿里雲上的容器服務,快速搭建微服務的開放治理平臺Istio,比較簡單地集成到自己項目的微服務開發中。
歡迎大家使用阿里雲上的容器服務,快速搭建微服務的開放治理平臺Istio,比較簡單地集成到自己項目的微服務開發中。