暴露 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 的高可用方案。

相关文章
相关标签/搜索