istio流量管理

流量管理

image-20231110102205352

目录

image-20231111150752155

文章目录

    • 流量管理
    • 目录
    • 流量管理概述
    • 请求路由
      • 1.路由到版本1
        • ==🚩 实战:路由到版本1-2023.11.11(测试成功)==
      • 2.基于用户身份的路由
        • ==🚩 实战:基于用户身份的路由-2023.11.11(测试成功)==
    • 关于我
    • 最后

流量管理概述

上面我们了解了 GatewayVirtualService 资源对象的作用,以及它们是如何影响 Envoy 的配置的,那么这些资源对象又是如何影响流量的呢?通过 Istio 如何实现流量管理的呢?

Istio 的流量路由规则可以很容易的控制服务之间的流量和 API 调用。Istio 简化了服务级别属性的配置,比如熔断器、超时和重试,并且能轻松的设置重要的任务,如 A/B 测试、金丝雀发布、基于流量百分比切分的分阶段发布等。它还提供了开箱即用的故障恢复特性, 有助于增强应用的健壮性,从而更好地应对被依赖的服务或网络发生故障的情况。

为了在网格中路由,Istio 需要知道所有的 endpoint 在哪以及它们属于哪些服务。为了定位到 service registry(服务注册中心),Istio 会连接到一个服务发现系统。如果在 Kubernetes 集群上安装了 Istio,那么它将自动检测该集群中的服务和 endpoint。

使用此服务注册中心,Envoy 代理可以将流量定向到相关服务。大多数基于微服务的应用程序,每个服务的工作负载都有多个实例来处理流量,称为负载均衡池。默认情况下,Envoy 代理基于轮询调度模型在服务的负载均衡池内分发流量,按顺序将请求发送给池中每个成员, 一旦所有服务实例均接收过一次请求后,就重新回到第一个池成员。

Istio 基本的服务发现和负载均衡能力提供了一个可用的服务网格,但它能做到的远比这多的多。在许多情况下我们可能希望对网格的流量情况进行更细粒度的控制。作为 A/B 测试的一部分,可能想将特定百分比的流量定向到新版本的服务,或者为特定的服务实例子集应用不同的负载均衡策略。可能还想对进出网格的流量应用特殊的规则,或者将网格的外部依赖项添加到服务注册中心。通过使用 Istio 的流量管理 API 将流量配置添加到 Istio,就可以完成所有这些甚至更多的工作。

请求路由

首先我们来实现下最基本的流量请求路由的功能,这里我们将学习如何将请求动态路由到微服务的多个版本。

我们知道 Bookinfo 示例包含四个独立的微服务,每个微服务都有多个版本。其中 reviews 服务的三个不同版本已经部署并同时运行。我们可以在浏览器中访问 Bookinfo 应用程序并刷新几次。正常会看到三种不同的 reviews 服务版本的输出,有时书评的输出包含星级评分,有时则不包含。这是因为没有明确的默认服务版本可路由,Istio 将以循环方式将请求路由到所有可用版本。

我们首先来将所有流量路由到微服务的 v1 版本,稍后,您将应用规则根据 HTTP 请求 header 的值路由流量。

1.路由到版本1

🚩 实战:路由到版本1-2023.11.11(测试成功)

实验环境:

k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)

[root@master1 ~]#istioctl version
client version: 1.19.3
control plane version: 1.19.3
data plane version: 1.19.3 (8 proxies)

实验软件:

链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功) --本节测试yaml在此目录里

image-20231105111842627

实验步骤:

image-20231111150558060

graph LR
	A[实战步骤] -->B(1️⃣ 部署VirtualService)
	A[实战步骤] -->C(2️⃣ DestinationRule)
    A[实战步骤] -->D(3️⃣ 验证)

要只路由到一个版本,则需要为微服务设置默认版本的 VirtualService

🍀

应用规则

Istio 使用 VirtualService 来定义路由规则,只需要应用下面的资源对象即可:

$ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created

该资源清单中定义了四个 VirtualService 对象,分别是 productpagereviewsratingsdetails,它们分别对应着 Bookinfo 应用中的四个微服务,完整的清单如下所示:

# virtual-service-all-v1.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
    - productpage
  http:
    - route:
        - destination:
            host: productpage
            subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
    - ratings
  http:
    - route:
        - destination:
            host: ratings
            subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: details
spec:
  hosts:
    - details
  http:
    - route:
        - destination:
            host: details
            subset: v1
---

我们可以看到这里的 VirtualService 对象中都定义了 subset 字段,这个字段就是用来指定微服务的版本的,这里我们将所有的微服务都指定为 v1 版本,这样所有的流量都会被路由到 v1 版本的微服务中,包括 reviews 服务,这样我们就不会再看到星级评分了。

🍀

但是如果我们现在直接去访问 Bookinfo 应用的话,是不能正常访问的,因为我们压根就还没指定这些 v1 版本的微服务到底在哪里。

image-20231111144249758

🍀

这个时候就需要用到另外一个资源对象 DestinationRule 了,我们需要为每个微服务创建一个 DestinationRule 对象,用来指定这些微服务的实际地址,这样 VirtualService 对象才能将流量路由到这些微服务中。Istio 在 DestinationRule 目标规则中使用 subsets 定义服务的版本,运行以下命令为 Bookinfo 服务创建默认的目标规则即可:

$ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created

该资源清单中定义了四个 DestinationRule 对象,分别是 productpagereviewsratingsdetails 几个服务的目标规则,它们分别对应着 Bookinfo 应用中的四个微服务,完整的清单如下所示:

# destination-rule-all.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: productpage
spec:
  host: productpage
  subsets:
    - name: v1
      labels:
        version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
    - name: v3
      labels:
        version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ratings
spec:
  host: ratings
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
    - name: v2-mysql
      labels:
        version: v2-mysql
    - name: v2-mysql-vm
      labels:
        version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: details
spec:
  host: details
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
---

🍀

现在我们就可以正常访问 Bookinfo 应用了,并且无论刷新多少次,页面的评论部分都不会显示评级星标,这是因为我们将 Istio 配置为将 reviews 服务的所有流量路由到版本 reviews:v1,而此版本的服务不访问星级评分服务。

img

这样我们就成功将流量路由到服务的某一个版本上了。

原理分析

🍀

前面章节中我们只定义了一个名为 bookinfoVirtualService 资源对象就可以正常访问了:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: bookinfo
  namespace: default
spec:
  gateways:
    - bookinfo-gateway
  hosts:
    - "*"
  http:
    - match:
        - uri:
            exact: /productpage
        - uri:
            prefix: /static
        - uri:
            exact: /login
        - uri:
            exact: /logout
        - uri:
            prefix: /api/v1/products
      route:
        - destination:
            host: productpage
            port:
              number: 9080

很明显上面这个虚拟服务对象是我们访问 Bookinfo 应用的入口路由规则,所以这个虚拟服务对象实际上是为 istio-ingressgateway 入口网关服务定义的。 它将所有的流量都路由到了 productpage 这个服务上,而 productpage 这个服务又会去调用其他的服务来获取数据,在 productpage 服务中调用其他微服务 其实就是直接通过服务名称来调用的,比如调用 reviews 服务就是直接通过 reviews:9080 这个服务来调用的,我们可以查看 productpage 的代码来验证这一点:

img

🍀

我们可以再次查看 Bookinfo 在网格内的请求架构图:

img

当我们在浏览器中访问 http://<gateway url>/productpage 时,请求将进入网格中的 istio-ingressgateway 服务,然后将请求转发到 productpage 服务。productpage 服务将调用 reviewsdetails 服务来填充页面的内容,然后将其返回给用户。(reviews 服务包括 3 个不同版本的应用,可以通过 version 标签区分)

🍀

现在我们只想将流量路由到 reviews:v1 版本去,按照传统的方法只需要将 reviews 的 Service 对象去强制关联 version: v1 这个标签即可,现在我们所有的服务都被注入了一个 Envoy 的 Sidecar 代理,通过 Envoy 很容易就可以实现这个路由功能,而相应的在 Istio 中我们只需要通过 VirtualServiceDestinationRule 这两个资源对象就可以来实现了。上面我们创建的关于 reviews 服务的这两个对象如下所示:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
    - route:
        - destination:
            host: reviews
            subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
    - name: v3
      labels:
        version: v3

那么这两个对象是如何来影响 Envoy Sidecar 的呢?前面我们已经分析了流量从 istio-ingressgateway 进来后被路由到了 productpage 服务,那么 productpage 又该如何去访问其他微服务呢?同样我们可以使用 istioctl proxy-config 来查看 productpage 服务的 Envoy 配置。

🍀

每个 Envoy Sidecar 都有一个绑定到 0.0.0.0:15001 的监听器,然后利用 IP tables 将 pod 的所有入站和出站流量路由到这里,此监听器会配置一个 useOriginalDst: true,这意味着它将请求交给最符合请求原始目标的监听器。如果找不到任何匹配的虚拟监听器,它会将请求发送给返回 404 的 BlackHoleCluster,我们可以查看下 15001 端口的监听器配置:

[root@master1 istio-1.19.3]#istioctl proxy-config listeners productpage-v1-564d4686f-7vhks --port 15001 -oyaml
- accessLog:
  - filter:
      responseFlagFilter:
        flags:
        - NR
    name: envoy.access_loggers.file
    typedConfig:
      '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
      logFormat:
        textFormatSource:
          inlineString: |
            [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS% %CONNECTION_TERMINATION_DETAILS% "%UPSTREAM_TRANSPORT_FAILURE_REASON%" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%
      path: /dev/stdout
  address:
    socketAddress:
      address: 0.0.0.0
      portValue: 15001
  filterChains:
  - filterChainMatch:
      destinationPort: 15001
    filters:
    - name: istio.stats
      typedConfig:
        '@type': type.googleapis.com/stats.PluginConfig
    - name: envoy.filters.network.tcp_proxy
      typedConfig:
        '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
        cluster: BlackHoleCluster
        statPrefix: BlackHoleCluster
    name: virtualOutbound-blackhole
  - filters:
    - name: istio.stats
      typedConfig:
        '@type': type.googleapis.com/stats.PluginConfig
    - name: envoy.filters.network.tcp_proxy
      typedConfig:
        '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
        accessLog:
        - name: envoy.access_loggers.file
          typedConfig:
            '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
            logFormat:
              textFormatSource:
                inlineString: |
                  [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS% %CONNECTION_TERMINATION_DETAILS% "%UPSTREAM_TRANSPORT_FAILURE_REASON%" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%
            path: /dev/stdout
        cluster: PassthroughCluster
        statPrefix: PassthroughCluster
    name: virtualOutbound-catchall-tcp
  name: virtualOutbound
  trafficDirection: OUTBOUND
  useOriginalDst: true

[root@master1 istio-1.19.3]#

🍀

实际上我们的请求是到 9080 端口(productpage 服务绑定 9080 端口)的 HTTP 出站请求,这意味着它被切换到 0.0.0.0:9080 虚拟监听器。所以我们查看下 9080 端口的监听器配置:

# productpage 默认访问其他服务的 9080 端口
$ istioctl proxy-config listeners productpage-v1-564d4686f-wwqqf --port 9080 -oyaml
- address:
    socketAddress:
      address: 0.0.0.0
      portValue: 9080
  # ......
        rds:
          configSource:
            ads: {}
            initialFetchTimeout: 0s
            resourceApiVersion: V3
          routeConfigName: "9080"  # RDS的路由配置名称
  # ......
  name: 0.0.0.0_9080
  trafficDirection: OUTBOUND  # 出流量

可以看到此监听器在其配置的 RDS 中查找名为 9080 的路由配置,我们可以使用 istioctl proxy-config routes 命令来查看这个路由配置的详细信息:

# 查看 9080 这个路由配置
$ istioctl proxy-config routes productpage-v1-564d4686f-wwqqf --name 9080 -oyaml
- name: "9080"
  virtualHosts:
  - domains:
    - details.default.svc.cluster.local
    - details
    - details.default.svc
    - details.default
    - 10.111.83.224
    name: details.default.svc.cluster.local:9080
    routes:
    - decorator:
        operation: details.default.svc.cluster.local:9080/*
      match:
        prefix: /
      metadata:
        filterMetadata:
          istio:
            config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/details
      route:
        cluster: outbound|9080|v1|details.default.svc.cluster.local
        # ......
  - domains:
    - productpage.default.svc.cluster.local
    - productpage
    - productpage.default.svc
    - productpage.default
    - 10.97.120.23
    name: productpage.default.svc.cluster.local:9080
    routes:
    - decorator:
        operation: productpage.default.svc.cluster.local:9080/*
      match:
        prefix: /
      name: default
      route:
        cluster: outbound|9080||productpage.default.svc.cluster.local
        # ......
  - domains:
    - ratings.default.svc.cluster.local
    - ratings
    - ratings.default.svc
    - ratings.default
    - 10.101.184.235
    name: ratings.default.svc.cluster.local:9080
    routes:
    - decorator:
        operation: ratings.default.svc.cluster.local:9080/*
      match:
        prefix: /
      metadata:
        filterMetadata:
          istio:
            config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/ratings
      route:
        cluster: outbound|9080|v1|ratings.default.svc.cluster.local
        # ......
  - domains:
    - reviews.default.svc.cluster.local
    - reviews
    - reviews.default.svc
    - reviews.default
    - 10.97.120.56
    name: reviews.default.svc.cluster.local:9080
    routes:
    - decorator:
        operation: reviews.default.svc.cluster.local:9080/*
      match:
        prefix: /
      metadata:
        filterMetadata:
          istio:
            config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/reviews
      route:
        cluster: outbound|9080|v1|reviews.default.svc.cluster.local
        # ......
  - domains:
    - '*'
    name: allow_any
    routes:
    - match:
        prefix: /
      name: allow_any
      route:
        cluster: PassthroughCluster
        # ......

这个路由配置中其实包含了 K8s Service 对象中监听 9080 端口的所有服务,如果没有创建对应的 VirtualService 对象,对应的路由配置就没有 metadata.filterMetadata.istio.config 这个属性。比如现在我们正在通过 productpage 请求前往 reviews 服务,因此 Envoy 将选择我们的请求与域匹配的虚拟主机。一旦在域上匹配,Envoy 会查找与请求匹配的第一条路径,我们这里没有任何高级路由,因此只有一条路由匹配所有内容。这条路由告诉 Envoy 将请求发送到 outbound|9080|v1|reviews.default.svc.cluster.local 集群,因为前面我们创建的 reviews 这个 VirtualService 对象配置了的 destination.subset: v1,所以这里的集群命名上多了一个 subset

需要注意的是我们在 VirtualService 对象里面配置了 destination.subset: v1,那么必须要有对应的 subset 存在才行,否则不会生成对应的 Envoy 集群配置,那么就不能正常访问该服务了,而该 subset 就是通过前面的 DestinationRule 对象来定义的,现在我们就可以来查看这个集群配置了:

$ istioctl proxy-config cluster productpage-v1-564d4686f-wwqqf --fqdn reviews.default.svc.cluster.local -o yaml
- edsClusterConfig:
    edsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
    serviceName: outbound|9080||reviews.default.svc.cluster.local
  lbPolicy: LEAST_REQUEST
  metadata:
    filterMetadata:
      istio:
        config: /apis/networking.istio.io/v1alpha3/namespaces/default/destination-rule/reviews
        services:
        - host: reviews.default.svc.cluster.local
          name: reviews
          namespace: default
  # ......
  name: outbound|9080||reviews.default.svc.cluster.local
  type: EDS
- edsClusterConfig:
    edsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
    serviceName: outbound|9080|v1|reviews.default.svc.cluster.local
  lbPolicy: LEAST_REQUEST
  metadata:
    filterMetadata:
      istio:
        config: /apis/networking.istio.io/v1alpha3/namespaces/default/destination-rule/reviews
        services:
        - host: reviews.default.svc.cluster.local
          name: reviews
          namespace: default
        subset: v1
  name: outbound|9080|v1|reviews.default.svc.cluster.local
  # ......
  type: EDS
- edsClusterConfig:
    edsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
    serviceName: outbound|9080|v2|reviews.default.svc.cluster.local
  filters:
  - name: istio.metadata_exchange
    typedConfig:
      '@type': type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange
      protocol: istio-peer-exchange
  lbPolicy: LEAST_REQUEST
  metadata:
    filterMetadata:
      istio:
        config: /apis/networking.istio.io/v1alpha3/namespaces/default/destination-rule/reviews
        services:
        - host: reviews.default.svc.cluster.local
          name: reviews
          namespace: default
        subset: v2
  name: outbound|9080|v2|reviews.default.svc.cluster.local
  # ......
  type: EDS
- edsClusterConfig:
    edsConfig:
      ads: {}
      initialFetchTimeout: 0s
      resourceApiVersion: V3
    serviceName: outbound|9080|v3|reviews.default.svc.cluster.local
  filters:
  - name: istio.metadata_exchange
    typedConfig:
      '@type': type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange
      protocol: istio-peer-exchange
  lbPolicy: LEAST_REQUEST
  metadata:
    filterMetadata:
      istio:
        config: /apis/networking.istio.io/v1alpha3/namespaces/default/destination-rule/reviews
        services:
        - host: reviews.default.svc.cluster.local
          name: reviews
          namespace: default
        subset: v3
  name: outbound|9080|v3|reviews.default.svc.cluster.local
  # ......
  type: EDS

从上面配置可以看到里面一共包含了 4 个 reviews 相关的集群,一个是原始的不包含 subset 的,而另外三个就是前面我们在 DestinationRule 对象中配置的 3 个 subset,所以其实 DestinationRule 映射到 Envoy 的配置文件中就是 Cluster

🍀

最后我们同样还可以查看每个集群下面包含的 endpoint 有哪些:

$ istioctl proxy-config endpoint productpage-v1-564d4686f-wwqqf --cluster "outbound|9080||reviews.default.svc.cluster.local" -o yaml
- edsServiceName: outbound|9080||reviews.default.svc.cluster.local
  - address:
      socketAddress:
        address: 10.244.2.84
        portValue: 9080
    # ......
    weight: 1
  - address:
      socketAddress:
        address: 10.244.2.83
        portValue: 9080
    # ......
    weight: 1
  - address:
      socketAddress:
        address: 10.244.2.88
        portValue: 9080
    # ......
    weight: 1
  name: outbound|9080||reviews.default.svc.cluster.local
  observabilityName: outbound|9080||reviews.default.svc.cluster.local

$ istioctl proxy-config endpoint productpage-v1-564d4686f-wwqqf --cluster "outbound|9080|v1|reviews.default.svc.cluster.local" -o yaml
- edsServiceName: outbound|9080|v1|reviews.default.svc.cluster.local
  hostStatuses:
  - address:
      socketAddress:
        address: 10.244.2.84
        portValue: 9080
    weight: 1
  name: outbound|9080|v1|reviews.default.svc.cluster.local
  observabilityName: outbound|9080|v1|reviews.default.svc.cluster.local

# 过滤 version=v1 的 reviews pod
$ kubectl get pod -l app=reviews,version=v1 -o wide
NAME                          READY   STATUS    RESTARTS        AGE     IP            NODE    NOMINATED NODE   READINESS GATES
reviews-v1-86896b7648-zjh2n   2/2     Running   4 (5h18m ago)   6d17h   10.244.2.84   node2   <none>           <none>

可以看到不包含 subset 的集群下面的 endpoint 其实就是 reviews 这个 Service 对象的 endpoint 集合,包含 subset 就只有和该子集匹配的后端实例了。到了这一步,一切皆明了,后面的事情就跟之前的套路一样了,具体的 Endpoint 对应打了标签 version=v1 的 Pod。

🍀

到这里我们是不是就实现了通过 VirtualServiceDestinationRule 对象将流量路由到了指定的版本上面了,上面的整个过程就是请求从 productpage 到 reviews 的过程,从 reviews 到网格内其他应用的流量与上面类似,就不展开讨论了。

2.基于用户身份的路由

🚩 实战:基于用户身份的路由-2023.11.11(测试成功)

实验环境:

k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)

[root@master1 ~]#istioctl version
client version: 1.19.3
control plane version: 1.19.3
data plane version: 1.19.3 (8 proxies)

实验软件:

链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功) --本节测试yaml在此目录里

image-20231105111842627

实验步骤:

image-20231111150647965

graph LR
	A[实战步骤] -->B(1️⃣ 更新VirtualService)
	A[实战步骤] -->C(2️⃣ 测试)

接下来我们继续更改路由配置,将来自特定用户的所有流量路由到特定服务版本。我们这里将配置来自名为 Jason 的用户的所有流量被路由到服务 reviews:v2

注意 Istio 对用户身份没有任何特殊的内置机制,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头来实现该效果:headers['end-user'] = session['user']

🍀

要实现该功能,只需要创建下面的资源对象即可:

$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
virtualservice.networking.istio.io/reviews configured

该资源清单文件创建了一个如下所示的 VirtualService 资源对象:

# virtual-service-reviews-test-v2.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
    - match:
        - headers:
            end-user:
              exact: jason
      route:
        - destination:
            host: reviews
            subset: v2
    - route:
        - destination:
            host: reviews
            subset: v1

该对象设置了一条路由规则,它会根据 productpage 服务发起的请求的 end-user 自定义请求头内容进行匹配,如果有该内容且为 jason 则会将流量路由到 reviews 服务的 v2 版本,其余的还是被路由到 v1 版本去。

🍀

现在我们可以前往浏览器访问 Bookinfo 应用,多刷新几次可以看到评论始终访问到的是 v1 版本的服务,即没有星标的:

img

🍀

然后我们点击页面右上角的 Sign in 按钮,使用 jason 进行登录,登录后页面就会出现带有黑色星标的 v2 版本的评论服务,即使多刷新几次依然如此:

img

如果我们选择使用其他用户进行登录或者注销则星标就会消失,这是因为除了 Jason 之外,所有用户的流量都被路由到 reviews:v1

🍀

同样的我们可以去查看下对应的 Envoy Sidecar 配置的变化,因为这里我们只更新了一个 VirtualService 对象,所以只会对 Envoy 的路由表产生影响,查看对应的路由配置即可:

$ istioctl proxy-config routes productpage-v1-564d4686f-wwqqf --name 9080 -oyaml
- name: "9080"
  validateClusters: false
  virtualHosts:
  # ......
  - domains:
    - reviews.default.svc.cluster.local
    - reviews
    - reviews.default.svc
    - reviews.default
    - 10.97.120.56
    includeRequestAttemptCount: true
    name: reviews.default.svc.cluster.local:9080
    routes:
    - decorator:
        operation: reviews.default.svc.cluster.local:9080/*
      match:
        caseSensitive: true
        headers:
        - name: end-user
          stringMatch:
            exact: jason
        prefix: /
      metadata:
        filterMetadata:
          istio:
            config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/reviews
      route:
        cluster: outbound|9080|v2|reviews.default.svc.cluster.local
        maxGrpcTimeout: 0s
        # ......
    - decorator:
        operation: reviews.default.svc.cluster.local:9080/*
      match:
        prefix: /
      metadata:
        filterMetadata:
          istio:
            config: /apis/networking.istio.io/v1alpha3/namespaces/default/virtual-service/reviews
      route:
        cluster: outbound|9080|v1|reviews.default.svc.cluster.local
        maxGrpcTimeout: 0s
        # ......

从配置上我们可以看到现在的 Envoy 配置中新增了一条路由规则,如下所示:

match:
  caseSensitive: true
  headers:
    - name: end-user
      stringMatch:
        exact: jason
  prefix: /
route:
  cluster: outbound|9080|v2|reviews.default.svc.cluster.local

当请求头中包含 end-user:jason 的时候请求会被路由到 outbound|9080|v2|reviews.default.svc.cluster.local 这个 Envoy Cluster 集群,这个集群就是前面我们通过 DestinationRule 创建的 v2 这个子集,所以最后请求会被路由到带有黑色星标的评论服务去。

img

🍀

到这里我们就明白了要通过 Istio 实现服务的流量管理,需要用到 GatewayVirtualServiceDestinationRule 三个 CRD 对象,这些对象其实最终都是去拼凑 Envoy 的配置,每个对象管理 Envoy 配置的一部分,把这个关系搞清楚我们就能更好的掌握 Istio 的使用了。

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码
x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号
《云原生架构师实战》

image-20230107215126971

🍀 个人博客站点

http://onedayxyy.cn/

image-20231106071817374

🍀 语雀

https://www.yuque.com/xyy-onlyone

image-20231106071948492

🍀 csdn

https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎

https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

image-20231016062113861

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/132237.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

跨镜头目标融合__追踪之目标重识别研究(跨镜头目标追踪)

文章目录 标题&#xff1a;跨镜头目标融合&#xff1b;目标重识别&#xff1b;跨镜头目标追踪&#xff1b; 1 目的&#xff1a;2 实现方法/策略&#xff1a;2.1 目标类型位置匹配&#xff08;或考虑结合目标轨迹&#xff09;2.2 目标重识别2.3 目标类型位置匹配(轨迹)目标重识别…

LeetCode【701】二叉搜索数的插入操作

题目&#xff1a; 思路&#xff1a; https://zhuanlan.zhihu.com/p/272781596 代码&#xff1a; class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {return process(root,val); }//递归public TreeNode process(TreeNode root,int val){//base ca…

Hls学习(一)

1&#xff1a;CPU、DSP、GPU都算软件可编程的硬件 2&#xff1a;dsp在递归方面有所减弱&#xff0c;在递归方面有所增强&#xff0c;比如递归啊等&#xff0c;GPU可以同时处理多个进程&#xff0c;对于大块数据&#xff0c;流处理比较适用 3&#xff1a;为了提高运算量处理更多…

可视化 | 3D文字球状标签云

文章目录 &#x1f4da;改编点&#x1f4da;final 改编自echarts 3d词云&#xff08;指向滑动、拖动、缩放、点击、自转 &#xff09; &#x1f4da;改编点 背景透明&#xff1a;background:rgb(0,0,0,0);不用链接&#xff0c;用span&#xff0c;重点span标class"star&q…

文心耀乌镇,“大模型之光”展现了什么?

“乌镇的小桥流水&#xff0c;能照见全球科技的风起云涌。” 多年以来&#xff0c;伴随着中国科技的腾飞&#xff0c;以及世界互联网大会乌镇峰会的连续成功举办&#xff0c;这句话已经成为全球科技产业的共识。乌镇是科技与互联网的风向标、晴雨表&#xff0c;也是无数新故事开…

【ATTCK】MITRE Caldera 简介

一、什么是Caldera caldera是一个基于MITRE ATT&CK™构建的网络安全框架。其目标是创建一种工具&#xff0c;通过提供自动化安全评估来增强网络从业者的能力&#xff0c;从而节省用户的时间、金钱和精力。为此&#xff0c;需要几个关键组件才能使 Caldera 成为行业领先的平…

外接式网络隔离变压器/网络隔离滤波器/网口变压器/脉冲变压器/网络隔离变压器模块

Hqst华强盛&#xff08;石门盈盛&#xff09;电子导读&#xff1a;外接式网络隔离变压器/网络隔离滤波器/网口变压器/脉冲变压器/网络隔离变压器模块&#xff0c;后统称网络隔离变压器&#xff0c;它是一种安装在电路外部的隔离变压器&#xff0c;主要用于隔离网络中的干扰信号…

巨好用又实用的18款3dMax插件!

3dMax是一款功能强大的 3D 软件&#xff0c;具有建模、动画、粒子动力学等许多强大功能。但并不是每个人都能有效地利用max的每一个功能&#xff0c;例如&#xff0c;很多人发现3dmax粒子流太难使用&#xff0c;3ds max蒙皮工具也是如此。 这让我们一些专业的开发公司或个人和…

跨域:利用iframe实现跨域DOM互访的四种方式

注&#xff1a;跨域的知识点详见&#xff1a;跨域相关知识点 目录 实验验证环境配置&#xff1a; 1、利用document.domain降域 方法1&#xff1a; 方法2&#xff1a; 2、利用location.hash 3、利用window.name 4、利用postMessage(最推荐) 使用postmessage实现跨域访问…

视频剪辑助手:轻松实现视频随机分割并提取音频保存

随着社交媒体和视频平台的日益普及&#xff0c;视频制作和分享已成为人们日常生活的一部分。无论是分享个人生活&#xff0c;还是展示才艺&#xff0c;或是推广产品&#xff0c;视频都是一个非常有效的工具。但是&#xff0c;视频制作往往涉及到大量的视频剪辑工作&#xff0c;…

卡码网语言基础课 | 11. 句子缩写

目录 一、 字符串大小的比较 二、 ASCII码值 三、 基本框架代码 四、 解题思路 4.1 首字母问题 4.2 判定小写字母 4.3 小写字母转换为大写字母 五、空格判断 六、 代码模块化 6.1 满足的条件 6.2 代码完善 七、 题目解答 7.1 原始代码 7.2 改进代码 八、 拓展与…

Redis五种数据类型及命令操作(一)

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇记录Redis五种数据类型及命令操作&#xff0c;如…

[BJDCTF2020]Easy MD5 1

题目环境&#xff1a; 尝试了SQL注入、命令执行等都不行 点击提交并burp进行抓包Repeater进行重放这里看到了内置的SQL语句select * from admin where passwordmd5($pass,true) 发现传进去的值会进行md5加密 这里看了大佬们的解释 ffifdyop绕过&#xff0c;绕过原理是&#xff…

计算机网络期末复习-Part3

1、rdt1.0&#xff0c;rdt2.0&#xff0c;rdt3.0的底层信道模型 RDT 1.0: 完全可靠的底层信道&#xff0c;没有比特差错&#xff0c;也没有分组丢失。 RDT 2.0: 具有比特差错的底层信道&#xff0c;有比特差错&#xff0c;但没有分组丢失。 RDT 3.0: 具有差错和丢包的底层信道…

聊聊性能测试的左移右移

前面的文章中&#xff0c;分享过我对于测试左移右移的一些思考和实践方法。有同学在后台留言问我&#xff1a;常规的性能测试一般都是在测试阶段集成测试时候才开始介入&#xff0c;很容易测试时间不够&#xff0c;可不可以借鉴测试左移右移的思路&#xff0c;更早的介入和发现…

实战Leetcode(三)

Practice makes perfect&#xff01; 实战一&#xff1a; 带环问题其实我们小学时就接触过&#xff0c;就比如在操场上比赛跑步的追击问题&#xff0c;这里也是一样&#xff0c;如果我们定义两个指针&#xff0c;一个快指针&#xff0c;一个慢指针&#xff0c;快指针走的快&…

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:

错误描述如下所示&#xff1a; 我们将错误拉到最下面如下所示为导致异常的原因&#xff1a; Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type com.example.reviewmybatisplus.Service.UserService available: expec…

基于Mahony互补滤波的IMU数据优化_学习笔记整理

这周自己被安排进行优化软件 IMU 姿态解算项目&#xff0c;之前自己只简单了解四元数&#xff0c;对IMU数据处理从未接触&#xff0c;通过这一周的学习感觉收获颇丰&#xff0c;在今天光棍节之际&#xff0c;&#xff0c;&#xff0c;用大半天的时间对这一周的收获进行整理&…

SwiftUI 如何保证 Text 中字符数量相等的字符串显示宽度一定相同?

0. 问题现象 在 SwiftUI 中我们往往需要将内容相似的字符串展列出来给用户比较,这些字符串内容各有不同但字符数量始终是相等的,我们希望它们的显示宽度始终保持一致: 如上图所示:即使是等宽字符组成的字符串在字符数量相等时它们的显示宽度仍然可能不一致。但演示中最底部…

迷雾系统-人物驱散迷雾

使用linerRender,将人物移动数据动态添加进去&#xff0c;同样是特殊层级让FogCamera渲染 EndCapVertices的数量越多&#xff0c;矩形就变为一个椭圆形的形状&#xff0c;更适合圆形视野探索 当拐点的两个点距离太近&#xff0c;LineRender会发生扭曲&#xff0c;解决方案是在…