1、Gateway网关
Istio中的Gateway是一个用于将外部流量引入Istio服务网格的组件。它提供了入出口流量管理的功能,充当了服务网格中的边界和负载均衡器。Gateway可以让在服务网格外部的流量可以通过统一的入口接入到服务网格中的服务。
以下是一些与Istio Gateway相关的特性和概念:
- 1. 边界流量:Istio Gateway负责接收来自外部的流量,并将其传递到服务网格中的目标服务。这些外部流量可以是来自互联网的请求,也可以是来自其他网络环境的请求。Gateway允许你定义和配置多个虚拟主机(VirtualHosts),并将其映射到特定的服务。
- 负载均衡:Gateway支持对流量进行负载均衡,将请求分发到后端服务实例。咱们可以配置不同的负载均衡策略,如轮询、最小连接、最少请求数等。这样可以确保流量在后端服务之间均匀分布,增加系统的可伸缩性和可靠性。
- TLS 加密:Istio Gateway支持通过TLS(Transport Layer Security)对外部流量进行加密,以确保数据的安全性和私密性。我们可以配置Gateway来使用自签名证书、公有证书或者通过集成第三方证书管理工具来管理证书。
- 路由规则:Gateway通过路由规则来定义如何将外部流量路由到后端服务。大家可以根据请求的目标主机名、路径、协议等条件来配置路由规则。这样可以根据不同的条件将流量导向到不同的服务版本或环境中。
- 过滤器:Gateway提供了强大的过滤器功能,可以对请求和响应进行改变、增加或删除。我们可以使用过滤器来实现各种功能,如认证、鉴权、请求转换、响应转换等。
#istio-ingressgateway-869d777659-hbmq9是入口网关
#istio-egressgateway-765d784c5-5q5ch是出口网关
$ kubectl get pod -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-5f9b8c6c5d-8lwwb 1/1 Running 0 12m
istio-egressgateway-765d784c5-5q5ch 1/1 Running 0 171m
istio-ingressgateway-869d777659-hbmq9 1/1 Running 0 171m
istiod-5c4f4498d-5bkpg 1/1 Running 0 171m
kiali-cc67f8648-dw98r 1/1 Running 0 3m11s
prometheus-5d5d6d6fc-cgzrm 2/2 Running 0 18m
zipkin-7d7cd94c9b-6ssjg 1/1 Running 0 6m10s
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;
#...
}
2、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 中,可以实现各种功能。
3、DestinationRule
在本章中,算是提前预告 DestinationRule,下一章才会使用 DestinationRule,这里我们知道还有 DestinationRule 这个东西即可。
Istio VistualService 中可以限制外部能够访问的路由地址,而 DestinationRule 则可以配置访问的 Pod 策略。可以为 Istio VistualService 绑定一个 Istio DestinationRule,通过 DestinationRule 我们还可以定义版本子集等,通过更加丰富的策略转发流量。

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

5、实战(1):使用Gateway发布服务
1、创建部署并使用网关暴露
在这个实验中,我们将在集群中部署一个 tomcat 应用程序。然后我们将部署一个Gateway 资源和一个与 Gateway 绑定的 VirtualService,以便在外部 IP 地址上公开该应用程序。
#可以看到istio-ingressgateway的service类型为LoadBalancer,外部IP为10.0.10.0
$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana ClusterIP 10.15.91.110 <none> 3000/TCP 23m
istio-egressgateway ClusterIP 10.15.58.173 <none> 80/TCP,443/TCP 27h
istio-ingressgateway LoadBalancer 10.15.18.33 10.0.10.0 15021:30211/TCP,80:32225/TCP,443:30513/TCP,31400:32313/TCP,15443:30656/TCP 27h
istiod ClusterIP 10.15.117.150 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 27h
kiali ClusterIP 10.15.68.12 <none> 20001/TCP,9090/TCP 14m
prometheus ClusterIP 10.15.61.43 <none> 9090/TCP 30m
tracing ClusterIP 10.15.94.242 <none> 80/TCP 17m
zipkin ClusterIP 10.15.198.147 <none> 9411/TCP 17m
让我们先从部署 Gateway 资源开始。我们将把hosts
字段设置为*
,所以我们可以直接从外部 IP 地址访问入口网关。如果我们想通过域名访问入口网关,我们可以将hosts
的值设置为域名(例如example.com
),然后将外部 IP 地址添加到该域名的 A记录中。
按照如下方法创建网关:
$ 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:
- '*'
$ kubectl apply -f ingressgateway80.yaml
gateway.networking.istio.io/ingressgateway80 created
#网关创建完成,名字为ingressgateway80
$ kubectl get gw.networking.istio.io -o wide -nmicroservice
NAME AGE
ingressgateway80 75s
如果我们试图访问入口网关的外部 IP 地址,我们将得到一个 HTTP 404,因为没有任何绑定到网关的 VirtualService。因为我们还没有定义任何路由,所以入口代理不知道要把流量路由到哪里。
我们可以通过如下方式获得 Istio 网关的 LB 地址:
$ kubectl get service -l istio=ingressgateway -n istio-system
#访问入口网关的80端口,什么内容都没有
$ curl 10.0.10.0 -i
HTTP/1.1 404 Not Found
之后当我们谈到入口网关的外部 IP 时,我们将在例子和文本中使用GATEWAY_URL
。
创建 Tomcat 部署和服务:
#使用hub.c.163.com/library/tomcat:latest镜像创建deploy,生成deploy的yaml文件
$ kubectl create deploy tomcat --image=hub.c.163.com/library/tomcat:latest -n microservice --dryrun=client -o yaml > tomcatdeploy.yaml
#yaml文件如下,标签设置为app: tomcat ,副本数为1
#- containerPort: 8080表示Tomcat镜像的端口为8080
$ 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
$ kubectl apply -f tomcatdeploy.yaml
deployment.apps/tomcat created
#deploy创建成功
$ kubectl get deploy -n microservice
NAME READY UP-TO-DATE AVAILABLE AGE
tomcat 1/1 1 1 6s
#pod创建成功,pod里有2个容器
#**如果我们看一下创建的 Pod,我们会发现有两个容器在运行。一个是 Envoy sidecar代理,第二个是应用程序**。
$ kubectl get pod -nmicroservice
NAME READY STATUS RESTARTS AGE
nginx-b64475554-c62n4 2/2 Running 0 32m
tomcat-5b4b9896d4-4xkgb 2/2 Running 0 18s
接着创建service
#生成service的yaml文件
$ kubectl expose deployment tomcat --name=tomcat --port=80 --target-port=8080 -nmicroservice --dry-run=client -o yaml > tomcatsvc.yaml
#- port: 80使service暴露的端口,targetPort: 8080 是tomcat容器的端口
$ cat 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
$ kubectl apply -f tomcatsvc.yaml
service/tomcat created
#svc的类型为ClusterIP,外界环境访问不了
$ kubectl get svc -o wide -nmicroservice
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginxsvc NodePort 10.15.215.87 <none> 80:32101/TCP 36m
tomcat ClusterIP 10.15.171.152 <none> 80/TCP 17s
下一步是为tomcat
服务创建一个 VirtualService,并将其绑定到 Gateway 资源上:
$ 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
$ kubectl apply -f tomcat-virtualservice.yaml
virtualservice.networking.istio.io/tomcat-virtualservice created
#virtualservices创建成功
$ kubectl get vs.networking.istio.io -o wide -nmicroservice
NAME GATEWAYS HOSTS AGE
tomcat-virtualservice ["ingressgateway80"] ["*"] 50s
我们在hosts
字段中使用*
,就像我们在Gateway
中做的那样。我们还将之前创建的Gateway 资源(gateway
)添加到gateways
数组中。
最后,我们指定了一个目的地为 Kubernetes 服务tomcat.microservice.svc.cluster.local
的单一路由。
如果我们对GATEWAY_URL
运行cURL
或在浏览器中打开它,我们将得到tomcat
的响应:
#查看istio-ingressgateway的EXTERNAL-IP
$ kubectl get svc -l istio=ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.15.18.33 10.0.10.0 15021:30211/TCP,80:32225/TCP,443:30513/TCP,31400:32313/TCP,15443:30656/TCP 27h
#访问EXTERNAL-IP的80端口
#curl -v 参数表示显示一次 http 通信的整个过程,包括端口连接和 http request 头信息
$ curl -v 10.0.10.0:80
* Rebuilt URL to: 10.0.10.0:80/
* Uses proxy env variable NO_PROXY == '127.0.0.1,localhost,10.0.0.0/16,10.15.0.0/16,10.18.0.0/16,.local,local,*.zhoumx.cc,*.aliyuncs.com'
* Trying 10.0.10.0...
* TCP_NODELAY set
* Connected to 10.0.10.0 (10.0.10.0) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.0.10.0
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/html;charset=UTF-8
< date: Mon, 08 Jan 2024 12:40:20 GMT
< x-envoy-upstream-service-time: 647
< server: istio-envoy
< transfer-encoding: chunked
<
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/8.5.20</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="tomcat.css" rel="stylesheet" type="text/css" />
</head>
另外,注意到server
头设置为istio-envoy
,告诉我们该请求通过了 Envoy 代理。
2、清理(后续会有大量类似实验,按照章节保留好数据,方便后续恢复!)
删除 Deployment、Service、VirtualService 和 Gateway:
$ kubectl delete deployments tomcat -nmicroservice
deployment.apps "tomcat" deleted
$ kubectl delete service tomcat -nmicroservice
service "tomcat" deleted
$ kubectl delete virtualservices.networking.istio.io tomcat-virtualservice -nmicroservice
virtualservice.networking.istio.io "tomcat-virtualservice" deleted
$ kubectl delete gateways.networking.istio.io ingressgateway80 -nmicroservice
gateway.networking.istio.io "ingressgateway80" deleted
6、实战(2):将Prometheus服务通过Istio的Ingress进行暴露
1、Gateway
#网关暴露80端口
$ cat 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.kubernets.cn'
2、Virtualservices
#vs绑定网关
$ cat prometheus-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: prometheus-istio
namespace: istio-system
spec:
hosts:
- 'prometheus-istio.kubernets.cn'
gateways:
- gateway
http:
- route:
- destination:
host: prometheus.istio-system.svc.cluster.local
port:
number: 9090
7、实战(3)、多个服务绑定一个网关
需求:将Grafana,Zipkin,Kiali绑定到一个虚拟网关
1、Gateway
#网关暴露80端口
$ cat 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:
- '*'
2、Virtualservices
Grafana:
#vs绑定网关
$ cat grafana-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: grafana-istio
namespace: istio-system
spec:
hosts:
- 'grafana-istio.kubernets.cn'
gateways:
- allgateway
http:
- route:
- destination:
host: grafana.istio-system.svc.cluster.local
port:
number: 3000
Kiali:
#vs绑定网关
$ cat kiali-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: kiali-istio
namespace: istio-system
spec:
hosts:
- 'kiali-istio.kubernets.cn'
gateways:
- allgateway
http:
- route:
- destination:
host: kiali.istio-system.svc.cluster.local
port:
number: 20001
Zipkin:
#vs绑定网关
$ cat zipkin-vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: zipkin-istio
namespace: istio-system
spec:
hosts:
- 'zipkin-istio.zhoumx.cc'
gateways:
- allgateway
http:
- route:
- destination:
host: zipkin.istio-system.svc.cluster.local
port:
number: 9411
8、总结
Istio中的Gateway、VirtualService和DestinationRule是三个核心组件,它们共同构成了流量管理和服务配置的基础。
下面对它们进行简要总结:
- Gateway(网关):作为服务网格的入口流量管理组件,Gateway负责接收来自外部的流量,并将其传递到服务网格中的目标服务。它充当了服务网格的边界和负载均衡器,支持入口流量的路由、负载均衡和TLS加密等功能。
- VirtualService(虚拟服务):VirtualService用于定义流量路由规则和请求转发规则。它根据请求的属性(如主机名、路径、头部信息等)将流量引导到特定的后端服务。VirtualService能够灵活地控制流量的路由、负载均衡、超时和重试、流量镜像等策略,实现高级的流量管理和控制。
- DestinationRule(目标规则):DestinationRule用于配置目标服务的规则和属性。它定义了服务的负载均衡策略、TLS设置、连接池大小、故障恢复等参数。DestinationRule允许对某个服务或服务的子集进行独立配置,以满足不同服务的需求。
综合来看,Gateway负责将外部流量引入服务网格,VirtualService定义了流量的路由和转发规则,而DestinationRule则配置了服务的属性和行为。它们共同协作,提供了对服务网格中流量和服务的灵活控制,实现了可靠、安全和可观察的微服务架构。