在以前的文章 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 的高可用方案。