在以前的文章 Istio 服務網格中的網關 中,我已經介紹了簡單的暴露 Ingress Gateway
的方案。當時的方案只是用於臨時測試,不適合在大規模場景下使用,本文將探討更加優化的暴露 Ingress Gateway 的方案。前端
第一種方法比較簡單,能夠直接使用 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
咱們已經知道,Ingress Gateway 實際上內部運行的是 Envoy
代理,咱們能夠在 Ingress Gateway 前面再加一層代理,這樣就解決了高可用問題,你能夠將 Ingress Gateway 的副本數擴展爲多個,前端代理只須要經過 Service Name
來鏈接後端的 Gateway 就好了。同時建議採用獨佔節點的方式部署前端代理,以免業務應用與前端代理服務發生資源爭搶。瀏覽器
前端代理能夠使用通常的負載均衡軟件(如 Haproxy
、Nginx
等),也能夠使用 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
表示使用 TCP 代理。詳情參考:listener.Filter其餘配置解析請參考:Envoy 的架構與基本術語
接下來經過 Dockerfile-frontenvoy
和 front-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 的高可用方案。