Service Mesh入门

Service Mesh入门

1、Service Mesh简介

1.1、⽬前微服务架构⾯临的⼀些挑战

⽬前,微服务的架构⽅式在企业中得到了极⼤的发展,主要原因是其解决了传统的单体架构中存在的问题。
在这里插入图片描述
当单体架构拆分成微服务架构就可以⾼枕⽆忧了吗? 显然不是的。
微服务架构体系中同样也存在很多的挑战,⽐如:

  • 原来的单个应⽤拆分成了许多分散的微服务,它们之间相互调⽤才能完成⼀个任务,⽽⼀旦某个过程出错(组件越多,出错的概率也就越⼤),就⾮常难以排查。
  • 如果⽤户请求的响应太慢,我们就需要知道到底哪些地⽅⽐较慢?整个链路的调⽤各阶段耗时是多少?哪些调⽤是并发执⾏的,哪些是串⾏的?这些问题需要我们能⾮常清楚整个集群的调⽤以及流量情况。
  • 微服务拆分成这么多组件,如果单个组件出错的概率不变,那么整体有地⽅出错的概率就会增⼤。服务调⽤的时候如果没有错误处理机制,那么会导致⾮常多的问题。
  • 应⽤数量的增多,对于⽇常的应⽤发布来说也是个难题。应⽤的发布需要⾮常谨慎,如果应⽤都是⼀次性升级的,出现错误会导致整个线上应⽤不可⽤,影响范围太⼤。
  • 很多情况我们需要同时存在不同的版本,使⽤ AB 测试验证哪个版本更好。
  • 如果版本升级改动了 API,并且互相有依赖,那么我们还希望能⾃动地控制发布期间不同版本访问不同的地址。这些问题都需要智能的流量控制机制。
  • 为了保证整个系统的安全性,每个应⽤都需要实现⼀套相似的认证、授权、HTTPS、限流等功能。

1.2、技术架构演进

1.2.1、发展历史时间轴

在这里插入图片描述

1.2.2、单机⼩型机时代

第⼀个计算机⽹络诞⽣于1969年,也就是美军的阿帕⽹,阿帕⽹能够实现与其它计算机进⾏联机操作,但是早期仅仅是为了军事⽬的⽽服务 2000年初,中国的⽹⺠⼤约890万,很多⼈都不知道互联⽹为何物,因此⼤多数服务业务单⼀且简单,采⽤典型的单机+数据库模式,所有的功能都写在⼀个应⽤⾥并进⾏集中部署。
在这里插入图片描述
说明:论坛业务、聊天室业务、邮箱业务全部都耦合在⼀台⼩型机上⾯,所有的业务数据也都存储在⼀台数据库上。

1.2.3、垂直拆分

随着应⽤的⽇益复杂与多样化,开发者对系统的容灾,伸缩以及业务响应能⼒有了更⾼的要求,如果⼩型机和数据库中任何⼀个出现故障,整个系统都会崩溃,若某个板块的功能需要更新,那么整个系统都需要重新发布,显然,对于业务迅速发展的万物互联⽹时代是不允许的。
如何保障可⽤性的同时快速响应业务的变化,需要将系统进⾏拆分,将上⾯的应⽤拆分出多个⼦应⽤。
在这里插入图片描述
优点:应⽤间进⾏了解耦,系统容错提⾼了,也解决了独⽴应⽤发布的问题。
应⽤垂直拆分解决了应⽤发布的问题,但是随着⽤户数量的增加,单机的计算能⼒依旧是杯⽔⻋薪。

1.2.4、集群化负载均衡架构

⽤户量越来越⼤,就意味着需要更多的⼩型机,但是⼩型机价格昂贵,操作维护成本⾼。 此时更优的选择是采⽤多台PC机部署同⼀个应⽤的⽅案,但是此时就需要对这些应⽤做负载均衡,因为客户端不知道请求会落到哪⼀个后端PC应⽤上的。
负载均衡可以分为硬件层⾯和软件层⾯。 硬件层⾯:F5 软件负载层⾯:LVS、Nginx、Haproxy
负载均衡的思想:对外暴露⼀个统⼀的接⼝,根据⽤户的请求进⾏对应规则转发,同时负载均衡还可以做限流等等
有了负载均衡之后,后端的应⽤可以根据流量的⼤⼩进⾏动态扩容,我们称为"⽔平扩展"。

在这里插入图片描述

阿⾥巴巴在2008提出去“IOE”,也就是IBM⼩型机、Oracle数据库,EMC存储,全部改成集群化负载均衡架构,在2013年⽀付宝最后⼀台IBM⼩型机下线。
优点:通过⽔平扩展,增强了系统的并发能⼒。

1.2.5、服务化改造架构

虽然系统经过了垂直拆分,但是拆分之后发现在论坛和聊天室中有重复的功能,⽐如,⽤户注册、发邮件等等,⼀旦项⽬⼤了,集群部署多了,这些重复的功能⽆疑会造成资源浪费,所以会把重复功能抽取出来,名字叫"XX服务(Service)"
在这里插入图片描述
为了解决服务跟服务如何相互调⽤,需要⼀个程序之间的通信协议,所以就有了远程过程调⽤(RPC),作⽤就是让服务之间的程序调⽤变得像本地调⽤⼀样的简单。
优点:在前⾯的架构之上解决了业务重⽤的问题。

1.2.6、服务治理

随着业务的增⼤,基础服务越来越多,调⽤⽹的关系由最初的⼏个增加到⼏⼗上百,造成了调⽤链路错综复杂,需要对服务进⾏治理。
服务治理要求:

  • 当我们服务节点数⼏⼗上百的时候,需要对服务有动态的感知,引⼊了注册中⼼。
  • 当服务链路调⽤很⻓的时候如何实现链路的监控。
  • 单个服务的异常,如何能避免整条链路的异常(雪崩),需要考虑熔断、降级、限流。
  • 服务⾼可⽤:负载均衡。

典型框架⽐如有:Dubbo,默认采⽤的是Zookeeper作为注册中⼼。

1.2.7、微服务时代

微服务是在2012年提出的概念,微服务的希望的重点是⼀个服务只负责⼀个独⽴的功能。
拆分原则,任何⼀个需求不会因为发布或者维护⽽影响到不相关的服务,⼀切可以做到独⽴部署运维。
⽐如传统的“⽤户中⼼”服务,对于微服务来说,需要根据业务再次拆分,可能需要拆分成“买家服务”、 “卖家服务”、“商家服务”等。
典型代表:Spring Cloud,相对于传统分布式架构,SpringCloud使⽤的是HTTP作为RPC远程调⽤,配合上注册中⼼Eureka和API⽹关Zuul,可以做到细分内部服务的同时⼜可以对外暴露统⼀的接⼝,让外部对系统内部架构⽆感,此外Spring Cloud的config组件还可以把配置统⼀管理。
在这里插入图片描述
Spring Cloud微服务架构存在的不⾜:

  • Spring Cloud属于侵⼊式框架,在项⽬中需要添加spring cloud maven依赖,加上springcloud组件注解,写配置,打成jar的时候还必须要把⾮业务的代码也要融合在⼀起。
  • 微服务中的服务⽀持不同语⾔开发,也需要维护不同语⾔和⾮业务代码的成本;
  • 业务代码开发者应该把更多的精⼒投⼊到业务熟悉度上,⽽不应该是⾮业务上,Spring Cloud虽然能解决微服务领域的很多问题,但是学习成本还是较⼤的。
  • 互联⽹公司产品的版本升级是⾮常频繁的,为了维护各个版本的兼容性、权限、流量等,因为SpringCloud是“代码侵⼊式的框架”,这时候版本的升级就注定要让⾮业务代码⼀起,⼀旦出现问题,再加上多语⾔之间的调⽤,⼯程师会⾮常痛苦。
  • 我们已经感觉到了,服务拆分的越细,只是感觉上轻量级解耦了,但是维护成本却越⾼了
1.2.8、服务⽹格新时期 (Service Mesh)

Service Mesh主要解决的问题就希望开发⼈员对于业务的聚焦,服务发现、服务注册、负载均衡等对于开发⼈员透明,可以更加专注业务逻辑的实现。
如果将为微服务提供通信服务的这部分逻辑从应⽤程序进程中抽取出来,作为⼀个单独的进程进⾏部署,并将其作为服务间的通信代理,可以得到如下图所示的架构:
在这里插入图片描述

Sidecar,翻译成中⽂是边⻋,⾮常的形象。
在这里插入图片描述

当服务⼤量部署时,随着服务部署的Sidecar代理之间的连接形成了⼀个如下图所示的⽹格,该⽹格成为了微服务的通讯基础设施层,承载了微服务之间的所有流量,被称之为Service Mesh(服务⽹格)。

在这里插入图片描述

服务⽹格中有数量众多的Sidecar代理,如果对每个代理分别进⾏设置,⼯作量将⾮常巨⼤。为了更⽅便地对服务⽹格中的代理进⾏统⼀集中控制,在服务⽹格上增加了控制⾯组件。
在这里插入图片描述

1.3、什么是Service Mesh

服务⽹格⽤来描述组成这些应⽤程序的微服务⽹络以及它们之间的交互。随着服务⽹格的规模和复杂性不断的增⻓,它将会变得越来越难以理解和管理。它的需求包括服务发现、负载均衡、故障恢复、度量和监控等。服务⽹格通常还有更复杂的运维需求,⽐如 A/B 测试、⾦丝雀发布、速率限制、访问控制和端到端认证。
在这里插入图片描述

1.4、Service Mesh产品

1.4.1、CNCF

CNCF 是⼀个开源软件基⾦会,致⼒于使云原⽣计算具有普遍性和可持续性。 云原⽣计算使⽤开源软件
技术栈将应⽤程序部署为微服务,将每个部分打包到⾃⼰的容器中,并动态编排这些容器以优化资源利
⽤率。 云原⽣技术使软件开发⼈员能够更快地构建出⾊的产品。
官⽹:https://www.cncf.io/
常⽤的已经毕业的云原⽣项⽬:

  • 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 容器镜像作为新平台或产品的⼀部分进⾏管理。

1.4.2、Linkerd

在这里插入图片描述
Linkerd是Buoyant公司2016年率先开源的⾼性能⽹络代理程序,是业界的第⼀款Service Mesh产品,甚⾄可以说Linkerd的诞⽣标志着Service Mesh时代的开始,其引领后来Service Mesh的快速发展。
其主要⽤于解决分布式环境中服务之间通信⾯临的⼀些问题,⽐如⽹络不可靠、不安全、延迟丢包等问题。Linkerd使⽤Scala语⾔编写,运⾏于JVM,底层基于Twitter的Finagle库,并对其做相应的扩展。
最主要的是Linkerd具有快速、轻量级、⾼性能等特点,每秒以最⼩的时延及负载处理万级请求,易于⽔平扩展,经过⽣产线测试及验证,可运⾏任何平台的产线级Service Mesh⼯具。

1.4.3、Envoy

在这里插入图片描述
Envoy也是⼀款⾼性能的⽹络代理程序,于2016年10⽉份由Lyft公司开源,为云原⽣应⽤⽽设计,可作为边界⼊⼝,处理外部流量,当然,也作为内部服务间通信代理,实现服务间可靠通信。
Envoy的实现借鉴现有产线级代理及负载均衡器,如Nginx、HAProxy、硬件负载均衡器及云负载均衡器的实践经验,同时基于C++编写及Lyft公司产线实践证明,Envoy性能⾮常优秀、稳定。
Envoy既可⽤作独⽴代理层运⾏,也可作为Service Mesh架构中数据平⾯层,因此通常Envoy跟服务运⾏在⼀起,将应⽤的⽹络功能抽象化,Envoy提供通⽤⽹络功能,实现平台及语⾔⽆关。

1.4.4、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的控制平⾯则负责服务间流量管理、安全通信策略等功能。

1.4.5、Conduit

在这里插入图片描述
Conduit于2017年12⽉发布,作为由Buoyant继Linkerd后赞助的另⼀个开源项⽬。Conduit旨在彻底简化⽤户在Kubernetes使⽤服务⽹格的复杂度,提⾼⽤户体验,⽽不是像Linkerd⼀样针对各种平台进⾏优化。

1.4.6、国内产品

国内很多团队也已经在着⼿研究了,这些团队主要分为四类体系:
以蚂蚁⾦服为⾸的开源系:蚂蚁⾦服⾃研的 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 体系。

2、Istio简介

2.1、istio架构

在这里插入图片描述
实际上Istio 就是 Service Mesh 架构的⼀种实现,服务之间的通信(⽐如这⾥的 Service A 访问 ServiceB)会通过代理(默认是 Envoy)来进⾏。
⽽且中间的⽹络协议⽀持 HTTP/1.1,HTTP/2,gRPC 或者 TCP,可以说覆盖了主流的通信协议。代理这⼀层,称之为数据平⾯。
控制平⾯做了进⼀步的细分,分成了 Pilot、Citadel 和 Galley,它们的各⾃功能如下:

  • Pilot:为 Envoy 提供了服务发现,流量管理和智能路由(AB 测试、⾦丝雀发布等),以及错误处理(超时、重试、熔断)功能。
  • Citadel:为服务之间提供认证和证书管理,可以让服务⾃动升级成 TLS 协议。
  • Galley:Galley 是 Istio 的配置验证、提取、处理和分发组件。它负责将其余的 Istio 组件与从底层平台(例如Kubernetes)获取⽤户配置的细节隔离开来。
    数据平⾯会和控制平⾯通信,⼀⽅⾯可以获取需要的服务之间的信息,另⼀⽅⾯也可以汇报服务调⽤的Metrics 数据。

2.1、为什么使⽤ Istio?

通过负载均衡、服务间的身份验证、监控等⽅法,Istio 可以轻松地创建⼀个已经部署了服务的⽹络,⽽服务的代码只需很少更改甚⾄⽆需更改。通过在整个环境中部署⼀个特殊的 sidecar 代理为服务添加Istio 的⽀持,⽽代理会拦截微服务之间的所有⽹络通信,然后使⽤其控制平⾯的功能来配置和管理Istio,这包括:

  • 为 HTTP、gRPC、WebSocket 和 TCP 流量⾃动负载均衡。
  • 通过丰富的路由规则、重试、故障转移和故障注⼊对流量⾏为进⾏细粒度控制。
  • 可插拔的策略层和配置 API,⽀持访问控制、速率限制和配额。
  • 集群内(包括集群的⼊⼝和出⼝)所有流量的⾃动化度量、⽇志记录和追踪。
  • 在具有强⼤的基于身份验证和授权的集群中实现安全的服务间通信。

Istio 为可扩展性⽽设计,可以满⾜不同的部署需求。

2.2、核⼼特性

Istio 以统⼀的⽅式提供了许多跨服务⽹络的关键功能。

2.2.1、流量管理

Istio 简单的规则配置和流量路由允许您控制服务之间的流量和 API 调⽤过程。
Istio 简化了服务级属性(如熔断器、超时和重试)的配置,并且让它轻⽽易举的执⾏重要的任务(如A/B 测试、⾦丝雀发布和按流量百分⽐划分的分阶段发布)。
有了更好的对流量的可视性和开箱即⽤的故障恢复特性,就可以在问题产⽣之前捕获它们,⽆论⾯对什么情况都可以使调⽤更可靠,⽹络更健壮。

2.2.2、安全

Istio 的安全特性解放了开发⼈员,使其只需要专注于应⽤程序级别的安全。
Istio 提供了底层的安全通信通道,并为⼤规模的服务通信管理认证、授权和加密。有了 Istio,服务通信在默认情况下就是受保护的,可以让您在跨不同协议和运⾏时的情况下实施⼀致的策略——⽽所有这些都只需要很少甚⾄不需要修改应⽤程序。
Istio 是独⽴于平台的,可以与 Kubernetes(或基础设施)的⽹络策略⼀起使⽤。但它更强⼤,能够在⽹络和应⽤层⾯保护pod到 pod 或者服务到服务之间的通信。

2.2.3、可观察性

Istio 健壮的追踪、监控和⽇志特性让您能够深⼊的了解服务⽹格部署。
通过 Istio 的监控能⼒,可以真正的了解到服务的性能是如何影响上游和下游的;⽽它的定制
Dashboard 提供了对所有服务性能的可视化能⼒,并让您看到它如何影响其他进程。
Istio 的 Mixer 组件负责策略控制和遥测数据收集。它提供了后端抽象和中介,将⼀部分 Istio 与后端的基础设施实现细节隔离开来,并为运维⼈员提供了对⽹格与后端基础实施之间交互的细粒度控制。
所有这些特性都使您能够更有效地设置、监控和加强服务的 SLO。当然,底线是您可以快速有效地检测到并修复出现的问题。

2.3、平台⽀持

Istio 独⽴于平台,被设计为可以在各种环境中运⾏,包括跨云、内部环境、Kubernetes、Mesos 等等。您可以在 Kubernetes 或是装有 Consul 的 Nomad 环境上部署 Istio。Istio ⽬前⽀持:

  • Kubernetes 上的服务部署
  • 基于 Consul 的服务注册
  • 服务运⾏在独⽴的虚拟机上

3、Istio快速⼊⻔

下⾯我们将Istio进⾏部署安装,来体验下它的魅⼒。

3.1、搭建kubernetes集群

Istio运⾏在kubernetes平台是最佳的选择,所以我们先搭建kubernetes环境。

3.1.1

准备3台Centos7虚拟机:
在这里插入图片描述

3.1.2、前置⼯作

搭建K8S之前,需要⼀些前置的准备⼯作,否则不能完成集群的搭建。

#修改主机名
hostnamectl set-hostname node2
hostnamectl set-hostname node3
#更新yum源,并且完成yum update操作
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo
https://mirrors.aliyun.com/repo/Centos-7.repo
yum makecache
yum -y update
#安装docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/dockerce/linux/centos/docker-ce.repo
yum makecache fast
yum -y install docker-ce

#启动docker服务
systemctl start docker.service
#开机⾃启
systemctl enable docker.service
#添加docker阿⾥云加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://c6n8vys4.mirror.aliyuncs.com"] }
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
#测试⼀下,看下载速度怎么样
docker pull redis
docker rmi redis:latest
#关闭防⽕墙
systemctl stop firewalld.service
systemctl disable firewalld.service
#添加hosts映射
vim /etc/hosts
192.168.31.106 node1
192.168.31.107 node2
192.168.31.108 node3
scp /etc/hosts node2:/etc/
scp /etc/hosts node3:/etc/
#设置node1到node2、node3免登陆
ssh-keygen #⼀路下⼀步操作
ssh-copy-id node2
ssh-copy-id node3
#测试
ssh node2
ssh node3
3.1.3、搭建集群
#修改系统参数
# 将 SELinux 设置为 permissive 模式(相当于将其禁⽤)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

# 禁⽤swap⽂件,编辑/etc/fstab,注释掉引⽤ swap 的⾏
vim /etc/fstab
swapoff -a
# 设置⽹桥参数
vim /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.ipv4.tcp_tw_recycle = 0

scp /etc/sysctl.conf node2:/etc/
scp /etc/sysctl.conf node3:/etc/
#⽴即⽣效
sysctl -p
#安装kubectl
vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0

yum list kubectl –showduplicates
yum install -y kubectl.x86_64
kubectl version

yum install -y kubelet kubeadm --disableexcludes=kubernetes

#拉取所需要的镜像
kubeadm config images pull --image-repository=registry.cnhangzhou.aliyuncs.com/itcast --kubernetes-version=v1.18.6
#如果拉取失败,尝试这个:kubeadm config images pull --image-repository=lank8s.cn --kubernetes-version=v1.18.6
#开始初始化,如果使⽤lank8s.cn拉取的镜像,需要指定--image-repository=lank8s.cn
kubeadm init --apiserver-advertise-address 192.168.31.106 --pod-networkcidr=10.244.0.0/16 --image-repository=registry.cn-hangzhou.aliyuncs.com/itcast --kubernetes-version=v1.18.6
#当看到 Your Kubernetes control-plane has initialized successfully! 说明初始化成功
了!

#拷⻉admin.conf到home⽬录,否则出错:The connection to the server localhost:8080 was refused - did you specify the right host or port?
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#设置⽹络 kube-flannel.yml ⽂件在资料中
kubectl apply -f kube-flannel.yml
#测试
[root@node1 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready master 23m v1.18.6
#将node2、node3加⼊到集群,token要替换成⾃⼰的
kubeadm join 192.168.31.106:6443 --token ekw4eu.cfi77sji1jyczhj6 --discoverytoken-ca-cert-hash
sha256:21de4177eaf76353dd060f2a783c9dafe17636437ade020bc40d60a8ab903483
#测试
[root@node1 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready master 31m v1.18.6
node2 Ready <none> 6m46s v1.18.6
node3 Ready <none> 2m21s v1.18.6
#说明集群组件成功了
#如果需要删除集群,执⾏ kubeadm reset ,3台机器都需要执⾏
#查看正在执⾏的pod
kubectl get pod --all-namespaces -o wide

查看正在执⾏的pod,kubectl get pod --all-namespaces -o wide

在这里插入图片描述
kube-flannel.yml

---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp.flannel.unprivileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
    seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
    apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
    apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
  privileged: false
  volumes:
    - configMap
    - secret
    - emptyDir
    - hostPath
  allowedHostPaths:
    - pathPrefix: "/etc/cni/net.d"
    - pathPrefix: "/etc/kube-flannel"
    - pathPrefix: "/run/flannel"
  readOnlyRootFilesystem: false
  # Users and groups
  runAsUser:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  # Privilege Escalation
  allowPrivilegeEscalation: false
  defaultAllowPrivilegeEscalation: false
  # Capabilities
  allowedCapabilities: ['NET_ADMIN']
  defaultAddCapabilities: []
  requiredDropCapabilities: []
  # Host namespaces
  hostPID: false
  hostIPC: false
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  # SELinux
  seLinux:
    # SELinux is unused in CaaSP
    rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: flannel
rules:
  - apiGroups: ['extensions']
    resources: ['podsecuritypolicies']
    verbs: ['use']
    resourceNames: ['psp.flannel.unprivileged']
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes/status
    verbs:
      - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-amd64
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: kubernetes.io/arch
                    operator: In
                    values:
                      - amd64
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.12.0-amd64
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.12.0-amd64
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-arm64
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: kubernetes.io/arch
                    operator: In
                    values:
                      - arm64
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.12.0-arm64
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.12.0-arm64
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-arm
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: kubernetes.io/arch
                    operator: In
                    values:
                      - arm
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.12.0-arm
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.12.0-arm
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-ppc64le
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: kubernetes.io/arch
                    operator: In
                    values:
                      - ppc64le
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.12.0-ppc64le
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.12.0-ppc64le
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-s390x
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: kubernetes.io/arch
                    operator: In
                    values:
                      - s390x
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.12.0-s390x
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        volumeMounts:
        - name: cni
          mountPath: /etc/cni/net.d
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.12.0-s390x
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg

3.2、搭建Istio环境

3.2.1、下载 Istio

下载 Istio,下载内容将包含:安装⽂件、示例和 istioctl 命令⾏⼯具。

  1. 访问 Istio release ⻚⾯下载与您操作系统对应的安装⽂件。在 macOS 或 Linux 系统中,也可以通过以下命令下载最新版本的 Istio:
$ curl -L https://istio.io/downloadIstio | sh -
  1. 切换到 Istio 包所在⽬录下。例如:Istio 包名为 istio-1.6.5 ,则:
$ cd istio-1.6.5

安装⽬录包含如下内容:

  • samples/ ⽬录下,有示例应⽤程序
  • bin/ ⽬录下,包含 istioctl 的客户端⽂件。 istioctl ⼯具⽤于⼿动注⼊ Envoy sidecar 代理。
  • 将 istioctl 客户端路径增加到 path 环境变量中,macOS 或 Linux 系统的增加⽅式如下:
$ export PATH=$PWD/bin:$PATH

安装 bash ⾃动补全⽂件
如果您使⽤ bash,istioctl ⾃动补全的⽂件位于 tools ⽬录。通过复制 istioctl.bash ⽂件到您的 home⽬录,然后添加下⾏内容到您的 .bashrc ⽂件执⾏ istioctl tab 补全⽂件:

source ~/istioctl.bash

如果 istioctl 补全⽂件已经正确安装,在您输⼊ istioctl 命令时通过按 Tab 键,它会返回⼀组推荐命令供您选择:

$ istioctl proxy-<TAB>
proxy-config proxy-status
3.2.2、安装Istio

请按照以下步骤在您所选的平台上使⽤ demo 配置⽂件安装 Istio。

  1. 安装 demo 配置
$ istioctl manifest apply --set profile=demo
  1. 为了验证是否安装成功,需要先确保以下 Kubernetes 服务正确部署,然后验证除 jaegeragent 服务外的其他服务,是否均有正确的 CLUSTER-IP :
$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana ClusterIP 172.21.211.123 <none> 3000/TCP 
 2m
istio-citadel ClusterIP 172.21.177.222 <none> 
8060/TCP,15014/TCP 
 2m
istio-egressgateway ClusterIP 172.21.113.24 <none> 
80/TCP,443/TCP,15443/TCP 
 2m
istio-galley ClusterIP 172.21.132.247 <none> 
443/TCP,15014/TCP,9901/TCP 
 2m
istio-ingressgateway LoadBalancer 172.21.144.254 52.116.22.242 
15020:31831/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:30318/TCP
,15030:32645/TCP,15031:31933/TCP,15032:31188/TCP,15443:30838/TCP 2m
istio-pilot ClusterIP 172.21.105.205 <none> 
15010/TCP,15011/TCP,8080/TCP,15014/TCP 
 2m
istio-policy ClusterIP 172.21.14.236 <none> 
9091/TCP,15004/TCP,15014/TCP 
 2m
istio-sidecar-injector ClusterIP 172.21.155.47 <none> 
443/TCP,15014/TCP 
 2m
istio-telemetry ClusterIP 172.21.196.79 <none> 
9091/TCP,15004/TCP,15014/TCP,42422/TCP 
 2m
jaeger-agent ClusterIP None <none> 
5775/UDP,6831/UDP,6832/UDP 
 2m
jaeger-collector ClusterIP 172.21.135.51 <none> 
14267/TCP,14268/TCP 
 2m
jaeger-query ClusterIP 172.21.26.187 <none> 
16686/TCP 
 2m
kiali ClusterIP 172.21.155.201 <none> 
20001/TCP 
 2m
prometheus ClusterIP 172.21.63.159 <none> 
9090/TCP 
 2m
tracing ClusterIP 172.21.2.245 <none> 
80/TCP 
 2m
zipkin ClusterIP 172.21.182.245 <none> 
9411/TCP 
 2m

如果集群运⾏在⼀个不⽀持外部负载均衡器的环境中(例如:minikube), istioingressgateway 的 EXTERNAL-IP 将显示为 状态。请使⽤服务的 NodePort或 端⼝转发来访问⽹关。
请确保关联的 Kubernetes pod 已经部署,并且 STATUS 为 Running :

$ kubectl get pods -n istio-system
NAME READY 
STATUS RESTARTS AGE
grafana-f8467cc6-rbjlg 1/1 
Running 0 1m
istio-citadel-78df5b548f-g5cpw 1/1 
Running 0 1m
istio-egressgateway-78569df5c4-zwtb5 1/1 
Running 0 1m
istio-galley-74d5f764fc-q7nrk 1/1 
Running 0 1m
istio-ingressgateway-7ddcfd665c-dmtqz 1/1 
Running 0 1m
istio-pilot-f479bbf5c-qwr28 1/1 
Running 0 1m
istio-policy-6fccc5c868-xhblv 1/1 
Running 2 1m
istio-sidecar-injector-78499d85b8-x44m6 1/1 
Running 0 1m
istio-telemetry-78b96c6cb6-ldm9q 1/1 
Running 2 1m
istio-tracing-69b5f778b7-s2zvw 1/1 
Running 0 1m
kiali-99f7467dc-6rvwp 1/1 
Running 0 1m
prometheus-67cdb66cbb-9w2hm 1/1 
Running 0 1m

3.3、Bookinfo示例

3.3.1、应⽤说明

这个示例部署了⼀个⽤于演示多种 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 服务具有多个版本。

3.3.2、部署应⽤

要在 Istio 中运⾏这⼀应⽤,⽆需对应⽤⾃身做出任何改变。 您只要简单的在 Istio 环境中对服务进⾏配置和运⾏,具体⼀点说就是把 Envoy sidecar 注⼊到每个服务之中。 最终的部署结果将如下图所示:

在这里插入图片描述
所有的微服务都和 Envoy sidecar 集成在⼀起,被集成服务所有的出⼊流量都被 sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利⽤ Istio 控制平⾯为应⽤提供服务路由、遥测数据收集以及策略实施等功能。

3.3.3、启动应⽤服务
  1. 进⼊ Istio 安装⽬录。
  2. Istio 默认⾃动注⼊ Sidecar. 请为 default 命名空间打上标签 istio-injection=enabled :
$ kubectl label namespace default istio-injection=enabled
  1. 使⽤ kubectl 部署应⽤:
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

如果您在安装过程中禁⽤了 Sidecar ⾃动注⼊功能⽽选择⼿动注⼊ Sidecar,请在部署应⽤之前使⽤ istioctl kube-inject 命令修改 bookinfo.yaml ⽂件。

$ kubectl apply -f <(istioctl kube-inject -f
samples/bookinfo/platform/kube/bookinfo.yaml)

上⾯的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)。
在实际部署中,微服务版本的启动过程需要持续⼀段时间,并不是同时完成的。
4. 确认所有的服务和 Pod 都已经正确的定义和启动:

$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) 
AGE
details 10.0.0.31 <none> 9080/TCP 
6m
kubernetes 10.0.0.1 <none> 443/TCP 
7d
productpage 10.0.0.120 <none> 9080/TCP 
6m
ratings 10.0.0.15 <none> 9080/TCP 
6m
reviews 10.0.0.170 <none> 9080/TCP 
6m

还有:

$ kubectl get pods
NAME READY STATUS RESTARTS 
AGE
details-v1-1520924117-48z17 2/2 Running 0
6m
productpage-v1-560495357-jk1lz 2/2 Running 0
6m
ratings-v1-734492171-rnr5l 2/2 Running 0
6m
reviews-v1-874083890-f0qf0 2/2 Running 0
6m
reviews-v2-1343845940-b34q5 2/2 Running 0
6m
reviews-v3-1813607990-8ch52 2/2 Running 0
6m
  1. 要确认 Bookinfo 应⽤是否正在运⾏,请在某个 Pod 中⽤ curl 命令对应⽤发送请求,例如
    ratings :
$ 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>
3.3.4、确定 Ingress 的 IP

现在 Bookinfo 服务启动并运⾏中,您需要使应⽤程序可以从外部访问 Kubernetes 集群,例如使⽤浏览器。可以⽤ Istio Gateway 来实现这个⽬标。

  1. 为应⽤程序定义 Ingress ⽹关:
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
  1. 确认⽹关创建完成:
$ kubectl get gateway
NAME AGE
bookinfo-gateway 32s
  1. 设置访问⽹关的 INGRESS_HOST 和 INGRESS_PORT 变量。确认并设置。
#设置 ingress 端⼝
export INGRESS_PORT=$(kubectl -n istio-system get service istioingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istioingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
#设置 ingress IP
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istiosystem -o jsonpath='{.items[0].status.hostIP}')
  1. 设置 GATEWAY_URL :
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

可以⽤浏览器打开⽹址 http://$GATEWAY_URL/productpage ,来浏览应⽤的 Web ⻚⾯。如果刷新⼏次应⽤的⻚⾯,就会看到 productpage ⻚⾯中会随机展示 reviews 服务的不同版本的效果(红⾊、⿊⾊的星形或者没有显示)。 reviews 服务出现这种情况是因为我们还没有使⽤ Istio 来控制版本的路由。
在这里插入图片描述

3.3.5、应⽤默认⽬标规则

在使⽤ Istio 控制 Bookinfo 版本路由之前,您需要在⽬标规则中定义好可⽤的版本,命名为 subsets 。

#设置
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
#查询
kubectl get destinationrules -o yaml

⾄此,Istio 完成了全部的接管,第⼀个示例部署完成。

3.4、体验Istio

https://github.com/istio/istio

3.4.1、按照版本路由

reviews有三个版本,默认情况下,会进⾏轮询,也就是我们看到的,每⼀次刷新都会有不同的效果。
如果,我们需要将请求全部切换到某⼀个版本,需要Istio是⾮常简单的,只需要添加虚拟服务即可。
示例:

#virtual-service-all-v1.yaml是官⽅提供的示例⽂件
kubectl apply -f samples/bookinfo/networking/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. #在这⾥指定了所有的http请求都通过v1完成,⽽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
---

经过测试,发现reviews不再切换样式。
在这里插入图片描述
还可以将部分流量转移到v3版本,基于此可以实现灰度发布、A/B测试等:

#将50%的流程转移到v3
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 50
    - destination:
        host: reviews
        subset: v3
      weight: 50

刷新浏览器中的 /productpage ⻚⾯,⼤约有 50% 的⼏率会看到⻚⾯中出带 红⾊ 星级的评价内容。这是因为 v3 版本的 reviews 访问了带星级评级的 ratings 服务,但 v1 版本却没有。
如果认为 reviews:v3 微服务已经稳定,可以通过应⽤此 virtual service 规则将 100% 的流量路由到
reviews:v3:

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-v3.yaml

这样,所有的请求都转向到了v3了。
如果需要删除虚拟⽹络,可以执⾏:

kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml
3.4.2、按照不同⽤户身份路由

接下来,您将更改路由配置,以便将来⾃特定⽤户的所有流量路由到特定服务版本。在这,来⾃名为Jason 的⽤户的所有流量将被路由到服务 reviews:v2 。
请注意,Istio 对⽤户身份没有任何特殊的内置机制。事实上, productpage 服务在所有到 reviews服务的 HTTP 请求中都增加了⼀个⾃定义的 end-user 请求头,从⽽达到了本例⼦的效果。
请记住, reviews:v2 是包含星级评分功能的版本。

  1. 运⾏以下命令以启⽤基于⽤户的路由:
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviewstest-v2.yaml
  1. 确认规则已创建:
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
  1. 在 Bookinfo 应⽤程序的 /productpage 上,以⽤户 jason 身份登录。
    刷新浏览器。你看到了什么?星级评分显示在每个评论旁边。
  2. 以其他⽤户身份登录(选择您想要的任何名称)。
    刷新浏览器。现在星星消失了。这是因为除了 Jason 之外,所有⽤户的流量都被路由到reviews:v1 。
    您已成功配置 Istio 以根据⽤户身份路由流量。
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值