服务网格Istio

是否一定要用istio

在Kubernetes运维环境下,使用Istio作为服务网格解决方案是可选的,而不是必须的。以下是为什么可以选择不使用Istio的原因:

  1. 简化性:Istio是一个功能强大的服务网格解决方案,提供了丰富的功能和配置选项。但对于某些应用程序和环境来说,这种复杂性可能是不必要的。如果您的应用程序架构相对简单、服务之间的通信较少且易于管理,可能不需要引入Istio的复杂性。
  2. 资源消耗:Istio在性能和资源消耗方面相对较高。Istio使用Envoy作为数据平面代理,这可能需要更多的计算资源和内存来支持较大规模的部署。如果您的集群资源有限或者您关注资源效率,那么选择轻量级的解决方案可能更适合您。
  3. 其他解决方案:除了Istio,还有其他服务网格解决方案可供选择,例如Linkerd、Consul等。这些解决方案提供类似的功能,但可能在配置和使用上有所不同。根据您的需求和偏好,您可以评估并选择适合的工具。
  4. 组织需求:每个组织的需求和环境都不同。某些组织可能有特定的安全性要求、监控需求或网络策略,这可能需要定制化的解决方案而不是通用的服务网格。

综上所述,使用Istio与否取决于您的具体需求和环境。如果您需要Istio提供的高级功能和控制,并且有足够的资源来支持它,那么使用Istio可能是有益的。但如果您的需求较简单、资源有限或者您更倾向于其他解决方案,那么不使用Istio也是完全可行的。

微服务与服务网格

微服务架构可谓是当前软件开发领域的技术热点,它在各种博客、社交媒体和会议演讲上的出镜率非常之高,无论是做基础架构还是做业务系统的工程师,对微服务都相当关注,而这个现象与热度到目前为止,已经持续了近 5 年之久。

尤其是近些年来,微服务架构逐渐发展成熟,从最初的星星之火到现在的大规模的落地与实践,几乎已经成为分布式环境下的首选架构。微服务成为时下技术热点,大量互联网公司都在做微服务架构的落地和推广。同时,也有很多传统企业基于微服务和容器,在做互联网技术转型。

而在这个技术转型中,国内有一个趋势,以 Spring Cloud 与 Dubbo 为代表的微服务开发框架非常普及和受欢迎。

然而软件开发没有银弹,基于这些传统微服务框架构建的应用系统在享受其优势的同时,痛点也越加明显。这些痛点包括但不限于以下几点:

  • 侵入性强。想要集成 SDK 的能力,除了需要添加相关依赖,往往还需要在业务代码中增加一部分的代码、或注解、或配置;业务代码与治理层代码界限不清晰。
  • 升级成本高。每次升级都需要业务应用修改 SDK 版本,重新进行功能回归测试,并且对每一台机器进行部署上线,而这对于业务方来说,与业务的快速迭代开发是有冲突的,大多不愿意停下来做这些与业务目标不太相关的事情。
  • 版本碎片化严重。由于升级成本高,而中间件却不会停止向前发展的步伐,久而久之,就会导致线上不同服务引用的 SDK 版本不统一、能力参差不齐,造成很难统一治理。
  • 中间件演变困难。由于版本碎片化严重,导致中间件向前演进的过程中就需要在代码中兼容各种各样的老版本逻辑,带着 “枷锁” 前行,无法实现快速迭代。
  • 内容多、门槛高。Spring Cloud 被称为微服务治理的全家桶,包含大大小小几十个组件,内容相当之多,往往需要几年时间去熟悉其中的关键组件。而要想使用 Spring Cloud 作为完整的治理框架,则需要深入了解其中原理与实现,否则遇到问题还是很难定位。
  • 治理功能不全。不同于 RPC 框架,Spring Cloud 作为治理全家桶的典型,也不是万能的,诸如协议转换支持、多重授权机制、动态请求路由、故障注入、灰度发布等高级功能并没有覆盖到。而这些功能往往是企业大规模落地不可获缺的功能,因此公司往往还需要投入其它人力进行相关功能的自研或者调研其它组件作为补充。

简单总结就是,以前提到微服务开发就是java开发语言的 Spring Cloud ,以及围绕这框架衍生的微服务组件,但是存在上述问题。

并且非java系的公司,用python、golang作开发语言的,如何进行微服务开发与运维呢

Service Mesh服务网格

Service Mesh是一种用于管理、监控和保护微服务架构的网络基础设施层。它通过在应用程序服务之间插入专用的代理(称为sidecar)来实现这些功能。这些代理负责处理服务之间的通信,提供诸如服务发现、负载均衡、流量控制、故障恢复和安全认证等功能。

Service Mesh的设计目标是解决微服务架构中的常见问题,例如服务之间的复杂通信模式、服务发现和负载均衡的挑战、流量管理和故障恢复等。通过将这些功能从应用程序代码中抽象出来,Service Mesh可以提供更高级别的可观察性、安全性和弹性,而无需修改应用程序的代码。

Service Mesh通常使用代理(如Envoy、Linkerd或Istio)来实现其功能。这些代理与每个服务部署在一起,并通过侧车(sidecar)模式与应用程序容器共同工作。代理负责管理进出服务的网络流量,并提供与Service Mesh控制平面交互的能力。

总结来说,Service Mesh是一种提供网络基础设施层的技术,用于解决微服务架构中的通信、管理和安全性等方面的挑战。它通过在服务之间插入代理来提供这些功能,并以透明的方式与应用程序集成。

什么是sidecar

  • 不修改代码
  • 不限制于某个语言

Sidecar是一种软件模式,它与主应用程序并行运行,并提供辅助功能和服务。在Service Mesh的上下文中,sidecar是一个独立的代理进程,与每个微服务实例一起部署在同一个容器或虚拟机中。

Sidecar代理负责处理服务之间的通信和网络流量管理。它位于每个微服务实例的旁边(因此得名sidecar),并通过与主应用程序容器共同工作来实现其功能。它可以通过拦截和转发网络请求,提供服务发现、负载均衡、流量控制、故障恢复、安全认证等功能。

通过使用sidecar代理,Service Mesh能够实现对微服务通信的细粒度控制和可观察性。每个微服务的所有网络流量都经过其所关联的sidecar代理,这使得Service Mesh能够收集流量数据、监控服务性能,并提供弹性和安全性功能,如故障恢复和安全认证。

Sidecar模式的好处是它能够与现有的应用程序无缝集成,而不需要修改应用程序代码。每个微服务只需要专注于自己的核心业务逻辑,而代理负责处理与网络通信相关的事务。

因此,sidecar是Service Mesh中的关键组件之一,通过为每个微服务实例提供附加的代理功能,实现了服务之间通信和管理的抽象层。

什么是Istio

Istio是一个开源的服务网格(Service Mesh)解决方案,用于管理和连接微服务应用程序中的服务通信。它提供了一组功能强大的特性,用于流量管理可观察性安全性策略执行等方面。

服务网格是一种用于处理服务之间通信的基础设施层。它通过将通信逻辑从应用程序代码中分离出来,为微服务架构提供了更好的可扩展性、可靠性和可管理性。

与微服务的关系,Istio可以看作是微服务架构中的一部分,用于解决服务之间通信和管理的挑战。

具体来说,Istio通过在应用程序容器之间注入一个轻量级的代理(称为sidecar),来实现对服务之间流量的控制和管理。这使得开发人员可以将关注点放在业务逻辑上,而无需关心服务之间的通信细节。

通过使用Istio,开发人员可以轻松实现服务发现、负载均衡、故障恢复、流量控制、可观察性和安全性等功能。

它还提供了丰富的指标、日志和分布式追踪功能,帮助开发人员更好地了解和监控微服务应用的运行状况。

总之,Istio与微服务密切相关,它为微服务架构提供了一种可靠且可扩展的解决方案,帮助开发人员管理和控制服务之间的通信,并提供了丰富的功能来提高应用程序的可观察性和安全性。

k8s如何管理微服务流量

  • 默认情况下,如多副本的pod,默认流量是负载均衡转发的。

  • 如果想精准的控制流量转发到具体的pod,就是Istio的作用。

  • Istio可以在不侵入代码的情况下,还能完成微服务链路追踪。

在微服务架构中,流量控制是指对服务之间的请求流量进行管理和控制的过程。

Istio作为一个服务网格解决方案,提供了流量控制的功能,可以帮助开发人员更好地管理和控制微服务应用程序中的请求流量。

Istio和Kubernetes是两个独立但密切相关的技术,它们通常一起使用来构建和管理现代化的容器化应用程序。

Kubernetes是一个开源的容器编排平台,用于自动化应用程序的部署、扩展和管理。它提供了容器编排、服务发现、负载均衡、自动伸缩、滚动更新等功能,使得应用程序可以在分布式环境中高效运行。

Istio是一个开源的Service Mesh平台,用于管理和保护在Kubernetes集群中运行的微服务架构。它通过在应用程序服务之间插入专用的代理(sidecar)来实现流量管理、安全认证、故障恢复等功能。Istio利用Kubernetes的弹性和自动化特性,并为微服务提供了更高级别的可观察性和安全性。

Istio和Kubernetes的联系在于:

  1. 部署:Istio可以与Kubernetes集群无缝集成,利用Kubernetes的部署和扩展机制来管理Istio的代理(sidecar)和其他组件的部署。
  2. 服务发现和负载均衡:Kubernetes提供了基本的服务发现和负载均衡功能,而Istio通过其代理实现了更高级别的服务发现、智能路由和负载均衡,以支持更复杂的微服务通信模式。
  3. 安全性:Istio通过在代理中提供身份验证、授权和加密功能,增强了在Kubernetes集群中运行的微服务的安全性。
  4. 监控和可观察性:Istio提供了丰富的监控、跟踪和日志功能,帮助管理员和开发人员了解微服务之间的通信模式和性能,并在需要时进行故障排除。

综上所述,Istio和Kubernetes是紧密结合的技术,它们共同为构建和管理现代化的容器化应用程序提供了强大的功能。Kubernetes提供了容器编排和基础设施层面的功能,而Istio通过为微服务架构提供Service Mesh能力,增强了应用程序的可观察性、安全性和弹性。

图解Sidecar

Sidecar 在软件系统架构中特指边车模式。这个模式的灵感来源于我们生活中的边三轮:即在两轮摩托车的旁边添加一个边车的方式扩展现有的服务和功能。

这个模式的精髓在于实现了数据面(业务逻辑)和控制面的解耦:原来两轮摩托车的驾驶者集中注意力跑赛道,边车上的领航员专注周围信息和地图,专注导航。

image-20230519170846293

第一代微服务运维

何谓微服务?据维基百科的定义:微服务是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关的API集相互通信。

Service Mesh 最早在2016年9月29日由开发 Linkerd 的 Buoyant 公司首次提出,Service Mesh 是用于处理服务间通信的基础设施层,它负责通过构成现代云原生应用程序的复杂拓扑结构来可靠地传递请求。

因此 Service Mesh 也被称为微服务时代的TCP协议。

第一代微服务的常见架构如下图所示:

image-20230519173102136

在容器内有服务A、服务B。A和B都包含自己的业务逻辑,如果想要A调用B,同时试图对这个服务进行治理,通常会在业务的内部集成一个SDK,来实现服务发现、负载均衡、服务路由、重试、熔断限流等功能。

但是,这个架构存在三个主要问题:

第一,开发成本。因为A和B的服务已经是微服务了,它们可能是由不同语言开发的而且各自的框架可能也不同,如果希望把服务治理的部分进行升级或者提供新的功能,就需要重复的迭代和开发。

第二,升级成本。因为SDK的部分跟业务耦合在一起,在新增一些能力时需要重新部署业务的模块。

第三,部署成本。由于相关治理的功能需要耦合在业务的配置里面,所以很难做到实时的下发配置,服务间拓扑关系和治理配置无法统一管理。

Service Mesh进化

如下图左侧所示,它通过将SDK 、开发框架提供的服务治理能力下沉到一个和业务进程独立的轻量级网络代理中,由这个网络代理作为微服务通信的基础设施层,它可以提供业务无关、语言无关、独立演进,透明升级的特性。这个轻量级的网络进程被称作Sidecar代理,是服务网格的数据面。

image-20230519173434361

同时如右侧所示,通过一个对 Sidecar 进行统一控制和管理的服务控制平面,来提供对微服务治理和运维的统一入口。

这种架构实现了服务治理技术和业务逻辑的解耦,是云原生时代微服务治理技术的发展方向,也得到了越来越多的公司的关注。

百度微服务进化史

image-20230519173526273

Istio Mesh图

image-20230519173856691

istiod、pilot、citadel和galley是Istio中的关键组件,用于实现Service Mesh的功能。

  1. istiod:istiod是Istio的控制平面组件,负责管理和协调整个Istio系统。它是一个中心化的组件,用于处理Istio配置、策略和服务发现等功能。istiod集成了其他组件,如pilot、citadel和galley,并提供对它们的管理和控制。
  2. pilot:pilot是Istio的数据平面组件之一,主要负责流量管理。它与Envoy代理协同工作,将Istio配置转换为Envoy可理解的配置,并将流量管理规则(如路由、负载均衡和故障恢复策略)下发到Envoy代理。pilot监控流量并收集运行时统计信息,用于Istio的可观察性功能。
  3. citadel:citadel是Istio的安全性组件,负责提供服务间的身份验证和安全通信。它管理服务之间的证书颁发和续订,确保只有经过身份验证的服务才能相互通信。citadel与istiod合作,共同提供Istio的安全功能。
  4. galley:galley是Istio的配置验证和分发组件,负责验证和转换Istio配置文件,并将其分发给其他组件。galley与istiod密切合作,以确保配置的一致性和正确性。它还提供了配置验证和策略检查等功能。

综上所述,istiod、pilot、citadel和galley是Istio的核心组件,它们共同协作以实现流量管理、安全性、配置分发和验证等功能,构建了完整的Service Mesh平台。

安装Istio

安装istioctl客户端

官网文档

https://istio.io/latest/docs/setup/getting-started/

下载内容将包含:安装文件、示例和 istioctl 命令行工具。

访问 Istio release 页面下载与您操作系统对应的安装文件。在 macOS 或 Linux 系统中,也可以通过以下命令下载最新版本的 Istio:

$ wget https://github.com/istio/istio/releases/download/1.15.3/istio-1.15.3-linux-amd64.tar.gz

[root@k8s-master ~/servicemesh]#tar -xf istio-1.15.3-linux-amd64.tar.gz 
[root@k8s-master ~/servicemesh]#cd istio-1.15.3/
[root@k8s-master ~/servicemesh/istio-1.15.3]#ls 
bin  LICENSE  manifests  manifest.yaml  README.md  samples  tools
[root@k8s-master ~/servicemesh/istio-1.15.3]#ls bin
istioctl
[root@k8s-master ~/servicemesh/istio-1.15.3]#

[root@k8s-master ~/servicemesh/istio-1.15.3]#cp bin/istioctl /usr/local/bin
[root@k8s-master ~/servicemesh/istio-1.15.3]#
[root@k8s-master ~/servicemesh/istio-1.15.3]#cd
[root@k8s-master ~]#
[root@k8s-master ~]#istioctl version
no running Istio pods in "istio-system"
1.15.3

# 配置命令补全
[root@k8s-master ~]#source ~/servicemesh/istio-1.15.3/tools/istioctl.bash 
[root@k8s-master ~]#

安装istio组件

https://istio.io/latest/zh/docs/setup/install/istioctl/#install-a-different-profile

https://istio.io/latest/zh/docs/setup/additional-setup/config-profiles/

image-20230519180150932

istioctl install --set profile=demo 是一个用于安装 Istio 的命令,它设置了安装配置文件中的参数。

具体解释如下:

  • istioctl: 是 Istio 控制命令行工具。
  • install: 是一个用于安装 Istio 的子命令。
  • --set profile=demo: 是一个参数,用于设置安装配置文件中的配置选项。在这里,profile=demo 表示选择名为 "demo" 的预定义配置文件。预定义配置文件是预先定义的一组配置选项,旨在提供特定的配置方案。"demo" 配置文件通常用于演示和测试目的,包含了一组常用的配置和示例。通过设置 profile=demo,安装过程会采用该配置文件中的选项进行安装。

综上所述,istioctl install --set profile=demo 命令的含义是使用 Istio 控制命令行工具安装 Istio,采用名为 "demo" 的预定义配置文件进行安装。

这将根据 "demo" 配置文件中的选项进行安装,提供一组常用的配置和示例。

生产环境下也是直接装demo配置文件。

[root@k8s-master ~]#istioctl install --set profile=demo
This will install the Istio 1.15.3 demo profile with ["Istio core" "Istiod" "Ingress gateways" "Egress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                           
✔ Istiod installed                                                                                                               
✔ Egress gateways installed                                                                                                      
✔ Ingress gateways installed                                                                                                     
✔ Installation complete                                                                                                          Making this installation the default for injection and validation.

Thank you for installing Istio 1.15.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/SWHFBmwJspusK1hv6
[root@k8s-master ~]#

查看安装了哪些组件

[root@k8s-master ~]#kubectl -n istio-system get all
NAME                                       READY   STATUS    RESTARTS   AGE
pod/istio-egressgateway-df6f6d597-cg9ns    1/1     Running   0          86s
pod/istio-ingressgateway-577d9994f-2lbzn   1/1     Running   0          86s
pod/istiod-64775594cd-qj46r                1/1     Running   0          3m21s

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                                      AGE
service/istio-egressgateway    ClusterIP      10.96.64.78    <none>        80/TCP,443/TCP                                                               86s
service/istio-ingressgateway   LoadBalancer   10.111.5.56    <pending>     15021:30257/TCP,80:31858/TCP,443:32249/TCP,31400:30732/TCP,15443:31472/TCP   86s
service/istiod                 ClusterIP      10.110.44.82   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP                                        3m20s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/istio-egressgateway    1/1     1            1           86s
deployment.apps/istio-ingressgateway   1/1     1            1           86s
deployment.apps/istiod                 1/1     1            1           3m21s

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/istio-egressgateway-df6f6d597    1         1         1       86s
replicaset.apps/istio-ingressgateway-577d9994f   1         1         1       86s
replicaset.apps/istiod-64775594cd                1         1         1       3m21s
[root@k8s-master ~]#

# 确认仨po可以运行

[root@k8s-master ~]#kubectl -n istio-system get po
NAME                                   READY   STATUS    RESTARTS   AGE
istio-egressgateway-df6f6d597-cg9ns    1/1     Running   0          9m41s
istio-ingressgateway-577d9994f-2lbzn   1/1     Running   0          9m41s
istiod-64775594cd-qj46r                1/1     Running   0          11m

istio针对不同的环境,提供了几种不同的初始化部署的profile

# 查看提供的profile类型
[root@k8s-master ~]#istioctl profile list
Istio configuration profiles:
    default
    demo
    empty
    external
    minimal
    openshift
    preview


# 获取kubernetes的yaml:
$ istioctl manifest generate --set profile=demo > istio-kubernetes-manifest.yaml

卸载istio组件

# 其实就是走yaml清理组件
$ istioctl manifest generate --set profile=demo | kubectl delete -f -

Istio实践

场景一

image-20230519183716065

Front-tomcat

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: front-tomcat
    version: v1
  name: front-tomcat-v1
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: front-tomcat
      version: v1
  template:
    metadata:
      labels:
        app: front-tomcat
        version: v1
    spec:
      containers:
      - image: consol/tomcat-7.0:latest
        name: front-tomcat

Bill-v1

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: bill-service
    version: v1
  name: bill-service-v1
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      service: bill-service
      version: v1
  template:
    metadata:
      labels:
        service: bill-service
        version: v1
    spec:
      containers:
      - image: nginx:alpine
        name: bill-service
        command: ["/bin/sh", "-c", "echo 'this is bill-service-v1'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]

bill-svc

这里是k8s的服务代理

apiVersion: v1
kind: Service
metadata:
  labels:
    service: bill-service
  name: bill-service
  namespace: istio-demo
spec:
  ports:
  - name: http
    port: 9999
    protocol: TCP
    targetPort: 80
  selector:
    service: bill-service
  type: ClusterIP

创建所有应用

[root@k8s-master ~/servicemesh]#kubectl create namespace istio-demo
namespace/istio-demo created
[root@k8s-master ~/servicemesh]#kubectl apply -f .
service/bill-service created
deployment.apps/bill-service-v1 created
deployment.apps/front-tomcat-v1 created
[root@k8s-master ~/servicemesh]#

# 确保应用启动
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/bill-service-v1-54c8dbf4cb-spnch   1/1     Running   0          5m10s
pod/front-tomcat-v1-77c8896cb9-7vgs2   1/1     Running   0          5m10s

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/bill-service   ClusterIP   10.104.245.11   <none>        9999/TCP   5m10s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/bill-service-v1   1/1     1            1           5m10s
deployment.apps/front-tomcat-v1   1/1     1            1           5m10s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/bill-service-v1-54c8dbf4cb   1         1         1       5m10s
replicaset.apps/front-tomcat-v1-77c8896cb9   1         1         1       5m10s
[root@k8s-master ~/servicemesh]#

# 访问service代理接口
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
bill-service   ClusterIP   10.104.245.11   <none>        9999/TCP   8m59s


[root@k8s-master ~/servicemesh]#curl 10.104.245.11:9999
this is bill-service-v1



# 直接访问bill接口
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get po -owide
NAME                               READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
bill-service-v1-54c8dbf4cb-spnch   1/1     Running   0          6m59s   10.244.2.168   k8s-slave1   <none>           <none>
front-tomcat-v1-77c8896cb9-7vgs2   1/1     Running   0          6m59s   10.244.2.169   k8s-slave1   <none>           <none>
[root@k8s-master ~/servicemesh]#
[root@k8s-master ~/servicemesh]#curl 10.244.2.168
this is bill-service-v1


# 访问前端
[root@k8s-master ~/servicemesh]#curl 10.244.2.169:8080 -I
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Transfer-Encoding: chunked
Date: Fri, 19 May 2023 10:35:18 GMT



# 接口访问 前端 > bill服务
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-77c8896cb9-7vgs2 -- curl -s bill-service:9999
this is bill-service-v1

场景2

后台账单服务更新v2版本,前期规划90%的流量访问v1版本,导入10%的流量到v2版本

image-20230519183837680

bill-v2

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: bill-service
    version: v2
  name: bill-service-v2
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      service: bill-service
      version: v2
  template:
    metadata:
      labels:
        service: bill-service
        version: v2
    spec:
      containers:
      - image: nginx:alpine
        name: bill-service
        command: ["/bin/sh", "-c", "echo 'hello, this is bill-service-v2'>/usr/share/nginx/html/index.html;nginx -g 'daemon off;'"]

默认k8s调度是负载均衡的

此时,访问规则会按照v1和v2的pod各50%的流量分配。

[root@k8s-master ~/servicemesh]#kubectl apply -f bill-v2.yml 
deployment.apps/bill-service-v2 created
[root@k8s-master ~/servicemesh]#


[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get po -owide
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
bill-service-v1-54c8dbf4cb-spnch   1/1     Running   0          13m   10.244.2.168   k8s-slave1   <none>           <none>
bill-service-v2-5d9dbf6558-44c7q   1/1     Running   0          23s   10.244.2.170   k8s-slave1   <none>           <none>
front-tomcat-v1-77c8896cb9-7vgs2   1/1     Running   0          13m   10.244.2.169   k8s-slave1   <none>           <none>
[root@k8s-master ~/servicemesh]#

# 查看service、endpoints
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo describe svc bill-service 
Name:              bill-service
Namespace:         istio-demo
Labels:            service=bill-service
Annotations:       <none>
Selector:          service=bill-service
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.104.245.11
IPs:               10.104.245.11
Port:              http  9999/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.168:80,10.244.2.170:80
Session Affinity:  None
Events:            <none>

默认一比一分配

image-20230519184246018

[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-77c8896cb9-7vgs2 -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-77c8896cb9-7vgs2 -- curl -s bill-service:9999
hello, this is bill-service-v2

image-20230519184154368

k8s自身的service资源,是没实现流量治理的,只是能实现应用通信就行。

但是你想更细粒度的对代理做控制,k8s自身是没提供的。

但是并未实现我们上述1:9的需求。

istio实现流量管理

若想实现上述需求,需要解决如下两个问题:

  • 让访问账单服务的流量按照我们期望的比例,其实是一条路由规则,如何定义这个规则
  • 如何区分两个版本的服务

istio提供了如下2个新的k8s资源类型,是自定义类型资源,并且k8s自身的。

VirtualServiceDestinationRule

在 Istio 中,VirtualServiceDestinationRule 是两个重要的资源类型,用于配置流量管理和服务策略。

  1. VirtualService(虚拟服务):
    • 作用:VirtualService 用于定义服务之间的流量路由规则和请求转发策略。
    • 功能:
      • 流量路由:您可以使用 VirtualService 来指定特定的流量目标,如服务版本、子集或标签。它允许您将流量分发到不同的服务实例或版本,实现灰度发布、A/B 测试等场景。
      • 请求转发:您可以使用 VirtualService 配置请求转发规则,如路径匹配、请求头过滤、重试策略等。这样可以灵活控制请求的转发和处理方式。
      • 超时和故障恢复:VirtualService 允许您配置超时时间和故障恢复策略,以确保请求的稳定性和可靠性。
  2. DestinationRule(目标规则):
    • 作用:DestinationRule 用于定义服务的流量策略和负载均衡设置。
    • 功能:
      • 子集和标签:您可以使用 DestinationRule 定义服务的子集,通过标签或选择器来区分不同版本、实例或环境的服务。这样可以更精细地控制流量的目标和行为。
      • 负载均衡:DestinationRule 允许您配置负载均衡算法和权重,以控制流量在不同服务实例之间的分发方式。
      • 服务策略:通过 DestinationRule,您可以配置服务的连接池大小、超时时间、重试策略和安全选项,以确保请求的可靠性和安全性。

综上所述,VirtualService 用于定义流量的路由和请求转发策略,而 DestinationRule 则用于定义服务的流量策略和负载均衡设置。通过配置这两个资源,您可以灵活控制服务之间的流量管理和请求处理方式,实现更高级别的流量控制和服务策略。

注入Sidecar

# inject 注入
$ istioctl kube-inject -f bill-service-dpl-v1.yaml|kubectl apply -f -
$ istioctl kube-inject -f bill-service-dpl-v2.yaml|kubectl apply -f -
$ istioctl kube-inject -f front-tomcat-dpl-v1.yaml|kubectl apply -f -

查看注入了什么容器

# 查看yml修改了什么
[root@k8s-master ~/servicemesh]# istioctl kube-inject -f bill.yml > bill-inject.yml
[root@k8s-master ~/servicemesh]#

注入的Sidecar容器信息

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    service: bill-service
    version: v1
  name: bill-service-v1
  namespace: istio-demo
spec:
  replicas: 1
  selector:
    matchLabels:
      service: bill-service
      version: v1
  strategy: {}
  template:
    metadata:
      annotations:
        kubectl.kubernetes.io/default-container: bill-service
        kubectl.kubernetes.io/default-logs-container: bill-service
        prometheus.io/path: /stats/prometheus
        prometheus.io/port: "15020"
        prometheus.io/scrape: "true"
        sidecar.istio.io/status: '{"initContainers":["istio-init"],"containers":["istio-proxy"],"volumes":["workload-socket","credential-socket","workload-certs","istio-envoy","istio-data","istio-podinfo","istio-token","istiod-ca-cert"],"imagePullSecrets":null,"revision":"default"}'
      creationTimestamp: null
      labels:
        security.istio.io/tlsMode: istio
        service: bill-service
        service.istio.io/canonical-name: ""
        service.istio.io/canonical-revision: v1
        version: v1
    spec:
      containers:
      - command:
        - /bin/sh
        - -c
        - echo 'this is bill-service-v1'>/usr/share/nginx/html/index.html;nginx -g
          'daemon off;'
        image: nginx:alpine
        name: bill-service
        resources: {}
      - args:
        - proxy
        - sidecar
        - --domain
        - $(POD_NAMESPACE).svc.cluster.local
        - --proxyLogLevel=warning
        - --proxyComponentLogLevel=misc:error
        - --log_output_level=default:info
        - --concurrency
        - "2"
        env:
        - name: JWT_POLICY
          value: third-party-jwt
        - name: PILOT_CERT_PROVIDER
          value: istiod
        - name: CA_ADDR
          value: istiod.istio-system.svc:15012
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: INSTANCE_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
        - name: HOST_IP
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: PROXY_CONFIG
          value: |
            {}
        - name: ISTIO_META_POD_PORTS
          value: |-
            [
            ]
        - name: ISTIO_META_APP_CONTAINERS
          value: bill-service
        - name: ISTIO_META_CLUSTER_ID
          value: Kubernetes
        - name: ISTIO_META_INTERCEPTION_MODE
          value: REDIRECT
        - name: ISTIO_META_MESH_ID
          value: cluster.local
        - name: TRUST_DOMAIN
          value: cluster.local
        image: docker.io/istio/proxyv2:1.15.3
        name: istio-proxy
        ports:
        - containerPort: 15090
          name: http-envoy-prom
          protocol: TCP
        readinessProbe:
          failureThreshold: 30
          httpGet:
            path: /healthz/ready
            port: 15021
          initialDelaySeconds: 1
          periodSeconds: 2
          timeoutSeconds: 3
        resources:
          limits:
            cpu: "2"
            memory: 1Gi
          requests:
            cpu: 10m
            memory: 40Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
          privileged: false
          readOnlyRootFilesystem: true
          runAsGroup: 1337
          runAsNonRoot: true
          runAsUser: 1337
        volumeMounts:
        - mountPath: /var/run/secrets/workload-spiffe-uds
          name: workload-socket
        - mountPath: /var/run/secrets/credential-uds
          name: credential-socket
        - mountPath: /var/run/secrets/workload-spiffe-credentials
          name: workload-certs
        - mountPath: /var/run/secrets/istio
          name: istiod-ca-cert
        - mountPath: /var/lib/istio/data
          name: istio-data
        - mountPath: /etc/istio/proxy
          name: istio-envoy
        - mountPath: /var/run/secrets/tokens
          name: istio-token
        - mountPath: /etc/istio/pod
          name: istio-podinfo
      initContainers:
      - args:
        - istio-iptables
        - -p
        - "15001"
        - -z
        - "15006"
        - -u
        - "1337"
        - -m
        - REDIRECT
        - -i
        - '*'
        - -x
        - ""
        - -b
        - '*'
        - -d
        - 15090,15021,15020
        - --log_output_level=default:info
        image: docker.io/istio/proxyv2:1.15.3
        name: istio-init
        resources:
          limits:
            cpu: "2"
            memory: 1Gi
          requests:
            cpu: 10m
            memory: 40Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_ADMIN
            - NET_RAW
            drop:
            - ALL
          privileged: false
          readOnlyRootFilesystem: false
          runAsGroup: 0
          runAsNonRoot: false
          runAsUser: 0
      volumes:
      - name: workload-socket
      - name: credential-socket
      - name: workload-certs
      - emptyDir:
          medium: Memory
        name: istio-envoy
      - emptyDir: {}
        name: istio-data
      - downwardAPI:
          items:
          - fieldRef:
              fieldPath: metadata.labels
            path: labels
          - fieldRef:
              fieldPath: metadata.annotations
            path: annotations
        name: istio-podinfo
      - name: istio-token
        projected:
          sources:
          - serviceAccountToken:
              audience: istio-ca
              expirationSeconds: 43200
              path: istio-token
      - configMap:
          name: istio-ca-root-cert
        name: istiod-ca-cert
status: {}
---

yaml解释

这段 YAML 配置文件是一个 Kubernetes Deployment 对象的定义,用于部署 Istio 注入的容器。

该 Deployment 名为 bill-service-v1,属于 istio-demo 命名空间。它包含两个容器:bill-serviceistio-proxy。以下是对其中的关键部分进行解释:

  • bill-service 容器:
    • 镜像:nginx:alpine
    • 作用:运行一个 Nginx Web 服务器,并在 /usr/share/nginx/html/index.html 文件中输出 this is bill-service-v1
    • 其他配置:无资源限制和环境变量配置。
  • istio-proxy 容器:
    • 镜像:docker.io/istio/proxyv2:1.15.3
    • 作用:运行 Istio 的代理(Envoy),作为 sidecar 容器与 bill-service 容器一起部署在同一个 Pod 中。
    • 其他配置:容器的配置参数通过 args 字段指定,包括代理的域名、日志级别、连接池等。
    • 环境变量:定义了一系列与 Istio 代理相关的环境变量,如 JWT_POLICY、PILOT_CERT_PROVIDER、CA_ADDR 等。

此外,Deployment 还包含一些其他的配置,如副本数、标签选择器、资源限制等。

通过这个配置文件,当该 Deployment 对象被创建并部署到 Kubernetes 集群中时,Istio 将会自动注入 sidecar 容器(即 istio-proxy)到 bill-service-v1 的 Pod 中,以实现 Istio 的流量管理和服务治理功能。这样,bill-service-v1 就能受益于 Istio 的特性,例如流量控制、故障恢复和可观察性等。

3个后端都注入sidecar

[root@k8s-master ~/servicemesh]#istioctl kube-inject -f bill.yml |kubectl apply -f -
deployment.apps/bill-service-v1 configured
[root@k8s-master ~/servicemesh]#istioctl kube-inject -f bill-v2.yml |kubectl apply -f -
deployment.apps/bill-service-v2 configured
[root@k8s-master ~/servicemesh]#
[root@k8s-master ~/servicemesh]#istioctl kube-inject -f front-tomcat.yml |kubectl apply -f -
deployment.apps/front-tomcat-v1 configured
[root@k8s-master ~/servicemesh]#

检查
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get po 
NAME                               READY   STATUS    RESTARTS   AGE
bill-service-v1-86b7c5cf4-2dx8x    2/2     Running   0          2m33s
bill-service-v2-7d547769fc-h2g5x   2/2     Running   0          2m13s
front-tomcat-v1-74b8ff99db-lbk79   2/2     Running   0          2m

之前pod是 1/1 就一个容器,现在都是2/2 表示注入了一个容器

创建流量治理规则

如果有大量的服务,就会表现出来网格。图中左边绿色方格是应用,右边蓝色的方框是Service Mesh,蓝色之间的线条是表示服务之间的调用关系。

Sidecar之间的连接就会形成一个网络,这个就是服务网格名字的由来。这个时候代理体现出来的就和前面的Sidecar不一样了,形成网状。

首先第一个,服务网格是抽象的,实际上是抽象出了一个基础设施层,在应用之外。其次,功能是实现请求的可靠传递。部署上体现为轻量级的网络代理。最后一个关键词是,对应用程序透明。

image-20230521134637162

大家注意看,上面的图中,网络在这种情况下,可能不是特别明显。但是如果把左边的应用程序去掉,现在只呈现出来Service Mesh和他们之间的调用,这个时候关系就会特别清晰,就是一个完整的网络。这是Service Mesh定义当中一个非常重要的关键点,和Sidecar不相同的地方:不再将代理视为单独的组件,而是强调由这些代理连接而形成的网络。在Service Mesh里面非常强调代理连接组成的网络,而不像Sidecar那样看待个体。

现在我们基本上把Service Mesh的定义介绍清楚了,大家应该可以大概了解什么是Service Mesh了。

接下来会开始研究Serivce Mesh的典型应用:istio

image-20230521134747864

bill-service-destnation-rule.yaml

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: dest-bill-service
  namespace: istio-demo
spec:
  host: bill-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

这段 YAML 配置文件是一个 Istio 的 DestinationRule 对象的定义,用于定义目标服务的规则。

该 DestinationRule 名为 dest-bill-service,属于 istio-demo 命名空间。它指定了一个名为 bill-service 的目标主机,并定义了两个子集:v1v2,分别对应着标签选择器 version: v1version: v2

DestinationRule 的作用是为特定的目标服务定义路由规则、负载均衡策略和流量策略。

在这个配置中,bill-service 目标主机的流量将被分割成 v1v2 两个子集,并且每个子集都有一个标签选择器来选择相应的 Pod。

通过这个 DestinationRule 配置,可以实现针对 bill-service 目标服务的流量控制和服务版本管理。例如,可以通过 VirtualService 配置将流量按照一定的比例分发到不同的子集,实现 A/B 测试或者灰度发布等场景。

# 查看标签
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get po --show-labels
NAME                               READY   STATUS    RESTARTS   AGE   LABELS
bill-service-v1-86b7c5cf4-2dx8x    2/2     Running   0          21m   pod-template-hash=86b7c5cf4,security.istio.io/tlsMode=istio,service.istio.io/canonical-name=,service.istio.io/canonical-revision=v1,service=bill-service,version=v1
bill-service-v2-7d547769fc-h2g5x   2/2     Running   0          20m   pod-template-hash=7d547769fc,security.istio.io/tlsMode=istio,service.istio.io/canonical-name=,service.istio.io/canonical-revision=v2,service=bill-service,version=v2
front-tomcat-v1-74b8ff99db-lbk79   2/2     Running   0          20m   app=front-tomcat,pod-template-hash=74b8ff99db,security.istio.io/tlsMode=istio,service.istio.io/canonical-name=front-tomcat,service.istio.io/canonical-revision=v1,version=v1
[root@k8s-master ~/servicemesh]#


#创建目标规则
[root@k8s-master ~/servicemesh]#kubectl apply -f bill-service-dest-rule.yml 
destinationrule.networking.istio.io/dest-bill-service created
[root@k8s-master ~/servicemesh]#
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get destinationrules.networking.istio.io 
NAME                HOST           AGE
dest-bill-service   bill-service   9s

bill-service-virtualservice.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-bill-service
  namespace: istio-demo
spec:
  hosts:
  - bill-service
  http:
  - name: bill-service-route
    route:
    - destination:
        host: bill-service
        subset: v1
      weight: 90
    - destination:
        host: bill-service
        subset: v2
      weight: 10

这段 YAML 配置文件是一个 Istio 的 VirtualService 对象的定义,用于定义虚拟服务的规则。

该 VirtualService 名为 vs-bill-service,属于 istio-demo 命名空间。它指定了一个名为 bill-service 的主机,并定义了一个 HTTP 路由规则。

在这个路由规则中,名为 bill-service-route 的路由将流量分发到 bill-service 目标主机的两个子集:v1v2。具体配置如下:

  • 对于 v1 子集,权重为 90,表示将 90% 的流量发送到该子集。
  • 对于 v2 子集,权重为 10,表示将 10% 的流量发送到该子集。

通过这个 VirtualService 配置,可以实现流量的分发和控制。

在这个例子中,大部分流量将被路由到 v1 子集,而少量流量将被路由到 v2 子集。

这样可以实现对不同版本服务的流量控制,例如实现灰度发布、A/B 测试或者金丝雀部署等场景。

[root@k8s-master ~/servicemesh]#kubectl apply -f bill-service-virtualservice.yml 


[root@k8s-master ~/servicemesh]#kubectl -n istio-demo get virtualservices.networking.istio.io 
NAME              GATEWAYS   HOSTS              AGE
vs-bill-service              ["bill-service"]   15s

验证流量分配比例

[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
hello, this is bill-service-v2
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
this is bill-service-v1
[root@k8s-master ~/servicemesh]#kubectl -n istio-demo exec front-tomcat-v1-74b8ff99db-lbk79 -c front-tomcat -- curl -s bill-service:9999
hello, this is bill-service-v2
[root@k8s-master ~/servicemesh]#

在您提供的 YAML 配置中,VirtualService 对象定义了针对 bill-service 目标服务的路由规则,其中权重配置为 90:10,即 90% 的流量分配给 v1 子集,10% 的流量分配给 v2 子集。

虽然在理论上,根据权重配置,90% 的流量应该被路由到 v1 子集,而10% 的流量应该被路由到 v2 子集,但实际情况可能会有一些偏差。这是因为 Istio 的负载均衡算法并不是严格按照权重来分配流量,而是根据一定的策略来进行分配。

Istio 默认使用的是轮询(Round Robin)策略,即按照一定的顺序循环分配流量给后端的实例。这种策略可能导致实际的流量分配与权重配置略有偏差,因为它只是简单地按照顺序分配请求,而不考虑后端实例的响应时间或负载情况。

如果您希望更精确地控制流量的分配,可以考虑使用 Istio 提供的其他负载均衡策略,例如基于权重的负载均衡(Weighted Round Robin)或基于负载的负载均衡(Least Connection),以更好地满足您的需求。

总结:尽管在 Istio 的配置中定义了权重为 90:10 的路由规则,但实际的流量分配可能会有一些偏差,这是因为 Istio 的负载均衡算法会根据一定的策略进行流量分配。如果需要更精确的流量控制,可以尝试使用其他负载均衡策略。

图解小结

image-20230521141531178

Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2024-03-31 19:43:50

results matching ""

    No results matching ""