编辑推荐: |
本文来自于infoq,介绍如何全面了解Kubernetes基础设施以及如何在基于容器的基础设施中使用Istio服务网格。 |
|
运营容器化的基础设施带来了一系列新的挑战。我们需要增强容器、评估API端点的性能以及识别出基础设施中的有害部分。Istio服务网格可在不修改代码的情况下实现API增强,并且不会带来服务延迟。这篇文章将介绍如何全面了解Kubernetes基础设施以及如何在基于容器的基础设施中使用Istio服务网格。
Istio概览
Istio是用于Kubernetes的服务网格,负责处理服务之间的通信,就像网络路由软件处理TCP/IP流量那样。除了Kubernetes之外,Istio还可以与基于Docker和Consul的服务发生交互。它与已经存在了一段时间的LinkerD有点相似。
Istio是由来自谷歌、IBM、思科和Lyft Envoy的团队共同开发的一个开源项目。Istio最近刚满一岁,却已经被大规模部署到生产环境中。在写这篇文章时
(2018年1月10日),Istio版本为0.8。
那么,如何在Kubernetes生态系统中使用Istio?可以这么说,Kubernetes充当的是数据平面,Istio则充当控制平面。Kubernetes负责承载应用程序流量,进行容器的编配、部署和扩展。Istio则负责路由应用程序流量,处理策略执行、流量管理和负载均衡问题。它还聚合遥测元素,如指标、日志和跟踪。Istio是基于容器基础设施的协管员和警报员。
上图描绘了服务网格的架构。Istio为每项服务运行一个Envoy边车代理。Envoy代理通过GRPC调用将入站请求转发至Istio
Mixer服务。然后,Mixer应用流量管理规则来聚合遥测元素。Mixer是Istio的大脑。运维人员可以通过编写YAML文件来指定Envoy如何重定向流量,还可以指定将哪些遥测元素推送到监控系统和观测系统。我们可以在运行时根据具体情况应用相应的规则,无需重新启动任何Istio组件。
Istio支持多种适配器,用于将数据发送到各种监控工具,如Prometheus、Circonus或Statsd。我们也可以同时启用Zipkin和Jaeger跟踪,生成图形以便对服务进行可视化。
Istio的部署非常简单。大概七八个月之前,我们必须通过一系列kubectl命令将Istio安装到Kubernetes群集上。现在当然也可以这么做,不过有另一种更加简便的方式,就是在谷歌云平台上点击几下鼠标即可部署启用了Istio的Kubernetes群集,包括监控、跟踪和示例应用程序。
另一个好处是,我们可以在不要求开发人员对他们的服务进行增强的情况下收集服务数据。这样可以减少维护工作、消除代码中的失败点。它还提供了与供应商无关的接口,降低了被供应商锁定的可能性。
借助Istio,我们可以部署单个服务的不同版本,并权衡它们之间的流量。Istio本身使用了多个不同的pod,如下所示:
> kubectl
get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istio-ca-797dfb66c5 1/1 Running 0 2m
istio-ingress-84f75844c4 1/1 Running 0 2m
istio-egress-29a16321d3 1/1 Running 0 2m
istio-mixer-9bf85fc68 3/3 Running 0 2m
istio-pilot-575679c565 2/2 Running 0 2m
grafana-182346ba12 2/2 Running 0 2m
prometheus-837521fe34 2/2 Running 0 2m |
Istio实际上不是轻量级的。Istio的强大功能和灵活性带来了一些运营成本。但是,如果应用程序中包含多个微服务,那么应用程序容器很快会表现出比系统配置容器更大的优势。
服务水平目标
关于服务水平目标的概述将为我们如何衡量服务健康状况奠定基础。服务水平协议(Service Level
Agreement,SLA)的概念已经存在了至少十年。而直到最近,与服务水平目标(Service Level
Objective,SLO)和服务水平指示器(Service Level Indicator,SLI)相关的网络内容才出现爆发式的增长。
除了谷歌的那本“Site Reliability Engineering”之外,还有两本有关SLO的新书即将问世。“The
Site Reliability Workbook”有专门的章节介绍了SLO,而Circonus创始人兼首席执行官Theo
Schlossnagle在“Seeking SRE”的一个章节中对SLO的目标进行了定义。建议观看由Seth
Vargo和Liz Fong Jones呈献的YouTube视频“SLIs,SLOs,SLAs,oh
my!” (链接:https://youtu.be/tEylFyxbDLE),以便深入了解SLI、SLO和SLA之间的差别。
总的来说:SLI驱动SLO,SLO通知SLA。
SLI是衡量服务健康状况的指标。例如,我们可以有这样的一个SLI,它表示在过去5分钟内,95%的主页面请求延迟应小于300毫秒。
SLO是SLI的目标。我们对SLI进行扩展,用以量化我们对服务在给定时间间隔内执行情况的期望。以上面的SLI为例,我们可以说,我们希望这个SLI设定的标准在下一年可以达到99.9%。
SLA是企业与客户之间的协议,定义了未能满足SLO的后果。一般来说,SLA所依据的SLO比内部SLO更宽松,因为我们希望内部目标比外部目标更为严格。
RED仪表盘
怎样的SLI组合最适合用于量化主机和服务的健康程度?在过去几年中,出现了一些新兴的标准。其中最有影响力的是USE方法、RED方法和谷歌SRE手册中讨论的“四个黄金信号”。
USE方法由Brendan Gregg提出,旨在根据利用率、饱和度和错误指标量化系统主机的健康状况。对于像CPU这样的产品,我们可以使用常用的指标,如用户、系统和闲置百分比。我们可以使用平均负载和运行队列来衡量饱和度。UNIX的perf分析器是用来测量CPU错误事件的一个很好的工具。
几年前,Tom Wilkie提出了RED方法。借助RED方法,我们对请求率、请求错误和请求持续时间进行监控。谷歌SRE手册讨论了如何使用延迟、流量、错误和饱和度这四个指标。这“四个黄金信号”主要针对服务健康,与RED方法类似,只是多了饱和度这一项。但在实践中,可能难以量化服务饱和度。
那么,我们如何监控容器?容器存活期短,通过直接监控它们来识别服务健康状况将带来很多复杂的问题,例如高基数问题。通过聚合这些容器的输出来监控它们会更容易和有效。如果一个服务是健康的,我们就不会在乎容器的行为是否正常。我们的编配框架会捕获到这个容器,并用新的容器取而代之。
让我们来看看如何将Istio的SLI作为RED仪表盘的一部分。首先看看Istio都提供了哪些遥测元素:
基于响应码的请求数
请求时长
请求大小
响应大小
连接收到的字节
连接发送的字节
连接时长
基于模板的元数据(度量标签)
Istio提供了几个有关收到的请求、响应延迟和连接信息的指标。请注意上述列表中的前两项,我们希望将它们包含在RED仪表盘中。
Istio还赋予我们添加度量标签的能力,就是所谓的维度。我们可以按照主机、集群等对遥测元素进行拆解。我们可以通过计算请求数的一阶导数来获得每秒请求速率。我们还可以通过计算不成功请求数的导数来获得错误率。Istio还为我们提供了每个请求的延迟,因此我们可以记录每个服务请求需要多少时间才能处理完。
另外,Istio还为我们提供了一个Grafana仪表盘,它包含了我们想要的部分:
上面截图中以红色圈起来的部分是我们想要的组件。左上角是每秒操作请求速率,右上角是每秒失败请求数,底下是响应时间。现在让我们来仔细看看圈出的那几个指标:
这个截图显示了仪表盘的速率组件。我们统计返回200响应码的请求数,并绘制成图形。
Istio仪表盘为返回5xx错误码的响应做了类似的操作。在上面的截图中,可以看到,它按照摄入控制器或应用程序产品页的错误来区分错误。
这个截图显示了请求持续时间,提供了丰富的有关服务健康状况的信息。这些数据由Prometheus监控系统提供,因此我们可以看到请求时间百分位,包括中位数、90th、95th和99th这些百分位。
这些百分位为我们提供了有关服务执行情况的全面指示。但是,这种方法也存在一些缺陷。在活动不是很活跃的时候,由于样本数量有限,这些百分位可能会大幅偏离,给我们带来误导。这种方法可能出现的其他问题:
持续时间问题:
百分位是基于固定时间窗口的聚合指标。
无法为群集健康重新聚合百分位。
不能计算百分位平均数(这是一个常见的错误)。
这种方法存储的聚合是输出,而不是输入。
很难用这种方法测量集群SLI。
百分位通常比平均数提供更深刻的洞见,因为它们使用多个数据点来表示数值范围。但与平均数一样,百分位是一种聚合度量。它们是基于固定时间窗口对固定数据集计算得出的。如果我们要计算某个集群成员的持续时间百分比,就不能将其与另一个集群成员合并,因为这样得到的是整个集群的聚合指标。
我们不能计算百分位的平均数,除非产生这些百分位的分布几乎是一样的,但这种情况很少见。如果你只有百分位,而不是源数据,那么就不知道它是不是这种情况。这是一个鸡生蛋和蛋生鸡的问题。
这也意味着,如果你只是基于百分比衡量单个集群成员的性能,就会因缺少聚合而无法为整个服务设置SLI。
由于在固定时间窗口内只有4个延迟数据点,我们只能在有限的范围内设置有意义的SLI。因此,在你使用基于百分位的持续时间指标时,必须问自己,你的SLI是否真的足够好。我们可以借助数学来设定更好的SLI,从而全面了解服务的性能和健康状况。
直方图遥测
上面是以微秒为单位显示服务延迟数据的一个直方图。样本数量位于Y轴上,样本值(微秒级延迟)位于X轴上。这是我们在Circonus开发的开源直方图,也请参考C语言(https://github.com/circonus-labs/libcircllhist)和Golang(https://github.com/circonus-labs/circonusllhist)的直方图开源实现。还有其他一些开源的直方图实现,如Ted
Dunning的t-digest直方图(https://github.com/tdunning/t-digest)和HDR直方图(http://hdrhistogram.org/)。
Envoy项目最近采用了Circonus开发的C语言版本的对数线性直方图库,因此可以显示所收集数据的分布情况。
直方图是可以合并的,只要bin的边界相同,任何两个或多个直方图都可以合并在一起。这意味着我们可以将多个分布组合在一起。可合并的度量指标对于监控和可观测性来说非常有用。我们因此可以合并来自相似资源(如服务成员)的输出,并获得聚合的服务指标。
如上图所示,在这个对数线性直方图中,每10次幂对应90个bin。从图中可以看到100K到1M个之间的90个bin。对于每10次幂,bin的大小就以10的倍数增长。这样我们就能够以较高的相对精度记录各种数值,而不需要提前知道数据的分布情况。如果我们将一些百分位重叠起来会是什么样子:
可以看到,现在有平均值、50th百分位(也称为中位数)和90th百分位。90th百分位是指90%样本低于该值。
现在回到之前的SLI示例,如果按照这种格式来显示延迟数据,就可以通过将直方图合并在一起来获得5分钟的数据视图,然后计算出该分布的90th百分位,从而得到服务的SLI。如果它低于1,000毫秒,就达到了我们的目标。
上面截图中的RED仪表盘包含了四个百分位:50th、90th、95th和99th。我们也可以重叠这些百分位。即使在没有数据的情况下,我们也可以看到请求分布的大致轮廓,当然,这里需做出很多假设。要想知道仅基于几个百分位做出的假设将给我们造成怎样的误导,可以看看这个带有其他模式的分布:
这个直方图显示了两种不同模式的分布。左边的模式表示快速响应,可能是因为使用了缓存,而右边的表示从磁盘上读取数据再做出响应。仅使用四个百分位来衡量延迟几乎不可能辨别这种分布。可见,百分位会隐藏掉一些复杂性。现在让我们来看看具有两种以上模式的分布:
这个分布至少有四种模式。如果我们在全分布上运行数学运算,可以找到20多种模式。那么我们需要记录多少个百分位才能获得一个近似于上面这样的延迟分布呢?又比如下面这个分布呢?
由很多服务组成的复杂系统将生成无法用百分位准确表示的延迟分布,我们必须记录整个延迟分布才能完整地表示它。这就是为什么要将数据的完整分布放在直方图中,并根据实际需要计算出百分位,而不只是保存几个百分位。
这种直方图显示了固定时间窗口上的分布。我们可以存储多个分布,以了解它随时间变化的情况,如下所示:
这是一个热图,代表一组随时间变化的直方图。想象一下,这个热图中的每一列都有一个单独的条形图,用颜色来表示每个bin的高度。这是一个集群(包含10个负载均衡器)响应延迟在Grafana中的可视化。我们因此能够深入了解整个集群一周之内的行为,这里包含了100万个数据样本。这里的中位数大约在500微秒左右,以红色条形表示。
上面是另一种类型的热图,其中使用饱和度表示每个bin的“高度”(块颜色越深表示越“饱和”)。此外,这次我们在热图上重叠了随时间变化的百分位。百分位是可靠的度量指标,而且非常有用,但它们本身并不能发挥这种作用。我们可以看到90以上的百分位将如何随着延迟分布向上移动而增加。
让我们来看看这些时间段分布图,看看是否可以生成比样本仪表盘包含更多信息的东西:
上面的截图是修改后的RED仪表盘,显示了基于分布的延迟数据。左下角显示了固定时间窗口的延迟直方图。在它的右边,我们使用热图将分布分解成更小的时间窗口。利用RED仪表盘的布局,我们只需要借助几个信息面板就可以全面了解我们的服务是如何运作的。这个仪表盘是使用Grafana实现的,后台使用了IRONdb时间序列数据库,该数据库在本地存储延迟数据,用于构建对数线性直方图。
我们可以进一步扩展这个RED仪表盘,并将SLI重叠到上面:
对于速率面板,我们的SLI可能会保持最低水平的每秒请求数,每秒错误数也可能保持在某个值之下。正如我们之前研究过的SLI,我们可能希望整个服务的99th百分位在固定时间窗口内保持一定的延迟。我们可以借助这些直方图来设置有意义的SLI。现在我们还有很多工作要做,而且可以更好地审查我们的数据。
问正确的问题
我们已经把所有的东西都放在了一起,并看到了如何利用Istio从服务中获取有意义的数据,现在让我们看看可以解决哪些问题。
我们都希望能够解决技术问题,但不是每个人都专注于此。业务人员会问业务方面的问题,所以你要能够回答这些问题。接下来让我们看看已经组装好的工具将怎样解决业务人员向SRE提出的问题:
示例问题:
在周二的大促活动后,有多少用户因为速度变慢而感到不愉快?
我们的结帐服务是过度配置了还是配置不足?
先看第一个例子。每个人可能都有过访问龟速网站的体验。假设一次市场大推广导致流量暴增,性能下降,用户抱怨网站速度太慢。我们如何量化速度有多慢?有多少用户感到不愉快?假设市场营销部门想知道这些问题的答案,然后就可以向受影响的用户发送10%折扣的电子邮件,同时希望避免同样问题再次发生。我们定义了一个SLI,假设用户注意到速度变慢,并在请求超过500毫秒时感到生气。我们如何基于这个500毫秒的SLI计算有多少用户感到生气?
首先,我们需要记录请求延迟,然后将它们绘制成热图。我们可以使用分布数据来计算超过500毫秒SLI的请求的百分比(借助反向百分位),然后将其乘以该时间窗口中的请求总数,最后将随时间变化的结果重叠在热图上:
在上面的截图中,我们已经在热图上圈出了速度变慢的部分。增加的延迟分布足以告诉我们速度变慢了。图中的线表示受影响的请求总数随时间变化的情况。
在这个例子中,有400万个请求达不到我们的SLI。右边的两处速度变慢不是很明显,因为它们的幅度较小,但每处都有200万个请求达不到SLI。
我们可以继续进行这类数学分析,因为数据被存储为分布,而不只是聚合的百分位。
现在让我们来考虑另一个问题,即我们的服务是配置不足还是配置过度?
答案通常是“视情况而定”。除了碰上特殊日子,负载在一天中和一周中的每一天也都有所不同。在我们搞清楚系统在特定负载下的行为之前,我们所知道的就是这些。现在我们来做一些简单的数学运算,使用延迟来可视化系统是如何运行的:
上面的可视化显示了延迟分布随时间变化的情况,包括低于25毫秒的请求数、25毫秒到100毫秒的请求数、100毫秒到250毫秒的请求数、250毫秒到1000毫秒的请求数以及超过1000毫秒的请求数。它们按照颜色进行分组,绿色表示快速请求,红色表示慢请求。
这种可视化告诉了我们什么?我们可以看到,服务请求在一开始非常快,几分钟后快请求的百分比下降,大约10分钟后慢请求的百分比增加。这种模式在两次流量会话中重复出现。这又告诉了我们什么?这表明,最初服务过度配置,但在随后的10到20分钟内配置不足。看起来,这里很适合使用自动伸缩。
我们也可以将这种类型的可视化添加到RED仪表盘中。这种类型的数据对业务利益相关者来说非常有用,而且他们不需要掌握大量的技术知识就可以了解它们对业务的影响。
结论
我们应该监控服务,而不是容器。服务是长期存活的实体,而容器不是。用户并不关心容器如何运行,他们只关心服务如何运行。
我们应该记录分布而不是聚合,不过要能够从这些分布中生成聚合。聚合是非常有价值的信息来源。但它们是不可合并的,因此不适用于统计分析。
Istio提供了很多现成的东西,我们没有必要去修改我们的代码,也没必要从头开始构建高质量的应用程序框架。
使用数学方法提出并回答有关服务的问题。当我们通过解决重要的业务问题让系统变得更加可靠时,其实是实现了组织的目标。 |