前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在Kubernetes上使用Istio进行微服务流量管理

在Kubernetes上使用Istio进行微服务流量管理

作者头像
Steve Wang
发布2018-06-20 10:50:03
2.1K0
发布2018-06-20 10:50:03
举报
文章被收录于专栏:从流域到海域从流域到海域

Microservices Traffic Management Using Istio on Kubernetes

原文作者:Piotr Mińkowski

原文地址:https://dzone.com/articles/microservices-traffic-management-using-istio-on-ku

译者微博:@从流域到海域

译者博客:blog.csdn.net/solo95

在Kubernetes上使用Istio进行微服务流量管理

我已经在之前的一篇文章(5步在Kubernetes上搭建使用Istio的Service Mesh)中介绍了在Kubernetes上部署的两个微服务之间的路由配置的简单示例。如果您对Istio的基本信息以及通过Minikube在Kubernetes上进行的部署感兴趣,可以参考本文。今天,我们将基于上一篇关于Istio的文章中使用的相同示例应用程序,创建一些更高级的流量管理规则。

示例应用程序的源代码可在GitHub的sample-istio-serviceshttps://github.com/piomin/sample-istio-services.git中找到。有两个示例应用程序callme-servicecaller-service,并部署在两个不同的版本1.02.01.0版本在分支v1(https://github.com/piomin/sample-istio-services/tree/v1)中可以找到,而2.0版本在分支v2中(https://github.com/piomin/sample-istio-services/tree/v2)中可以找到。在不同版本中使用这些示例应用程序时,我将根据传入的请求中设置的HTTP标头向您展示不同的流量管理策略。

我们可能会强制callme-service将所有请求路由到特定版本的callme-service,方法是将标头x-version设置为v1v2。我们也可以不在请求中设置此标头,这会导致所有现有版本的服务之间的流量分割。如果请求到达caller-servicev1版本,那么流量在callme-service的两个实例之间按50-50进行分割(即五五开)。如果请求被caller-serviceV2版本的实例接收,那么75%的流量被转发到callme-servicev2版本,而只有25%到达v1版本。上面描述的情形已在下图中进行了说明。

在我们开始这个例子之前,我应该说一些关于Istio流量管理的话。如果你已经阅读过我之前关于Istio的文章,那么你可能会知道每个规则都被分配到了一个目的地。这些规则控制着服务网格内请求的路由过程。关于它们有一个非常重要的事情,特别是对于上图中所示的例子而言,可以将多个规则应用于相同的目的地。每条规则的优先级取决于规则的precedence域。有一个与该字段的值相关的原则:该整数字段的值越高,则对应规则的优先级越高。正如您可以猜到的那样,如果有多个具有相同优先级值的规则,则规则评估的顺序是未定义的。除了目的地之外,我们还可以定义请求的来源,以便仅将规则限制到特定的调用者。如果一个正在调用的服务有多个部署,我们甚至可以通过设置其来源的标签字段将其过滤掉(一部分)。当然,我们也可以指定HTTP请求的属性,例如URl,scheme或用于匹配请求和定义规则的header(即报文头,下面不再注释)。

现在我们来看看具有最高优先级的规则。它的名字是callme-service-v1(1)。它适用于callme-service(2),并且与其他规则(3)相比具有最高的优先级。它仅适用于由caller-service(4)发送的请求,这种请求包含带有v1(5)值的 HTTP header x-version。这条路线的规则只适用于callme-service(6)v1版本 。

代码语言:txt
复制
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: callme-service-v1 # (1)
spec:
  destination:
    name: callme-service # (2)
  precedence: 4 # (3)
  match:
    source:
      name: caller-service # (4)
    request:
      headers:
        x-version:
          exact: "v1" # (5)
  route:
  - labels:
      version: v1 # (6)

这是第一个图的片段,按此路线规则处理。

下一个规则callme-service-v2(1)的优先级较低(2)。但是,它与第一条规则不冲突,因为它仅适用于包含值为v2(3)的x-version header的请求。它把所有请求转发到的callme-service(4)v2版本。

代码语言:txt
复制
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: callme-service-v2 # (1)
spec:
  destination:
    name: callme-service
  precedence: 3 # (2)
  match:
    source:
      name: caller-service
    request:
      headers:
        x-version:
          exact: "v2" # (3)
  route:
  - labels:
      version: v2 # (4)

和上面一样,这里是第一个图的片段,它按这条路线规则处理。

下面代码片段中可见规则callme-service-v1-default(1)的优先级(2)低于前面描述的两个规则。在实践中,这意味着只有在前两条规则中定义的条件未得到满足时才能够执行。如果您没有在HTTP请求中传递headerx-version,或者它的值不同于v1v2,则会出现这种情况。下面可见的规则仅适用于标有v1version(3)的服务实例。最后,到callme-service的流量在两种版本的服务(4)之间以50比50的比例进行负载均衡。

代码语言:txt
复制
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: callme-service-v1-default # (1)
spec:
  destination:
    name: callme-service
  precedence: 2 # (2)
  match:
    source:
      name: caller-service
      labels:
        version: v1 # (3)
  route: # (4)
  - labels:
      version: v1
    weight: 50
  - labels:
      version: v2
    weight: 50

这是第一个图的片段,按此路线规则处理。

最后一条规则与前面描述的callme-service-v1-default非常相似。它的名字是callme-service-v2-default(1) ,它仅适用于caller-servicev2版本(3) 。它具有最低的优先级(2),并且按75-25的比例在callme-service两个版本之间按版本v2的偏好(4)进行分割。

代码语言:txt
复制
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
  name: callme-service-v2-default # (1)
spec:
  destination:
    name: callme-service
  precedence: 1 # (2)
  match:
    source:
      name: caller-service
      labels:
        version: v2 # (3)
  route: # (4)
  - labels:
      version: v1
    weight: 25
  - labels:
      version: v2
    weight: 75

与上面一样,我也提供了说明此规则行为的图表。

所有规则都可以放在一个文件中。在这种情况下,它们应该使用---行分隔开。该文件在callme-service模块的代码仓库中作为multi-rule.yaml文件可以找到。要在Kubernetes上部署所有定义的规则,只需执行以下命令。

代码语言:txt
复制
$ kubectl apply -f multi-rule.yaml

部署成功后,您可以通过运行该命令来查看可用规则的列表istioctl get routerule

在我们开始任何测试之前,我们显然需要在Kubernetes上部署示例应用程序。这些应用程序非常简单,非常类似于我之前关于Istio的文章中用于测试的应用程序。以下可见的控制器实现了GET /callme/ping方法,该方法打印出从pom.xml中获取的应用程序的版本以及请求中接收到的x-versionHTTP标头的值。

代码语言:txt
复制
@RestController
@RequestMapping("/callme")
public class CallmeController {
 private static final Logger LOGGER = LoggerFactory.getLogger(CallmeController.class);
 @Autowired
 BuildProperties buildProperties;
 @GetMapping("/ping")
 public String ping(@RequestHeader(name = "x-version", required = false) String version) {
  LOGGER.info("Ping: name={}, version={}, header={}", buildProperties.getName(), buildProperties.getVersion(), version);
  return buildProperties.getName() + ":" + buildProperties.getVersion() + " with version " + version;
 }
}

下面是实现GET /caller/ping方法的控制器类。它打印出从pom.xml获取的caller-service版本并调用由callme-service暴露出的GET callme/ping方法。发送到下游服务时,它需要在请求中包含x-version header。

代码语言:txt
复制
@RestController
@RequestMapping("/caller")
public class CallerController {
 private static final Logger LOGGER = LoggerFactory.getLogger(CallerController.class);
 @Autowired
 BuildProperties buildProperties;
 @Autowired
 RestTemplate restTemplate;
 @GetMapping("/ping")
 public String ping(@RequestHeader(name = "x-version", required = false) String version) {
  LOGGER.info("Ping: name={}, version={}, header={}", buildProperties.getName(), buildProperties.getVersion(), version);
  HttpHeaders headers = new HttpHeaders();
  if (version != null)
   headers.set("x-version", version); < span id = "mce_SELREST_start"
  style = "overflow:hidden;line-height:0;" > < /span>
  HttpEntity entity = new HttpEntity(headers);
  ResponseEntity response = restTemplate.exchange("http://callme-service:8091/callme/ping", HttpMethod.GET, entity, String.class);
  return buildProperties.getName() + ":" + buildProperties.getVersion() + ". Calling... " + response.getBody() + " with header " + version;
 }
}

现在,我们可以继续在Kubernetes上构建和部署应用程序。以下是后面的步骤。

1.构建应用程序

首先,通过执行命令mvn clean install切换到分支v1并构建整个sample-istio-services项目。

2.构建Docker镜像

Dockerfiles放置在每个应用程序的根目录中。通过执行以下命令来构建Docker镜像。

代码语言:txt
复制
$ docker build -t piomin/callme-service:1.0 .
$ docker build -t piomin/caller-service:1.0 .

或者,你可以省略这个步骤,因为图像piomin/callme-servicepiomin/caller-service可以在Docker Hub帐户中找到。

3.将Istio组件注入到Kubernetes部署文件中

Kubernetes YAML部署文件在每个应用程序的根目录中都作为deployment.yaml文件可用。以下命令的结果应保存为单独的文件,例如deployment-with-istio.yaml:。

代码语言:txt
复制
$ istioctl kube-inject -f deployment.yaml

4.在Kubernetes上部署

最后,您可以执行追梦的kubectl命令,以便使用我们的示例应用程序部署Docker容器。

代码语言:txt
复制
$ kubectl apply -f deployment-with-istio.yaml

然后切换到分支v2,并针对示例应用程序的2.0版本重复上述步骤。最终的部署结果在下图中可以看到。

在Kubernetes上运行Istio时,一个非常有用的功能是与Zipkin,Grafana或Prometheus等工具的即插即用集成。Istio会自动发送一些由Prometheus收集的指标,例如计算指标istio_request_count的请求的总数。这些插件的YAML部署文件在目录${ISTIO_HOME}/install/kubernetes/addons中可以找到。在使用kubectl命令安装Prometheus之前,我建议将服务类型从默认的ClusterIP通过添加line type: NodePort更改为Nodeport

代码语言:txt
复制
apiVersion: v1
kind: Service
metadata:
  annotations:
    prometheus.io/scrape: 'true'
  labels:
    name: prometheus
  name: prometheus
  namespace: istio-system
spec:
  type: NodePort
  selector:
    app: prometheus
  ports:
  - name: prometheus
    protocol: TCP
    port: 9090

然后我们应该运行kubectl apply -f prometheus.yamlistio-system命令以便在Kubernetes上部署Prometheus。部署在命名空间中可用。要检查服务的外部端口,请运行以下命令。对我而言,它能在http://192.168.99.100:32293/下获得。

在使用Prometheus可视化的下图中,我只过滤了发送给callme-service的请求。绿色指向由服务的v2版本接收的请求,而红色指向由服务的版本v1处理的请求。就像你可以在该图中看到的,在一开始的时候,我发送给caller-service的带有HTTP header x-version的请求设置为值v2,接着我不设置这个header的值,流量在服务的部署实例之间被分配。最后,我将它设置为v1。我定义了一个表达式rate(istio_request_count{callme-service.default.svc.cluster.local}[1m]),它返回每秒callme-service接收到的请求的速率。

测试

在向caller-service发送一些测试请求之前,我们需要在Kubernetes上获取它的地址。执行以下命令后,您会看到它在该地址下可用。http://192.168.99.100:32237/caller/ping

有四种可能的情况。在第一种情况中,当我们设置标题时,请求总是被路由到x-versionv1callme-service-v1。

如果header x-version1未包含在请求中,则流量将在callme-service-v1...

...和callme-service-v2之间分割。

最后,如果我们将header x-version设置为v2,即将请求始终路由到callme-service-v2

结论

通过使用Istio,您可以轻松地为部署在Kubernetes上的应用程序创建并应用简单并且更为先进的流量管理规则。您还可以通过Istio和Zipkin,Prometheus和Grafana之间的集成来监控一些指标和进行溯源。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Microservices Traffic Management Using Istio on Kubernetes
  • 在Kubernetes上使用Istio进行微服务流量管理
    • 1.构建应用程序
      • 2.构建Docker镜像
        • 3.将Istio组件注入到Kubernetes部署文件中
          • 4.在Kubernetes上部署
            • 测试
          • 结论
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档