暴露 Istio Service Mesh 中的 Gateway

在以前的文章 Istio 服務網格中的網關 中,我已經介紹了簡單的暴露 Ingress Gateway 的方案。當時的方案只是用於臨時測試,不適合在大規模場景下使用,本文將探討更加優化的暴露 Ingress Gateway 的方案。前端

HostNetwork

第一種方法比較簡單,能夠直接使用 HostNetwork 模式運行 Ingress Gateway。但你會發現沒法啓動 ingressgateway 的 Pod,由於若是 Pod 設置了 HostNetwork=true,則 dnsPolicy 就會從 ClusterFirst 被強制轉換成 Default。而 Ingress Gateway 啓動過程當中須要經過 DNS 域名鏈接 pilot 等其餘組件,因此沒法啓動。node

咱們能夠經過強制將 dnsPolicy 的值設置爲 ClusterFirstWithHostNet 來解決這個問題,詳情參考:Kubernetes DNS 高階指南git

修改後的 ingressgateway deployment 配置文件以下:github

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: istio-ingressgateway
 namespace: istio-system
  ...
spec:
  ...
 template:
 metadata:
    ...
 spec:
 affinity:
 nodeAffinity:
          ...
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchExpressions:
 - key: kubernetes.io/hostname
 operator: In
 values:
 - 192.168.123.248   # 好比你想調度到這臺主機上
      ...
 dnsPolicy: ClusterFirstWithHostNet
 hostNetwork: true
 restartPolicy: Always
      ...
複製代碼

接下來咱們就能夠在瀏覽器中經過 Gateway 的 URL 來訪問服務網格中的服務了。後端

可是做爲服務網格的流量接入層,Ingress Gateway 的高可靠性顯得尤其重要,高可靠性首先要解決的就是單點故障問題,通常經常使用的是採用多副本部署的方式。而上述方案只適用於單實例(Deployment 的副本數爲 1)的狀況,爲了適應多節點部署架構,須要尋求更好的暴露方案。api

使用 Envoy 做爲前端代理

咱們已經知道,Ingress Gateway 實際上內部運行的是 Envoy 代理,咱們能夠在 Ingress Gateway 前面再加一層代理,這樣就解決了高可用問題,你能夠將 Ingress Gateway 的副本數擴展爲多個,前端代理只須要經過 Service Name 來鏈接後端的 Gateway 就好了。同時建議採用獨佔節點的方式部署前端代理,以免業務應用與前端代理服務發生資源爭搶。瀏覽器

前端代理能夠使用通常的負載均衡軟件(如 HaproxyNginx 等),也能夠使用 Envoy。因爲 Envoy 是 Istio Service Mesh 中默認的 data plane,因此這裏推薦使用 Envoy。bash

Envoy 官方提供了一組 Envoy 的用例,咱們只須要用到其中的 Dockerfile。首先克隆 Envoy 的代碼倉庫並轉到 examples/front-proxy 目錄:架構

$ git clone https://github.com/envoyproxy/envoy
$ cd envoy/examples/front-proxy
複製代碼

修改 front-envoy.yaml 配置文件,修改後的內容以下:app

static_resources:
 listeners:
 - address:
 socket_address:
 address: 0.0.0.0
 port_value: 80
 filter_chains:
 - filters:
 - name: envoy.tcp_proxy  
 config:
 stat_prefix: ingress_tcp
 cluster: ingressgateway
 access_log:
 - name: envoy.file_access_log
 config:
 path: /dev/stdout
 - address:
 socket_address:
 address: 0.0.0.0
 port_value: 443
 filter_chains:
 - filters:
 - name: envoy.tcp_proxy
 config:
 stat_prefix: ingress_tcp
 cluster: ingressgateway_tls
 access_log:
 - name: envoy.file_access_log
 config:
 path: /dev/stdout
 clusters:
 - name: ingressgateway
 connect_timeout: 0.25s
 type: strict_dns
 lb_policy: round_robin
 http2_protocol_options: {}
 hosts:
 - socket_address:
 address: istio-ingressgateway.istio-system  
 port_value: 80
 - name: ingressgateway_tls
 connect_timeout: 0.25s
 type: strict_dns
 lb_policy: round_robin
 http2_protocol_options: {}
 hosts:
 - socket_address:
 address: istio-ingressgateway.istio-system
 port_value: 443
admin:
 access_log_path: "/dev/null"
 address:
 socket_address:
 address: 0.0.0.0
 port_value: 8001
複製代碼
  • envoy.tcp_proxy 表示要實例化的過濾器的名稱。該名稱必須與內置支持的過濾器匹配,也就是說,該字段的值不可隨意填寫,必須使用指定的幾個值。這裏 envoy.tcp_proxy 表示使用 TCP 代理。詳情參考:listener.Filter
  • istio-ingressgateway.istio-system 表示 Ingress Gateway 在集羣內部的 DNS 域名。

其餘配置解析請參考:Envoy 的架構與基本術語

接下來經過 Dockerfile-frontenvoyfront-envoy.yaml 來構建 Docker 鏡像,咱們來看下該 Dockerfile 的內容。

FROM envoyproxy/envoy:latest

RUN apt-get update && apt-get -q install -y \ curl CMD /usr/local/bin/envoy -c /etc/front-envoy.yaml --service-cluster front-proxy 複製代碼

其中 /etc/front-envoy.yaml 是本地的 front-envoy.yaml 掛載進去的。在 Kubernetes 中能夠經過 ConfigMap 來掛載,因此咱們還要建立一個 ConfigMap:

$ kubectl -n istio-system create cm front-envoy --from-file=front-envoy.yaml
複製代碼

你能夠將構建好的鏡像 push 到私有鏡像倉庫中或者公共倉庫中,也能夠使用我已經上傳好的鏡像。

最後咱們就能夠經過該鏡像來部署前端代理了,須要建立一個 Deployment,配置文件 front-envoy-deploy.yaml 內容以下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: front-envoy
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: front-envoy
 spec:
 affinity:
 nodeAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchExpressions:
 - key: kubernetes.io/hostname
 operator: In
 values:
 - 192.168.123.248 # 好比你想調度到這臺主機上
 containers:
 - name: front-envoy
 image: yangchuansheng/front-envoy
 ports:
 - containerPort: 80
 volumeMounts:
 - name: front-envoy
 mountPath: /etc/front-envoy.yaml
 subPath: front-envoy.yaml
 hostNetwork: true
 volumes:
 - name: front-envoy
 configMap:
 name: front-envoy
複製代碼

你能夠將鏡像換成你本身的鏡像,而後經過該 yaml 文件來部署:

$ kubectl -n istio-system create -f front-envoy-deploy.yaml
複製代碼

接下來咱們就能夠在瀏覽器中經過前端代理所在節點的 URL 來訪問服務網格中的服務了。

更通常的場景,咱們還能夠配置前端代理的高可用。對於 Kubernetes 集羣之外只暴露一個訪問入口,能夠使用 keepalived 排除單節點問題。具體實現方式與 Ingress 的高可用相似,能夠參考 Ingress 的高可用方案。

相關文章
相關標籤/搜索