Ambassador和Istio:边缘代理和服务网格

小数 发表了文章 • 0 个评论 • 10 次浏览 • 3 小时前 • 来自相关话题

 作者:Richard Li

翻译:王斌


原文:Ambassador and Istio: Edge proxy and service mesh




Ambassador(https://www.getambassador.io)是一个 Kubernetes 原生的微服务 API 网关,它部署在网络边缘,将传入网络的流量路由到相应的内部服务(也被称为“南北”流量)。Istio 是微服务的服务网格,旨在将L7的可观察性、路由和弹性加入到从服务到服务的流量中(也被称为“东西”流量)。 Istio 和 Ambassador底层都使用了 Envoy。

Ambassador 和 Istio 可以一起部署在 Kubernetes 上。在这种部署方式下,来自集群外部的入站流量首先会经过 Ambassador,再由 Ambassador将流量路由到 Istio。Ambassador 主要处理认证、边缘路由、TLS终结,以及一些传统的边缘功能。

这种部署方式能让运维人员得到一个高性能、现代化的边缘服务(Ambassador)与最先进的服务网格(Istio)相结合的网络。虽然 Istio 本身就有一个基本入口控制器,但其功能非常有限,并且不支持身份验证以及 Ambassador所拥有的许多功能。







Ambassador和 Istio 协同工作

要让 Ambassador 与 Istio 协同工作其实很简单,我们以 Istio 的bookinfo示例来举个例子:





1. 首先,在 Kubernetes 上安装 Istio。

参考指南:https://istio.io/docs/setup/ku ... .html

2. 然后,安装 Bookinfo 示例应用。

参考指南:https://istio.io/docs/guides/bookinfo.html

3. 验证示例是否按预期正常工作。




Bookinfo 示例默认使用的是 Istio 的入口控制器,要使用 Ambassador,我们还需要进行以下操作:

1. 安装Ambassador。

参考指南:https://www.getambassador.io/u ... arted

2. 更新 bookinfo.yaml 清单以包含必要的Ambassador注解,操作如下:


apiVersion: v1
kind: Service
metadata:
 name: productpage
 labels:
   app: productpage
 annotations:
   getambassador.io/config: |
      ---
     apiVersion: ambassador/v0
     kind: Mapping
     name: productpage_mapping
     prefix: /productpage/
     rewrite: /productpage
     service: productpage:9080
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: productpage


输入kubectl delete ingress gateway命令,这将会删除bookinfo.yaml 清单中的入口控制器。此步骤为可选。




访问$AMBASSADOR_IP/productpage/,测试 Ambassador 是否已经起作用。可以通过 kubectl get services ambassador 命令来获取 Ambassador 的实际IP地址。







Sidecar注入

新版本的 Istio 支持 Kubernetes 初始化程序自动注入Istio Sidecar。有了Ambassador,你不再需要注入Istio Sidecar,因为 Ambassador 的 Envoy 实例将自动路由到相应的服务。如果你正在使用的是自动Sidecar注入方式,那么需要将 Istio 配置成不要自动为 Ambassador pods 注入Sidecar。具体操作方法可以参阅这份说明文档。

文档链接:https://istio.io/docs/setup/ku ... tions


点击阅读原文,即可查看文档



  查看全部
 作者:Richard Li

翻译:王斌


原文:Ambassador and Istio: Edge proxy and service mesh




Ambassador(https://www.getambassador.io)是一个 Kubernetes 原生的微服务 API 网关,它部署在网络边缘,将传入网络的流量路由到相应的内部服务(也被称为“南北”流量)。Istio 是微服务的服务网格,旨在将L7的可观察性、路由和弹性加入到从服务到服务的流量中(也被称为“东西”流量)。 Istio 和 Ambassador底层都使用了 Envoy。

Ambassador 和 Istio 可以一起部署在 Kubernetes 上。在这种部署方式下,来自集群外部的入站流量首先会经过 Ambassador,再由 Ambassador将流量路由到 Istio。Ambassador 主要处理认证、边缘路由、TLS终结,以及一些传统的边缘功能。

这种部署方式能让运维人员得到一个高性能、现代化的边缘服务(Ambassador)与最先进的服务网格(Istio)相结合的网络。虽然 Istio 本身就有一个基本入口控制器,但其功能非常有限,并且不支持身份验证以及 Ambassador所拥有的许多功能。







Ambassador和 Istio 协同工作

要让 Ambassador 与 Istio 协同工作其实很简单,我们以 Istio 的bookinfo示例来举个例子:





1. 首先,在 Kubernetes 上安装 Istio。

参考指南:https://istio.io/docs/setup/ku ... .html

2. 然后,安装 Bookinfo 示例应用。

参考指南:https://istio.io/docs/guides/bookinfo.html

3. 验证示例是否按预期正常工作。




Bookinfo 示例默认使用的是 Istio 的入口控制器,要使用 Ambassador,我们还需要进行以下操作:

1. 安装Ambassador。

参考指南:https://www.getambassador.io/u ... arted

2. 更新 bookinfo.yaml 清单以包含必要的Ambassador注解,操作如下:


apiVersion: v1
kind: Service
metadata:
 name: productpage
 labels:
   app: productpage
 annotations:
   getambassador.io/config: |
      ---
     apiVersion: ambassador/v0
     kind: Mapping
     name: productpage_mapping
     prefix: /productpage/
     rewrite: /productpage
     service: productpage:9080
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: productpage


输入kubectl delete ingress gateway命令,这将会删除bookinfo.yaml 清单中的入口控制器。此步骤为可选。




访问$AMBASSADOR_IP/productpage/,测试 Ambassador 是否已经起作用。可以通过 kubectl get services ambassador 命令来获取 Ambassador 的实际IP地址。







Sidecar注入

新版本的 Istio 支持 Kubernetes 初始化程序自动注入Istio Sidecar。有了Ambassador,你不再需要注入Istio Sidecar,因为 Ambassador 的 Envoy 实例将自动路由到相应的服务。如果你正在使用的是自动Sidecar注入方式,那么需要将 Istio 配置成不要自动为 Ambassador pods 注入Sidecar。具体操作方法可以参阅这份说明文档。

文档链接:https://istio.io/docs/setup/ku ... tions


点击阅读原文,即可查看文档



 

3种Ansible Roles分步指南,教你如何使用Weave Scope探索微服务通信和服务网格

小数 发表了文章 • 0 个评论 • 72 次浏览 • 6 天前 • 来自相关话题

 
 作者:Roger CARHUATOCTO 

翻译:张晔

原文:Using Weave Scope to explore Microservices Communication and Service Mesh 

原文地址:https://holisticsecurity.io/20 ... erral



如果你正在使用ESB、消息代理、BPMS、SOA或微服务,就会注意到,你正在以不同的方式解决相同的独立应用程序问题,因为它们都是不同类型的分布式应用程序。这些问题是:

用户管理、认证和授权

日志记录、调试、监视和报警

集群、高可用性、负载均衡等


什么是服务网格

服务网格是另一种类型的分布式应用程序,在这其中服务、微服务或者APIs都是相互关联的。







基于容器化和编排平台的服务网格

一般来说,基于微服务和/或APIs的服务网格是由多个容器来部署的,这些容器是用Kubernetes 来编排的。在这种情况下,我们需要面对新的挑战,比如临时基础设施、零信任网络、网络分割或者采用新的方法来测试、监控、部署、操作等等。这就是我们所说的DevOps。



容器部署模式

与 EIP (企业集成模式)和软件设计模式一样,在容器化的平台上部署服务网格也有一定的模式。Google、Microsoft、Netflix 等建议使用一些模式来实现上述问题的解决方案。


例如,Google解释了三种很好的模式:
 
Sidecar模式Ambassador模式适配器模式

它们都支持基于容器的服务网格的构建。欲知详情,请阅读:

《基于容器的分布式系统的设计模式》by 布伦丹·伯恩斯&大卫·奥本海默

PDF下载:https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45406.pdf 



什么是Istio

摘录自 Istio.io :

Istio是一个开放的平台,提供了一种统一的方式来连接、管理微服务,保证微服务安全。Istio支持管理微服务之间的交通流、执行访问策略和聚合遥测数据,这些都不需要对微服务代码进行更改。

Istio 给你:
自动负载平衡HTTP、gRPC WebSocket,TCP流量;
 
细粒度控制的交通行为与丰富的路由规则,重试,故障转移,故障注入;
 
可插入策略层和配置API支持访问控制,速度和配额限制;
 
自动度量、日志和跟踪所有流量在一个集群,包括集群入口和出口;


在集群中的服务之间,通过强身份断言,实现服务对服务的安全认证。







为什么使用Istio

    摘录自 Istio.io :

Istio解决了开发人员和运维人员在向分布式微服务架构过渡时所面临的诸多挑战。服务网格作为一个术语,通常用于描述组成此类应用程序的微服务网络和它们之间的交互。随着服务网格的规模和复杂性的增长,它会变得越来越难以理解和管理。它的需求包括发现、负载均衡、故障恢复、度量和监控,以及更复杂的操作需求,如A/B测试、canary发布、速率限制、访问控制和端到端验证。


Istio提供了一个完整的解决方案,通过行为洞察和对整个服务网格的操作控制,来满足微服务应用程序的不同需求。它在服务网络中统一提供了许多关键功能:
 
交通管理。控制服务之间的流量和API调用,使调用更加可靠,并使网络在面对不利条件时更加健壮。
 
可观测性。了解服务之间的依赖关系和它们之间的流量之间的关系,提供快速识别问题的能力。
 
政策执行。将组织策略应用于服务之间的交互,确保执行访问策略,并且在用户中公平地分配资源。策略更改不必通过更改应用程序代码来实现,而是通过配置网格。
 
标识和安全服务。在网格中提供可验证身份的服务,并提供保护服务流量的能力,因为它在不同程度的trustability网络中流动。


基于容器的服务网格与Istio

为了轻松得到一个极简 OpenShift 集群,我创建了3个 Ansible Roles--Weave Scope 、Istio 和 BookInfo 应用(基于容器的 API 和微服务) 来理解我们必须面对的挑战。3个 Ansible Roles是:

1. Minishift Ansible Role

    地址:https://github.com/chilcano/ansible-role-minishift

在虚拟机中通过 Minishift 获得 OpenShift 集群。


2. Weave Scope Ansible Role

   地址:https://github.com/chilcano/an ... scope

在 OpenShift 中部署本地运行的 Weave Scope 应用。


3. Istio Ansible Role

    地址:https://github.com/chilcano/ansible-role-istio

在本地运行的 OpenShift 中部署和配置 Istio,部署 BookInfo 应用,并注入 Sidecar 代理(Envoy Proxy)。


我还创建了一些示例,可以测试并快速尝试上述角色的环境。

Weave Scope 将在这里发挥重要作用,它能够对整个基于容器的服务网格进行监控、可视化、故障诊断和轻松管理。

一旦完成了分步指南,你将获得下一个:

(操作步骤详见:https://github.com/chilcano/an ... urity)






































 希望这篇文章对你能有所帮助。 查看全部

微信图片_20180116164346.jpg

 
 作者:Roger CARHUATOCTO 

翻译:张晔

原文:Using Weave Scope to explore Microservices Communication and Service Mesh 

原文地址:https://holisticsecurity.io/20 ... erral



如果你正在使用ESB、消息代理、BPMS、SOA或微服务,就会注意到,你正在以不同的方式解决相同的独立应用程序问题,因为它们都是不同类型的分布式应用程序。这些问题是:

用户管理、认证和授权

日志记录、调试、监视和报警

集群、高可用性、负载均衡等


什么是服务网格

服务网格是另一种类型的分布式应用程序,在这其中服务、微服务或者APIs都是相互关联的。

1.png



基于容器化和编排平台的服务网格

一般来说,基于微服务和/或APIs的服务网格是由多个容器来部署的,这些容器是用Kubernetes 来编排的。在这种情况下,我们需要面对新的挑战,比如临时基础设施、零信任网络、网络分割或者采用新的方法来测试、监控、部署、操作等等。这就是我们所说的DevOps。



容器部署模式

与 EIP (企业集成模式)和软件设计模式一样,在容器化的平台上部署服务网格也有一定的模式。Google、Microsoft、Netflix 等建议使用一些模式来实现上述问题的解决方案。


例如,Google解释了三种很好的模式:
 
  • Sidecar模式
  • Ambassador模式
  • 适配器模式


它们都支持基于容器的服务网格的构建。欲知详情,请阅读:

《基于容器的分布式系统的设计模式》by 布伦丹·伯恩斯&大卫·奥本海默

PDF下载:https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45406.pdf 



什么是Istio

摘录自 Istio.io :

Istio是一个开放的平台,提供了一种统一的方式来连接、管理微服务,保证微服务安全。Istio支持管理微服务之间的交通流、执行访问策略和聚合遥测数据,这些都不需要对微服务代码进行更改。

Istio 给你:
  • 自动负载平衡HTTP、gRPC WebSocket,TCP流量;

 
  • 细粒度控制的交通行为与丰富的路由规则,重试,故障转移,故障注入;

 
  • 可插入策略层和配置API支持访问控制,速度和配额限制;

 
  • 自动度量、日志和跟踪所有流量在一个集群,包括集群入口和出口;



在集群中的服务之间,通过强身份断言,实现服务对服务的安全认证。

2.png



为什么使用Istio

    摘录自 Istio.io :

Istio解决了开发人员和运维人员在向分布式微服务架构过渡时所面临的诸多挑战。服务网格作为一个术语,通常用于描述组成此类应用程序的微服务网络和它们之间的交互。随着服务网格的规模和复杂性的增长,它会变得越来越难以理解和管理。它的需求包括发现、负载均衡、故障恢复、度量和监控,以及更复杂的操作需求,如A/B测试、canary发布、速率限制、访问控制和端到端验证。


Istio提供了一个完整的解决方案,通过行为洞察和对整个服务网格的操作控制,来满足微服务应用程序的不同需求。它在服务网络中统一提供了许多关键功能:
 
  • 交通管理。控制服务之间的流量和API调用,使调用更加可靠,并使网络在面对不利条件时更加健壮。

 
  • 可观测性。了解服务之间的依赖关系和它们之间的流量之间的关系,提供快速识别问题的能力。

 
  • 政策执行。将组织策略应用于服务之间的交互,确保执行访问策略,并且在用户中公平地分配资源。策略更改不必通过更改应用程序代码来实现,而是通过配置网格。

 
  • 标识和安全服务。在网格中提供可验证身份的服务,并提供保护服务流量的能力,因为它在不同程度的trustability网络中流动。



基于容器的服务网格与Istio

为了轻松得到一个极简 OpenShift 集群,我创建了3个 Ansible Roles--Weave Scope 、Istio 和 BookInfo 应用(基于容器的 API 和微服务) 来理解我们必须面对的挑战。3个 Ansible Roles是:

1. Minishift Ansible Role

    地址:https://github.com/chilcano/ansible-role-minishift

在虚拟机中通过 Minishift 获得 OpenShift 集群。


2. Weave Scope Ansible Role

   地址:https://github.com/chilcano/an ... scope

在 OpenShift 中部署本地运行的 Weave Scope 应用。


3. Istio Ansible Role

    地址:https://github.com/chilcano/ansible-role-istio

在本地运行的 OpenShift 中部署和配置 Istio,部署 BookInfo 应用,并注入 Sidecar 代理(Envoy Proxy)。


我还创建了一些示例,可以测试并快速尝试上述角色的环境。

Weave Scope 将在这里发挥重要作用,它能够对整个基于容器的服务网格进行监控、可视化、故障诊断和轻松管理。

一旦完成了分步指南,你将获得下一个:

(操作步骤详见:https://github.com/chilcano/an ... urity



3.png


4.png


5.png


6.png


7.png


8.png


9.png


 希望这篇文章对你能有所帮助。

使用 Istio治理微服务入门

小数 发表了文章 • 5 个评论 • 634 次浏览 • 2018-01-09 15:17 • 来自相关话题

作者:Tony Bai
 





 
近两年微服务架构流行,主流互联网厂商内部都已经微服务化,初创企业虽然技术积淀不行,但也通过各种开源工具拥抱微服务。再加上容器技术赋能,Kubernetes又添了一把火,微服务架构已然成为当前软件架构设计的首选。


但微服务化易弄,服务治理难搞!
 
 
微服务的“痛点”

微服务化没有统一标准,多数是进行业务领域垂直切分,业务按一定的粒度划分职责,并形成清晰、职责单一的服务接口,这样每一块规划为一个微服务。微服务之间的通信方案相对成熟,开源领域选择较多的有RPC或RESTful API方案,比如:gRPC、apache thrift等。这些方案多偏重于数据如何打包、传输与解包,对服务治理的内容涉及甚少。


微服务治理是头疼的事,也是微服务架构中的痛点。治理这个词有多元含义,很难下达一个精确定义,这里可以像小学二年级学生那样列出治理的诸多近义词:管理、控制、规则、掌控、监督、支配、规定、统治等。对于微服务而言,治理体现在以下诸多方面:
服务注册与发现 身份验证与授权 服务的伸缩控制 反向代理与负载均衡 路由控制 流量切换 日志管理 性能度量、监控与调优 分布式跟踪 过载保护 服务降级 服务部署与版本升级策略支持 错误处理

… …

从微服务治理角度来说,微服务其实是一个“大系统”,要想将这个大系统全部落地,绝非易事,尤其是之前尚没有一种特别优雅的技术方案。多数方案(比如:dubbo、go-kit等。)都或多或少地对应用逻辑有一定的侵入性,让业务开发人员不能只focus到业务本身,还要关心那些“治理”逻辑。并且市面上内置了微服务治理逻辑的框架较少,且很多编程语言相关。这种情况下,大厂多选择自研或基于某个框架改造,小厂一般只能“东拼西凑”一些“半成品”凑合着使用,就这样微服务也走过了若干年。


Service Mesh横空出世,Istio带来“福音”

我不知道在没有TCP/IP协议的年代,主机和主机之间的应用通信时是否需要应用关心底层通信协议实现逻辑。但是和TCP/IP诞生的思想类似,在微服务使用多年后,人们发现需要独立地抽象出一层逻辑网络,专门用于“微服务通信与治理策略的落地”,让应用只关心业务,把服务治理的事情全部交由“这一层”去处理。





图:传统微服务之间的微服务治理逻辑的位置
 





图:微服务治理逻辑被独立出来之后的位置
 
由“Service Govern Logic”这一层组成的逻辑网络被定义为Service Mesh,每个微服务都包含一个Service Mesh的端点。


“Service Mesh”概念还非常年轻,这个词在国内被翻译为“服务网格”或“服务啮合层”,我们这里就用Service Mesh这个英文词。这里摘录一下 ServiceMesh 中文网社区上的一篇名为“年度盘点2017之Service Mesh:群雄逐鹿烽烟起”的文章中对Service Mesh概念的回顾:


在 2016 年年初,“Service Mesh”还只是 Buoyant 公司的内部词汇,而之后,它开始逐步走向社区:

2016 年 9 月 29 日在 SF Microservices 上,“Service Mesh”这个词汇第一次在公开场合被使用。这标志着“Service Mesh”这个词,从 Buoyant 公司走向社区。

2016 年 10 月,Alex Leong 开始在 Buoyant 公司的官方 Blog 中连载系列文章“A Service Mesh for Kubernetes”。随着“The Services must Mesh”口号的喊出,Buoyant 和 Linkerd 开始 Service Mesh 概念的布道。

2017 年 4 月 25 日,William Morgan 发布博文“What’s a service mesh? And why do I need one?”。正式给 Service Mesh 做了一个权威定义。

而Service Mesh真正引起大家关注要源于Istio项目的开源发布。为什么呢?个人觉得还是因为“爹好”!Istio项目由Google、IBM共同合作创建,lyft公司贡献了Envoy项目将作为Istio Service Mesh的data panel。Google、IBM的影响力让Service Mesh概念迅速传播,同时也让大家认识到了Istio项目在Service Mesh领域的重要性,于是纷纷选择积极支持并将自己的产品或项目与Istio项目集成。


Istio项目是Service Mesh概念的最新实现,旨在所有主流集群管理平台上提供Service Mesh层,初期以实现Kubernetes上的服务治理层为目标。它由控制平面和数据平面组成(是不是感觉和SDN的设计理念相似啊)。控制平面由Go语言实现,包括pilot、mixer、auth三个组件;数据平面功能暂由Envoy在pod中以Sidecar的部署形式提供。下面是官方的架构图:





图:Istio架构图(来自官网)
Sidecar中Envoy代理了pod中真正业务container的所有进出流量,并对这些流量按照控制平面设定的“治理逻辑”进行处理。而这一切对pod中的业务应用是透明的,开发人员可以专心于业务逻辑,而无需再关心微服务治理的逻辑。Istio代表的Service Mesh的设计理念被认为是下一代“微服务统一框架”,甚至有人认为是微服务框架演化的终点。

Istio于2017 年 5 月 24 日发布了0.1 release 版本,截至目前为止Istio的版本更新到v0.4.0,演进速度相当快,不过目前依然不要用于生产环境,至少要等到1.0版本发布吧。但对于Istio的早期接纳者而言,现在正是深入研究Istio的好时机。在本篇的接下来内容中,我们将带领大家感性的认识一下Istio,入个门儿。
 
 
Istio安装
istio目前支持最好的就是kubernetes了,因此我们的实验环境就定在kubernetes上。至于版本,Istio当前最新版本为0.4.0,这个版本据说要K8S 1.7.4及以上版本用起来才不会发生小毛病:)。我的K8S集群是v1.7.6版本的,恰好满足条件。下面是安装过程:(Node上的os是ubuntu 16.04)
# wget -c https://github.com/istio/istio ... ar.gz



解压后,进入istio-0.4.0目录,



# ls -F

bin/  install/  istio.VERSION  LICENSE  README.md  samples/



# cat istio.VERSION

# DO NOT EDIT THIS FILE MANUALLY instead use

# install/updateVersion.sh (see install/README.md)

export CA_HUB="docker.io/istio"

export CA_TAG="0.4.0"

export MIXER_HUB="docker.io/istio"

export MIXER_TAG="0.4.0"

export PILOT_HUB="docker.io/istio"

export PILOT_TAG="0.4.0"

export ISTIOCTL_URL="https://storage.googleapis.com ... ot%3B

export PROXY_TAG="0.4.0"

export ISTIO_NAMESPACE="istio-system"

export AUTH_DEBIAN_URL="https://storage.googleapis.com ... ot%3B

export PILOT_DEBIAN_URL="https://storage.googleapis.com ... ot%3B

export PROXY_DEBIAN_URL="https://storage.googleapis.com ... ot%3B

export FORTIO_HUB="docker.io/istio"

export FORTIO_TAG="0.4.2"



# cd install/kubernetes



我们先不用auth功能,因此使用istio.yaml这个文件进行istio组件安装:



# kubectl apply -f istio.yaml

namespace "istio-system" created

clusterrole "istio-pilot-istio-system" created

clusterrole "istio-initializer-istio-system" created

clusterrole "istio-mixer-istio-system" created

clusterrole "istio-ca-istio-system" created

clusterrole "istio-sidecar-istio-system" created

clusterrolebinding "istio-pilot-admin-role-binding-istio-system" created

clusterrolebinding "istio-initializer-admin-role-binding-istio-system" created

clusterrolebinding "istio-ca-role-binding-istio-system" created

clusterrolebinding "istio-ingress-admin-role-binding-istio-system" created

clusterrolebinding "istio-sidecar-role-binding-istio-system" created

clusterrolebinding "istio-mixer-admin-role-binding-istio-system" created

configmap "istio-mixer" created

service "istio-mixer" created

serviceaccount "istio-mixer-service-account" created

deployment "istio-mixer" created

customresourcedefinition "rules.config.istio.io" created

customresourcedefinition "attributemanifests.config.istio.io" created

... ...

customresourcedefinition "reportnothings.config.istio.io" created

attributemanifest "istioproxy" created

attributemanifest "kubernetes" created

stdio "handler" created

logentry "accesslog" created

rule "stdio" created

metric "requestcount" created

metric "requestduration" created

metric "requestsize" created

metric "responsesize" created

metric "tcpbytesent" created

metric "tcpbytereceived" created

prometheus "handler" created

rule "promhttp" created

rule "promtcp" created

kubernetesenv "handler" created

rule "kubeattrgenrulerule" created

kubernetes "attributes" created

configmap "istio" created

customresourcedefinition "destinationpolicies.config.istio.io" created

customresourcedefinition "egressrules.config.istio.io" created

customresourcedefinition "routerules.config.istio.io" created

service "istio-pilot" created

serviceaccount "istio-pilot-service-account" created

deployment "istio-pilot" created

service "istio-ingress" created

serviceaccount "istio-ingress-service-account" created

deployment "istio-ingress" created

serviceaccount "istio-ca-service-account" created

deployment "istio-ca" created
 
注:我还曾在K8S v1.7.3上安装过istio 0.3.0版本,但在创建组件时会报下面错误(这个错误可能会导致后续addon安装后工作不正常):
unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric
安装后,我们在istio-system这个namespace下会看到如下pod和service在运行(由于istio的各个组件的image size都不小,因此pod状态变为running需要一丢丢时间,耐心等待)
# kubectl get pods -n istio-system

NAME                             READY     STATUS    RESTARTS   AGE

istio-ca-1363003450-jskp5        1/1       Running   0          3d

istio-ingress-1005666339-c7776   1/1       Running   4          3d

istio-mixer-465004155-twhxq      3/3       Running   24         3d

istio-pilot-1861292947-6v37w     2/2       Running   18         3d



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                   AGE

istio-ingress   10.98.10.87      <pending>     80:31759/TCP,443:25804/TCP                         4d

istio-mixer     10.109.244.155   <none>        9091/TCP,15004/TCP,9093/TCP,9094/TCP,9102/TCP,9125/UDP,42422/TCP   4d

istio-pilot     10.105.80.55     <none>        15003/TCP,443/TCP                                              4d
 
istio安装成功!
 
 
服务治理策略验证
 
接下来我们来用几个例子验证一下Istio在服务治理方面的能力!(istio自带一些完整的例子,比如bookinfo,用于验证服务治理的能力,但这里先不打算用这些例子)

验证环境和拓扑我们先来看一下验证环境的示意图:





 
我们看到在Service Mesh中部署了两个service: server_a和service_b,前者调用后者完成某项业务,后者则调用外部服务完成业务逻辑。




service_a: 模拟pay服务,在收到client请求后,进行pay处理,并将处理结果通过service_b提供的msg notify服务下发给user。该服务的endpoint为/pay;

service_b: 模拟notify服务,在收到service_a请求后,将message转发给external service,完成notify逻辑。该服务的endpoint为/notify;

external service: 位于service mesh之外。

client:我们使用curl模拟。
 





 
我们先来部署service_a和service_b的v0.1版本:
以service_a的部署为例, service_a的deployment文件如下:
 
//svca-v0.1.yaml

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

 name: svca

spec:

 replicas: 1

 template:

   metadata:

     labels:

       app: svca

       version: v0.1

   spec:

     containers:

     - name: svca

       image: docker.io/bigwhite/istio-demo-svca:v0.1

       imagePullPolicy: Always

---

apiVersion: v1

kind: Service

metadata:

 name: svca

 labels:

   app: svca

spec:

 ports:

 - port: 80

   targetPort: 8080

   protocol: TCP

 selector:

   app: svca
 
注意,我们部署service_a时不能直接使用kubectl apply -f svca-v0.1.yaml,而是要apply经过istioctl(需将Istio安装目录下的bin放入PATH)处理过的yaml,以注入sidecar容器。当然也可以配置为自动为每个k8s启动的pod注入sidecar,但我们这里没有使用自动注入。我们执行下面命令:
 
# kubectl apply -f <(istioctl kube-inject -f svca-v0.1.yaml)

deployment "svca" created

service "svca" created



# kubectl get pods

NAME                               READY     STATUS    RESTARTS   AGE

svca-1997590752-tpwjf              2/2       Running   0          2m
 
 
同样的方法,我们来创建svcb:v0.1:
 
# kubectl apply -f <(istioctl kube-inject -f svcb-v0.1.yaml)

deployment "svcb" created

service "svcb" created
 
 
我们看到istio向每个pod中插入一个sidecar container,这个就是前面说的envoy,只不过container名字为istio-proxy。

接下来,我们把那个external service启动起来:
# nohup ./msgd > 1.log & 2>&1

[1] 9423
 
实验环境ok了。下面我们来验证一下业务是否是通的。
 

egress rule
按照之前我们的设定,我们使用curl去访问service_a服务的/pay端点,我们查看一下svca服务的ip和端口:
# kubectl get svc

NAME               CLUSTER-IP       EXTERNAL-IP   PORT(S)

svca               10.105.38.238    <none>        80/TCP                                         9h

svcb               10.105.119.194   <none>        80/TCP                                         9h
 
我们访问一下svca服务,svca的服务地址可以通过kubectl get svc查到:

# curl {svca_ip}/pay

查看svca和svcb的日志:
//service_a的日志:



service_a:v0.1 is serving the request...

service_a:v0.1 pays ok

&{500 Internal Server Error 500 HTTP/1.1 1 1 map[X-Content-Type-Options:[nosniff] Date:[Tue, 02 Jan 2018 15:41:50 GMT] Content-Length:[66] Content-Type:[text/plain; charset=utf-8]] 0xc420058d40 66  false false map 0xc4200eaf00 <nil>}

service_a:v0.1 notify customer ok



// service_b的日志:

&{GET /notify?msg=service_a:v0.1-pays-ok HTTP/1.1 1 1 map[User-Agent:[Go-http-client/1.1] Accept-Encoding:[gzip]] {} <nil> 0  false svcb map map <nil> map 127.0.0.1:58778 /notify?msg=service_a:v0.1-pays-ok <nil> <nil> <nil> 0xc4200fa3c0}

service_b:v0.1 is serving the request...

service_b:v0.1 send msg error: Get http://10.100.35.27:9997/send% ... s-ok: EOF
我们看到service_a和service_b都返回了错误日志(注意:go http get方法对于non-2xx response不会返回错误,我们只是看到了response中的500状态码才意识到错误的存在)。其中源头在service_b,原因是其连不上那个external service!那么为什么连不上external service呢?这是由于缺省情况下,启用了Istio的服务是无法访问外部URL的,这是因为Pod中的iptables把所有外发传输都转向到了Sidecar代理,而这一代理只处理集群内的访问目标。因此位于service mesh内的服务svcb无法访问外部的服务(msgd),我们需要显式的添加egressrule规则:

我们创建一个允许svcb访问外部特定服务的EgressRule:
//rules/enable-svcb-engress-rule.yaml



apiVersion: config.istio.io/v1alpha2

kind: EgressRule

metadata:

 name: enable-svcb-engress-rule

spec:

 destination:

   service: 10.100.35.27

 ports:

   - port: 9997

     protocol: http
 
使规则生效:

# istioctl create -f enable-svcb-engress-rule.yaml

Created config egress-rule/default/enable-svcb-engress-rule at revision 30031258


这时你再尝试curl svca,我们可以看到msgd的日志中出现了下面的内容:
 

2018/01/02 23:58:16 &{GET /send?msg=service_a:v0.1-pays-ok HTTP/1.1 1 1 map[X-Ot-Span-Context:[2157e7ffb8105330;2157e7ffb8105330;0000000000000000] Content-Length:[0] User-Agent:[Go-http-client/1.1] X-Forwarded-Proto:[http] X-Request-Id:[13c3af6e-2f52-993d-905f-aa6aa4b57e2d] X-Envoy-Decorator-Operation:[default-route] X-B3-Spanid:[2157e7ffb8105330] X-B3-Sampled:[1] Accept-Encoding:[gzip] X-B3-Traceid:[2157e7ffb8105330] X-Istio-Attributes:[Ch8KCXNvdXJjZS5pcBISMhAAAAAAAAAAAAAA//8KLgAMCjoKCnNvdXJjZS51aWQSLBIqa3ViZXJuZXRlczovL3N2Y2ItMjAwODk3Mzc2OS1ncTBsaC5kZWZhdWx0]] {} <nil> 0 false 10.100.35.27:9997 map map <nil> map 10.100.35.28:38188 /send?msg=service_a:v0.1-pays-ok <nil> <nil> <nil> 0xc4200584c0} 2018/01/02 23:58:16 Msgd is serving the request... 2018/01/02 23:58:16 Msgd recv msg ok, msg= service_a:v0.1-pays-ok
 
 
说明Svcb到外部服务的通信被打通了!

迁移流量到新版本svcb:v0.2我们经常有这样的需求,当svcb运行一段时间后,svcb添加了新feature,版本要升级到v0.2了,这时我们会部署svcb:v0.2,并将流量逐步切到v0.2上。

我们先来部署一下svcb:v0.2:
// svcb-v0.2.yaml

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

 name: svcb-v0.2

spec:

 replicas: 1

 template:

   metadata:

     labels:

       app: svcb

       version: v0.2

   spec:

     containers:

     - name: svcb

       image: docker.io/bigwhite/istio-demo-svcb:v0.2

       imagePullPolicy: Always
我们可以看到,服务名不变,但版本的label变成了v0.2,我们来执行这次部署:
 
# kubectl apply -f <(istioctl kube-inject -f svcb-v0.2.yaml)

deployment "svcb-v0.2" created



# kubectl get pods

NAME                               READY     STATUS    RESTARTS   AGE

svca-1997590752-pq9zg              2/2       Running   0          9h

svcb-2008973769-gq0lh              2/2       Running   0          9h

svcb-v0.2-3233505404-0g55w         2/2       Running   0          1m
 
svcb服务下又增加了一个endpoint:
# kubectl describe svc/svcb



.... ...

Selector:        app=svcb

Type:            ClusterIP

IP:            10.105.119.194

Port:            <unset>    80/TCP

Endpoints:        10.40.0.28:8080,10.46.0.12:8080

... ...
 
此时,如果按照K8S的调度方式,v0.1和v0.2版本的两个svcb pod应该1:1均衡地承载流量。为了方便查看流量分布,我们将每个版本的svcb的pod副本数量都扩展为2个(replicas: 2),这样service mesh中一共会有4个 svcb endpoints。

通过curl访问svca注入流量后,我们发现流量都集中在一个svcb:v0.2的pod上,并且长时间没有变化。我们通过下面的route rule规则来尝试将流量在svcb:v0.1和svcb:v0.2之间1:1均衡:
 
// route-rules-svcb-v0.2-50.yaml

apiVersion: config.istio.io/v1alpha2

kind: RouteRule

metadata:

 name: route-rules-svcb

spec:

 destination:

   name: svcb

 precedence: 1

 route:

 - labels:

     version: v0.1

   weight: 50

 - labels:

     version: v0.2

   weight: 50



# istioctl create -f route-rules-svcb-v0.2-50.yaml

Created config route-rule/default/route-rules-svcb at revision 30080638
 
 
按照istio文档中的说法,这个规则的生效需要一些时间。之后我们注入流量,发现流量切换到svcb:v0.1的一个pod上去了,并且很长一段时间不曾变化,未均衡到svcb:v0.2上去。

我们更新一下route rule,将流量全部切到svcb:v0.2上去:
 

//route-rules-svcb-v0.2-100.yaml apiVersion: config.istio.io/v1alpha2 kind: RouteRule metadata:  name: route-rules-svcb spec:  destination:    name: svcb  precedence: 1  route:  - labels:      version: v0.2    weight: 100 # istioctl replace -f route-rules-svcb-v0.2-100.yaml Updated config route-rule/default/route-rules-svcb to revision 30082944
 
我们用Istio的replace命令更新了规则:route-rules-svcb。更新后,再次注入流量,这回流量重新集中在svcb:v0.2的一个pod上了,再过一段时间另外一个svcb:v0.2的pod上才有了一些流量。但svcb:v0.1上不再有流量,这个切换是成功的。


在K8S的service的负载均衡中,K8S就利用了iptables的概率转发(random –probability 0.5),因此这种流量均衡并非是精确的,只有在长时间大量流量经过后,才能看到流量的分布与设定的权重是相似的,可能Istio也是如此,这里仅是入门,就不深入挖掘了。


当然Istio在路由规则设施方面的“能耐”远不止上面例子中所展示的那样,如果要悉数列出,那本文的长度可是要爆掉了。有兴趣的朋友可以去翻看官方文档。
 
插件安装
Istio的强大微服务治理能力还体现在其集成了grafana、prometheus、servicegraph、zipkin等addons,应用程序无需做任何改动,就可以具有数据收集、度量与可视化的监控能力、服务的分布式跟踪能力等。我们可以在Istio的安装包中找到这些addons的安装文件,我们来逐一试试。

prometheus&grafana
我们先来安装一下prometheus 和 grafana插件(位于istio-0.4.0/install/kubernetes/addon下面):
# kubectl apply -f prometheus.yaml

configmap "prometheus" created

service "prometheus" created

deployment "prometheus" created



# kubectl apply -f grafana.yaml

service "grafana" created

deployment "grafana" created



# kubectl get pods -n istio-system

NAME                             READY     STATUS    RESTARTS   AGE

grafana-3617079618-zpglx         1/1       Running   0          5m

prometheus-168775884-ppfxr       1/1       Running   0          5m

... ...



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)            AGE

grafana         10.105.21.25     <none>        3000/TCP                     16m

prometheus      10.103.160.37    <none>        9090/TCP                16m
 
浏览器中输入prometheus的服务地址http://10.103.160.37:9090,访问prometheus:





点击菜单项:status -> targets,查看各个target的状态是否正常:





如果像上图所示那样,各个target都是up状态,那就说明Istio运行时ok的。否则请参考istio troubleshooting中的内容对Istio逐一进行排查,尤其是istio-mesh这个Target在istio-0.3.0+kubernetes 1.7.3的环境中就是Down的状态。

浏览器输入grafana的服务地址:http://10.105.21.25:3000/,打开grafana面板:





 
切换到Istio Dashboard,并向istio service mesh注入流量,我们会看到仪表盘变化如下:





 





 

servicegraph
servicegraph插件是用来查看服务调用关系的,我们来创建一下该组件:
# kubectl apply -f servicegraph.yaml

deployment "servicegraph" created

service "servicegraph" created



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)                 AGE

servicegraph    10.108.245.21    <none>        8088/TCP                     52s

... ...
 
 
创建成功后,向service mesh网络注入流量,然后访问servicegraph:http://{servicegraph_ip}:8088/dotviz,在我的环境里,我看到的图示如下:





 
调用关系似乎有些乱,难道是我在程序使用的调用方法不够标准?:(
 

zipkin
Istio集成了zipkin,利用zipkin我们可以做分布式服务调用的追踪。之前自己曾经搭建过基于jaeger和opentracing的分布式调用服务,十分繁琐。并且要想使用tracing,对应用代码的侵入必不可少。

我们安装一下zipkin addon:
# kubectl apply -f zipkin.yaml

deployment "zipkin" created

service "zipkin" created



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE

zipkin          10.105.7.219     <none>        9411/TCP                             1h
我们访问以下zikpin的UI,通过浏览器打开http://{zipkin_service_ip}:9411。
 





 
接下来,我们向service mesh注入一些流量,然后再zipkin首页的“服务名”下拉框中选择”svcb”,查找跟踪情况:





 
我们看到:在没有对svca, svcb做任何修改的情况下,我们依然可以在zipkin中找到svcb相关的调用。点击其中一个trace,可以查看细节:
 





 
当然如果你想做内容更为丰富的、更为强大的跟踪,可能需要在应用代码中做些配合,具体可以参见:istio的分布式跟踪。
 
 
小结
Istio项目诞生不到一年,目前离成熟还远。快速积极开发可能会导致istio的接口和实现机制都会发生很大的变化,因此本文不能保证内容将适用于后续所有istio的发布版本。

本文涉及到的源码在这里 https://github.com/bigwhite/ex ... -demo 可以下载到,demo service的镜像可以在我的docker hub: https://hub.docker.com/u/bigwhite 上pull。

© 2018, bigwhite. 版权所有.
 
原文链接 查看全部
作者:Tony Bai
 

is.jpg

 
近两年微服务架构流行,主流互联网厂商内部都已经微服务化,初创企业虽然技术积淀不行,但也通过各种开源工具拥抱微服务。再加上容器技术赋能,Kubernetes又添了一把火,微服务架构已然成为当前软件架构设计的首选。


但微服务化易弄,服务治理难搞!
 
 
微服务的“痛点”

微服务化没有统一标准,多数是进行业务领域垂直切分,业务按一定的粒度划分职责,并形成清晰、职责单一的服务接口,这样每一块规划为一个微服务。微服务之间的通信方案相对成熟,开源领域选择较多的有RPC或RESTful API方案,比如:gRPC、apache thrift等。这些方案多偏重于数据如何打包、传输与解包,对服务治理的内容涉及甚少。


微服务治理是头疼的事,也是微服务架构中的痛点。治理这个词有多元含义,很难下达一个精确定义,这里可以像小学二年级学生那样列出治理的诸多近义词:管理、控制、规则、掌控、监督、支配、规定、统治等。对于微服务而言,治理体现在以下诸多方面:
  • 服务注册与发现
  •  
  • 身份验证与授权
  •  
  • 服务的伸缩控制
  •  
  • 反向代理与负载均衡
  •  
  • 路由控制
  •  
  • 流量切换
  •  
  • 日志管理
  •  
  • 性能度量、监控与调优
  •  
  • 分布式跟踪
  •  
  • 过载保护
  •  
  • 服务降级
  •  
  • 服务部署与版本升级策略支持
  •  
  • 错误处理


… …

从微服务治理角度来说,微服务其实是一个“大系统”,要想将这个大系统全部落地,绝非易事,尤其是之前尚没有一种特别优雅的技术方案。多数方案(比如:dubbo、go-kit等。)都或多或少地对应用逻辑有一定的侵入性,让业务开发人员不能只focus到业务本身,还要关心那些“治理”逻辑。并且市面上内置了微服务治理逻辑的框架较少,且很多编程语言相关。这种情况下,大厂多选择自研或基于某个框架改造,小厂一般只能“东拼西凑”一些“半成品”凑合着使用,就这样微服务也走过了若干年。


Service Mesh横空出世,Istio带来“福音”

我不知道在没有TCP/IP协议的年代,主机和主机之间的应用通信时是否需要应用关心底层通信协议实现逻辑。但是和TCP/IP诞生的思想类似,在微服务使用多年后,人们发现需要独立地抽象出一层逻辑网络,专门用于“微服务通信与治理策略的落地”,让应用只关心业务,把服务治理的事情全部交由“这一层”去处理。

1.png

图:传统微服务之间的微服务治理逻辑的位置
 

2.jpg

图:微服务治理逻辑被独立出来之后的位置
 
由“Service Govern Logic”这一层组成的逻辑网络被定义为Service Mesh,每个微服务都包含一个Service Mesh的端点。


“Service Mesh”概念还非常年轻,这个词在国内被翻译为“服务网格”或“服务啮合层”,我们这里就用Service Mesh这个英文词。这里摘录一下 ServiceMesh 中文网社区上的一篇名为“年度盘点2017之Service Mesh:群雄逐鹿烽烟起”的文章中对Service Mesh概念的回顾:


在 2016 年年初,“Service Mesh”还只是 Buoyant 公司的内部词汇,而之后,它开始逐步走向社区:

2016 年 9 月 29 日在 SF Microservices 上,“Service Mesh”这个词汇第一次在公开场合被使用。这标志着“Service Mesh”这个词,从 Buoyant 公司走向社区。

2016 年 10 月,Alex Leong 开始在 Buoyant 公司的官方 Blog 中连载系列文章“A Service Mesh for Kubernetes”。随着“The Services must Mesh”口号的喊出,Buoyant 和 Linkerd 开始 Service Mesh 概念的布道。

2017 年 4 月 25 日,William Morgan 发布博文“What’s a service mesh? And why do I need one?”。正式给 Service Mesh 做了一个权威定义。

而Service Mesh真正引起大家关注要源于Istio项目的开源发布。为什么呢?个人觉得还是因为“爹好”!Istio项目由Google、IBM共同合作创建,lyft公司贡献了Envoy项目将作为Istio Service Mesh的data panel。Google、IBM的影响力让Service Mesh概念迅速传播,同时也让大家认识到了Istio项目在Service Mesh领域的重要性,于是纷纷选择积极支持并将自己的产品或项目与Istio项目集成。


Istio项目是Service Mesh概念的最新实现,旨在所有主流集群管理平台上提供Service Mesh层,初期以实现Kubernetes上的服务治理层为目标。它由控制平面和数据平面组成(是不是感觉和SDN的设计理念相似啊)。控制平面由Go语言实现,包括pilot、mixer、auth三个组件;数据平面功能暂由Envoy在pod中以Sidecar的部署形式提供。下面是官方的架构图:

3.jpg

图:Istio架构图(来自官网)
Sidecar中Envoy代理了pod中真正业务container的所有进出流量,并对这些流量按照控制平面设定的“治理逻辑”进行处理。而这一切对pod中的业务应用是透明的,开发人员可以专心于业务逻辑,而无需再关心微服务治理的逻辑。Istio代表的Service Mesh的设计理念被认为是下一代“微服务统一框架”,甚至有人认为是微服务框架演化的终点。

Istio于2017 年 5 月 24 日发布了0.1 release 版本,截至目前为止Istio的版本更新到v0.4.0,演进速度相当快,不过目前依然不要用于生产环境,至少要等到1.0版本发布吧。但对于Istio的早期接纳者而言,现在正是深入研究Istio的好时机。在本篇的接下来内容中,我们将带领大家感性的认识一下Istio,入个门儿。
 
 
Istio安装
istio目前支持最好的就是kubernetes了,因此我们的实验环境就定在kubernetes上。至于版本,Istio当前最新版本为0.4.0,这个版本据说要K8S 1.7.4及以上版本用起来才不会发生小毛病:)。我的K8S集群是v1.7.6版本的,恰好满足条件。下面是安装过程:(Node上的os是ubuntu 16.04)
# wget -c https://github.com/istio/istio ... ar.gz



解压后,进入istio-0.4.0目录,



# ls -F

bin/  install/  istio.VERSION  LICENSE  README.md  samples/



# cat istio.VERSION

# DO NOT EDIT THIS FILE MANUALLY instead use

# install/updateVersion.sh (see install/README.md)

export CA_HUB="docker.io/istio"

export CA_TAG="0.4.0"

export MIXER_HUB="docker.io/istio"

export MIXER_TAG="0.4.0"

export PILOT_HUB="docker.io/istio"

export PILOT_TAG="0.4.0"

export ISTIOCTL_URL="https://storage.googleapis.com ... ot%3B

export PROXY_TAG="0.4.0"

export ISTIO_NAMESPACE="istio-system"

export AUTH_DEBIAN_URL="https://storage.googleapis.com ... ot%3B

export PILOT_DEBIAN_URL="https://storage.googleapis.com ... ot%3B

export PROXY_DEBIAN_URL="https://storage.googleapis.com ... ot%3B

export FORTIO_HUB="docker.io/istio"

export FORTIO_TAG="0.4.2"



# cd install/kubernetes



我们先不用auth功能,因此使用istio.yaml这个文件进行istio组件安装:



# kubectl apply -f istio.yaml

namespace "istio-system" created

clusterrole "istio-pilot-istio-system" created

clusterrole "istio-initializer-istio-system" created

clusterrole "istio-mixer-istio-system" created

clusterrole "istio-ca-istio-system" created

clusterrole "istio-sidecar-istio-system" created

clusterrolebinding "istio-pilot-admin-role-binding-istio-system" created

clusterrolebinding "istio-initializer-admin-role-binding-istio-system" created

clusterrolebinding "istio-ca-role-binding-istio-system" created

clusterrolebinding "istio-ingress-admin-role-binding-istio-system" created

clusterrolebinding "istio-sidecar-role-binding-istio-system" created

clusterrolebinding "istio-mixer-admin-role-binding-istio-system" created

configmap "istio-mixer" created

service "istio-mixer" created

serviceaccount "istio-mixer-service-account" created

deployment "istio-mixer" created

customresourcedefinition "rules.config.istio.io" created

customresourcedefinition "attributemanifests.config.istio.io" created

... ...

customresourcedefinition "reportnothings.config.istio.io" created

attributemanifest "istioproxy" created

attributemanifest "kubernetes" created

stdio "handler" created

logentry "accesslog" created

rule "stdio" created

metric "requestcount" created

metric "requestduration" created

metric "requestsize" created

metric "responsesize" created

metric "tcpbytesent" created

metric "tcpbytereceived" created

prometheus "handler" created

rule "promhttp" created

rule "promtcp" created

kubernetesenv "handler" created

rule "kubeattrgenrulerule" created

kubernetes "attributes" created

configmap "istio" created

customresourcedefinition "destinationpolicies.config.istio.io" created

customresourcedefinition "egressrules.config.istio.io" created

customresourcedefinition "routerules.config.istio.io" created

service "istio-pilot" created

serviceaccount "istio-pilot-service-account" created

deployment "istio-pilot" created

service "istio-ingress" created

serviceaccount "istio-ingress-service-account" created

deployment "istio-ingress" created

serviceaccount "istio-ca-service-account" created

deployment "istio-ca" created
 
注:我还曾在K8S v1.7.3上安装过istio 0.3.0版本,但在创建组件时会报下面错误(这个错误可能会导致后续addon安装后工作不正常):
unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric

unable to recognize "istio.yaml": no matches for config.istio.io/, Kind=metric
安装后,我们在istio-system这个namespace下会看到如下pod和service在运行(由于istio的各个组件的image size都不小,因此pod状态变为running需要一丢丢时间,耐心等待)
# kubectl get pods -n istio-system

NAME                             READY     STATUS    RESTARTS   AGE

istio-ca-1363003450-jskp5        1/1       Running   0          3d

istio-ingress-1005666339-c7776   1/1       Running   4          3d

istio-mixer-465004155-twhxq      3/3       Running   24         3d

istio-pilot-1861292947-6v37w     2/2       Running   18         3d



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                   AGE

istio-ingress   10.98.10.87      <pending>     80:31759/TCP,443:25804/TCP                         4d

istio-mixer     10.109.244.155   <none>        9091/TCP,15004/TCP,9093/TCP,9094/TCP,9102/TCP,9125/UDP,42422/TCP   4d

istio-pilot     10.105.80.55     <none>        15003/TCP,443/TCP                                              4d
 
istio安装成功!
 
 
服务治理策略验证
 
接下来我们来用几个例子验证一下Istio在服务治理方面的能力!(istio自带一些完整的例子,比如bookinfo,用于验证服务治理的能力,但这里先不打算用这些例子)

验证环境和拓扑我们先来看一下验证环境的示意图:

4.jpg

 
我们看到在Service Mesh中部署了两个service: server_a和service_b,前者调用后者完成某项业务,后者则调用外部服务完成业务逻辑。




service_a: 模拟pay服务,在收到client请求后,进行pay处理,并将处理结果通过service_b提供的msg notify服务下发给user。该服务的endpoint为/pay;

service_b: 模拟notify服务,在收到service_a请求后,将message转发给external service,完成notify逻辑。该服务的endpoint为/notify;

external service: 位于service mesh之外。

client:我们使用curl模拟。
 

5.jpg

 
我们先来部署service_a和service_b的v0.1版本:
以service_a的部署为例, service_a的deployment文件如下:
 
//svca-v0.1.yaml

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

 name: svca

spec:

 replicas: 1

 template:

   metadata:

     labels:

       app: svca

       version: v0.1

   spec:

     containers:

     - name: svca

       image: docker.io/bigwhite/istio-demo-svca:v0.1

       imagePullPolicy: Always

---

apiVersion: v1

kind: Service

metadata:

 name: svca

 labels:

   app: svca

spec:

 ports:

 - port: 80

   targetPort: 8080

   protocol: TCP

 selector:

   app: svca
 
注意,我们部署service_a时不能直接使用kubectl apply -f svca-v0.1.yaml,而是要apply经过istioctl(需将Istio安装目录下的bin放入PATH)处理过的yaml,以注入sidecar容器。当然也可以配置为自动为每个k8s启动的pod注入sidecar,但我们这里没有使用自动注入。我们执行下面命令:
 
# kubectl apply -f <(istioctl kube-inject -f svca-v0.1.yaml)

deployment "svca" created

service "svca" created



# kubectl get pods

NAME                               READY     STATUS    RESTARTS   AGE

svca-1997590752-tpwjf              2/2       Running   0          2m
 
 
同样的方法,我们来创建svcb:v0.1:
 
# kubectl apply -f <(istioctl kube-inject -f svcb-v0.1.yaml)

deployment "svcb" created

service "svcb" created
 
 
我们看到istio向每个pod中插入一个sidecar container,这个就是前面说的envoy,只不过container名字为istio-proxy。

接下来,我们把那个external service启动起来:
# nohup ./msgd > 1.log & 2>&1

[1] 9423
 
实验环境ok了。下面我们来验证一下业务是否是通的。
 

egress rule
按照之前我们的设定,我们使用curl去访问service_a服务的/pay端点,我们查看一下svca服务的ip和端口:
# kubectl get svc

NAME               CLUSTER-IP       EXTERNAL-IP   PORT(S)

svca               10.105.38.238    <none>        80/TCP                                         9h

svcb               10.105.119.194   <none>        80/TCP                                         9h
 
我们访问一下svca服务,svca的服务地址可以通过kubectl get svc查到:

# curl {svca_ip}/pay

查看svca和svcb的日志:
//service_a的日志:



service_a:v0.1 is serving the request...

service_a:v0.1 pays ok

&{500 Internal Server Error 500 HTTP/1.1 1 1 map[X-Content-Type-Options:[nosniff] Date:[Tue, 02 Jan 2018 15:41:50 GMT] Content-Length:[66] Content-Type:[text/plain; charset=utf-8]] 0xc420058d40 66  false false map 0xc4200eaf00 <nil>}

service_a:v0.1 notify customer ok



// service_b的日志:

&{GET /notify?msg=service_a:v0.1-pays-ok HTTP/1.1 1 1 map[User-Agent:[Go-http-client/1.1] Accept-Encoding:[gzip]] {} <nil> 0  false svcb map map <nil> map 127.0.0.1:58778 /notify?msg=service_a:v0.1-pays-ok <nil> <nil> <nil> 0xc4200fa3c0}

service_b:v0.1 is serving the request...

service_b:v0.1 send msg error: Get http://10.100.35.27:9997/send% ... s-ok: EOF
我们看到service_a和service_b都返回了错误日志(注意:go http get方法对于non-2xx response不会返回错误,我们只是看到了response中的500状态码才意识到错误的存在)。其中源头在service_b,原因是其连不上那个external service!那么为什么连不上external service呢?这是由于缺省情况下,启用了Istio的服务是无法访问外部URL的,这是因为Pod中的iptables把所有外发传输都转向到了Sidecar代理,而这一代理只处理集群内的访问目标。因此位于service mesh内的服务svcb无法访问外部的服务(msgd),我们需要显式的添加egressrule规则:

我们创建一个允许svcb访问外部特定服务的EgressRule:
//rules/enable-svcb-engress-rule.yaml



apiVersion: config.istio.io/v1alpha2

kind: EgressRule

metadata:

 name: enable-svcb-engress-rule

spec:

 destination:

   service: 10.100.35.27

 ports:

   - port: 9997

     protocol: http
 
使规则生效:

# istioctl create -f enable-svcb-engress-rule.yaml

Created config egress-rule/default/enable-svcb-engress-rule at revision 30031258


这时你再尝试curl svca,我们可以看到msgd的日志中出现了下面的内容:
 

2018/01/02 23:58:16 &{GET /send?msg=service_a:v0.1-pays-ok HTTP/1.1 1 1 map[X-Ot-Span-Context:[2157e7ffb8105330;2157e7ffb8105330;0000000000000000] Content-Length:[0] User-Agent:[Go-http-client/1.1] X-Forwarded-Proto:[http] X-Request-Id:[13c3af6e-2f52-993d-905f-aa6aa4b57e2d] X-Envoy-Decorator-Operation:[default-route] X-B3-Spanid:[2157e7ffb8105330] X-B3-Sampled:[1] Accept-Encoding:[gzip] X-B3-Traceid:[2157e7ffb8105330] X-Istio-Attributes:[Ch8KCXNvdXJjZS5pcBISMhAAAAAAAAAAAAAA//8KLgAMCjoKCnNvdXJjZS51aWQSLBIqa3ViZXJuZXRlczovL3N2Y2ItMjAwODk3Mzc2OS1ncTBsaC5kZWZhdWx0]] {} <nil> 0 false 10.100.35.27:9997 map map <nil> map 10.100.35.28:38188 /send?msg=service_a:v0.1-pays-ok <nil> <nil> <nil> 0xc4200584c0} 2018/01/02 23:58:16 Msgd is serving the request... 2018/01/02 23:58:16 Msgd recv msg ok, msg= service_a:v0.1-pays-ok
 
 
说明Svcb到外部服务的通信被打通了!

迁移流量到新版本svcb:v0.2我们经常有这样的需求,当svcb运行一段时间后,svcb添加了新feature,版本要升级到v0.2了,这时我们会部署svcb:v0.2,并将流量逐步切到v0.2上。

我们先来部署一下svcb:v0.2:
// svcb-v0.2.yaml

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

 name: svcb-v0.2

spec:

 replicas: 1

 template:

   metadata:

     labels:

       app: svcb

       version: v0.2

   spec:

     containers:

     - name: svcb

       image: docker.io/bigwhite/istio-demo-svcb:v0.2

       imagePullPolicy: Always
我们可以看到,服务名不变,但版本的label变成了v0.2,我们来执行这次部署:
 
# kubectl apply -f <(istioctl kube-inject -f svcb-v0.2.yaml)

deployment "svcb-v0.2" created



# kubectl get pods

NAME                               READY     STATUS    RESTARTS   AGE

svca-1997590752-pq9zg              2/2       Running   0          9h

svcb-2008973769-gq0lh              2/2       Running   0          9h

svcb-v0.2-3233505404-0g55w         2/2       Running   0          1m
 
svcb服务下又增加了一个endpoint:
# kubectl describe svc/svcb



.... ...

Selector:        app=svcb

Type:            ClusterIP

IP:            10.105.119.194

Port:            <unset>    80/TCP

Endpoints:        10.40.0.28:8080,10.46.0.12:8080

... ...
 
此时,如果按照K8S的调度方式,v0.1和v0.2版本的两个svcb pod应该1:1均衡地承载流量。为了方便查看流量分布,我们将每个版本的svcb的pod副本数量都扩展为2个(replicas: 2),这样service mesh中一共会有4个 svcb endpoints。

通过curl访问svca注入流量后,我们发现流量都集中在一个svcb:v0.2的pod上,并且长时间没有变化。我们通过下面的route rule规则来尝试将流量在svcb:v0.1和svcb:v0.2之间1:1均衡:
 
// route-rules-svcb-v0.2-50.yaml

apiVersion: config.istio.io/v1alpha2

kind: RouteRule

metadata:

 name: route-rules-svcb

spec:

 destination:

   name: svcb

 precedence: 1

 route:

 - labels:

     version: v0.1

   weight: 50

 - labels:

     version: v0.2

   weight: 50



# istioctl create -f route-rules-svcb-v0.2-50.yaml

Created config route-rule/default/route-rules-svcb at revision 30080638
 
 
按照istio文档中的说法,这个规则的生效需要一些时间。之后我们注入流量,发现流量切换到svcb:v0.1的一个pod上去了,并且很长一段时间不曾变化,未均衡到svcb:v0.2上去。

我们更新一下route rule,将流量全部切到svcb:v0.2上去:
 

//route-rules-svcb-v0.2-100.yaml apiVersion: config.istio.io/v1alpha2 kind: RouteRule metadata:  name: route-rules-svcb spec:  destination:    name: svcb  precedence: 1  route:  - labels:      version: v0.2    weight: 100 # istioctl replace -f route-rules-svcb-v0.2-100.yaml Updated config route-rule/default/route-rules-svcb to revision 30082944
 
我们用Istio的replace命令更新了规则:route-rules-svcb。更新后,再次注入流量,这回流量重新集中在svcb:v0.2的一个pod上了,再过一段时间另外一个svcb:v0.2的pod上才有了一些流量。但svcb:v0.1上不再有流量,这个切换是成功的。


在K8S的service的负载均衡中,K8S就利用了iptables的概率转发(random –probability 0.5),因此这种流量均衡并非是精确的,只有在长时间大量流量经过后,才能看到流量的分布与设定的权重是相似的,可能Istio也是如此,这里仅是入门,就不深入挖掘了。


当然Istio在路由规则设施方面的“能耐”远不止上面例子中所展示的那样,如果要悉数列出,那本文的长度可是要爆掉了。有兴趣的朋友可以去翻看官方文档。
 
插件安装
Istio的强大微服务治理能力还体现在其集成了grafana、prometheus、servicegraph、zipkin等addons,应用程序无需做任何改动,就可以具有数据收集、度量与可视化的监控能力、服务的分布式跟踪能力等。我们可以在Istio的安装包中找到这些addons的安装文件,我们来逐一试试。

prometheus&grafana
我们先来安装一下prometheus 和 grafana插件(位于istio-0.4.0/install/kubernetes/addon下面):
# kubectl apply -f prometheus.yaml

configmap "prometheus" created

service "prometheus" created

deployment "prometheus" created



# kubectl apply -f grafana.yaml

service "grafana" created

deployment "grafana" created



# kubectl get pods -n istio-system

NAME                             READY     STATUS    RESTARTS   AGE

grafana-3617079618-zpglx         1/1       Running   0          5m

prometheus-168775884-ppfxr       1/1       Running   0          5m

... ...



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)            AGE

grafana         10.105.21.25     <none>        3000/TCP                     16m

prometheus      10.103.160.37    <none>        9090/TCP                16m
 
浏览器中输入prometheus的服务地址http://10.103.160.37:9090,访问prometheus:

6.jpg

点击菜单项:status -> targets,查看各个target的状态是否正常:

6.jpg

如果像上图所示那样,各个target都是up状态,那就说明Istio运行时ok的。否则请参考istio troubleshooting中的内容对Istio逐一进行排查,尤其是istio-mesh这个Target在istio-0.3.0+kubernetes 1.7.3的环境中就是Down的状态。

浏览器输入grafana的服务地址:http://10.105.21.25:3000/,打开grafana面板:

8.jpg

 
切换到Istio Dashboard,并向istio service mesh注入流量,我们会看到仪表盘变化如下:

9.jpg

 

10.jpg

 

servicegraph
servicegraph插件是用来查看服务调用关系的,我们来创建一下该组件:
# kubectl apply -f servicegraph.yaml

deployment "servicegraph" created

service "servicegraph" created



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)                 AGE

servicegraph    10.108.245.21    <none>        8088/TCP                     52s

... ...
 
 
创建成功后,向service mesh网络注入流量,然后访问servicegraph:http://{servicegraph_ip}:8088/dotviz,在我的环境里,我看到的图示如下:

11.jpg

 
调用关系似乎有些乱,难道是我在程序使用的调用方法不够标准?:(
 

zipkin
Istio集成了zipkin,利用zipkin我们可以做分布式服务调用的追踪。之前自己曾经搭建过基于jaeger和opentracing的分布式调用服务,十分繁琐。并且要想使用tracing,对应用代码的侵入必不可少。

我们安装一下zipkin addon:
# kubectl apply -f zipkin.yaml

deployment "zipkin" created

service "zipkin" created



# kubectl get svc -n istio-system

NAME            CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE

zipkin          10.105.7.219     <none>        9411/TCP                             1h
我们访问以下zikpin的UI,通过浏览器打开http://{zipkin_service_ip}:9411。
 

12.jpg

 
接下来,我们向service mesh注入一些流量,然后再zipkin首页的“服务名”下拉框中选择”svcb”,查找跟踪情况:

13.jpg

 
我们看到:在没有对svca, svcb做任何修改的情况下,我们依然可以在zipkin中找到svcb相关的调用。点击其中一个trace,可以查看细节:
 

14.jpg

 
当然如果你想做内容更为丰富的、更为强大的跟踪,可能需要在应用代码中做些配合,具体可以参见:istio的分布式跟踪。
 
 
小结
Istio项目诞生不到一年,目前离成熟还远。快速积极开发可能会导致istio的接口和实现机制都会发生很大的变化,因此本文不能保证内容将适用于后续所有istio的发布版本。

本文涉及到的源码在这里 https://github.com/bigwhite/ex ... -demo 可以下载到,demo service的镜像可以在我的docker hub: https://hub.docker.com/u/bigwhite 上pull。

© 2018, bigwhite. 版权所有.
 
原文链接

k8s 1.7.3 下安装 istio 0.3.0 手动注入Envoy容器有问题

回复

fzhsh 回复了问题 • 1 人关注 • 1 个回复 • 234 次浏览 • 2017-12-28 11:30 • 来自相关话题

kube-dns 增加 istio 的 address

小数 回复了问题 • 2 人关注 • 1 个回复 • 155 次浏览 • 2017-12-13 14:01 • 来自相关话题

Istio安装错误,无法运行?

leon 回复了问题 • 2 人关注 • 1 个回复 • 197 次浏览 • 2017-12-11 16:04 • 来自相关话题

Istio配置请求路由失败?

回复

tiger_kin 回复了问题 • 1 人关注 • 1 个回复 • 117 次浏览 • 2017-12-01 09:04 • 来自相关话题

转载:Istio 的频率限制 by 崔秀龙

小数 发表了文章 • 0 个评论 • 131 次浏览 • 2017-11-30 17:34 • 来自相关话题

Istio 的频率限制原创 2017-10-13 崔秀龙 伪架构师
 
本来这个应该是作为第三天“零散功能点”介绍的,结果目标规则部分遇到一个 bug 一直没得到修正,就拖着了——然后后来发现自己这个想法挺无知的——零散的功能点非常多,非常大,而且文档非常弱,很难搞,只好
逐个介绍了。

简介

调用频率限制这个功能其实也是比较常见的东西了。这里就不多做介绍了。下面简单粗暴的介绍一下测试要完
成的目标。

测试中我们将使用两个服务,服务叫 workload,客户端叫 sleep,workload 服务正常返回群众喜闻乐见
的 “Hello World”,而 sleep 仅用来做 Shell 方便测试。

测试过程将为 workload 建立规则:

对于任意访问,十秒钟之内仅能访问两次;

对于来自 sleep 的访问,十秒钟之内仅能访问一次

下面所有内容都在 default 命名空间进行

建立测试环境

编辑 workload.yaml 以及 sleep.yaml 之后,
我们使用如下命令运行(这两部分源码,只有些乌七八糟的标签和命名有点问题,其他很普通。
见最后页)
istioctl kube-inject -f workload.yaml | kubectl apply -f -
 istioctl kube-inject -f sleep.yaml | kubectl apply -f -
kubectl get pods 确定 Pod 成功启动,也可以使用 curl 测试 NodePort,会得到 40x 的错误
页面。

建立规则

quota.yaml

这部分内容规则来自:https://istio.io/docs/referenc ... .html

这个对象用于设置检测服务来源、目标的标准维度,下面我们设置的是利用服务名称来检测。

这部分可能存在 bug,官方介绍的 source 定义是 source.labels["app"] | source.service | "unknown"
我的理解是说首先获取服务 Pod 的 app 标签内容,如果没有,再获取服务名称。但是后面我们会看到,
删除source.labels["app"]的定义之后,最终生效的依旧是 app 标签,这也是为什么给 workload

加上这么多奇怪标签的原因。
apiVersion: config.istio.io/v1alpha2 
kind: quota 
metadata:  
   name: requestcount 
spec:  
  dimensions:    
  source: source.service | "unknown"    
  sourceVersion: source.labels["version"] | "unknown"    
  destination:  destination.service | "unknown"
handler.yaml

这一对象的定义来自:https://istio.io/docs/referenc ... .html

下面的代码对应我们之前的目的,任意访问都是每 10 秒钟两次,而特定源和目标的访问则是每 10 秒钟一
次。

其中 quotas 部分,name 字段的来源是上面的 quota.yaml

这个不知道是不是 bug,必须写上半个 fqdn。

dimentions 字段则需要使用 quota.yaml 定义的维度。这里的维度可以比 quota.yaml 中定义的
维度宽松(也就是少,例如定义三个,只使用其中的两个),可以理解,这也符合匹配的规则。
apiVersion: config.istio.io/v1alpha2 
kind: memquota 
metadata:  
  name: handler 
spec:  
  quotas:  
  - name: requestcount.quota.default    
  maxAmount: 2    
  validDuration: 10s    
  overrides:   
  - dimensions:        
      destination: workload-pod.default.svc.cluster.local        
      source: sleep.default.svc.cluster.local      
  maxAmount: 1      
  validDuration: 10s
 
rule.yaml

这部分的定义参考:https://istio.io/docs/referenc ... .Rule

这个对象的作用就是,对于符合筛选条件的服务调用,使用对应的 handler 进行处理。

这里的 handler 和 requestcount 两个字段的内容,也需要是 实力名称.对象类型的方式。
apiVersion: config.istio.io/v1alpha2 
kind: rule 
metadata:  
  name: quota 
spec:  
  actions:  
  - handler: handler.memquota    
    instances:   
    - requestcount.quota
 
 
测试运行
集群外

使用 curl 重复访问 NodePort 三次,会发现第三次出现:RESOURCE_EXHAUSTED:Quota is exhausted for: RequestCount#

这说明我们设置的通用规则生效了。

集群内

在 sleep pod 中同样执行 curl 三次,发现第二次就开始出现超限说明。

上面两种情况,在超过时间窗口限制之后,都会自动恢复。

幕后

定义 quota 对象,在系统中会展现为一系列的计数器,计数器的维度就是quota 中的维度的笛卡尔积。
如果在 validDuration 的时间窗口过期之前调用次数超过了 maxAmount 规定,Mixer
就会返回 RESOURCE_EXHAUSTED 给 Envoy,Envoy 则会反馈 429 代码给调用方。

结论

文档不完善的开源系统。。坑真大啊!

源码
Workload 的 Deployment 和 Service:
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata:  
  labels:    
    app: workload-app    
    version: http200  
  name: workload-200 
spec:  
  replicas: 1  
  selector:    
    matchLabels:      
      app: workload-pod     
      version: http200  
template:    
  metadata:      
    creationTimestamp: null      
    labels:        
      app: workload-pod       
      version: http200    
  spec:      
    containers:     
    - image: php:7.0-apache        
      imagePullPolicy: IfNotPresent        
      name: http200        
      ports:        
      - containerPort: 80         
        name: http             
        protocol: TCP      
    dnsPolicy: ClusterFirst      
    restartPolicy: Always 
--- 
apiVersion: v1 
kind: Service
metadata:  
   labels:    
     app: workload-service    
     version: http200  
   name: workload-200 
spec:  
  ports: 
   - name: http    
     port: 80    
     protocol: TCP    
     targetPort: 80    
     nodePort: 30200  
  selector:    
     app: workload-pod
     version: http200  
  sessionAffinity: None  
  type: NodePort
 
Sleep 的定义
apiVersion: v1 
kind: Service 
metadata:  
  name: sleep  
  labels:    
    app: sleep 
spec:  
  ports: 
   - port: 80    
     name: http  
   selector:    
     app: sleep 
--- 
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata:  
  name: sleep 
spec:  
  replicas: 1  
  template:    
    metadata:     
      labels:        
        app: sleep   
   spec:      
     containers:     
     - name: sleep        
       image: tutum/curl        
       command: ["/bin/sleep","infinity"]        
       imagePullPolicy: IfNotPresent
  查看全部
Istio 的频率限制原创 2017-10-13 崔秀龙 伪架构师
 
本来这个应该是作为第三天“零散功能点”介绍的,结果目标规则部分遇到一个 bug 一直没得到修正,就拖着了——然后后来发现自己这个想法挺无知的——零散的功能点非常多,非常大,而且文档非常弱,很难搞,只好
逐个介绍了。

简介

调用频率限制这个功能其实也是比较常见的东西了。这里就不多做介绍了。下面简单粗暴的介绍一下测试要完
成的目标。

测试中我们将使用两个服务,服务叫 workload,客户端叫 sleep,workload 服务正常返回群众喜闻乐见
的 “Hello World”,而 sleep 仅用来做 Shell 方便测试。

测试过程将为 workload 建立规则:

对于任意访问,十秒钟之内仅能访问两次;

对于来自 sleep 的访问,十秒钟之内仅能访问一次

下面所有内容都在 default 命名空间进行

建立测试环境

编辑 workload.yaml 以及 sleep.yaml 之后,
我们使用如下命令运行(这两部分源码,只有些乌七八糟的标签和命名有点问题,其他很普通。
见最后页)
istioctl kube-inject -f workload.yaml | kubectl apply -f -
 istioctl kube-inject -f sleep.yaml | kubectl apply -f -
kubectl get pods 确定 Pod 成功启动,也可以使用 curl 测试 NodePort,会得到 40x 的错误
页面。

建立规则

quota.yaml

这部分内容规则来自:https://istio.io/docs/referenc ... .html

这个对象用于设置检测服务来源、目标的标准维度,下面我们设置的是利用服务名称来检测。

这部分可能存在 bug,官方介绍的 source 定义是 source.labels["app"] | source.service | "unknown"
我的理解是说首先获取服务 Pod 的 app 标签内容,如果没有,再获取服务名称。但是后面我们会看到,
删除source.labels["app"]的定义之后,最终生效的依旧是 app 标签,这也是为什么给 workload

加上这么多奇怪标签的原因。
apiVersion: config.istio.io/v1alpha2 
kind: quota 
metadata:  
   name: requestcount 
spec:  
  dimensions:    
  source: source.service | "unknown"    
  sourceVersion: source.labels["version"] | "unknown"    
  destination:  destination.service | "unknown"
handler.yaml

这一对象的定义来自:https://istio.io/docs/referenc ... .html

下面的代码对应我们之前的目的,任意访问都是每 10 秒钟两次,而特定源和目标的访问则是每 10 秒钟一
次。

其中 quotas 部分,name 字段的来源是上面的 quota.yaml

这个不知道是不是 bug,必须写上半个 fqdn。

dimentions 字段则需要使用 quota.yaml 定义的维度。这里的维度可以比 quota.yaml 中定义的
维度宽松(也就是少,例如定义三个,只使用其中的两个),可以理解,这也符合匹配的规则。
apiVersion: config.istio.io/v1alpha2 
kind: memquota 
metadata:  
  name: handler 
spec:  
  quotas:  
  - name: requestcount.quota.default    
  maxAmount: 2    
  validDuration: 10s    
  overrides:   
  - dimensions:        
      destination: workload-pod.default.svc.cluster.local        
      source: sleep.default.svc.cluster.local      
  maxAmount: 1      
  validDuration: 10s
 
rule.yaml

这部分的定义参考:https://istio.io/docs/referenc ... .Rule

这个对象的作用就是,对于符合筛选条件的服务调用,使用对应的 handler 进行处理。

这里的 handler 和 requestcount 两个字段的内容,也需要是 实力名称.对象类型的方式。
apiVersion: config.istio.io/v1alpha2 
kind: rule 
metadata:  
  name: quota 
spec:  
  actions:  
  - handler: handler.memquota    
    instances:   
    - requestcount.quota
 
 
测试运行
集群外

使用 curl 重复访问 NodePort 三次,会发现第三次出现:RESOURCE_EXHAUSTED:Quota is exhausted for: RequestCount#

这说明我们设置的通用规则生效了。

集群内

在 sleep pod 中同样执行 curl 三次,发现第二次就开始出现超限说明。

上面两种情况,在超过时间窗口限制之后,都会自动恢复。

幕后

定义 quota 对象,在系统中会展现为一系列的计数器,计数器的维度就是quota 中的维度的笛卡尔积。
如果在 validDuration 的时间窗口过期之前调用次数超过了 maxAmount 规定,Mixer
就会返回 RESOURCE_EXHAUSTED 给 Envoy,Envoy 则会反馈 429 代码给调用方。

结论

文档不完善的开源系统。。坑真大啊!

源码
Workload 的 Deployment 和 Service:
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata:  
  labels:    
    app: workload-app    
    version: http200  
  name: workload-200 
spec:  
  replicas: 1  
  selector:    
    matchLabels:      
      app: workload-pod     
      version: http200  
template:    
  metadata:      
    creationTimestamp: null      
    labels:        
      app: workload-pod       
      version: http200    
  spec:      
    containers:     
    - image: php:7.0-apache        
      imagePullPolicy: IfNotPresent        
      name: http200        
      ports:        
      - containerPort: 80         
        name: http             
        protocol: TCP      
    dnsPolicy: ClusterFirst      
    restartPolicy: Always 
--- 
apiVersion: v1 
kind: Service
metadata:  
   labels:    
     app: workload-service    
     version: http200  
   name: workload-200 
spec:  
  ports: 
   - name: http    
     port: 80    
     protocol: TCP    
     targetPort: 80    
     nodePort: 30200  
  selector:    
     app: workload-pod
     version: http200  
  sessionAffinity: None  
  type: NodePort
 
Sleep 的定义
apiVersion: v1 
kind: Service 
metadata:  
  name: sleep  
  labels:    
    app: sleep 
spec:  
  ports: 
   - port: 80    
     name: http  
   selector:    
     app: sleep 
--- 
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata:  
  name: sleep 
spec:  
  replicas: 1  
  template:    
    metadata:     
      labels:        
        app: sleep   
   spec:      
     containers:     
     - name: sleep        
       image: tutum/curl        
       command: ["/bin/sleep","infinity"]        
       imagePullPolicy: IfNotPresent
 

服务网格新生代Istio进化,与传统模式相较5大特性更助容器扩展

小数 发表了文章 • 0 个评论 • 235 次浏览 • 2017-11-28 10:26 • 来自相关话题

关于Service Mesh,小数之前给大家分享了敖小剑老师的《Qcon2017实录|Service Mesh:下一代微服务》那么它对于容器相比传统模式都有哪方面的优势呢?同作为Service Mesh的新生代,Istio v0.2都有哪些添加与改进?本文见分晓!


容器仍然是目前极度火热的话题,一些人称,通过容器他们正处于崛起的边缘,成为数据中心的主宰,另外一些人则认为容器只适用于云计算,还有一些人在耐心地等待着看容器是不是应用程序基础设施的SDN,一些权威人士在极力吹捧,但其实很少在生产中付诸实践。


通过一些研究和调查可以看到容器确实在吸引着人们的注意:


32%的公司每年花费50万美元或更多的资金用于容器技术的授权和使用费(Portworx的年度容器采用率调查)


采用容器技术的公司在9个月内将其容器数量增加5倍(Datadog 8个令人惊讶的事实,关于Docker的采用。


容器的密度为平均每台主机10个容器(Sys Docker 使用报告2017)


2017年,Docker的使用率飙升至35%(2017年云计算报告)


5%的企业希望采用容器来部署传统的网络托管应用服务(F5 Networks State of Application Delivery 2017)


如大多数的基础设施——无论是应用还是网络——在可预见的未来,容器都将与日常运行在大型机和Midranges Alike上的应用程序共存,这是应用基础设施最重要的转变,当WEB堆栈上升到主导地位时,它并没有消除Fat Client-Server应用程序,至少在一段时间内,它们是一同运行的。

然而,它所做的都是迫使我们改变这些应用的规模,WEB应用程序对网络及其服务器施加了巨大的压力,需要新的方式来扩展容量和确保可用性,使用容器来部署应用程序——特别是那些使用微服务体系结构的应用。


在容器化环境和传统WEB应用程序中使用的扩展模式之间存在着显著的差异。




1传统模式

无论在云端(公有云、私有云)还是数据中心,传统的模式都采用了相当标准的模式,它使用固定的“池”资源,配置和行为最终基于端口和IP地址。


负责实际扩展应用程序的软件(无论部署在特定的目的硬件和是COTS上)都是在一个相当独立的操作前提下执行的,从算法到可用的资源,所有的一切都是按照比例服务的。


同时也包括这些资源的状态,在传统的模式中,通常是扩展应用,跟踪资源的健康状况,并在不可用的情况下进行轮转。


传统的规模模式依赖于命令式的配置模式,并且只有很少的明显例外(如状态)变化是由配置事件驱动的,这意味着一个操作符或外部脚本已经发布了一个非常特定的命令——通过API、CLI或GUI——来更改配置。


2The Cloud Half-Step

当“自动扩展”的概念出现时,云计算开始影响这个模式,于大多数容器化的环境中,自动伸缩是传统模式和服务网格模式之间的一个半步,它融合了环境变化的概念,比如增加需求出发配置更改,比如添加或删除资源,然而,模式仍然是一个“推”模式,这意味着对规模负责的系统仍然必须被隐式地告知需要进行的更改。



3服务网格模式

容器的管理通常由一些外部系统实现,比如Kubernetes或Mesos或Open Shift,通过一个类似于容器集群的命令和控制中心的“主”控制器,它的职责是管理容器,并将其保存到最新的目录中。

对于给定服务(或应用程序)可用资源的“池”是动态的,很多东西都是由一个特定容器的实际寿命所做而成,但事实是,跟它们的前辈虚拟机的几周或者几个月的寿命相比,可能只有几分钟或几个小时。


这种速度是不可能手动进行跟踪了,这也是为什么服务注册中心存在的原因——为了保存一个实时列表,列出哪些资源可用,以及它们属于什么服务。

这是服务网格模式避免将应用程序和服务紧密耦合到IP地址和端口的原因之一,当然,它们仍然被使用,但波动性(以及网络属性的重要)要求应用程序和服务必须由其他东西来表示——比如标签。


然后,真个系统中的所有配置和行为都是基于这些标记的,它们与FQDNs很相似。

通过DNS映射到IP地址。

所有这些都导致了需要一个更加协作的操作前提,负责扩展容器化应用和服务的软件,与传统的模式有很大不同,它们的前提是“我需要其他服务的信息来决定,而我的目的可能在另一个地方”。


但是不能期望主控制器通知每一个更改的组件,这种集中式控制不考虑系统中的组件数量,记住,它不只是容器,除了用于监控和报告业务以及操作分析所需要的远程数据守护进程之外,还存在诸如服务和规则之类的构造,但扩展软件仍然需要,知道什么时候改变(或者资源转移)。


在服务网格模式中,更改是由其他地方发布的操作事件所驱动,扩展软件的职责是拉出这些更改并对它们进行操作,而不是通过脚本或人工操作来实现特定的配置更改。

这意味着更改必须与实现无关,更改不可能是特定的API调用或需要实现的命令,他们必须是“什么”而非“如何”。这是一种声明式的配置模式,而不是与传统的规模模式相关的命令式模式。


这就意味着:


这些变化对网络的流量产生了相当大的影响

传统的模式可以被看做是一个交通信号灯系统

固定的配置

限定方向

路线预定义


另一方面,一个服务网格模式更类似于现代的交通管理系统:

基于实时条件的动态

路径变量

路线灵活


接受这个模式最困难的部分,从作者的个人经验来看,是在一个服务的设备中有多少移动的部件,这使得很难从一端(客户端),到另一端(应用程序)跟踪数据路径,服务于主控制器和服务注册中心的服务依赖于对路由请求的依赖,因为它们对于路由请求的重要性,就像ARP映射表在核心网络中路由数据包一样重要。

服务网格模式在那些采用容器的用户中获取了极大的兴趣和新引力,在墙的另一边,要了解它对网络的影响,并准备好管理它。

4Istio v0.2

Istio是Google/IBM/Lyft联合开发的开源项目,2017年5月发布第一个release 0.1.0, 官方定义为:

Istio:一个连接,管理和保护微服务的开放平台。

按照Isito文档中给出的定义:

Istio提供一种简单的方式来建立已部署的服务的网络,具备负载均衡,服务到服务认证,监控等等功能,而不需要改动任何服务代码。


——敖小剑《万字解读:Service Mesh服务网格新生代--Istio》


Istio v0.2添加很多新的功能以及改建,下面来谈一谈,Istio v0.2让人激动的5大改进:


Automatic Sidecar Injection

对于自定义资源和初始化器的支持,Istio v0.2要求Kubernetes1.7.4或更新,如果集群中启用了I nitializer Alpha特性,建议安装Istio初始化器,它为所有想要的Istio管理的微服务部署注入了自动的Sidecar。IBM Bluemix容器服务集群在1.7.4或更新时自动运行,这与Istio初始化器很好地工作,由于仍然是Istio开发总体方案中的一个Alpha特性,所以建议谨慎使用。


Traffic Management Improvement

在Istio v0.1中,用户可以使用Ingress路由规则来制定想要通过微服务进入的流量,现在,还可以使用e外出路由规则来制定想要从微服务中获得哪些类型的流量,以及服务可以与哪些外部服务进行通信,例如,用户可以轻松地配置服务,与IBM Cloud中的IBM Watson服务之一进行对话,从而为用户的服务提供人工智能功能。


Improved Telemetry

作为Istio用户,无需做任何事情去启动各种度量或跟踪,这非常简便,用户可以部署微服务应用,让Istio进行管理,而不需要任何应用程序或部署。Yaml文件,Zipkin的跟踪为应用提供了详细的跟踪信息,Zipkin的进一步追踪让人可以深入到每一个请求中,以查看流量子啊服务网格中如何技术,如果用户更喜欢Jaeger,也提供支持。


多环境支持


Istio的最初目标之一就是进行多环境的支持,在微服务体系结构中,无法要求所有的工作负载都在Kubernetes中运行,用户的一些应用程序可能在Kubernetes中运维,而另外一些可能在Docker Swarm或者VM中运行,在Istio v0.2中,引入了早期对VM的支持,并与一些更流行的服务发现系统进行了集成,Istio已经被扩展支持到其他运行时环境,这是让人兴奋的一件事。


在Kubernetes环境中使用Kubectl与Istio进行交互

本文作者最喜欢的一项是Istio v0.2更新了配置的模式,并使用Kubernetes的自定义资源定义,这意味着用户现在可以在Kubernetes环境中使用Kubectl与Istio进行交互,如果有自动的Sidecar注入,在Kuberentes环境中与Istio互动时,就无需Istioctl了,当用户想要首都注入Sidecar或与诸如控制台和VM等多环境交互时,Istioctl就变得有用了。


原文作者:DevCentral

原文链接:https://www.tuicool.com/articles/uE3uyyV
  查看全部
关于Service Mesh,小数之前给大家分享了敖小剑老师的《Qcon2017实录|Service Mesh:下一代微服务》那么它对于容器相比传统模式都有哪方面的优势呢?同作为Service Mesh的新生代,Istio v0.2都有哪些添加与改进?本文见分晓!


容器仍然是目前极度火热的话题,一些人称,通过容器他们正处于崛起的边缘,成为数据中心的主宰,另外一些人则认为容器只适用于云计算,还有一些人在耐心地等待着看容器是不是应用程序基础设施的SDN,一些权威人士在极力吹捧,但其实很少在生产中付诸实践。


通过一些研究和调查可以看到容器确实在吸引着人们的注意:


32%的公司每年花费50万美元或更多的资金用于容器技术的授权和使用费(Portworx的年度容器采用率调查)


采用容器技术的公司在9个月内将其容器数量增加5倍(Datadog 8个令人惊讶的事实,关于Docker的采用。


容器的密度为平均每台主机10个容器(Sys Docker 使用报告2017)


2017年,Docker的使用率飙升至35%(2017年云计算报告)


5%的企业希望采用容器来部署传统的网络托管应用服务(F5 Networks State of Application Delivery 2017)


如大多数的基础设施——无论是应用还是网络——在可预见的未来,容器都将与日常运行在大型机和Midranges Alike上的应用程序共存,这是应用基础设施最重要的转变,当WEB堆栈上升到主导地位时,它并没有消除Fat Client-Server应用程序,至少在一段时间内,它们是一同运行的。

然而,它所做的都是迫使我们改变这些应用的规模,WEB应用程序对网络及其服务器施加了巨大的压力,需要新的方式来扩展容量和确保可用性,使用容器来部署应用程序——特别是那些使用微服务体系结构的应用。


在容器化环境和传统WEB应用程序中使用的扩展模式之间存在着显著的差异。




1传统模式

无论在云端(公有云、私有云)还是数据中心,传统的模式都采用了相当标准的模式,它使用固定的“池”资源,配置和行为最终基于端口和IP地址。


负责实际扩展应用程序的软件(无论部署在特定的目的硬件和是COTS上)都是在一个相当独立的操作前提下执行的,从算法到可用的资源,所有的一切都是按照比例服务的。


同时也包括这些资源的状态,在传统的模式中,通常是扩展应用,跟踪资源的健康状况,并在不可用的情况下进行轮转。


传统的规模模式依赖于命令式的配置模式,并且只有很少的明显例外(如状态)变化是由配置事件驱动的,这意味着一个操作符或外部脚本已经发布了一个非常特定的命令——通过API、CLI或GUI——来更改配置。


2The Cloud Half-Step

当“自动扩展”的概念出现时,云计算开始影响这个模式,于大多数容器化的环境中,自动伸缩是传统模式和服务网格模式之间的一个半步,它融合了环境变化的概念,比如增加需求出发配置更改,比如添加或删除资源,然而,模式仍然是一个“推”模式,这意味着对规模负责的系统仍然必须被隐式地告知需要进行的更改。



3服务网格模式

容器的管理通常由一些外部系统实现,比如Kubernetes或Mesos或Open Shift,通过一个类似于容器集群的命令和控制中心的“主”控制器,它的职责是管理容器,并将其保存到最新的目录中。

对于给定服务(或应用程序)可用资源的“池”是动态的,很多东西都是由一个特定容器的实际寿命所做而成,但事实是,跟它们的前辈虚拟机的几周或者几个月的寿命相比,可能只有几分钟或几个小时。


这种速度是不可能手动进行跟踪了,这也是为什么服务注册中心存在的原因——为了保存一个实时列表,列出哪些资源可用,以及它们属于什么服务。

这是服务网格模式避免将应用程序和服务紧密耦合到IP地址和端口的原因之一,当然,它们仍然被使用,但波动性(以及网络属性的重要)要求应用程序和服务必须由其他东西来表示——比如标签。


然后,真个系统中的所有配置和行为都是基于这些标记的,它们与FQDNs很相似。

通过DNS映射到IP地址。

所有这些都导致了需要一个更加协作的操作前提,负责扩展容器化应用和服务的软件,与传统的模式有很大不同,它们的前提是“我需要其他服务的信息来决定,而我的目的可能在另一个地方”。


但是不能期望主控制器通知每一个更改的组件,这种集中式控制不考虑系统中的组件数量,记住,它不只是容器,除了用于监控和报告业务以及操作分析所需要的远程数据守护进程之外,还存在诸如服务和规则之类的构造,但扩展软件仍然需要,知道什么时候改变(或者资源转移)。


在服务网格模式中,更改是由其他地方发布的操作事件所驱动,扩展软件的职责是拉出这些更改并对它们进行操作,而不是通过脚本或人工操作来实现特定的配置更改。

这意味着更改必须与实现无关,更改不可能是特定的API调用或需要实现的命令,他们必须是“什么”而非“如何”。这是一种声明式的配置模式,而不是与传统的规模模式相关的命令式模式。


这就意味着:


这些变化对网络的流量产生了相当大的影响

传统的模式可以被看做是一个交通信号灯系统

固定的配置

限定方向

路线预定义


另一方面,一个服务网格模式更类似于现代的交通管理系统:

基于实时条件的动态

路径变量

路线灵活


接受这个模式最困难的部分,从作者的个人经验来看,是在一个服务的设备中有多少移动的部件,这使得很难从一端(客户端),到另一端(应用程序)跟踪数据路径,服务于主控制器和服务注册中心的服务依赖于对路由请求的依赖,因为它们对于路由请求的重要性,就像ARP映射表在核心网络中路由数据包一样重要。

服务网格模式在那些采用容器的用户中获取了极大的兴趣和新引力,在墙的另一边,要了解它对网络的影响,并准备好管理它。

4Istio v0.2

Istio是Google/IBM/Lyft联合开发的开源项目,2017年5月发布第一个release 0.1.0, 官方定义为:

Istio:一个连接,管理和保护微服务的开放平台。

按照Isito文档中给出的定义:

Istio提供一种简单的方式来建立已部署的服务的网络,具备负载均衡,服务到服务认证,监控等等功能,而不需要改动任何服务代码。


——敖小剑《万字解读:Service Mesh服务网格新生代--Istio》


Istio v0.2添加很多新的功能以及改建,下面来谈一谈,Istio v0.2让人激动的5大改进:


Automatic Sidecar Injection

对于自定义资源和初始化器的支持,Istio v0.2要求Kubernetes1.7.4或更新,如果集群中启用了I nitializer Alpha特性,建议安装Istio初始化器,它为所有想要的Istio管理的微服务部署注入了自动的Sidecar。IBM Bluemix容器服务集群在1.7.4或更新时自动运行,这与Istio初始化器很好地工作,由于仍然是Istio开发总体方案中的一个Alpha特性,所以建议谨慎使用。


Traffic Management Improvement

在Istio v0.1中,用户可以使用Ingress路由规则来制定想要通过微服务进入的流量,现在,还可以使用e外出路由规则来制定想要从微服务中获得哪些类型的流量,以及服务可以与哪些外部服务进行通信,例如,用户可以轻松地配置服务,与IBM Cloud中的IBM Watson服务之一进行对话,从而为用户的服务提供人工智能功能。


Improved Telemetry

作为Istio用户,无需做任何事情去启动各种度量或跟踪,这非常简便,用户可以部署微服务应用,让Istio进行管理,而不需要任何应用程序或部署。Yaml文件,Zipkin的跟踪为应用提供了详细的跟踪信息,Zipkin的进一步追踪让人可以深入到每一个请求中,以查看流量子啊服务网格中如何技术,如果用户更喜欢Jaeger,也提供支持。


多环境支持


Istio的最初目标之一就是进行多环境的支持,在微服务体系结构中,无法要求所有的工作负载都在Kubernetes中运行,用户的一些应用程序可能在Kubernetes中运维,而另外一些可能在Docker Swarm或者VM中运行,在Istio v0.2中,引入了早期对VM的支持,并与一些更流行的服务发现系统进行了集成,Istio已经被扩展支持到其他运行时环境,这是让人兴奋的一件事。


在Kubernetes环境中使用Kubectl与Istio进行交互

本文作者最喜欢的一项是Istio v0.2更新了配置的模式,并使用Kubernetes的自定义资源定义,这意味着用户现在可以在Kubernetes环境中使用Kubectl与Istio进行交互,如果有自动的Sidecar注入,在Kuberentes环境中与Istio互动时,就无需Istioctl了,当用户想要首都注入Sidecar或与诸如控制台和VM等多环境交互时,Istioctl就变得有用了。


原文作者:DevCentral

原文链接:https://www.tuicool.com/articles/uE3uyyV
 

Istio官方文档中文版翻译基本完成!

敖小剑 发表了文章 • 0 个评论 • 809 次浏览 • 2017-11-16 14:19 • 来自相关话题

经过我们service mesh中国技术社区翻译小组的艰辛努力,在今天,Istio官方文档中文版的翻译主体部分基本完成。
 
浏览地址:
 
http://istio.doczh.cn/https://doczhcn.gitbooks.io/istio/
 
在接下来的两周中,我们将组织人力进行review和修订。也非常欢迎大家在浏览文档的同时,支持和参与我们的review和修订工作:如有谬误,或者发现英文文档有更新,请通过issue或者PR向我们提交。
 
另外,经过和istio官方的沟通,我们将在稍后(等待review完成)将这份翻译完成的中文文档贡献给istio官方,之后我们社区将继续组织人力维护和更新这份文档。
 
鸣谢参与翻译工作的翻译小组同学,也鸣谢在期间通过PR贡献力量的同学。感谢你们的辛苦努力!
 
contributors 列表如下:
 
https://github.com/doczhcn/istio/graphs/contributors
  查看全部
经过我们service mesh中国技术社区翻译小组的艰辛努力,在今天,Istio官方文档中文版的翻译主体部分基本完成。
 
浏览地址:
 

 
在接下来的两周中,我们将组织人力进行review和修订。也非常欢迎大家在浏览文档的同时,支持和参与我们的review和修订工作:如有谬误,或者发现英文文档有更新,请通过issue或者PR向我们提交。
 
另外,经过和istio官方的沟通,我们将在稍后(等待review完成)将这份翻译完成的中文文档贡献给istio官方,之后我们社区将继续组织人力维护和更新这份文档。
 
鸣谢参与翻译工作的翻译小组同学,也鸣谢在期间通过PR贡献力量的同学。感谢你们的辛苦努力!
 
contributors 列表如下:
 
https://github.com/doczhcn/istio/graphs/contributors