在微服務中另一個重點就是網關,網關理論包含入口網關和出口網關,傳統意義上的網關很難作到出口網絡控制,可是對於Istio是一件很是輕鬆的事情(由於全部的出口流量都會通過Istio),入口網關控制解析路由數據流向,出口網關控制對外訪問的限制,在Istio中使用了 Ingress和Egress 來實現網關的功能.html
附上:數據庫
喵了個咪的博客:w-blog.cnjson
Istio官方地址:https://preliminary.istio.io/zhapi
Istio中文文檔:https://preliminary.istio.io/zh/docs/bash
PS : 此處基於當前最新istio版本1.0.3版本進行搭建和演示網絡
Istio的網關運行配置路由規則以及流量如何進入到集羣中,咱們使用httpbin來做爲實驗項目app
>kubectl apply -n istio-test -f istio-1.0.3/samples/httpbin/httpbin.yaml
執行如下命令以肯定您的 Kubernetes 集羣是否在支持外部負載均衡器的環境中運行。負載均衡
> kubectl get svc istio-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.43.92.244 172.16.0.203 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30921/TCP,8060:30126/TCP,853:30117/TCP,15030:31865/TCP,15031:30683/TCP 22h
若是環境再也不一套內網中使用了負載均衡,須要使用映射的對應的IP和端口,筆者是內網因此對應的訪問能夠經過其中的任意一個節點便可運維
Ingress Gateway描述了在網格邊緣操做的負載平衡器,用於接收傳入的 HTTP/TCP 鏈接。它配置暴露的端口,協議等,但與 Kubernetes Ingress Resources 不一樣,它不包括任何流量路由配置。流入流量的流量路由使用 Istio 路由規則進行配置,與內部服務請求徹底相同。curl
讓咱們看看如何爲 Gateway 在 HTTP 80 端口上配置流量。
kubectl apply -n istio-test -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gateway spec: selector: istio: ingressgateway # use Istio default gateway implementation servers: - port: number: 80 name: http protocol: HTTP hosts: - "httpbin.example.com" EOF
爲經過 Gateway 進入的流量配置路由:
kubectl apply -n istio-test -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin spec: hosts: - "httpbin.example.com" gateways: - httpbin-gateway http: - match: - uri: prefix: /status - uri: prefix: /delay route: - destination: port: number: 8000 host: httpbin EOF
在這裏,咱們 爲服務建立了一個虛擬服務配置 httpbin ,其中包含兩條路由規則,容許路徑 /status 和 路徑的流量 /delay。
該網關列表指定,只有經過咱們的要求 httpbin-gateway 是容許的。全部其餘外部請求將被拒絕,並返回 404 響應。
請注意,在此配置中,來自網格中其餘服務的內部請求不受這些規則約束,而是簡單地默認爲循環路由。要將這些(或其餘規則)應用於內部調用,咱們能夠將特殊值 mesh 添加到 gateways 的列表中。
curl -I -HHost:httpbin.example.com http://172.16.0.203:31380/status/200 HTTP/1.1 200 OK server: envoy date: Thu, 08 Nov 2018 02:35:52 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 46
請注意,這裏使用該 -H 標誌將 Host HTTP Header 設置爲 「httpbin.example.com」。這以操做是必需的,由於上面的 Ingress Gateway 被配置爲處理 「httpbin.example.com」,但在測試環境中沒有該主機的 DNS 綁定,只是將請求發送到 Ingress IP。
curl -I -HHost:httpbin.example.com http://172.16.0.203:31380/headers HTTP/1.1 404 Not Found date: Thu, 08 Nov 2018 02:36:32 GMT server: envoy transfer-encoding: chunked
入口網關你們都很好理解不就是一個NGINX域名解析路由控制嘛,你這個出口網關有啥用啊? 在日益精細化運維管理的今天對於出口流量的控制愈來愈重要, 能夠訪問什麼不能夠訪問什麼對每個程序來講應該都是肯定的,這樣的限制能夠避免異常流量外部攻擊等.
缺省狀況下,Istio 服務網格內的 Pod,因爲其 iptables 將全部外發流量都透明的轉發給了 Sidecar,因此這些集羣內的服務沒法訪問集羣以外的 URL,而只能處理集羣內部的目標。
這就致使了文章開頭所說的問題Istio沒法外網訪問,若是你們的數據庫不在集羣內就會發現根本連不上
咱們仍是使用sleep來做爲咱們的例子
> kubectl apply -n istio-test -f istio-1.0.3/samples/sleep/sleep.yaml > export SOURCE_POD=$(kubectl get -n istio-test pod -l app=sleep -o jsonpath={.items..metadata.name}) # 嘗試訪問(訪問任何外部地址都會出現404) > kubectl exec -n istio-test -it $SOURCE_POD -c sleep bash crul -I baidu.com bash: crul: command not found root@sleep-76df4f989c-9hvvd:/# curl -I baidu.com HTTP/1.1 404 Not Found date: Thu, 08 Nov 2018 03:37:16 GMT server: envoy transfer-encoding: chunked
kubectl apply -n istio-test -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: baidu-ext spec: hosts: - baidu.com ports: - number: 80 name: http protocol: HTTP resolution: DNS location: MESH_EXTERNAL EOF
建立一個 ServiceEntry 以及 VirtualService,容許訪問外部 HTTPS 服務。注意:包括 HTTPS 在內的 TLS 協議,在 ServiceEntry 以外,還須要建立 TLS VirtualService
> kubectl exec -n istio-test -it $SOURCE_POD -c sleep bash > curl -I baidu.com HTTP/1.1 200 OK date: Thu, 08 Nov 2018 03:37:57 GMT server: envoy last-modified: Tue, 12 Jan 2010 13:48:00 GMT etag: "51-47cf7e6ee8400" accept-ranges: bytes content-length: 81 cache-control: max-age=86400 expires: Fri, 09 Nov 2018 03:37:57 GMT content-type: text/html x-envoy-upstream-service-time: 67
上面只配置了http能夠訪問,若是使用https會出現如下狀況
> curl -I https://baidu.com curl: (35) Unknown SSL protocol error in connection to baidu.com:443
建立一個 ServiceEntry 和一個 VirtualService 以容許訪問外部 HTTPS 服務。請注意, 對於 TLS 協議(包括 HTTPS),除了 ServiceEntry 以外,還須要 VirtualService。 VirtualService 必須在 match 子句中包含 tls 規則和 sni_hosts 以啓用 SNI 路由。
kubectl apply -n istio-test -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: baidu spec: hosts: - baidu.com ports: - number: 443 name: https protocol: HTTPS resolution: DNS location: MESH_EXTERNAL --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: baidu spec: hosts: - baidu.com tls: - match: - port: 443 sni_hosts: - baidu.com route: - destination: host: baidu.com port: number: 443 weight: 100 EOF
> curl -I https://baidu.com HTTP/1.1 302 Moved Temporarily Server: bfe/1.0.8.18 Date: Thu, 08 Nov 2018 03:41:05 GMT Content-Type: text/html Content-Length: 161 Connection: keep-alive Location: http://www.baidu.com/
經過 ServiceEntry 訪問外部服務的流量,和網格內流量相似,均可以進行 Istio 路由規則 的配置。下面咱們使用 istioctl 爲 httpbin.org 服務設置一個超時規則。
在測試 Pod 內部,使用 curl 調用 httpbin.org 這一外部服務的 /delay 端點:
> kubectl apply -n istio-test -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: name: httpbin-ext spec: hosts: - httpbin.org ports: - number: 80 name: http protocol: HTTP resolution: DNS location: MESH_EXTERNAL EOF > time curl -o /dev/null -s -w "%{http_code}\n" http://httpbin.org/delay/5 200 real 0m5.752s user 0m0.013s sys 0m0.022s
使用 kubectl 爲 httpbin.org 外部服務的訪問設置一個 3 秒鐘的超時
kubectl apply -n istio-test -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin-ext spec: hosts: - httpbin.org http: - timeout: 3s route: - destination: host: httpbin.org weight: 100 EOF
這一次會在 3 秒鐘以後收到一個內容爲 504 (Gateway Timeout) 的響應。雖然 httpbin.org 還在等待他的 5 秒鐘,Istio 卻在 3 秒鐘的時候切斷了請求。
time curl -o /dev/null -s -w "%{http_code}\n" http 504 real 0m3.046s user 0m0.010s sys 0m0.010s
確認限制能夠帶來更多的控制避免出錯,可是不少時候仍是會帶來不少麻煩,那麼若是不但願Istio進行限制能夠隨意的訪問須要怎麼辦呢?固然是能夠的,能夠配置Istio對於哪些範圍,首先咱們須要肯定內部集羣IP範圍:
方案一(HELM):
注意這裏應該使用和以前部署 Istio 的時候一樣的 Helm 命令,尤爲是 --namespace 參數。在安裝 Istio 原有命令的基礎之上,加入 --set global.proxy.includeIPRanges="10.0.0.1/24" -x templates/sidecar-injector-configmap.yaml 便可。
helm template install/kubernetes/helm/istio <安裝 Istio 時所使用的參數> --set global.proxy.includeIPRanges="10.0.0.1/24" -x templates/sidecar-injector-configmap.yaml | kubectl apply -f -
而後從新部署sleep就能夠了
方案二(改編排):
應爲筆者不是使用helm進行的istio安裝,直接使用的官方demo來安裝的,咱們能夠先找到includeOutboundIPRanges而後修改後面的*改爲對應的IP段
PS : 不一樣版本生成的yaml是不同的須要注意
istio-1.0.1版本
- "[[ index .ObjectMeta.Annotations "traffic.sidecar.istio.io/includeOutboundIPRanges" ]]" [[ else -]] - "10.43.0.1/24" [[ end -]]
istio1.0.3版本
- "[[ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` "10.43.0.1/24" ]]"
而後從新部署Istio就能夠沒有任何訪問限制了