一、Gateway网关¶
Istio中的Gateway是一个用于将外部流量引入Istio服务网格的组件。它提供了 入出口流量管理 的功能,充当了服务网格中的边界和负载均衡器。Gateway可以让在服务网格外 部的流量可以通过统一的入口接入到服务网格中的服务。
以下是一些与Istio Gateway相关的特性和概念:
-
边界流量:Istio Gateway负责接收来自外部的流量,并将其传递到服务网格中的目标服务。这些外部流量可以是来自互联网的请求,也可以是来自其他网络环境的请求。Gateway允许你定义和配置多个虚拟主机(VirtualHosts),并将其映射到特定的服务。
-
负载均衡:Gateway支持对流量进行负载均衡,将请求分发到后端服务实例。咱们 可以配置不同的负载均衡策略,如轮询、最小连接、最少请求数等。这样可以确保 流量在后端服务之间均匀分布,增加系统的可伸缩性和可靠性。
-
TLS 加密:Istio Gateway支持通过TLS(Transport Layer Security)对外部流量进 行加密,以确保数据的安全性和私密性。我们可以配置Gateway来使用自签名证书、公有证书或者通过集成第三方证书管理工具来管理证书。
-
路由规则:Gateway通过路由规则来定义如何将外部流量路由到后端服务。大家可 以根据请求的目标主机名、路径、协议等条件来配置路由规则。这样可以根据不同的条件将流量导向到不同的服务版本或环境中。
-
过滤器:Gateway提供了强大的过滤器功能,可以对请求和响应进行改变、增加或删除。我们可以使用过滤器来实现各种功能,如认证、鉴权、请求转换、响应转换 等。
#istio-ingressgateway-75bc568988-pjj9x是入口网关
#istio-egressgateway-58949b7c84-npgsq是出口网关
# 目前istio-system命名空间下面所有的pod
[root@master01 addons]# kubectl get pod -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-5f9cfb6b57-k4ngj 1/1 Running 0 36m
istio-egressgateway-7cbb4d6cff-nzglx 1/1 Running 1 (58m ago) 12h
istio-ingressgateway-7f8c8c6db7-lf5gw 1/1 Running 1 (58m ago) 12h
istiod-77cc598c96-79ln4 1/1 Running 1 (58m ago) 12h
kiali-6b4b5bb675-2jnwt 1/1 Running 0 8m30s
prometheus-5495fb4564-jj46j 2/2 Running 2 (58m ago) 11h
zipkin-697d567d65-2rdcm 1/1 Running 0 17m
Istio网关服务:

下面是一个网关资源的例子:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- dev.example.com
- test.kubernets.cn
类似nginx的监听配置:
server {
listen 80;
server_name dev.example.com test.kubernets.cn;
#...
}
二、Virtualservice¶
虽然创建了 Istio Gateway,但是我们还不能直接通过网关访问到前面部署的微服务,我 们还需要创建 Istio VirtualService 将 Istio Gateway 跟对应的 Kubernetes Service 绑定起来,然后流量才能正式流向 Pod。
Istio 中的 VirtualService 是一个用于定义流量路由规则和请求转发规则的重要组件。它 可以根据请求的属性(如主机名、路径、头部信息等)将流量引导到特定的目标服务, 从而实现灵活的流量管理和请求转发。
VirtualService 功能:
- 请求路由:将请求路由到特定的服务或版本,例如将请求分发到不同版本的服务, 以实现灰度发布或金丝雀发布。
- 请求重试:为失败的请求配置重试策略,以提高服务的可用性。
- 请求超时:设置请求的超时时间,以便在特定时间内没有得到响应时中断请求。
- 请求镜像:将请求的副本发送到另一个服务,用于测试新版本的服务,而不影响实 际的生产流量。
- 流量分割:将流量按照特定的比例分发到不同的服务或版本,以实现流量控制。
如下这张图形象的表达了流量从 Istio 的 ingressgateway 抓发到达最底层的应用pod。
他们之间的关系就类似于Kubernetes中的 Ingress --> SVC --> EP --> Pod

VirtualService 例子:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: tomcat-virtualservice
namespace: microservice
spec:
hosts:
- "*"
#把VirtualService绑定到ingressgateway80这个网关
gateways:
- ingressgateway80
http:
- route:
#表示路由到tomcat这个service,microservice表示命名空间
- destination:
host: tomcat.microservice.svc.cluster.local
port:
number: 80
这里类似 nginx 配置反向代理,配置监听之后,还需要指向将请求映射到哪个地址。
server {
listen 80;
server_name dev.example.com test.kubernets.cn;
#...
location /tomcat/path/ {
proxy_pass http://tomcat:9080;
}
}
为什么不直接将 Gateway 跟 Service 绑定,而是中间加个 VirtualService 呢?有句话叫做,计算机领域中的问题,都可以通过增加一个层来解决。
VirtualService 的主要目标是为服务提供稳定的入口地址,并通过配置一系列的路由规则来控制流量在网格内的行为。
就以最简单的路由区配来说,Kubernetes Service 是不支持路由规则的,而 Istio 可以通过指定路由后缀中;
Service 不支持流量分析,负载均衡只有轮询。而 Istio 利用 Service 来发现 Pod,然后直接将流量转发到 Pod 中,可以实现各种功能。
三、DestinationRule¶
在本章中,算是提前预告 DestinationRule,下一章才会使用 DestinationRule,这里我 们知道还有 DestinationRule 这个东西即可。
Istio VistualService 中可以限制外部能够访问的路由地址,而 DestinationRule 则可以 配置访问的 Pod 策略。可以为 Istio VistualService 绑定一个 Istio DestinationRule,通过 DestinationRule 我们还可以定义版本子集等,通过更加丰富的策略转发流量。

四、Gateway|VirtualService|DestinationRule 关系¶
Gateway负责将外部流量引入服务网格,VirtualService定义了流量的路由和转发规则, 而DestinationRule则配置了服务的属性和行为。
它们共同协作,提供了对服务网格中流量和服务的灵活控制,实现了可靠、安全和可观察的微服务架构。

五、实战(1):使用Gateway发布服务¶
5.1 创建部署并使用网关暴露¶
在这个实验中,我们将在集群中部署一个 tomcat 应用程序。然后我们将部署一个 Gateway 资源和一个与 Gateway 绑定的 VirtualService,以便在外部 IP 地址上公开该应用程序。
#可以看到istio-ingressgateway的service类型为LoadBalancer,外部IP为10.0.0.12
[root@master01 addons]# kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana ClusterIP 192.168.149.99 <none> 3000/TCP 48m
istio-egressgateway ClusterIP 192.168.139.213 <none> 80/TCP,443/TCP 12h
istio-ingressgateway LoadBalancer 192.168.149.121 10.0.0.12 15021:31360/TCP,80:31978/TCP,443:31805/TCP,31400:30191/TCP,15443:30922/TCP 12h
istiod ClusterIP 192.168.154.52 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 12h
kiali ClusterIP 192.168.184.211 <none> 20001/TCP,9090/TCP 21m
prometheus ClusterIP 192.168.12.202 <none> 9090/TCP 11h
tracing ClusterIP 192.168.122.92 <none> 80/TCP 29m
zipkin ClusterIP 192.168.35.20 <none> 9411/TCP 29m
让我们先从部署 Gateway 资源开始。我们将 把 hos t s 字段设置为 * ,所以我们可以直 接从外部IP 地址访问入口网关。如果我们想通过域名访问入口网关,我们可以将hosts 的值设置为域名(例如 example.com),然后将外部 IP 地址添加到该域名的 A 记录中。 按照如下方法创建网关:
#定义资源
[root@master01 addons]# vim ingressgateway80.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ingressgateway80
namespace: microservice
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- '*'
#应用
[root@master01 addons]# kubectl apply -f ingressgateway80.yaml
#网关创建完成,名字为ingressgateway80
[root@master01 addons]# kubectl get gw.networking.istio.io -o wide -nmicroservice
如果我们试图访问入口网关的外部 IP 地址,我们将得到一个 HTTP 404,因为没有任何 绑定到网关的 VirtualService。因为我们还没有定义任何路由,所以入口代理不知道要 把流量路由到哪里。
我们可以通过如下方式获得 Istio 网关的 LB 地址:
[root@master01 istioyaml]# kubectl get service -l istio=ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 192.168.149.121 10.0.0.12 15021:31360/TCP,80:31978/TCP,443:31805/TCP,31400:30191/TCP,15443:30922/TCP 12h
#访问入口网关的80端口,什么内容都没有
[root@master01 istioyaml]# curl 192.168.149.121 -i
HTTP/1.1 404 Not Found
date: Thu, 17 Apr 2025 01:07:36 GMT
server: istio-envoy
content-length: 0
之后当我们谈到入口网关的外部 IP 时,我们将在例子和文本中使用 GATEWAY_URL 。
创建Tomcat 部署和服务:
#使用hub.c.163.com/library/tomcat:latest镜像创建deploy,生成deploy的yaml
[root@master01 istioyaml]# kubectl create deploy tomcat -- image=hub.c.163.com/library/tomcat:latest -n microservice --dry- run=client -o yaml > tomcatdeploy.yaml
#yaml文件如下,标签设置为app: tomcat ,副本数为1
#- containerPort: 8080表示Tomcat镜像的端口为8080
[root@master01 istioyaml]# cat tomcatdeploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: tomcat
name: tomcat
namespace: microservice
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: tomcat
spec:
containers:
- image: hub.c.163.com/library/tomcat:latest
name: tomcat
resources: {}
status: {}
#创建deploy
[root@master01 istioyaml]# kubectl apply -f tomcatdeploy.yaml
#验证查看
[root@master01 istioyaml]# kubectl get deploy -n microservice | grep tomcat
tomcat 1/1 1 1 87s
#pod创建成功,pod里有2个容器
#如果我们看一下创建的 Pod,我们会发现有两个容器在运行。一个是 Envoy sidecar代理,第二个是应用程序。
[root@master01 istioyaml]# kgp -n microservice | grep tomcat
tomcat-7884d6567d-tlhpn 2/2 Running 0 110s
接着创建service
#生成service的yaml文件
[root@master01 istioyaml]# kubectl expose deployment tomcat --name=tomcat --port=80 --target-port=8080 -n microservice --dry-run=client -o yaml > tomcatsvc.yaml
#- port: 80使service暴露的端口,targetPort: 8080 是tomcat容器的端口
[root@master01 istioyaml]# vim tomcatsvc.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: tomcat
name: tomcat
namespace: microservice
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: tomcat
status:
loadBalancer: {}
#创建service
[root@master01 istioyaml]# kubectl apply -f tomcatsvc.yaml
#svc的类型为ClusterIP,外界环境访问不了
[root@master01 istioyaml]# kubectl get svc -nmicroservice | grep tomcat
tomcat ClusterIP 192.168.27.178 <none> 80/TCP 29s
下一步是为 tomcat 服务创建一个 VirtualService,并将其绑定到 Gateway 资源上:
[root@master01 istioyaml]# vim tomcat-virtualservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: tomcat-virtualservice
namespace: microservice
spec:
hosts:
- "*"
#把VirtualService绑定到ingressgateway80这个网关
gateways:
- ingressgateway80
http:
- route:
#表示路由到tomcat这个service,microservice表示命名空间
- destination:
host: tomcat.microservice.svc.cluster.local
port:
number: 80
#创建virtualservice
[root@master01 istioyaml]# kubectl apply -f tomcat-virtualservice.yaml
#virtualservices创建成功
[root@master01 istioyaml]# kubectl get vs.networking.istio.io -o wide -nmicroservice
NAME GATEWAYS HOSTS AGE
tomcat-virtualservice ["ingressgateway80"] ["*"] 13s
我们在 hosts 字段中使用 * ,就像我们在 Gateway 中做的那样。我们还将之前创建的Gateway 资源( gateway )添加到 gateways 数组中。
最后,我们指定了一个目的地为 Kubernetes 服务tomcat.microservice.svc.cluster.local 的单一路由
如果我们对 GATEWAY_URL 运行 cURL 或在浏览器中打开它,我们将得到 tomcat 的响应:
#查看istio-ingressgateway的EXTERNAL-IP
[root@master01 istioyaml]# kubectl get svc -l istio=ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 192.168.149.121 10.0.0.12 15021:31360/TCP,80:31978/TCP,443:31805/TCP,31400:30191/TCP,15443:30922/TCP 12h
#访问EXTERNAL-IP的80端口
#curl -v 参数表示显示一次 http 通信的整个过程,包括端口连接和 http request 头信息
[root@master01 istioyaml]# curl -v 192.168.149.121:80
* About to connect() to 192.168.149.121 port 80 (#0)
* Trying 192.168.149.121...
* Connected to 192.168.149.121 (192.168.149.121) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.149.121
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html;charset=UTF-8
< date: Thu, 17 Apr 2025 01:21:00 GMT
< x-envoy-upstream-service-time: 386
< server: istio-envoy
< transfer-encoding: chunked
<
...
...
另外,注意到 server 头设置为 istio-envoy ,告诉我们该请求通过了 Envoy 代理。
5.2 清理(后续会有大量类似实验,按照章节保留好数据,方便后续恢复!)¶
删除 Deployment、Service、VirtualService 和 Gateway:
[root@master01 istioyaml]# kubectl delete deployments tomcat -nmicroservice
[root@master01 istioyaml]# kubectl delete service tomcat -nmicroservice
[root@master01 istioyaml]# kubectl delete virtualservices.networking.istio.io tomcat-virtualservice -n microservice
[root@master01 istioyaml]# kubectl delete gateways.networking.istio.io ingressgateway80 -n microservice
六、实战(2):将Prometheus服务通过Istio的Ingress进行暴露¶
6.1 Gateway¶
#网关暴露80端口
[root@master01 istioyaml]# vim prometheus-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- 'prometheus-istio.zhang-qing.com'
# 应用
[root@master01 istioyaml]# kaf prometheus-gateway.yaml
# 验证
[root@master01 istioyaml]# kg gw -n istio-system
NAME AGE
gateway 25s
6.2 Virtualservices¶
#vs绑定网关
[root@master01 istioyaml]# vim prometheus-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: prometheus-istio
namespace: istio-system
spec:
hosts:
- 'prometheus-istio.zhang-qing.com'
gateways:
- gateway
http:
- route:
- destination:
host: prometheus.istio-system.svc.cluster.local
port:
number: 9090
#应用
[root@master01 istioyaml]# kaf prometheus-vs.yaml
#验证
[root@master01 istioyaml]# kg vs -n istio-system
NAME GATEWAYS HOSTS AGE
prometheus-istio ["gateway"] ["prometheus-istio.zhang-qing.com"] 39s
#查看服务
[root@master01 istioyaml]# kubectl get svc -l istio=ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 192.168.149.121 10.0.0.12 15021:31360/TCP,80:31978/TCP,443:31805/TCP,31400:30191/TCP,15443:30922/TCP 12h
修改prometheus-istio.zhang-qing.com这个域名的映射IP地址为10.0.0.12
# 阿里云上修改域名对应ip关系
prometheus-istio.zhang-qing.com 10.0.0.12
#验证
[root@master01 istioyaml]# ping -c1 prometheus-istio.zhang-qing.com
PING prometheus-istio.zhang-qing.com (10.0.0.12) 56(84) bytes of data.
From master01 (10.0.0.12) icmp_seq=1 Destination Port Unreachable
浏览器中重新输入prometheus-istio.zhang-qing.com进行访问即可
七、实战(3):多个服务绑定一个网关¶
需求:将Grafana,Zipkin,Kiali绑定到一个虚拟网关
7.1 Gateway¶
[root@master01 istioyaml]# vim allgateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: allgateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- 'grafana-istio.zhang-qing.com'
- 'kiali-istio.zhang-qing.com'
- 'prometheus-istio.zhang-qing.com'
#应用
[root@master01 istioyaml]# kaf allgateway.yaml
7.2 Virtualservices¶
Grafana:
[root@master01 istioyaml]# vim grafana-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: grafana-istio
namespace: istio-system
spec:
hosts:
- 'grafana-istio.zhang-qing.com'
gateways:
- allgateway
http:
- route:
- destination:
host: grafana.istio-system.svc.cluster.local
port:
number: 3000
# 应用
[root@master01 istioyaml]# kaf grafana-vs.yaml
Kiali:
[root@master01 istioyaml]# vim kiali-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: kiali-istio
namespace: istio-system
spec:
hosts:
- 'kiali-istio.zhang-qing.com'
gateways:
- allgateway
http:
- route:
- destination:
host: kiali.istio-system.svc.cluster.local
port:
number: 20001
# 应用
[root@master01 istioyaml]# kaf kiali-vs.yaml
Prometheus:
[root@master01 istioyaml]# vim prometheus-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: prometheus-istio
namespace: istio-system
spec:
hosts:
- 'prometheus-istio.zhang-qing.com'
gateways:
- allgateway
http:
- route:
- destination:
host: prometheus.istio-system.svc.cluster.local
port:
number: 9090
修改域名对应IP
kiali-istio.zhang-qing.com 10.0.0.12
grafana-istio.zhang-qing.com 10.0.0.12
prometheus-istio.zhang-qing.com 10.0.0.12
#验证
ping -c1 kiali-istio.zhang-qing.com
ping -c1 grafana-istio.zhang-qing.com
ping -c1 prometheus-istio.zhang-qing.com
浏览器输入kiali-istio.zhang-qing.com,点击【Graph】,命名空间选择istio-system,再选择【App graph】
说明:需要提前登录grafana-istio.zhang-qing.com和prometheus-istio.zhang-qing.com模拟访问,否则在kiali不显示

八、总结¶
Istio中的Gateway、VirtualService和DestinationRule是三个核心组件,它们共同构成 了流量管理和服务配置的基础。
下面对它们进行简要总结:
-
Gateway(网关):作为服务网格的入口流量管理组件,Gateway负责接收来自外 部的流量,并将其传递到服务网格中的目标服务。它充当了服务网格的边界和负载均衡器,支持入口流量的路由、负载均衡和TLS加密等功能。
-
VirtualService(虚拟服务):VirtualService用于定义流量路由规则和请求转发规则。它根据请求的属性(如主机名、路径、头部信息等)将流量引导到特定的后端服务。VirtualService能够灵活地控制流量的路由、负载均衡、超时和重试、流量镜像等策略,实现高级的流量管理和控制。
-
DestinationRule(目标规则):DestinationRule用于配置目标服务的规则和属 性。它定义了服务的负载均衡策略、TLS设置、连接池大小、故障恢复等参数。 DestinationRule允许对某个服务或服务的子集进行独立配置,以满足不同服务的需求。
综合来看,Gateway负责将外部流量引入服务网格,VirtualService定义了流量的路由和转发规则,而DestinationRule则配置了服务的属性和行为。它们共同协作,提供了对服务网格中流量和服务的灵活控制,实现了可靠、安全和可观察的微服务架构。