Istio 服務網格中的網關

原文連接:Istio 服務網格中的網關html

在一個典型的網格中,一般有一個或多個用於終結外部 TLS 連接,將流量引入網格的負載均衡器(咱們稱之爲 gateway)。 而後流量經過邊車網關(sidecar gateway)流經內部服務。 應用程序使用外部服務的狀況也很常見(例如訪問 Google Maps API),一些狀況下,這些外部服務可能被直接調用;但在某些部署中,網格中全部訪問外部服務的流量可能被要求強制經過專用的出口網關(Egress gateway)。 下圖描繪了網關在網格中的使用狀況。node

*Istio服務網格中的網關*

其中 Gateway 是一個獨立於平臺的抽象,用於對流入專用中間設備的流量進行建模。下圖描述了跨多個配置資源的控制流程。api

*不一樣v1alpha3元素之間的關係*

1. Gateway 介紹

Gateway 用於爲 HTTP / TCP 流量配置負載均衡器,並無論該負載均衡器將在哪裏運行。 網格中能夠存在任意數量的 Gateway,而且多個不一樣的 Gateway 實現能夠共存。 實際上,經過在配置中指定一組工做負載(Pod)標籤,能夠將 Gateway 配置綁定到特定的工做負載,從而容許用戶經過編寫簡單的 Gateway Controller 來重用現成的網絡設備。瀏覽器

對於入口流量管理,您可能會問: 爲何不直接使用 Kubernetes Ingress API ? 緣由是 Ingress API 沒法表達 Istio 的路由需求。 Ingress 試圖在不一樣的 HTTP 代理之間取一個公共的交集,所以只能支持最基本的 HTTP 路由,最終致使須要將代理的其餘高級功能放入到註解(annotation)中,而註解的方式在多個代理之間是不兼容的,沒法移植。bash

Istio Gateway 經過將 L4-L6 配置與 L7 配置分離的方式克服了 Ingress 的這些缺點。 Gateway 只用於配置 L4-L6 功能(例如,對外公開的端口,TLS 配置),全部主流的L7代理均以統一的方式實現了這些功能。 而後,經過在 Gateway 上綁定 VirtualService 的方式,可使用標準的 Istio 規則來控制進入 Gateway 的 HTTP 和 TCP 流量。網絡

例如,下面這個簡單的 Gateway 配置了一個 Load Balancer,以容許訪問 host bookinfo.com 的 https 外部流量進入網格中:負載均衡

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: bookinfo-gateway
spec:
 servers:
 - port:
 number: 80
 name: http
 protocol: HTTP
 hosts:
 - bookinfo.com
複製代碼

要爲進入上面的 Gateway 的流量配置相應的路由,必須爲同一個 host 定義一個 VirtualService(參考上一篇博文),並使用配置中的 gateways 字段綁定到前面定義的 Gateway 上:curl

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: bookinfo
spec:
 hosts:
 - bookinfo.com
 gateways:
 - bookinfo-gateway # <---- bind to gateway
 http:
 - match:
 - uri:
 prefix: /reviews
 route:
    ...
複製代碼

Gateway 能夠用於建模邊緣代理或純粹的內部代理,如第一張圖所示。 不管在哪一個位置,全部網關均可以用相同的方式進行配置和控制。ide

下面經過一個示例來演示如何配置 Istio 以使用 Istio Gateway 在服務網格外部公開服務。post

2. 使用 Istio 網關配置 Ingress

讓咱們看看如何爲 Gateway 在 HTTP 80 端口上配置流量。

  1. 建立一個 Istio Gateway

    $ cat <<EOF | istioctl create -f - 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    
    複製代碼
  2. 爲經過 Gateway 進入的流量配置路由

    $ cat <<EOF | istioctl create -f - 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
    複製代碼

    在這裏,咱們 爲服務建立了一個 VirtualService 配置 httpbin ,其中包含兩條路由規則,容許路徑 /status 和 路徑的流量 /delay

    網關列表指定,只有經過咱們的要求 httpbin-gateway 是容許的。全部其餘外部請求將被拒絕,並返回 404 響應。

    請注意,在此配置中,來自網格中其餘服務的內部請求不受這些規則約束,而是簡單地默認爲循環路由。要將這些(或其餘規則)應用於內部調用,咱們能夠將特殊值 mesh 添加到 gateways 的列表中

  3. 使用 curl 訪問 httpbin 服務。

    首先獲取 Ingress Gateway 的 IP 和 端口,參考上一篇文章:Istio 流量管理

    $ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/status/200
    
    HTTP/1.1 200 OK
    server: envoy
    date: Thu, 02 Aug 2018 04:18:41 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: 9
    複製代碼

    請注意,咱們使用該 -H 標誌將 Host HTTP Header 設置爲 「httpbin.example.com」。這是必需的,由於咱們的 ingress Gateway 被配置爲處理 「httpbin.example.com」,但在咱們的測試環境中,咱們沒有該主機的 DNS 綁定,而且只是將咱們的請求發送到 ingress IP。

  4. 訪問任何未明確公開的其餘 URL。您應該看到一個 HTTP 404 錯誤:

    $ curl -I -HHost:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
    
    HTTP/1.1 404 Not Found
    date: Thu, 02 Aug 2018 04:21:39 GMT
    server: envoy
    transfer-encoding: chunked
    複製代碼

3. 使用瀏覽器訪問 Ingress 服務

若是你想在瀏覽器中輸入 httpbin 服務的 URL 來訪問是行不通的,由於咱們沒有辦法像使用 curl 同樣告訴瀏覽器僞裝訪問 httpbin.example.com,只能經過向 /etc/hosts 文件中添加 hosts 來解決這個問題。

可是麻煩又來了,目前這種情況下即便你添加了 hosts,也仍然沒法訪問,由於 Istio Gateway 使用的是 NodePort 模式,暴露出來的不是 80 端口和 443 端口,而咱們要想經過域名來訪問服務,必需要求 Gateway 暴露出來的端口是 80 和 443。

因此咱們只能曲線救國了,經過修改 Ingress Gateway 的 Deployment,將 80 端口和 443 端口配置爲 hostPort 模式,而後再經過 Node 親和性將 Gateway 調度到某個固定的主機上。

$ kubectl -n istio-system edit deployment istio-ingressgateway
複製代碼
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: istio-ingressgateway
 namespace: istio-system
  ...
spec:
  ...
 template:
    ...
 spec:
 affinity:
 nodeAffinity:
          ...
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchExpressions:
 - key: kubernetes.io/hostname
 operator: In
 values:
 - 192.168.123.248   # 好比你想調度到這臺主機上
 containers:
 - name: ISTIO_META_POD_NAME
        ...
 - containerPort: 80
 hostPort: 80
 protocol: TCP
 - containerPort: 443
 hostPort: 443
 protocol: TCP
        ...
複製代碼

修改完以後保存退出,等待 Gateway 的 Pod 從新調度,而後在你的瀏覽器所在的本地電腦上添加一條 hosts:

192.168.123.248 httpbin.example.com
複製代碼

從新配置 VirtualService

$  cat <<EOF | istioctl replace -f -  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
 - uri:
 prefix: /headers
 route:
 - destination:
 port:
 number: 8000
 host: httpbin
 EOF
複製代碼

接下來就能夠在瀏覽器中輸入 URL:http://httpbin.example.com/headers 來訪問服務啦!

4. 清理

刪除 Gateway、VirtualService 和 httpbin 服務:

$ istioctl delete gateway httpbin-gateway
$ istioctl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml
複製代碼

5. 參考

相關文章
相關標籤/搜索