万字长文带你入门Istio

2022年05月15日 阅读数:2
这篇文章主要向大家介绍万字长文带你入门Istio,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

点击上方“芋道源码”,选择“设为星标vue

管她前浪,仍是后浪?git

能浪的浪,才是好浪!
github

天天 10:33 更新文章,天天掉亿点点头发...数据库

源码精品专栏后端

 

来源:zhuanlan.zhihu.com/
p/369068128

b60f834f7207fa3781d3b5e034b920c1.png


简介

在本教程中,咱们将介绍服务网格的基础知识,并了解它如何实现分布式系统架构。

咱们将主要关注Istio,它是服务网格的一种具体实现。在此过程当中,咱们将介绍Istio的核心架构。

推荐下本身作的 Spring Boot 的实战项目:

https://github.com/YunaiV/ruoyi-vue-pro

什么是服务网格?

在过去的几十年中,咱们已经看到了单体应用程序开始拆分为较小的应用程序。此外,诸如Docker之类的容器化技术和诸如Kubernetes之类的编排系统加速了这一变化。

尽管在像Kubernetes这样的分布式系统上采用微服务架构有许多优点,但它也具备至关的复杂性。因为分布式服务必须相互通讯,所以咱们必须考虑发现,路由,重试和故障转移。

还有其余一些问题,例如安全性和可观察性,咱们还必须注意如下问题:

e3f8e1dd90ae5e22e1d481b4b40c1f6e.png

如今,在每一个服务中创建这些通讯功能可能很是繁琐,尤为是当服务范围扩大且通讯变得复杂时,更是如此。这正是服务网格能够为咱们提供帮助的地方。基本上,服务网格消除了在分布式软件系统中管理全部服务到服务通讯的责任。

服务网格可以经过一组网络代理来作到这一点。本质上,服务之间的请求是经过与服务一块儿运行但位于基础结构层以外的代理路由的:

9b1f31fbe4889bdd99512ed5beb0cca9.png

这些代理基本上为服务建立了一个网状网络——所以得名为服务网格!经过这些代理,服务网格可以控制服务到服务通讯的各个方面。这样,咱们可使用它来解决分布式计算的八个谬误,这是一组断言,描述了咱们常常对分布式应用程序作出的错误假设。

推荐下本身作的 Spring Cloud 的实战项目:

https://github.com/YunaiV/onemall

服务网格的特征

如今,让咱们了解服务网格能够为咱们提供的一些功能。请注意,实际功能列表取决于服务网格的实现。可是,总的来讲,咱们应该在全部实现中都指望其中大多数功能。

咱们能够将这些功能大体分为三类:流量管理,安全性和可观察性。

流量管理

服务网格的基本特征之一是流量管理。这包括动态服务发现和路由。尤为影子流量和流量拆分功能,这些对于实现金丝雀发布和A/B测试很是有用。

因为全部服务之间的通讯都是由服务网格处理的,所以它还启用了一些可靠性功能。例如,服务网格能够提供重试,超时,速率限制和断路器。这些现成的故障恢复功能使通讯更加可靠。

安全性

服务网格一般还处理服务到服务通讯的安全性方面。这包括经过双向TLS(mTLS)强制进行流量加密,经过证书验证提供身份验证以及经过访问策略确保受权。

服务网格中还可能存在一些有趣的安全用例。例如,咱们能够实现网络分段,从而容许某些服务进行通讯而禁止其余服务。并且,服务网格能够为审核需求提供精确的历史信息。

可观察性

强大的可观察性是处理分布式系统复杂性的基本要求。因为服务网格能够处理全部通讯,所以正确放置了它能够提供可观察性的功能。例如,它能够提供有关分布式追踪的信息。

服务网格能够生成许多指标,例如延迟,流量,错误和饱和度。此外,服务网格还能够生成访问日志,为每一个请求提供完整记录。这些对于理解单个服务以及整个系统的行为很是有用。

Istio简介

Istio是最初由IBM,Google和Lyft开发的服务网格的开源实现。它能够透明地分层到分布式应用程序上,并提供服务网格的全部优势,例如流量管理,安全性和可观察性。

它旨在与各类部署配合使用,例如本地部署,云托管,Kubernetes容器以及虚拟机上运行的服务程序。尽管Istio与平台无关,但它常常与Kubernetes平台上部署的微服务一块儿使用。

从根本上讲,Istio的工做原理是以Sidcar的形式将Envoy的扩展版本做为代理布署到每一个微服务中:

a7f335b483f426b8f62c6bfd08e49ddc.png

该代理网络构成了Istio架构的数据平面。这些代理的配置和管理是从控制平面完成的:

4952dd6cba3a7582469d38ad0a6e1127.png

控制平面基本上是服务网格的大脑。它为数据平面中的Envoy代理提供发现,配置和证书管理。

固然,只有在拥有大量相互通讯的微服务时,咱们才能体现Istio的优点。在这里,sidecar代理在专用的基础架构层中造成一个复杂的服务网格:

02a81a785fa18b1aad9b4c56ff5e9ecd.png

Istio在与外部库和平台集成方面很是灵活。例如,咱们能够将Istio与外部日志记录平台,遥测或策略系统集成。

了解Istio组件

咱们已经看到,Istio体系结构由数据平面和控制平面组成。此外,还有几个使Istio起做用的核心组件。

在本节中,咱们将详细介绍这些核心组件。

数据平面

Istio的数据平面主要包括Envoy代理的扩展版本。Envoy是一个开源边缘和服务代理,可帮助将网络问题与底层应用程序分离开来。应用程序仅向localhost发送消息或从localhost接收消息,而无需了解网络拓扑。

Envoy的核心是在OSI模型的L3和L4层运行的网络代理。它经过使用可插入网络过滤器链来执行链接处理。此外,Envoy支持用于基于HTTP的流量的附加L7层过滤器。并且,Envoy对HTTP/2和gRPC传输具备一流的支持。

Istio做为服务网格提供的许多功能其实是由Envoy代理的基础内置功能启用的:

  • 流量控制:Envoy经过HTTP,gRPC,WebSocket和TCP流量的丰富路由规则启用细粒度的流量控制应用

  • 网络弹性:Envoy包括对自动重试,断路和故障注入的开箱即用支持

  • 安全性:Envoy还能够实施安全策略,并对基础服务之间的通讯应用访问控制和速率限制

Envoy在Istio上表现出色的另外一个缘由之一是它的可扩展性。Envoy提供了基于WebAssembly的可插拔扩展模型。这在定制策略执行和遥测生成中很是有用。此外,咱们还可使用基于Proxy-Wasm沙箱API的Istio扩展在Istio中扩展Envoy代理。

控制面

如上所述,控制平面负责管理和配置数据平面中的Envoy代理。在Istio架构中,控制面核心组件是istiod,Istiod负责将高级路由规则和流量控制行为转换为特定于Envoy的配置,并在运行时将其传播到Sidercar。

若是咱们回顾一下Istio控制平面的架构,将会注意到它曾经是一组相互协做的独立组件。它包括诸如用于服务发现的Pilot,用于配置的Galley,用于证书生成的Citadel以及用于可扩展性的Mixer之类的组件。因为复杂性,这些单独的组件被合并为一个称为istiod的单个组件。

从根本上来讲,istiod仍使用与先前各个组件相同的代码和API。例如,Pilot负责抽象特定于平台的服务发现机制,并将其合成为Sidecar可使用的标准格式。所以,Istio能够支持针对多个环境(例如Kubernetes或虚拟机)的发现。

此外,istiod还提供安全性,经过内置的身份和凭据管理实现强大的服务到服务和最终用户身份验证。此外,借助istiod,咱们能够基于服务身份来实施安全策略。该过程也充当证书颁发机构(CA)并生成证书,以促进数据平面中的相互TLS(MTLS)通讯。

Istio工做原理

咱们已经了解了服务网格的典型特征是什么。此外,咱们介绍了Istio架构及其核心组件的基础。如今,是时候了解Istio如何经过其架构中的核心组件提供这些功能了。

咱们将专一于咱们以前经历过的相同类别的功能。

流量管理

咱们可使用Istio流量管理API对服务网格中的流量进行精细控制。咱们可使用这些API将本身的流量配置添加到Istio。此外,咱们可使用Kubernetes自定义资源定义(CRD)定义API资源。帮助咱们控制流量路由的关键API资源是虚拟服务和目标规则:

0e7ba140dc5c76caa14f0f438f9e44ba.png

基本上,虚拟服务使咱们能够配置如何将请求路由到Istio服务网格中的服务。所以,虚拟服务由一个或多个按顺序评估的路由规则组成。评估虚拟服务的路由规则后,将应用目标规则。目标规则有助于咱们控制到达目标的流量,例如,按版本对服务实例进行分组。

安全性

Istio为每一个服务提供身份。与每一个Envoy代理一块儿运行的Istio代理与istiod一块儿使用以自动进行密钥和证书轮换:

06f5486e90398a2c8cfdec74d414b073.png

Istio提供两种身份验证——对等身份验证和请求身份验证。对等身份验证用于服务到服务的身份验证,其中Istio提供双向TLS做为全栈解决方案。请求身份验证用于最终用户身份验证,其中Istio使用自定义身份验证提供程序或OpenID Connect(OIDC)提供程序提供JSON Web令牌(JWT)验证。

Istio还容许咱们经过简单地将受权策略应用于服务来实施对服务的访问控制。受权策略对Envoy代理中的入站流量实施访问控制。这样,咱们就能够在各类级别上应用访问控制:网格,命名空间和服务范围。

可观察性

Istio为网格网络内的全部服务通讯生成详细的遥测,例如度量,分布式跟踪和访问日志。Istio生成一组丰富的代理级指标,面向服务的指标和控制平面指标。

以前,Istio遥测体系结构将Mixer做为核心组件。可是从Telemetry v2开始,混音器提供的功能已替换为Envoy代理插件:

ec9aed28147d5a2e95e9de404f30c414.png

此外,Istio经过Envoy代理生成分布式跟踪。Istio支持许多跟踪后端,例如Zipkin,Jaeger,Lightstep和Datadog。咱们还能够控制跟踪速率的采样率。此外,Istio还以一组可配置的格式生成服务流量的访问日志。

Istio实战

上面咱们已经讲述了Istio原理和架构,接下来咱们开始实战部分。首先,咱们将在Kubernetes集群中安装Istio。此外,咱们将使用一个简单的基于微服务的应用程序来演示Istio在Kubernetes上的功能。

安装

有多种安装Istio的方法,但最简单的方法是下载并解压缩特定操做系统(例如Windows)的最新版本。提取的软件包在bin目录中包含istioctl客户端二进制文件。咱们可使用istioctl在目标Kubernetes集群上安装Istio:

istioctl install --set profile=demo -y

这会使用演示配置文件将Istio组件安装在默认的Kubernetes集群上。咱们还可使用任何其余特定于供应商的配置文件来代替演示。

最后,当咱们在此Kubernetes集群上部署任何应用程序时,咱们须要指示Istio自动注入Envoy sidecar代理:

kubectl label namespace default istio-injection=enabled

咱们在这里使用kubectl的前提是,咱们的机器上已经有像Minikube这样的Kubernetes集群和Kubernetes CLI kubectl。

示例应用

为了演示,咱们将想象一个很是简单的在线下订单应用程序。该应用程序包含三个微服务,它们相互交互以知足最终用户的订购请求:

5523a03f1dac1436fc266879a27083d9.png

咱们没有讨论这些微服务的细节,可是使用Spring Boot和REST API能够很简单地建立它们。最重要的是,咱们为这些微服务建立了一个Docker镜像,以便咱们能够将它们部署在Kubernetes上。

部署

在像Minikube这样的Kubernetes集群上部署容器化的工做负载很是简单。咱们将使用Deployment和Service资源类型来声明和访问工做负载。一般,咱们在YAML文件中定义它们:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: order-service
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: order-service
        version: v1
    spec:
      containers:
      - name: order-service
        image: kchandrakant/order-service:v1
        resources:
          requests:
            cpu: 0.1
            memory: 200
---
apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: order-service

对于订单服务的“部署和服务”,这是一个很是简单的定义。一样,咱们能够为库存服务和运输服务定义YAML文件。

使用kubectl部署这些资源也很是简单:

kubectl apply -f booking-service.yaml -f inventory-service.yaml -f shipping-service.yaml

因为咱们已经为默认命名空间启用了自动注入Envoy sidecar代理,所以一切都会由istiod来处理。或者,咱们可使用istioctl的kube-inject命令手动注入Envoy sidecar代理。

访问应用

如今,Istio主要负责处理全部的网状网络流量。所以,默认状况下,不容许进出网格的任何流量。Istio使用网关来管理来自网格的入站和出站流量。这样,咱们能够精确地控制进入或离开网格的流量。Istio提供了一些预配置的网关代理部署:istio-ingressgateway和istio-egressgateway。

咱们将为咱们的应用程序建立一个网关和一个虚拟服务来实现此目的:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: booking-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: booking
spec:
  hosts:
  - "*"
  gateways:
  - booking-gateway
  http:
  - match:
    - uri:
        prefix: /api/v1/booking
    route:
    - destination:
        host: booking-service
        port:
          number: 8080

在这里,咱们利用了Istio提供的默认入口控制器。此外,咱们已经定义了一个虚拟服务,将咱们的请求路由到预订服务。

一样,咱们也能够为来自网格的出站流量定义出口网关。

Istio的常见用例

如今,咱们已经看到了如何使用Istio在Kubernetes上部署一个简单的应用程序。可是,咱们仍然没有利用Istio为咱们启用的任何有趣功能。在本节中,咱们将介绍服务网格的一些常见用例,并了解如何使用Istio为咱们的简单应用程序实现它们。

请求路由

咱们可能要以特定方式处理请求路由的缘由有多个。例如,咱们可能会部署微服务的多个版本,例如运输服务,并但愿仅将一小部分请求路由到新版本。

咱们可使用虚拟服务的路由规则来实现这一点:

apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: shipping-service
spec:
  hosts:
    - shipping-service
  http:
  - route:
    - destination:
        host: shipping-service
        subset: v1
      weight: 90
    - destination:
        host: shipping-service
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: shipping-service
spec:
  host: shipping-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

路由规则还容许咱们基于诸如header参数之类的属性来定义匹配条件。此外,目的地字段指定与条件匹配的流量的实际目的地。

熔断

熔断器基本上是一种软件设计模式,用于检测故障并封装防止故障进一步级联的逻辑。这有助于建立有弹性的微服务应用程序,以限制故障和延迟尖峰的影响。

在Istio中,咱们可使用DestinationRule中的trafficPolicy配置在调用诸如清单服务之类的服务时应用熔断:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: inventory-service
spec:
  host: inventory-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100

在这里,咱们将DestinationRule配置为maxConnections为1,httpMaxPendingRequests为1,maxRequestsPerConnection为1。这实际上意味着,若是咱们将并发请求数超过1,熔断器将开始trap一些请求。

启用双向 TLS

双向身份验证是指双方在诸如TLS之类的身份验证协议中同时相互进行身份验证的状况。默认状况下,具备代理的服务之间的全部流量在Istio中都使用相互TLS。可是,没有代理的服务仍继续以纯文本格式接收流量。

虽然Istio将具备代理的服务之间的全部流量自动升级为双向TLS,但这些服务仍能够接收纯文本流量。咱们能够选择使用PeerAuthentication策略在整个网格范围内实施双向TLS:

apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "default"
  namespace: "istio-system"
spec:
  mtls:
    mode: STRICT

咱们还提供了对每一个命名空间或服务而不是在网格范围内强制实施双向TLS的选项。可是,特定于服务的PeerAuthentication策略优先于命名空间范围的策略。

使用JWT进行访问控制

JSON Web令牌(JWT)是用于建立数据的标准,该数据的有效载荷中包含声明许多声明的JSON。为了在身份提供者和服务提供者之间传递通过身份验证的用户的身份和标准或自定义声明,这一点已被普遍接受。

咱们能够在Istio中启用受权策略,以容许访问基于JWT的预订服务之类的服务:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: default
spec:
  selector:
    matchLabels:
      app: booking-service
  action: ALLOW
  rules:
  - from:
    - source:
       requestPrincipals: ["testing@baeldung.com/testing@baeldung.io"]

在这里,AuthorizationPolicy强制全部请求具备有效的JWT,并将requestPrincipal设置为特定值。Istio经过组合声明JWT的iss和sub来建立requestPrincipal属性。

思考

所以,到目前为止,咱们已经看到像Istio这样的服务网格如何使咱们更轻松地处理诸如微服务之类的分布式架构中的许多常见问题。可是尽管如此,Istio仍是一个复杂的系统,会增长最终部署的复杂性。与其余全部技术同样,Istio并不是灵丹妙药,必须谨慎使用。

咱们应该始终使用服务网格吗?

尽管咱们已经看到了使用服务网格的足够理由,但下面列举了一些可能促使咱们不使用它的缘由:

  • 服务网格处理全部服务到服务的通讯,而部署和操做服务网格则须要支付额外的费用。对于较简单的应用程序,这多是不合理的

  • 因为咱们已经习惯于处理一些此类问题,例如应用程序代码中的熔断,所以可能致使服务网格中的重复处理

  • 愈来愈依赖于诸如服务网格之类的外部系统可能会损害应用程序的可移植性,尤为是由于没有针对服务网格的行业标准

  • 因为服务网格一般经过拦截经过代理的网格流量来工做,所以它可能会给请求增长不但愿的延迟

  • 服务网格增长了许多其余组件和配置,须要精确处理。这须要专业知识,并增长了学习曲线

  • 最后,咱们可能最终将操做逻辑(应在服务网格中存在)与业务逻辑(不该在服务网格中)混合在一块儿

所以,正如咱们所看到的,服务网格的故事不只仅涉及好处,但这并不意味着它们不是真的。对咱们来讲,重要的是要仔细评估咱们的需求和应用程序的复杂性,而后权衡服务网格的好处和它们所增长的复杂性。

Istio的替代品有哪些?

尽管Istio很是受欢迎,并获得了业内一些领导者的支持,但它固然不是惟一的选择。尽管咱们在这里没法进行全面的比较,但让咱们看一下Linkerd和Consul这两个选项。

Linkerd是已为Kubernetes平台建立的开源服务网格。它也很受欢迎,目前在CNCF中具备孵化项目的地位。它的工做原理相似于Istio等任何其余服务网格。它还利用TCP代理来处理网格流量。Linkerd使用用Rust编写的微型代理,称为Linkerd代理。

整体而言,Linkerd并不比Istio复杂,由于它仅支持Kubernetes。可是,除此以外,Linkerd中可用的功能列表与Istio中可用的功能很是类似。Linkerd的核心架构也很是相似于Istio。基本上,Linkerd包含三个主要组件:用户界面,数据平面和控制平面。

Consul是HashiCorp的服务网格的开源实现。它的好处是能够与HashiCorp的其余基础架构管理产品套件很好地集成,以提供更普遍的功能。Consul中的数据平面能够灵活地支持代理以及本机集成模型。它带有内置代理,但也能够与Envoy一块儿使用。

除了Kubernetes,Consul还能够与Nomad等其余平台一块儿使用。Consul经过在每一个节点上运行Consul代理以执行运行情况检查来工做。这些代理与一台或多台存储和复制数据的Consul服务器通讯。尽管它提供了服务网格(如Istio)的全部标准功能,但它是部署和管理的更复杂的系统。

总结

总而言之,在本教程中,咱们介绍了服务网格模式的基本概念以及它提供给咱们的功能。特别是,咱们详细介绍了Istio。这涵盖了Istio的核心架构及其基本组件。此外,咱们详细介绍了一些常见用例的安装和使用Istio的细节



欢迎加入个人知识星球,一块儿探讨架构,交流源码。加入方式,长按下方二维码噢

bca39dbc41c7d24e0c9d99534196a910.png

已在知识星球更新源码解析以下:

5be703f7b88e56bc39c9f93afe84d186.png

68775db963cba58cce0141908b1265a9.png

58f6d33c222f14969f33f7765895df29.png

f0d19d2da018347d6de13cc4f163f49d.png

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)