基于Istio的微服务Gateway实战

1、Gateway网关

Istio中的Gateway是一个用于将外部流量引入Istio服务网格的组件。它提供了入出口流量管理的功能,充当了服务网格中的边界和负载均衡器。Gateway可以让在服务网格外部的流量可以通过统一的入口接入到服务网格中的服务。

以下是一些与Istio Gateway相关的特性和概念:

  • 1. 边界流量:Istio Gateway负责接收来自外部的流量,并将其传递到服务网格中的目标服务。这些外部流量可以是来自互联网的请求,也可以是来自其他网络环境的请求。Gateway允许你定义和配置多个虚拟主机(VirtualHosts),并将其映射到特定的服务。
  1. 负载均衡:Gateway支持对流量进行负载均衡,将请求分发到后端服务实例。咱们可以配置不同的负载均衡策略,如轮询、最小连接、最少请求数等。这样可以确保流量在后端服务之间均匀分布,增加系统的可伸缩性和可靠性。
  2. TLS 加密:Istio Gateway支持通过TLS(Transport Layer Security)对外部流量进行加密,以确保数据的安全性和私密性。我们可以配置Gateway来使用自签名证书、公有证书或者通过集成第三方证书管理工具来管理证书。
  3. 路由规则:Gateway通过路由规则来定义如何将外部流量路由到后端服务。大家可以根据请求的目标主机名、路径、协议等条件来配置路由规则。这样可以根据不同的条件将流量导向到不同的服务版本或环境中。
  4. 过滤器: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网关服务

基于Istio的微服务Gateway实战

下面是一个网关资源的例子

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

基于Istio的微服务Gateway实战

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 我们还可以定义版本子集等,通过更加丰富的策略转发流量。

基于Istio的微服务Gateway实战

4、Gateway|VirtualService|DestinationRule 关系

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

基于Istio的微服务Gateway实战

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则配置了服务的属性和行为。它们共同协作,提供了对服务网格中流量和服务的灵活控制,实现了可靠、安全和可观察的微服务架构。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
Istio云原生

基于Istio的微服务可观察性

2025-7-15 7:03:38

Kubernetes云原生

MetalLB完整指南:Kubernetes裸机集群负载均衡解决方案

2025-8-4 12:19:14

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索
本站支持IPv6访问