【微服务从入门到入土】ServiceMesh基础知识
前置知识
- 会k8s
服务网格Service Mesh
- 目前微服务架构面临的一些挑战
- 技术架构演进
- 了解什么是Service Mesh
- Service Mesh产品
- 了解Istio
- Istio快速入门
- 体验Istio
- 完成bookinfo示例
- 完成istio项目实战
微服务现状
目前,微服务的架构方式在企业中得到了极大的发展,主要原因是其解决了传统的单体架构中存在的问题。
微服务架构的特性:
- 特点一:按业务划分团队
- 特点二:去中心化的数据管理
当单体架构拆分成微服务架构就可以高枕无忧了吗? 显然不是的。
微服务架构体系中同样也存在很多的挑战,比如:
原来的单个应用拆分成了许多分散的微服务,它们之间相互调用才能完成一个任务,而一旦某个过程出错(组件越多,出错的概率也就越大),就非常难以排查。
如果用户请求的响应太慢,我们就需要知道到底哪些地方比较慢?整个链路的调用各阶段耗时是多少?哪些调用是并发执行的,哪些是串行的?这些问题需要我们能非常清楚整个集群的调用以及流量情况。
微服务拆分成这么多组件,如果单个组件出错的概率不变,那么整体有地方出错的概率就会增大。服务调用的时候如果没有错误处理机制,那么会导致非常多的问题。
应用数量的增多,对于日常的应用发布来说也是个难题。应用的发布需要非常谨慎,如果应用都是一次性升级的,出现错误会导致整个线上应用不可用,影响范围太大。
很多情况我们需要同时存在不同的版本,使用 AB 测试验证哪个版本更好。
如果版本升级改动了 API,并且互相有依赖,那么我们还希望能自动地控制发布期间不同版本访问不同的地址。这些问题都需要智能的流量控制机制。
为了保证整个系统的安全性,每个应用都需要实现一套相似的认证、授权、HTTPS、限流等功能。
存在问题:1.语言绑定、2、大规模升级
没错,Service Mesh就是为了解决以上问题才出现的。这就是我们学习本套课程的目的。
技术架构演进
单机小型机时代
第一个计算机网络诞生于1969年,也就是美军的阿帕网,阿帕网能够实现与其它计算机进行联机操作,但是早期仅仅是为了军事目的而服务2000年初,中国的网民大约890万,很多人都不知道互联网为何物,因此大多数服务业务单一且简单,采用典型的单机+数据库模式,所有的功能都写在一个应用里并进行集中部署
说明:论坛业务、聊天室业务、邮箱业务全部都耦合在一台小型机上面,所有的业务数据也都存储在一台数据库上。
垂直拆分
随着应用的日益复杂与多样化,开发者对系统的容灾,伸缩以及业务响应能力有了更高的要求,如果小型机和数据库中任何一个出现故障,整个系统都会崩溃,若某个板块的功能需要更新,那么整个系统都需要重新发布,显然,对于业务迅速发展的万物互联网时代是不允许的。如何保障可用性的同时快速响应业务的变化,需要将系统进行拆分,将上面的应用拆分出多个子应用
优点:应用间进行了解耦,系统容错提高了,也解决了独立应用发布的问题。
应用垂直拆分解决了应用发布的问题,但是随着用户数量的增加,单机的计算能力依旧是杯水车薪。
集群化负载均衡架构
用户量越来越大,就意味着需要更多的小型机,但是小型机价格昂贵,操作维护成本高。
此时更优的选择是采用多台PC机部署同一个应用的方案,但是此时就需要对这些应用做负载均衡,因为客户端不知道请求会落到哪一个后端PC应用上的。
负载均衡可以分为硬件层面和软件层面。
硬件层面:F5
软件负载层面:LVS、Nginx、Haproxy
负载均衡的思想:对外暴露一个统一的接口,根据用户的请求进行对应规则转发,同时负载均衡还可以做限流等等
有了负载均衡之后,后端的应用可以根据流量的大小进行动态扩容,我们称为”水平扩展”。
阿里巴巴在2008提出去“IOE”,也就是IBM小型机、Oracle数据库,EMC存储,全部改成集群化负载均衡架构,在2013年支付宝最后一台IBM小型机下线。
优点:通过水平扩展,增强了系统的并发能力。
服务化改造架构
虽然系统经过了垂直拆分,但是拆分之后发现在论坛和聊天室中有重复的功能,比如,用户注册、发邮件等等,一旦项目大了,集群部署多了,这些重复的功能无疑会造成资源浪费,所以会把重复功能抽取出来,名字叫”XX服务(Service)”
为了解决服务跟服务如何相互调用,需要一个程序之间的通信协议,所以就有了远程过程调用(RPC),作用就是让服务之间的程序调用变得像本地调用一样的简单。
优点:在前面的架构之上解决了业务重用的问题。
服务治理
随着业务的增大,基础服务越来越多,调用网的关系由最初的几个增加到几十上百,造成了调用链路错综复杂,需要对服务进行治理。
服务治理要求:
- 当我们服务节点数几十上百的时候,需要对服务有动态的感知,引入了注册中心。
- 当服务链路调用很长的时候如何实现链路的监控。
- 单个服务的异常,如何能避免整条链路的异常(雪崩),需要考虑熔断、降级、限流。
- 服务高可用:负载均衡。
典型框架比如有:Dubbo,默认采用的是Zookeeper作为注册中心。
微服务时代
微服务是在2012年提出的概念,微服务的希望的重点是一个服务只负责一个独立的功能。
拆分原则,任何一个需求不会因为发布或者维护而影响到不相关的服务,一切可以做到独立部署运维。
比如传统的“用户中心”服务,对于微服务来说,需要根据业务再次拆分,可能需要拆分成“买家服务”、“卖家服务”、“商家服务”等。
典型代表:Spring Cloud,相对于传统分布式架构,SpringCloud使用的是HTTP作为RPC远程调用,配合上注册中心Eureka和API网关Zuul,可以做到细分内部服务的同时又可以对外暴露统一的接口,让外部对系统内部架构无感,此外Spring Cloud的config组件还可以把配置统一管理。
Spring Cloud微服务架构存在的不足:
- Spring Cloud属于侵入式框架,在项目中需要添加spring cloud maven依赖,加上spring cloud组件注解,写配置,打成jar的时候还必须要把非业务的代码也要融合在一起。
- 微服务中的服务支持不同语言开发,也需要维护不同语言和非业务代码的成本;
- 业务代码开发者应该把更多的精力投入到业务熟悉度上,而不应该是非业务上,Spring Cloud虽然能解决微服务领域的很多问题,但是学习成本还是较大的。
- 互联网公司产品的版本升级是非常频繁的,为了维护各个版本的兼容性、权限、流量等,因为Spring Cloud是“代码侵入式的框架”,这时候版本的升级就注定要让非业务代码一起,一旦出现问题,再加上多语言之间的调用,工程师会非常痛苦。
- 我们已经感觉到了,服务拆分的越细,只是感觉上轻量级解耦了,但是维护成本却越高了。
服务网格新时代
演进:
- 1、通信控制与业务耦合
- 2、三方库:一个进程内
- 3、代理:思路正确,功能不足
实际上nginx也能做到,只不过不够看
- 4、边车模式(Sidecar)
承载我们应用工作负载的形式已经从”物理机“过渡到”容器“
”物理机“,不仅仅包含物理机,而且包含缺乏高度自动化和弹性的VM。
”容器“,除了容器,还包括创建(包括初始化)和销毁高度自动化,具备极强弹性的VM。比如公有云提供的VM。
这里我们需要明白:基础设施的功能(服务发现,负载均衡,熔断限流,路由等)与 业务代码的集成需要在低成本前提下保证相同的生命周期。
在物理机时代,基础设施功能添加到业务代码的最佳方式无疑是SDK。
而容器时代,基础设施的功能添加到业务代码的最佳方式变成了Sidecar。
- 5、Service Mesh 出现
Service Mesh主要解决的问题就希望开发人员对于业务的聚焦,服务发现、服务注册、负载均衡等对于开发人员透明,可以更加专注业务逻辑的实现。
如果将为微服务提供通信服务的这部分逻辑从应用程序进程中抽取出来,作为一个单独的进程进行部署,并将其作为服务间的通信代理,可以得到如下图所示的架构:
Sidecar,翻译成中文是边车,非常的形象
当服务大量部署时,随着服务部署的Sidecar代理之间的连接形成了一个如下图所示的网格,该网格成为了微服务的通讯基础设施层,承载了微服务之间的所有流量,被称之为Service Mesh(服务网格)。
服务网格中有数量众多的Sidecar代理,如果对每个代理分别进行设置,工作量将非常巨大。为了更方便地对服务网格中的代理进行统一集中控制,在服务网格上增加了控制面组件。
Service Mesh是什么
服务网格用来描述组成这些应用程序的微服务网络以及它们之间的交互。随着服务网格的规模和复杂性不断的增长,它将会变得越来越难以理解和管理。它的需求包括服务发现、负载均衡、故障恢复、度量和监控等。服务网格通常还有更复杂的运维需求,比如 A/B 测试、金丝雀发布、速率限制、访问控制和端到端认证。
Service Mesh 又译作 “服务网格”,作为服务间通信的基础设施层。Buoyant 公司的 CEO Willian Morgan 在他的这篇文章 WHAT’S A Service Mesh? AND WHY DO I NEED ONE? 中解释了什么是 Service Mesh,为 什么云原生应用需要 Service Mesh。
Service Mesh 概述及功能
- 应用程序间通信的中间层(基础设施层)(本质)
- 轻量级网络代理(产品形态)
- 应用程序无感知(特点)
- 解耦应用程序的重试/超时、监控、追踪和服务发现等等(功能)
Service Mesh 和 Kubernetes 的关系
Kubernetes
解决容器编排与调度问题(本质上是管理应用生命周期)
给予 Service Mesh 支持和帮助
Service Mesh
- 解决服务间网络通信问题(本质上是管理服务通信的代理)
- 是对 Kubernetes 网络功能方面的扩展和延伸
Service Mesh 和 API 网关的异同点
- 功能上有重叠的部分,但是定位不一样
- Service Mesh 在应用内,API 网关在应用边界上
Service Mesh 技术标准
Service Mesh 产品大事记
Service Mesh产品有哪些
CNCF
CNCF 是一个开源软件基金会,致力于使云原生计算具有普遍性和可持续性。 云原生计算使用开源软件技术栈将应用程序部署为微服务,将每个部分打包到自己的容器中,并动态编排这些容器以优化资源利用率。 云原生技术使软件开发人员能够更快地构建出色的产品。
常用的已经毕业的云原生项目:
- Kubernetes
Kubernetes 是世界上最受欢迎的容器编排平台也是第一个CNCF 项目。 Kubernetes 帮助用户构建、扩展和管理应用程序及其动态生命周期。
- Prometheus
Prometheus 为云原生应用程序提供实时监控、警报包括强大的查询和可视化能力,并与许多流行的开源数据导入、导出工具集成。
- Jaeger
Jaeger 是由 Uber 开发的分布式追踪系统,用于监控其大型微服务环境。 Jaeger 被设计为具有高度可扩展性和可用性,它具有现代UI,旨在与云原生系统(如 OpenTracing、Kubernetes 和 Prometheus)集成。
- Envoy
Envoy 是最初在 Lyft 创建的 Service Mesh(服务网格),现在用于Google、Apple、Netflix等公司内部。 Envoy 是用 C++编写的,旨在最大限度地减少内存和 CPU 占用空间,同时提供诸如负载均衡、网络深度可观察性、微服务环境中的跟踪和数据库活动等功能。
- Containerd
Containerd 是由 Docker 开发并基于 Docker Engine 运行时的行业标准容器运行时组件。 作为容器生态系统的选择,Containerd 通过提供运行时,可以将 Docker 和 OCI 容器镜像作为新平台或产品的一部分进行管理。
Linkerd
Linkerd是Buoyant公司2016年率先开源的高性能网络代理程序,是业界的第一款Service Mesh产品,甚至可以说Linkerd的诞生标志着Service Mesh时代的开始,其引领后来Service Mesh的快速发展。
其主要用于解决分布式环境中服务之间通信面临的一些问题,比如网络不可靠、不安全、延迟丢包等问题。Linkerd使用Scala语言编写,运行于JVM,底层基于Twitter的Finagle库,并对其做相应的扩展。
最主要的是Linkerd具有快速、轻量级、高性能等特点,每秒以最小的时延及负载处理万级请求,易于水平扩展,经过生产线测试及验证,可运行任何平台的产线级Service Mesh工具
Envoy
Envoy也是一款高性能的网络代理程序,于2016年10月份由Lyft公司开源,为云原生应用而设计,可作为边界入口,处理外部流量,当然,也作为内部服务间通信代理,实现服务间可靠通信。
Envoy的实现借鉴现有产线级代理及负载均衡器,如Nginx、HAProxy、硬件负载均衡器及云负载均衡器的实践经验,同时基于C++编写及Lyft公司产线实践证明,Envoy性能非常优秀、稳定。
Envoy既可用作独立代理层运行,也可作为Service Mesh架构中数据平面层,因此通常Envoy跟服务运行在一起,将应用的网络功能抽象化,Envoy提供通用网络功能,实现平台及语言无关。
Istio
2017年5月24日,Google, IBM 和 Lyft 共同发布 Istio 的第一个公开版本(0.1)。Istio为一款开源的为微服务提供服务间连接、管理以及安全保障的平台软件,支持运行在Kubernetes、Mesos等容器管理工具,但不限于Kubernetes、Mesos,其底层依赖于Envoy。
Istio提供一种简单的方法实现服务间的负载均衡、服务间认证、监控等功能,而且无需应用层代码调整。其控制平面由Pilot、Citadel 和 Galley组成,数据平面由Envoy实现,通常情况下,数据平面代理Envoy以sidecar模式部署,使得所有服务间的网络通信均由Envoy实现,而Istio的控制平面则负责服务间流量管理、安全通信策略等功能。
Conduit
Conduit于2017年12月发布,作为由Buoyant继Linkerd后赞助的另一个开源项目。Conduit旨在彻底简化用户在Kubernetes使用服务网格的复杂度,提高用户体验,而不是像Linkerd一样针对各种平台进行优化。
APP mesh
国内产品
国内很多团队也已经在着手研究了,这些团队主要分为四类体系:
- 以蚂蚁金服为首的开源系:蚂蚁金服自研的 SOFA (Scalable Open Financial Architecture)Mesh 在开始的时候走的就是开源路线,他们参考了 Istio 及 Envoy 的设计思想,重新实现了自己的 Service Mesh系统,旁路网关(Sidecar)基于 Go 语言,该系统的前身是已经开源的 SOFA RPC 框架。蚂蚁金服于 2018 年 7 月正式将其开源,正式的可以用于生产的框架可能还需要一些时间。
以华为为代表的自研系:华为可能在 Service Mesh 概念出来前就已经有类似的想法了,只是没有抽取出一个公共的概念。无论是华为早期的HSA 还是之后出现的 CSE Mesher,都是对 Service Mesh 的探索。CSE Mesher 的整个架构都是基于华为自身微服务架构经验研发的,其Sidecar 也是用 Go 语言编写的。如其官方文档所述,其资源占用非常小,常规状态下仅为 30MB。
以腾讯为代表的拿来主义系:腾讯的 Tencent Service Mesh对开源的产品(如 Istio)进行定制,强化吸收后再加入自身特殊的业务逻辑。腾讯选择的Sidecar是Envoy,使用 C++编写,比较符合腾讯的技术栈。其公开的技术并不多,仍然以内部小范围使用为主。
以 UCloud 为代表的适配系:主要也是依赖开源方案,但不是完全将其产品引入,只是对其中几个关键部分添加适配器,以适应企业现有产品,以最小的变更成本引入Service Mesh 体系。
istio
istio架构
istio 架构v1.0
istio 架构v1.1
关于架构的思考?
istio 架构v1.5
实际上Istio 就是 Service Mesh 架构的一种实现,服务之间的通信(比如这里的 Service A 访问 Service B)会通过代理(默认是 Envoy)来进行。
而且中间的网络协议支持 HTTP/1.1,HTTP/2,gRPC 或者 TCP,可以说覆盖了主流的通信协议。代理这一层,称之为数据平面。
控制平面做了进一步的细分,分成了 Pilot、Citadel 和 Galley,它们的各自功能如下:
- Pilot:为 Envoy 提供了服务发现,流量管理和智能路由(AB 测试、金丝雀发布等),以及错误处理(超时、重试、熔断)功能。
- Citadel:为服务之间提供认证和证书管理,可以让服务自动升级成 TLS协议。
- Galley:Galley 是 Istio 的配置验证、提取、处理和分发组件。它负责将其余的 Istio 组件与从底层平台(例如 Kubernetes)获取用户配置的细节隔离开来。
数据平面会和控制平面通信,一方面可以获取需要的服务之间的信息,另一方面也可以汇报服务调用的 Metrics 数据。
为什么用istio
通过负载均衡、服务间的身份验证、监控等方法,Istio 可以轻松地创建一个已经部署了服务的网络,而服务的代码只需很少更改甚至无需更改。通过在整个环境中部署一个特殊的 sidecar 代理为服务添加 Istio 的支持,而代理会拦截微服务之间的所有网络通信,然后使用其控制平面的功能来配置和管理Istio,这包括:
- 为 HTTP、gRPC、WebSocket 和 TCP 流量自动负载均衡。
- 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。
- 可插拔的策略层和配置 API,支持访问控制、速率限制和配额。
- 集群内(包括集群的入口和出口)所有流量的自动化度量、日志记录和追踪。
- 在具有强大的基于身份验证和授权的集群中实现安全的服务间通信。Istio 为可扩展性而设计,可以满足不同的部署需求。
核心特性
Istio 以统一的方式提供了许多跨服务网络的关键功能。
流量管理
流量管理文档:https://istio.io/v1.6/zh/docs/concepts/traffic-management/
Istio 简单的规则配置和流量路由允许您控制服务之间的流量和 API 调用过程。
Istio 简化了服务级属性(如熔断器、超时和重试)的配置,并且让它轻而易举的执行重要的任务(如 A/B 测试、金丝雀发布和按流量百分比划分的分阶段发布)。
有了更好的对流量的可视性和开箱即用的故障恢复特性,就可以在问题产生之前捕获它们,无论面对什么情况都可以使调用更可靠,网络更健壮。
istio流量控制核心组件:
虚拟服务(Virtual Service)
虚拟服务(Virtual Service) 和目标规则(Destination Rule) 是 Istio 流量路由功能的关键拼图。虚拟服务让您配置如何在服务网格内将请求路由到服务,这基于 Istio 和平台提供的基本的连通性和服务发现能力。每个虚拟服务包含一组路由规则,Istio 按顺序评估它们,Istio 将每个给定的请求匹配到虚拟服务指定的实际目标地址
- 将流量路由到给定目标地址
- 请求地址与真实的工作负载解耦
- 包含一组路由规则
- 通常和目标规则(Destination Rule)成对出现
- 丰富的路由匹配规则
目标规则(Destination Rule)
与虚拟服务一样,目标规则也是 Istio 流量路由功能的关键部分。您可以将虚拟服务视为将流量如何路由到给定目标地址,然后使用目标规则来配置该目标的流量。在评估虚拟服务路由规则之后,目标规则将应用于流量的“真实”目标地址。
特别是,您可以使用目标规则来指定命名的服务子集,例如按版本为所有给定服务的实例分组。然后可以在虚拟服务的路由规则中使用这些服务子集来控制到服务不同实例的流量
- 虚拟服务将流量路由到”目标地址”
- 目标规则将应用于流量的“真实”目标地址
- 目标规则允许定制 Envoy 的流量策略,比如您喜欢的负载均衡模型、TLS 安全模式或熔断器设置
- 负载均衡(随机,权重,最少请求)
网关(Gateway)
使用网关为网格来管理入站和出站流量,可以让您指定要进入或离开网格的流量。网关配置被用于运行在网格边界的独立 Envoy 代理,而不是服务工作负载的 sidecar 代理
- 管理网格入站/出站流量
- 处在网格边界
服务入口(Service Entry)
服务入口(Service Entry) 来添加一个入口到 Istio 内部维护的服务注册中心。添加了服务入口后,Envoy 代理可以向外部服务发送流量,就好像它是网格内部的服务一样
- 将外部服务注入内部网格
- 为外部目标转发请求
- 为外部目标定义超时,重试,故障注入等策略
- 扩展网格
Sidecar
Istio 让每个 Envoy 代理都可以访问来自和它关联的工作负载的所有端口的请求,然后转发到对应的工作负载
- 微调 Envoy 代理接受的端口和协议集
- 限制 Envoy 代理可以访问的服务集合
网络弹性和测试
除了为您的网格导流之外,Istio 还提供了可选的故障恢复和故障注入功能,您可以在运行时动态配置这些功能。使用这些特性可以让您的应用程序运行稳定,确保服务网格能够容忍故障节点,并防止局部故障级联影响到其他节点
- 超时
- 重试
- 熔断器
- 故障注入
- 和应用程序一起运行
安全
安全文档:https://istio.io/v1.6/zh/docs/concepts/security/
Istio 的安全特性解放了开发人员,使其只需要专注于应用程序级别的安全。
Istio 提供了底层的安全通信通道,并为大规模的服务通信管理认证、授权和加密。有了 Istio,服务通信在默认情况下就是受保护的,可以让您在跨不同协议和运行时的情况下实施一致的策略——而所有这些都只需要很少甚至不需要修改应用程序
Istio 是独立于平台的,可以与 Kubernetes(或基础设施)的网络策略一起使用。但它更强大,能够在网络和应用层面保护pod到 pod 或者服务到服务之间的通信。
- 用于密钥和证书管理的证书颁发机构(CA)
- 配置 API 服务器分发给代理
- 认证策略
- 授权策略
- 安全命名
- Sidecar 和边缘代理作为 Policy Enforcement Points(PEPs) 以保护客户端和 服务器之间的通信安全
- 一组 Envoy 代理扩展,用于管理遥测和审计
可观察性
可观察性文档:https://istio.io/v1.6/zh/docs/concepts/observability/
Istio 健壮的追踪、监控和日志特性让您能够深入的了解服务网格部署。通过 Istio 的监控能力,可以真正的了解到服务的性能是如何影响上游和下游的;而它的定制 Dashboard 提供了对所有服务性能的可视化能力,并让您看到它如何影响其他进程。
Istio 的 Mixer 组件负责策略控制和遥测数据收集。它提供了后端抽象和中介,将一部分 Istio 与后端的基础设施实现细节隔离开来,并为运维人员提供了对网格与后端基础实施之间交互的细粒度控制。
所有这些特性都使您能够更有效地设置、监控和加强服务的 SLO。当然,底线是您可以快速有效地检测到并修复出现的问题。
平台支持
Istio 独立于平台,被设计为可以在各种环境中运行,包括跨云、内部环境、Kubernetes、Mesos 等等。您可以在 Kubernetes 或是装有 Consul 的Nomad 环境上部署 Istio。Istio 目前支持:
- Kubernetes 上的服务部署
- 基于 Consul 的服务注册
- 服务运行在独立的虚拟机上
快速入门
下面我们将Istio进行部署安装,来体验下它的魅力。
- 安装文档:https://istio.io/v1.6/zh/docs/setup/getting-started/
- 在线 Playground (katacoda)
搭建kubernates集群
Istio运行在kubernetes平台是最佳的选择,所以我们先搭建kubernetes环境。
注意:初学者请参考课程资料提供的 一键安装文档
环境准备
环境: 2个服务器 master和node节点 内存8G 处理器6个 硬盘30G
搭建K8S之前,需要一些前置的准备工作,否则不能完成集群的搭建。yum如果不能用,则使用,
1 | yum -y install yum-utils 或者 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo |
然后再使用yum。
1 | 修改主机名 |
搭建集群
1 | 修改系统参数 |
查看正在执行的pod,kubectl get pod --all-namespaces -o wide
注意:如果虚拟机重启导致k8s关闭,可以采用 systemctl status kubelet 查看状态,采用 systemctl start kubelet 启动k8s,无论是主节点还是工作节点,都需要执行
1 | kubeadm join 192.168.211.151:6443 --token zkkd3y.iompmpb402kyvdq6 --discovery-token-ca-cert-hash sha256:3c500a7df3a3e6857b50c31f9a9a209d57e669d7acd69905f040 023094945c04 |
1 | registry.cn-hangzhou.aliyuncs.com/itcast/kube-proxy v1.18.6 |
搭建istio环境
下载istio
下载 Istio,下载内容将包含:安装文件、示例和 istioctl 命令行工具。
- 访问 Istio release 页面下载与您操作系统对应的安装文件。在 macOS或 Linux 系统中,也可以通过以下命令下载最新版本的 Istio:
1 | curl -L https://istio.io/downloadIstio | sh - |
- 切换到 Istio 包所在目录下。例如:Istio 包名为 istio-1.6.5 ,则:
1 | cd istio-1.6.5 |
安装目录包含如下内容:
- samples/ 目录下,有示例应用程序
- bin/ 目录下,包含 istioctl 的客户端文件。 istioctl 工具用于手动注入 Envoy sidecar 代理。
- 将 istioctl 客户端路径增加到 path 环境变量中,macOS 或 Linux系统的增加方式如下:
1 | export PATH=$PWD/bin:$PATH |
安装 bash 自动补全文件
如果您使用 bash,istioctl 自动补全的文件位于 tools 目录。通过复制istioctl.bash 文件到您的 home 目录,然后添加下行内容到您的 .bashrc 文件执行 istioctl tab 补全文件:
1 | source ~/istio-1.6.5/tools/istioctl.bash |
如果 istioctl 补全文件已经正确安装,在您输入 istioctl 命令时通过按 Tab键,它会返回一组推荐命令供您选择:
1 | istioctl proxy-<TAB> |
安装istio
请按照以下步骤在您所选的平台上使用 demo 配置文件安装 Istio。
- 安装 demo 配置
1 | istioctl manifest apply --set profile=demo |
- 为了验证是否安装成功,需要先确保以下 Kubernetes 服务正确部署,然后验证除 jaeger-agent 服务外的其他服务,是否均有正确的CLUSTER-IP :
1 | kubectl get svc -n istio-system |
如果集群运行在一个不支持外部负载均衡器的环境中(例如:minikube), istio-ingressgateway 的 EXTERNAL-IP 将显示为 <pending>
状态。请使用服务的 NodePort 或 端口转发来访问网关。
请确保关联的 Kubernetes pod 已经部署,并且 STATUS 为 Running
1 | [root@k8-master ~]# kubectl get pods -n istio-system |
卸载istio
1 | istioctl manifest generate --set profile=demo | kubectl delete -f - |
bookinfo示例
参照文档:https://istio.io/v1.6/zh/docs/examples/bookinfo/
应用说明
这个示例部署了一个用于演示多种 Istio 特性的应用,该应用由四个单独的微服务构成。 这个应用模仿在线书店的一个分类,显示一本书的信息。 页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。
Bookinfo 应用分为四个单独的微服务:
- productpage . 这个微服务会调用 details 和 reviews 两个微服务,用来生成页面。
- details . 这个微服务中包含了书籍的信息。
- reviews . 这个微服务中包含了书籍相关的评论。它还会调用 ratings微服务。
- ratings . 这个微服务中包含了由书籍评价组成的评级信息。
reviews 微服务有 3 个版本:
- v1 版本不会调用 ratings 服务。
- v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息。
- v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。
下图展示了这个应用的端到端架构。
Bookinfo 应用中的几个微服务是由不同的语言编写的。 这些服务对 Istio并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 reviews 服务具有多个版本。
部署应用
要在 Istio 中运行这一应用,无需对应用自身做出任何改变。 您只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务之中。 最终的部署结果将如下图所示:
所有的微服务都和 Envoy sidecar 集成在一起,被集成服务所有的出入流量都被 sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利用 Istio 控制平面为应用提供服务路由、遥测数据收集以及策略实施等功能。
启动应用服务
进入 Istio 安装目录。
Istio 默认自动注入 Sidecar. 请为 default 命名空间打上标签 istio-injection=enabled :
1 | kubectl label namespace default istio-injection=enabled |
- 使用 kubectl 部署应用:
1 | kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml |
如果您在安装过程中禁用了 Sidecar 自动注入功能而选择手动注入Sidecar,请在部署应用之前使用 istioctl kube-inject 命令修改bookinfo.yaml 文件。
1 | kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml) |
上面的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)。
在实际部署中,微服务版本的启动过程需要持续一段时间,并不是同时完成的。
- 确认所有的服务和 Pod 都已经正确的定义和启动:
1 | kubectl get services |
1 | kubectl get pods |
- 要确认 Bookinfo 应用是否正在运行,请在某个 Pod 中用 curl 命令对应用发送请求,例如 ratings :
1 | $ kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o " <title>.*</title>" <title>Simple Bookstore App</title> |
确定Ingress Ip
现在 Bookinfo 服务启动并运行中,您需要使应用程序可以从外部访问Kubernetes 集群,例如使用浏览器。可以用 Istio Gateway 来实现这个目标。
- 为应用程序定义 Ingress 网关:
1 | $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml |
- 确认网关创建完成:
1 | $ kubectl get gateway |
- 设置访问网关的 INGRESS_HOST 和 INGRESS_PORT 变量。确认并设置。
1 | 设置 ingress 端口 |
- 设置 GATEWAY_URL :
1 | export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT |
可以用浏览器打开网址 http://$GATEWAY_URL/productpage ,来浏览应用的 Web 页面。如果刷新几次应用的页面,就会看到 productpage 页面中会随机展示 reviews 服务的不同版本的效果(红色、黑色的星形或者没有显示)。 reviews 服务出现这种情况是因为我们还没有使用 Istio 来控制版本的路由。
应用默认目标规则
给各个服务创建 DestinationRule
在使用 Istio 控制 Bookinfo 版本路由之前,您需要在目标规则中定义好可用的版本,命名为 subsets 。
1 | #设置 |
至此,Istio 完成了全部的接管,第一个示例部署完成
体验istio
请求路由
按照版本路由
目前 reviews 有三个版本,在浏览器中访问 Bookinfo 应用程序的/productpage 并刷新几次。我们发现有时书评的输出包含星级评分,有时则不包含。 这是因为没有明确的默认服务版本路由。
现在我们要做就是让 istio 接管路由,比如将所有流量都路由到每个微服务的v1版本,Istio实现起来是非常简单的,只需要添加虚拟服务(VirtualService)即可。
示例:将所有流量都路由到各个微服务的v1版本
1 | #virtual-service-all-v1.yaml是官方提供的示例文件 |
经过测试,发现reviews不再切换样式
安装不同的用户身份路由
接下来,您将更改路由配置,以便将来自特定用户的所有流量路由到特定服务版本。在这,来自名为 Jason 的用户的所有流量将被路由到服务reviews:v2 。
请注意,Istio 对用户身份没有任何特殊的内置机制。事实上,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头,从而达到了本例子的效果。
请记住, reviews:v2 是包含星级评分功能的版本。
- 运行以下命令以启用基于用户的路由:
1 | $ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml |
- 确认规则已创建:
1 | $ kubectl get virtualservice reviews -o yaml |
- 在 Bookinfo 应用程序的 /productpage 上,以用户 jason 身份登录。刷新浏览器。你看到了什么?星级评分显示在每个评论旁边。
- 以其他用户身份登录(选择您想要的任何名称)。刷新浏览器。现在星星消失了。这是因为除了 Jason 之外,所有用户的流量都被路由到 reviews:v1 。您已成功配置 Istio 以根据用户身份路由流量
流量转移
还可以将 reviews 的部分流量转移到v3版本,基于此可以实现灰度发布、A/B测试等:
1 | #将所有流量都路由到每个服务的v1版本 kubectl apply -f samples/bookinfo/networking/virtual- service-all-v1.yaml |
刷新浏览器中的 /productpage 页面,大约有 50% 的几率会看到页面中出带 红色 星级的评价内容。这是因为 v3 版本的 reviews 访问了带星级评级的ratings 服务,但 v1 版本却没有。
如果认为 reviews:v3 微服务已经稳定,可以通过应用此 virtual service 规则将 100% 的流量路由到 reviews:v3:
1 | 将reviews服务的全部流量都切换到v3版本 |
这样,所有的请求都转向到了v3了。
如果需要删除所有服务的虚拟网络,可以执行:
1 | kubectl delete -f samples/bookinfo/networking/virtual- service-all-v1.yaml |
virtual-service-all-v1.yaml 配置文件中配置了所有服务的路由信息,如果删除了则所有的路由信息都删了
超时与重试
http 请求的超时可以用路由规则的 timeout 字段来指定。 默认情况下,超时是禁用的
这里我们来实验 reviews 服务的请求超时,将请求路由到 reviews 服务的 v2 版本,它会去调用 ratings 服务,我们首先在 ratings 服务上人为的引入2s的延迟(故障注入),再对 reviews 服务配置超时 timeout
1、在 istio-1.6.5/samples/bookinfo/networking 目录下创建配置文件
1 | 创建配置文件 |
在 ratings 服务上注入2s的延迟,
2、应用该路由配置,就在当前目录下执行即可
1 | kubectl apply -f virtual-service-reviews-v2-timeout.yaml |
3、访问该网址,这时可以看到 Bookinfo 应用运行正常(显示了评级的星型符号),但是每次刷新页面,都会有 2 秒的延迟。
4、重新编辑该文件,放开对 reviews 服务的调用增加一个半秒的请求超时(去掉timeout的注释)
5、重新应用该配置,还是执行第2步的命令,然后通过如下命令查看配置是否更新
1 | kubectl get virtualservice -o yaml |
6、再次刷新网页
这时候应该看到 1 秒钟就会返回,而不是之前的 2 秒钟,但 reviews 是不可用的(页面没有reviews的数据)
即使超时配置为半秒,响应仍需要 1 秒,是因为 productpage 服务中存在硬编码重试,因此它在返回之前调用 reviews 服务超时两次(重试)
关于重试:直接参考文档
- https://istio.io/v1.6/zh/docs/reference/config/networking/virtual-service/#HTTPRoute
- https://istio.io/v1.6/zh/docs/reference/config/networking/virtual-service/#HTTPRetry
熔断
熔断器是 Istio 为创建具有弹性的微服务应用提供的有用的机制。在熔断器中,设置一个对服务中的单个主机调用的限制,例如并发连接的数量或对该主机调用失败的次数。一旦限制被触发,熔断器就会“跳闸”并停止连接到该主机。
使用熔断模式可以快速失败而不必让客户端尝试连接到过载或有故障的主机。
部署httpbin
httpbin是一个开源项目,使用Python+Flask编写,利用它可以测试各种HTTP请求和响应。官网:http://httpbin.org/
1 | kubectl apply -f samples/httpbin/httpbin.yaml |
该配置文件的内容为:
1 | 待补充 |
配置熔断器
创建一个目标熔断规则(DestinationRule),在调用 httpbin 服务时应用熔断设置:
1 | 待补充 |
验证目标规则是否已正确创建:
1 | kubectl get destinationrule httpbin -o yaml |
客户端
创建客户端程序以发送流量到 httpbin 服务。这是一个名为 Fortio 的负载测试客户的,其可以控制连接数、并发数及发送 HTTP 请求的延迟。通过Fortio 能够有效的触发前面 在 DestinationRule 中设置的熔断策略。
- 向客户端注入 Istio Sidecar 代理,以便 Istio 对其网络交互进行管理:
1 | $ kubectl apply -f <(istioctl kube-inject -f samples/httpbin/sample-client/fortio-deploy.yaml) |
中间稍等一会,让客户端部署成功!!!
- 登入客户端 Pod 并使用 Fortio 工具调用 httpbin 服务。 -curl 参数表明发送一次调用:
1 | $ FORTIO_POD=$(kubectl get pod | grep fortio | awk |
可以看到调用后端服务的请求已经成功!接下来,可以测试熔断
触发熔断器
在 DestinationRule 配置中,定义了 maxConnections: 1 和http1MaxPendingRequests: 1。 这些规则意味着,如果并发的连接和请求数超过一个,在 istio-proxy 进行进一步的请求和连接时,后续请求或 连接将被阻止。
- 发送并发数为 2 的连接( -c 2 ),请求 20 次( -n 20 ):
1 | [root@node1 istio-1.6.5]# kubectl exec -it $FORTIO_POD -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get |
- 将并发连接数提高到 3 个:
1 | [root@node1 istio-1.6.5]# kubectl exec -it $FORTIO_POD -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get |
- 查询 istio-proxy 状态以了解更多熔断详情
1 | [root@node1 istio-1.6.5]# kubectl exec $FORTIO_POD - c istio-proxy -- pilot-agent request GET stats | grep httpbin | grep pending |
可以看到 upstream_rq_pending_overflow 值 59 ,这意味着,目前为止已有 59 个调用被标记为熔断
清理
- 清理规则:
1 | $ kubectl delete destinationrule httpbin |
- 下线 httpbin 服务和客户端
1 | $ kubectl delete deploy httpbin fortio-deploy |
可观察性
istio的可观测性体现在:指标度量,日志,分布式追踪,网格可视化等方面
网格可视化
我们可以将istio网格以可视化的方式呈现,基于 Web 的图形用户界面来查看网格和 Istio 配置对象的服务图,使我们的操作更方便(摆脱命令的困扰!!!)
在Istio中可以使用 Kiali 进行可视化的管理服务网格。Kiali官网:https://www.kiali.io/
Kiali的安装:在demo环境中已经默认安装了kiali,我们可以通过如下命令查看
1 | kubectl -n istio-system get services |
1、要打开 Kiali UI,请在您的 Kubernetes 环境中执行以下命令:
1 | [root@k8-master ~]# istioctl dashboard kiali --address 192.168.200.200 |
将流量发送到网格,有三种选择:
- 在浏览器中访问 http://$GATEWAY_URL/productpage
- 多次使用以下命令:
$ curl http://$GATEWAY_URL/productpage
- 如果您在系统中安装了 watch 命令,请通过以下方式连续发送请求,时间间隔为1秒:
1 | $ watch -n 1 curl -o /dev/null -s -w %{http_code} $GATEWAY_URL/productpage |
使用该地址打开,注意替换localhost为 address 地址,登录用户名和密码均为 admin
图表
查看流量分配的百分比
请求统计数据,RPS数据(最小/最大的比值)
显示不同的图表类型,有四种类型:
- App 图形类型将一个应用程序的所有版本聚合到一个图形节点中。
- Versioned App 图类型显示每个应用程序版本的节点,但是特定应用程序的所有版本都组合在一起。
- Workload 图类型显示了服务网格中每个工作负载的节点。
- Service 图类型显示网格中每个服务的节点。
路由加权
默认路由规则会平均分配浏览到每个可用节点,通过kiali可以可行可视化的调节:
第一步,查看servers列表:
第二步,进入reviews服务:
第三步,删除原有路由规则:
第四步,创建权重的规则:
默认情况:
进行调整:
保存操作。
第五步,通过watch执行一段时间,观察效果:
可以看到,分配到reviews的v1、v2、v3的百分比发生了变化。
查看工作负载
入站、出站信息:
日志信息:
入站指标信息:
出站指标信息:
istio实战
0、从资料中找到项目 itcast-service-mesh2.zip ,导入ide,制作movie.tar
1、将 movie.tar 分别上传到 k8-node1(201主机) 和 k8-master(200主 机) ,然后分别解压
2、在 k8-node1 主机上,执行 build-images.sh 脚本,先构建镜像(注意是在 node 节点上)
3、在 k8-master 主机上,在 movie/movie-istio 目录下先进行部署
1 | kubectl apply -f movie.yaml |
等待启动
1 | kubectl get service -o wide |
4、登录 neo4j 导入初始化数据,访问:http://192.168.200.201:31001/browser/ (访问的地址是node节点的ip)
用: neo4j , neo4j 登录,第一次登录后修改密码为: neo4j123 ,切记,切记,切记!
5、导入初始数据,从资料中找到 电影数据.txt ,在 neo4j 中执行,执行完成后查询
1 | match (n) return n |
6、创建初始 目标规则 ,执行如下命令
1 | kubectl apply -f destination-rule-all.yaml |
7、创建网关,执行如下命令
1 | kubectl apply -f movie-gateway.yaml |
8、获取网关访问地址,通过如下命令完成
1 | export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[? (@.name=="http2")].nodePort}') |
9、根据输出的地址访问,比如:http://192.168.200.201:31557/index
进行测试,反复刷新几次,可以看到评分部分,红/黑 进行切换。
10、将流量全部导向评分的 v2 版本,只显示红色评分,则可以执行下面这个规则
1 | kubectl apply -f virtual-service-rating-v2.yaml |
再次查看网页的评分显示内容!!!
附录
参考