从微服务到云原生---入门
[TOC]
微服务
微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。
微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。
架构演进
微服务架构区别于传统的单体软件架构,是一种为了适应当前互联网后台服务的「三高需求:高并发、高性能、高可用」而产生的的软件架构。
单体架构
单体应用程序的优点
- 开发简单,功能都在单个程序内部,便于软件设计和开发规划。
- 容易部署,程序单一不存在分布式集群的复杂部署环境,降低了部署难度。
- 容易测试,没有各种复杂的服务调用关系,都是内部调用方便测试。
- 高效通信,程序间可直接调用,通信成本低。
单体应用程序的缺点
- 开发效率低:所有的开发在一个项目改代码,递交代码相互等待,代码冲突不断。
- 代码维护难:代码功能耦合在一起,依赖程度过高,新人不知道何从下手,牵一发而动全身。
- 部署不灵活:构建时间长,任何小修改必须重新构建整个项目,这个过程往往很长。
- 稳定性不高:一个微不足道的小问题,可以导致整个应用挂掉。
- 扩展性不够:无法满足高并发情况下的业务需求。
微服务架构
2014年,Martin Fowler 与 James Lewis 共同提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 API 通信。同时服务会使用最小的规模的集中管理能力,服务可以用不同的编程语言与数据库等组件实现 。「维基百科」
鉴于「单体应用程序」有上述的缺点,单个应用程序被划分成各种小的、互相连接的微服务,一个微服务完成一个比较单一的功能,相互之间保持独立和解耦合,这就是微服务架构。
微服务架构的优点
- 代码解耦易维护:每个服务独立开发,只专注做一件事,逻辑清晰,新人容易上手。独立应用更易优化,
- 多团队协作开发:每个服务都能够由专注于该服务的团队独立开发。开发人员可以自由选择任何有用的技术,只要该服务符合API要求。
- 独立按需扩展:每个服务都可以独立部署,独立调整资源。可以仅部署满足其容量和可用性限制的服务的实例数。此外,可以使用最符合服务资源要求的硬件。
- 独立运行稳定:每个服务独立运行,发生故障影响面可控,不会导致整个系统down掉。
微服务架构的缺点
- 应用间通过网络调用,通信成本高,通信效率降低。网络间调用容易出现问题,失败机率增大。应用规模变大后,服务治理难度增大。
- 系统整体架构及调用关系复杂,开发人员对整个系统了解会有局限。
- 应用间调用会产生分布式事务,业务实现难度更大,对开发人员要求更高。
微服务现状
为了解决上面微服务架构缺点「服务治理」就出现了。出现了众多的组件,如:服务注册、配置中心、服务监控、服务容错(降级、熔断、限流、超时、重试)等。幸好,有巨人的肩膀可以借给我们站上去,通过引入「微服务框架」来帮助我们完成服务治理。
SpringCloud
Dubbo
阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。 Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现 。2011 年末对外开源,仅支持 Java 语言。
下一代微服务
在微服务架构下,基础架构团队一般会为应用提供一个封装了各种服务治理能力的 SDK,这种做法虽然保障了应用的正常运行,但缺点也非常明显,每次基础架构团队迭代一个新功能都需要业务方参与升级才能使用,尤其是 bugfix 版本,往往需要强推业务方升级,这里面的痛苦程度每一个基础架构团队成员都深有体会。
随之而来的就是应用使用的 SDK 版本差别非常大,生产环境同时跑着各种版本的 SDK,这种现象又会让新功能的迭代必须考虑各种兼容,就好像带着枷锁前进一般,这样随着不断迭代,会让代码维护非常困难,有些祖传逻辑更是一不小心就会掉坑里。
同时这种 “重” SDK 的开发模式,导致异构语言的治理能力非常薄弱,如果想为各种编程语言都提供一个功能完整且能持续迭代的 SDK 其中的成本可想而知。
2018 年的时候,Service Mesh 在国内持续火爆,这种架构理念旨在把服务治理能力跟业务解耦,让两者通过进程级别的通信方式进行交互。在这种架构模式下,服务治理能力从应用中剥离,运行在独立的进程中,迭代升级跟业务进程无关,这就可以让各种服务治理能力快速迭代,并且由于升级成本低,因此每个版本都可以全部升级,解决了历史包袱问题,同时 SDK 变 “轻” 直接降低了异构语言的治理门槛,再也不用为需要给各个语言开发相同服务治理能力的 SDK 头疼了。
Service Mesh(服务网格)被认为是下一代微服务架构,Service Mesh并没有给我们带来新的功能,它是用于解决其他工具已经解决过的服务网络调用、限流、熔断和监控等问题,只不过这次是在Cloud Native 的 kubernetes 环境下的实现。
Service Mesh 有如下几个特点:
- 应用程序间通讯的中间层
- 轻量级网络代理
- 应用程序无感知
- 解耦应用程序的重试/超时、监控、追踪和服务发现
目前几款流行的 Service Mesh 开源软件 Istio) 、 Linkerd)和MOSN都可以直接在kubernetes 中集成,其中Linkerd已经成为云原生计算基金会 CNCF (Cloud Native Computing Foundation) 成员。
Service Mesh之于微服务,就像TCP/IP之于互联网,TCP/IP为网络通信提供了面向连接的、可靠的、基于字节流的基础通信功能,你不再需要关心底层的重传、校验、流量控制、拥塞控制。
云原生
云原生是一种构建和运行应用程序的方法,是一套技术体系和方法论。云原生(CloudNative)是一个组合词,Cloud+Native。Cloud表示应用程序位于云中,而不是传统的数据中心;
Native表示应用程序从设计之初即考虑到云的环境,原生为云而设计,在云上以最佳姿势运行,充分利用和发挥云平台的弹性+分布式优势。Pivotal公司的Matt Stine于2013年首次提出云原生(CloudNative)的概念;
云原生架构总结为:微服务+容器化+DevOps+持续交付。CNCF,全称为Cloud Native Computing Foundation,中文译为“云原生计算基金会”。
容器技术(Docker)
简介
2010年一位年轻小伙子在美国旧金山成立了一家名叫【dotCloud】的公司, 开发了 Docker的核心技术,从此开启了容器技术的时代。
Docker是一个基于LXC的高级容器引擎。简单地说,docker是一个轻量级的虚拟化解决方案,或者说它是一个超轻量级的虚拟机(容器)。
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。当前应用的运行时也从物理机时代、虚拟机时代向容器化时代演进。
Docker入门请读:https://segmentfault.com/a/1190000016749553
理念
Docker 的理念为“Build, Ship and Run Any App, Anywhere”
架构
容器化解决了软件开发过程中一个令人非常头疼的问题,用一段对话描述:
测试人员:你这个功能有问题。
开发人员:我本地是好的啊。
开发人员编写代码,在自己本地环境测试完成后,将代码部署到测试或生产环境中,经常会遇到各种各样的问题。明明本地完美运行的代码为什么部署后出现很多 bug,原因有很多:不同的操作系统、不同的依赖库等,总结一句话就是因为本地环境和远程环境不一致。
容器化技术正好解决了这一关键问题,它将软件程序和运行的基础环境分开。开发人员编码完成后将程序打包到一个容器镜像中,镜像中详细列出了所依赖的环境,在不同的容器中运行标准化的镜像,从根本上解决了环境不一致的问题。
问题与挑战
在业务发展初期只有几个微服务,这时用 Docker 就足够了,但随着业务规模逐渐扩大,容器越来越多,运维人员的工作越来越复杂,这个时候就需要编排系统解救运维同学。尽管Docker为容器化的应用程序提供了开放标准,但随着容器越来越多出现了一系列新问题:
- 如何管理、协调和调度这些容器?
- 如何在升级应用程序时不会中断服务?
- 如何监视应用程序的运行状况?
- 如何批量重新启动容器里的程序?
为解决这些问题出现了很很多容器编排技术,现在业界比较流行的有:K8S、Mesos、Docker Swarm。
一个成熟的容器编排系统需要具备以下能力:
- 处理大量的容器
- 服务注册发现、负载均衡
- 鉴权和安全性
- 管理服务通信
- 多平台部署
容器编排(K8S)
简介
Kubernetes 是用于自动部署,扩展和管理容器化应用程序的开源系统。
K8S(Kubernetes)是Google研发的容器协调器,已捐赠给CNCF,现已开源。脱胎于Google内部久负盛名的大规模集群管理系统Borg,是Google在容器化基础设施领域十余年实践经验的沉淀和升华。
采用了非常优雅的软件工程设计和开源开放的态度,使得用户可以根据自己的使用场景、通过灵活插拔的方式,采用自定义的网络、存储、调度、监控、日志等模块。
Kubernetes在容器编排领域已经成为无可争辩的事实标准。
理念
自动化的容器部署、扩展和管理
架构
在K8S中,由Master控制节点和Worker节点共同构成一个集群,如下图所示:
Master
用于管理、监控K8S集群的节点,包含如下组件
- etcd:分布式KV数据库,使用Raft协议,用于保存集群中的相关数据,项目地址:https://github.com/etcd-io/etcd
- API Server:集群统一入口,以restful风格进行操作,同时交给etcd存储(是唯一能访问etcd的组件);提供认证、授权、访问控制、API注册和发现等机制,可以通过kubectl命令行工具,dashboard可视化面板,或者sdk等访问
- Scheduler:节点的调度,选择node节点应用部署
- Controller Manager:处理集群中常规后台任务,一个资源对应一个控制器,同时监控集群的状态,确保实际状态和最终状态一致
Worker(Node)
用于运行应用的节点,包含组件如下:
- kubelet:相当于Master派到node节点代表,管理本机容器,上报数据给API Server
- Container Runtime:容器运行时,K8S支持多个容器运行环境:Docker、Containerd、CRI-O、Rktlet以及任何实现Kubernetes CRI (容器运行环境接口) 的软件
- kube-proxy:实现服务(Service)抽象组件,屏蔽PodIP的变化和负载均衡
核心功能
K8S 提供功能如下:
服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。
自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。
自动完成装箱计算
Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。
自我修复
Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。
密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
核心概念
Pod
Pod本意是豌豆荚的意思,此处指的是K8S中资源调度的最小单位,豌豆荚里面的小豆子就像是Container,豌豆荚本身就像是一个Pod
- Pod是最小调度单元
- Pod里面会包含一个或多个容器(Container)
- Pod内的容器共享存储及网络,可通过localhost通信
Deployment
Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。一般大家用 Deployment 这个抽象来做应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。
- 定义一组Pod的副本数量,版本等
- 通过控制器维护Pod的数目
- 自动恢复失败的Pod
- 通过控制器以指定的策略控制版本
Service
Pod是不稳定的,IP是会变化的,所以需要一层抽象来屏蔽这种变化,这层抽象叫做Service
- 提供访问一个或者多个Pod实例稳定的访问地址
- 支持多种访问方式ClusterIP(对集群内部访问)NodePort(对集群外部访问)LoadBalancer(集群外部负载均衡)
Service的工作方式:
不论哪种,kube-proxy都通过watch的方式监控着kube-APIServer写入etcd中关于Pod的最新状态信息,它一旦检查到一个Pod资源被删除了 或 新建,它将立即将这些变化,反应再iptables 或 ipvs规则中,以便iptables和ipvs在调度Clinet Pod请求到Server Pod时,不会出现Server Pod不存在的情况。
userspace
Client Pod要访问Server Pod时,它先将请求发给本机内核空间中的service规则,由它再将请求,转给监听在指定套接字上的kube-proxy,kube-proxy处理完请求,并分发请求到指定Server Pod后,再将请求递交给内核空间中的service,由service将请求转给指定的Server Pod。由于其需要来回在用户空间和内核空间交互通信,因此效率很差。
iptables
此工作方式是直接由内核中的iptables规则,接受Client Pod的请求,并处理完成后,直接转发给指定ServerPod。
ipvs
它是直接有内核中的ipvs规则来接受Client Pod请求,并处理该请求,再有内核封包后,直接发给指定的Server Pod。
Volume
Volume就是存储卷,在Pod中可以声明卷来问访问文件系统,同时Volume也是一个抽象层,其具体的后端存储可以是本地存储、NFS网络存储、云存储(阿里云盘、AWS云盘、Google云盘等)、分布式存储(比如说像 ceph、GlusterFS )
- 声明在Pod中容器可以访问的文件系统。
- 可以被挂载在Pod中一个或多个容器的指定路径下。
- 支持多种后端储存,如NAS等。
Ingress
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由。对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。
Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。
下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:
Namespace
Namespace(命令空间)是用来做资源的逻辑隔离的,比如上面的Pod、Deployment、Service都属于资源,不同Namespace下资源可以重名。同一Namespace下资源名需唯一
- 一个集群内部的逻辑隔离机制(鉴权、资源等)
- 每个资源都属于一个Namespace
- 同一个Namespace中资源命名唯一
- 不同Namespace中资源可重名
问题与挑战
- 随着业务的不断发展,微服务的数量越来越多,微服务间的通信网络也变得十分复杂,微服务间的通信拓扑构成了一个巨大复杂的网络,治理难度加大。
- 对于流量管控功能较弱,服务间访问的管理如服务的熔断、限流、动态路由、调用链追踪等都不在K8S的范围。
- 使用门槛高,由于框架组件多,对于业务开发人员,就需要掌握较多非业务的知识,增加了业务开发人员的挑战。
- 跨语言是微服务的优势之一,它可以让不同语言编写的服务通过暴露接口服务调用的方式开放能力。而使用类库的微服务,将被类库支持的语言限制。
服务网格(Istio)
简介
现代应用程序通常被设计成微服务的分布式集合,每个服务执行一些离散的业务功能。服务网格是专门的基础设施层,包含了组成这类体系结构的微服务网络。 服务网格不仅描述了这个网络,而且还描述了分布式应用程序组件之间的交互。所有在服务之间传递的数据都由服务网格控制和路由。
随着分布式服务的部署——比如基于 Kubernetes 的系统——规模和复杂性的增长,它可能会变得更加难以理解和管理。需求可以包括发现、负载平衡、故障恢复、度量和监视。微服务体系结构通常还有更复杂的操作需求,比如 A/B 测试、canary 部署、速率限制、访问控制、加密和端到端身份验证。
服务到服务的通信使分布式应用成为可能。在应用程序集群内部和跨应用程序集群路由这种通信变得越来越复杂。 Istio 有助于减少这种复杂性,同时减轻开发团队的压力。
Istio简介
Istio 是一个开源服务网格,它透明地分层到现有的分布式应用程序上。 Istio 强大的特性提供了一种统一和更有效的方式来保护、连接和监视服务。 Istio 是实现负载平衡、服务到服务身份验证和监视的路径——只需要很少或不需要更改服务代码。它强大的控制平面带来了重要的特点,包括:
- 使用 TLS 加密、强身份认证和授权的集群内服务到服务的安全通信
- 自动负载均衡的 HTTP, gRPC, WebSocket,和 TCP 流量
- 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制
- 一个可插入的策略层和配置 API,支持访问控制、速率限制和配额
- 对集群内的所有流量(包括集群入口和出口)进行自动度量、日志和跟踪
Istio为微服务应用提供了一个完整的解决方案,可以以统一的方式去检测和管理微服务。同时,它还提供了管理流量、实施访问策略、收集数据等功能,而所有这些功能都对业务代码透明,即不需要修改业务代码就能实现。
有了Istio,就几乎可以不需要其他的微服务框架,也不需要自己去实现服务治理等功能,只要把网络层委托给Istio,它就能帮助完成这一系列的功能。简单来说,Istio就是一个提供了服务治理能力的服务网格,是Kubernetes的好帮手。
Istio的多样化特性可以让你高效地运行分布式微服务架构,并提供一种统一的方式来保护、连接和监控微服务。
理念
连接、安全、控制和可观测服务
Service Mesh 是微服务时代的 TCP/IP 协议。
架构
Istio的架构从逻辑上分成数据平面(Data Plane)和控制平面(Control Plane),Kubernetes的架构也具有相似的结构,分为控制节点和计算节点。毫无疑问,这样的设计可以很好地解耦各个功能组件。
- 数据平面:由一组和业务服务成对出现的Sidecar代理(Envoy)构成,它的主要功能是接管服务的进出流量,传递并控制服务和Mixer组件的所有网络通信(Mixer是一个策略和遥测数据的收集器,稍后会介绍)。
- 控制平面:主要包括了Pilot、Mixer、Citadel和Galley共4个组件,主要功能是通过配置和管理Sidecar代理来进行流量控制,并配置Mixer去执行策略和收集遥测数据(Telemetry)。
Istio的网络
核心功能
类别 | 功能 | 说明 |
---|---|---|
流量管理 | 请求路由 | A/B测试、金丝雀发布等,包括对集群出入口、及集群内部的流量的控制。比如某应用新版本发布,可以配置为5%的流量流向新版本,95%的给旧版本 |
流量转移 | 与上一条请求路由类似,可以平滑的将流量从旧版本转移到新版本上 | |
负载均衡 | 目前支持3种方式,轮询、随机和带权重的最少请求 | |
服务发现 | 带心跳的健康检查,失败率超标的Pod移出负载均衡池 | |
故障处理 | 超时、重发、熔断、上游并发请求或下游连接数限制等 | |
微调 | 支持用特殊的请求头参数,覆盖默认的超时、重发值 | |
故障注入 | 由Enovy在正常的集群中人为注入故障,比如TCP包损坏或延迟、HTTP错误码等,支持按百分比注入,比如给10%的流向服务A的请求包增加5秒延迟 | |
多重匹配 | 上述规则的配置,支持按多种条件匹配,且支持and或or的方式匹配多条规则 | |
Gateway | 接管集群入口的流量,替代了Ingress,从而对入口流量执行其他规则 | |
Service Entry | 接管集群内部访问外部服务的流量,从而对出口流量执行一些规则 | |
镜像 | 支持将特定的流量镜像到服务路径之外,而不影响主服务路径的正常执行 | |
安全 | 命名空间访问控制 | 支持配置某命名空间的所有或个别服务可以被其他命名空间访问 |
服务级别访问控制 | 允许或禁止访问某个服务 | |
双向TLS | HTTPS加密传输 | |
其他安全策略 | ||
策略 | 速率限制 | 比如限制每秒的请求次数 |
黑白名单 | 支持基于IP或属性的黑名单、白名单 | |
遥测 | 日志收集 | 支持将Prometheus、Jaeger等系统插入Mixer,从而完成数据的采集 |
指标采集 | ||
分布式追踪 |
流量治理
Istio的流量管理是通过Pilot和Envoy这两个组件实现的,将流量和基础设施进行了解耦。Pilot负责配置规则,并把规则分发到Envoy代理去实施;而Envoy按照规则执行各种流量管理的功能,比如动态请求路由,超时、重试和熔断,还可以通过故障注入来测试服务之间的容错能力。下面对这些具体的功能进行逐一介绍。
路由
不同需求开发在测试、发布阶段往往需要将特殊 pod 与基准服务 pod 进行联合调试,通过 virtual rule 和 destination rule 的配置规则,可以精确的将特性流量转到不同的微服务的指定特性 pod 上。
通过 istio 可以快速构建下图所示的基准环境、分支特性环境的通信过程,适应业务的需要。将请求动态路由到微服务的多个版本。
超时
可使用 Istio 在 Envoy 中设置请求超时时间,方便的控制应用间调用的超时时间。
重试
可设置请求重试次数与重试间隔时间,方便恢复服务。
熔断
熔断,是创建弹性微服务应用程序的重要模式。熔断能够使您的应用程序具备应对来自故障、潜在峰值和其他未知网络因素影响的能力。
流量镜像
流量镜像,也称为影子流量,镜像会将实时流量的副本发送到镜像服务。镜像流量发生在主服务的关键请求路径之外。
网关
服务间通信是通过Envoy代理进行的。同样,我们也可以在整个系统的入口和出口处部署代理,使得所有流入和流出的流量都由代理进行转发,而这两个负责入口和出口的代理就叫作入口网关和出口网关。它们相当于整个微服务应用的边界代理,把守着进入和流出服务网格的流量。图2-6展示了Ingress和Egress在请求流中的位置,通过设置Envoy代理,出入服务网格的流量也得到了控制。
入口网关(Ingress)
除了支持 Kubernetes Ingress,Istio还提供了另一种配置模式,Istio Gateway。与 Ingress
相比,Gateway
提供了更简单方便的自定义性和灵活性,并允许将 Istio 功能(例如监控和路由规则)应用于进入集群的流量。
出口网关(Egress)
由于默认情况下,来自Pod 的所有出站流量都会重定向到其 Sidecar 代理,集群外部 URL 的可访问性取决于代理的配置。默认情况下,Istio 将 Envoy 代理配置为允许访问未知服务的请求。尽管这为入门 Istio 带来了方便,但是,通常情况下,应该配置更严格的控制策略来管理和管制对外访问。
故障处理
Istio的故障处理都由Envoy代理完成。Envoy提供了一整套现成的故障处理机制,比如超时、重试、限流和熔断等。这些功能都能够以规则的形式进行动态配置,并且执行运行时修改。这使得服务具有更好的容错能力和弹性,并保证服务的稳定性。
故障注入
简单来说,故障注入就是在系统中人为地设置一些故障,来测试系统的稳定性和系统恢复的能力。比如为某服务设置一个延迟,使其长时间无响应,然后检测调用方是否能处理这种超时问题而自身不受影响(如及时终止对故障发生方的调用,避免自己受到影响且使故障扩展)。
Isito支持注入两种类型的故障:延迟和中断。延迟是模拟网络延迟或服务过载的情况;中断是模拟上游服务崩溃的情况,表现为HTTP的错误码和TCP连接失败。
服务管理
服务发现与负载均衡
服务发现的前提条件是具有服务注册的能力。目前Kubernetes这类容器编排平台也提供了服务注册的能力。Istio基于平台实现服务发现和负载均衡时,需要通过Pilot和Envoy协作完成,如图2-7所示。Pilot组件会从平台获取服务的注册信息,并提供服务发现的接口,Envoy获得这些信息并更新到自己的负载均衡池。Envoy会定期地对池中的实例进行健康检查,剔除离线的实例,保证服务信息的实时性。
可观测性
1.策略
在微服务应用中,除了流量管理以外,常常还需要进行一些额外的控制,比如限流(对调用频率、速率进行限制)、设置白名单和黑名单等。
Istio中的策略控制是依靠Mixer完成的。Envoy代理在每次网络请求时,都会调用Mixer进行预先检查,确定是否满足对应的策略。同时,Mixer又可以根据这些来自流量的数据,进行指标数据的采集和汇总,这就是遥测功能。
2.遥测(Telemetry)
遥测是工业上常用的一种技术,它是指从远程设备中收集数据,并传输到接收设备进行监测。在软件开发中,遥测的含义引申为对各种指标(metric)数据进行收集,并监控、分析这些指标,比如我们经常听到的BI数据分析。
Mixer的一大主要功能就是遥测。前面已经说过,Envoy代理会发送数据给Mixer,这就使得Mixer具有了数据收集的能力。在本章2.3节对Mixer的介绍中读者已经了解到Mixer的插件模型,也就是适配器。Mixer可以接入不同的后端设施作为适配器,来处理收集到的指标数据,比如日志分析系统、监控系统等。
核心组件
Envoy
Istio的核心原理,是网络代理,拦截下所有想拦截的TCP流量。通过对拦截下来的流量的解析和修改。
Envoy本质上是一个为面向服务的架构而设计的7层代理和通信总线。Envoy基于C++11开发而成,性能出色。Envoy包括但不限于以下功能:
• 动态服务发现
• 负载均衡
• TLS证书卸载
• HTTP/2 & gRPC 代理
• 熔断器
• 健康检查、基于百分比流量拆分的灰度发布
• 故障注入
• 丰富的度量指标
Pilot
Pilot是为我们提供Istio管理配置台,如智能路由(如A/B测试、金丝雀发布等)、弹性(超时、重发、熔断等)等功能的管理系统,它提供了一系列rules api,允许运维人员指定一系列高级的流量管理规则。Pilot负责将我们的配置转换并写入到每个sidecar(Enovy)。
简单来说,Pilot的主要任务有两个。
- 从平台(如Kubernetes)获取服务信息,完成服务发现。
- 获取Istio的各项配置,转换成Envoy代理可读的格式并分发。
Mixer
Mixer混合了各种策略以及后端数据采集或遥测系统的适配器,从而实现了前端Proxy与后端系统的隔离与汇合。Mixer是一个灵活的插件模型(无论是k8s还是Istio,实现上都很青睐于插件模型,这是一个很灵活的实现方式),它一端连着Envoy,同时我们可以将日志、监控、遥测等各种系统“插入”到Mixer的另一端中,从而得到我们想要的数据或结果。
Citadel
它管理着集群的密钥和证书,是集群的安全部门。典型的如果我们的服务是跨网络通讯(Istio允许我们建立一个安全的集群的集群网络),开发人员想省事懒得对通讯数据进行加解密和身份认证,这事就可以交给Citadel来处理了。更详细的说,Istio各个模块在安全性上分别扮演以下角色:
• Citadel,用于密钥和证书管理
• Sidecar和周边代理,实现客户端和服务器之间的安全通信
• Pilot,将授权策略和安全命名信息分发给代理
• Mixer,管理授权和审计
Galley
目前这个组件的作用是验证用户编写的Istio api配置。从官网的说法来看,后面这个组件会逐步接管获取配置、处理和分配的工作,比如从k8s的数据中心(etcd)获取集群信息的活,理论上应该交给Galley。Galley的定位类似于k8s的api server组件,提供集群内统一的配置信息接口,从而将用户配置的细节隔离开来。
其它组件
Kiali : 专用于 istio 系统的可视化的APM软件。
Jaeger: 是一个用于分布式链路追踪的开源软件,提供原生 OpenTracing
支持。
性能评估
官方给出了对最新版本V1.1.4的性能测试结果。在由1000个服务和2000个sidecar组成,每秒产生70000个网格范围内的请求的网格中,得到以下结果:
• Envoy在每秒处理 1000 请求的情况下,使用 0.6 个 vCPU 以及 50 MB 的内存。
• istio-telemetry在每秒1000个网格范围内的请求的情况下,消耗了0.6个vCPU。
• Pilot使用了 1 个 vCPU 以及 1.5 GB 的内存。
• Envoy在第 90 个百分位上增加了 8 毫秒的延迟。
问题与挑战
- 底层技术门槛大大增加,需要有更专业的基础平台的开发和运维来维护该复杂的平台,对人员知识量及专业度要求极高。
- 平台层若出现问题,调查难度较大,一般业务开发对网络、存储、安全等方面知识薄弱,好在平台一般都会提供各种工具协助。
- 业务开发人员也需要了解容器化或服务网格相关原理,对人员技能要求较高。
下一代云原生?
WASM
WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行 ,是一个可移植、体积小、加载快并且兼容 Web 的全新格式程序规范。WebAssembly 是由主流浏览器厂商组成的 W3C 社区团体 制定的一个新的规范。
高效:WebAssembly 有一套完整的语义,实际上 wasm 是体积小且加载快的二进制格式, 其目标就是充分发挥硬件能力以达到原生执行效率
安全:WebAssembly 运行在一个沙箱化的执行环境中,甚至可以在现有的 JavaScript 虚拟机中实现。在web环境中,WebAssembly将会严格遵守同源策略以及浏览器安全策略。
开放:WebAssembly 设计了一个非常规整的文本格式用来、调试、测试、实验、优化、学习、教学或者编写程序。可以以这种文本格式在web页面上查看wasm模块的源码。
标准:WebAssembly 在 web 中被设计成无版本、特性可测试、向后兼容的。WebAssembly 可以被 JavaScript 调用,进入 JavaScript 上下文,也可以像 Web API 一样调用浏览器的功能。当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。
Serverless
2019 年,Serverless 被 Gartner 称为最有潜力的云计算技术发展方向,并被赋予是必然性的发展趋势。从行业趋势看,Serverless 是云计算必经的一场革命。
Serverless ,被称为无服务器,可以解读为一种软件系统架构方法,通常称为 Serverless 架构。代表的是无需理解、管理服务器,按需使用,按使用付费的产品。Serverless 产品中,其中可以包含存储、计算等多种类型的产品,而典型的计算产品,就是云函数这种形态。
- 免运维:不需要管理服务器主机或者服务器进程。
- 弹性伸缩:根据负载进行自动规模伸缩与自动配置。伸缩范围零到无穷大。
- 按需付费:根据使用情况决定实际成本。
- 高可用:具备隐含的高可用性。
分布式应用运行时(Dapr)
Dapr 是 Distributed Application Runtime (分布式应用运行时)的缩写。是一种可移植的,事件驱动的运行时,用于构建跨云和边缘的分布式应用。号称:“Any language, any framework, anywhere”
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。