使用服务网格接口和Linkerd进行故障注入

原创
2020/04/16 10:20
阅读数 29

作者:Alex Leong


应用程序故障注入(failure injection)是混沌工程(chaos engineering)的形式之一,我们在其中人为地增加微服务应用程序中某些服务的错误率,以查看这对整个系统有什么影响。传统上,你需要在服务代码中添加某种类型的故障注入库,以便进行应用程序故障注入。值得庆幸的是,服务网格为我们提供了一种注入应用程序故障的方法,而无需修改或重新构建我们的服务。


结构良好的微服务应用程序的一个特点,是它能够优雅地容忍单个服务的失败。当这些故障以服务崩溃的形式出现时,Kubernetes通过创建新的pod来替换已经崩溃的pod,在治愈这些故障方面做得非常好。然而,失败也可能更加微妙,导致服务返回更高的错误率。这些类型的故障不能由Kubernetes自动修复,但仍然会导致功能损失。


使用流量分割SMI API注入故障

通过使用服务网格接口(Service Mesh Interface)的流量分割API(Traffic Split API),我们可以很容易地注入应用程序故障。这允许我们以一种与实现无关、跨服务网格工作的方式进行故障注入。


为此,我们首先部署一个只返回错误的新服务。这可以像配置为返回HTTP 500响应的NGINX服务一样简单,也可以是更复杂的服务,返回专门设计的错误,以执行你希望测试的某些条件。然后,我们创建一个流量分割资源,该资源指示服务网格将目标服务流量的百分比发送到错误服务。例如,通过将服务流量的10%发送给错误服务,我们向该服务注入了一个人工的10%故障率。


让我们来看一个使用Linkerd作为服务网格实现的实例。


例子

我们将首先安装Linkerd CLI,并将其部署到我们的Kubernetes集群:

> curl https://run.linkerd.io/install | sh> export PATH=$PATH:$HOME/.linkerd2/bin> linkerd install | kubectl apply -f -> linkerd check

现在我们将安装booksapp示例应用程序:

> linkerd inject https://run.linkerd.io/booksapp.yml | kubectl apply -f -

此应用程序中的一个服务配置了错误率。这个演示的重点,是表明我们可以在应用程序中不需要任何支持就可以注入故障,所以让我们删除配置的故障率:

> kubectl edit deploy/authors# Find and remove these lines:#        - name: FAILURE_RATE#          value: "0.5"

我们现在应该看到应用程序是健康的:

> linkerd stat deployNAME             MESHED   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99   TCP_CONNauthors             1/1   100.00%   6.6rps           3ms          58ms          92ms          6books               1/1   100.00%   8.0rps           4ms          81ms         119ms          6traffic             1/1         -        -             -             -             -          -webapp              3/3   100.00%   7.7rps          24ms          91ms         117ms          9

现在我们可以创建错误服务了。在这里,我将使用NGINX配置为只响应HTTP状态码500。创建一个名为error-injector.yaml的文件:

apiVersion: apps/v1kind: Deploymentmetadata:  name: error-injector  labels:    app: error-injectorspec:  selector:    matchLabels:      app: error-injector  replicas: 1  template:    metadata:      labels:        app: error-injector    spec:      containers:        - name: nginx          image: nginx:alpine          ports:          - containerPort: 80            name: nginx            protocol: TCP          volumeMounts:            - name: nginx-config              mountPath: /etc/nginx/nginx.conf              subPath: nginx.conf      volumes:        - name: nginx-config          configMap:            name: error-injector-config---apiVersion: v1kind: Servicemetadata:  labels:    app: error-injector  name: error-injectorspec:  clusterIP: None  ports:  - name: service    port: 7002    protocol: TCP    targetPort: nginx  selector:    app: error-injector  type: ClusterIP---apiVersion: v1data: nginx.conf: |2

events { worker_connections 1024; }

http { server { location / { return 500; } } }kind: ConfigMapmetadata: name: error-injector-config

和部署它:

> kubectl apply -f error-injector.yaml

现在我们可以创建一个流量分割资源,它将把10%的图书服务定向到错误服务。创建一个名为error-split.yaml的文件:

apiVersion: split.smi-spec.io/v1alpha1kind: TrafficSplitmetadata:  name: error-splitspec:  service: books  backends:  - service: books    weight: 900m  - service: error-injector    weight: 100m

和部署它:

> kubectl apply -f error-split.yaml

我们现在可以看到从webapp调用到书籍10%的故障

> linkerd routes deploy/webapp --to service/booksROUTE       SERVICE   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99[DEFAULT]     books    90.66%   6.6rps           5ms          80ms          96ms

我们还可以看到应用程序如何优雅地处理这些故障:

> kubectl port-forward deploy/webapp 7000 &> open http://localhost:7000

看起来其实不太好!如果刷新页面几次,有时会看到内部服务器错误页面。



我们学习了一些有价值的东西,关于我们的应用程序如何面对服务错误。让我们恢复我们的应用程序,只需删除流量分割资源:

> kubectl delete trafficsplit/error-split


总结

在本文中,通过使用SMI API(由Linkerd提供)将一部分流量动态重定向到一个简单的“总是失败”目的地,我们演示了在服务级别进行故障注入的快速而简单的方法。这种方法的美妙之处在于,我们能够完全通过SMI API来完成它,而不需要更改任何应用程序代码。


当然,故障注入是一个广泛的主题,还有许多更复杂的方法来注入故障,包括某些路由故障、只匹配特定条件的请求故障或在整个应用程序拓扑中传播单个“毒丸”请求。这些类型的故障注入将需要比这篇文章所涵盖的更多的设定。


Linkerd是一个社区项目,由CNCF(Cloud Native Computing Foundation,云原生计算基金会)托管。如果你有功能需求、问题或评论,我们欢迎你加入我们快速增长的社区!Linkerd代码托管在GitHub上,我们在Slack、Twitter和邮件列表上都有一个蓬勃发展的社区。来一起玩吧!


点击文末<<阅读原文>>进入网页了解更多。




CNCF邀请你加入最终用户社区

加入CNCF最终用户社区的权益包括:

  • 5张门票参加云原生社区的盛会KubeCon + CloudNativeCon北美、欧洲或中国(公司少于300名员工的提供2张门票)。




CNCF (Cloud Native Computing Foundation)成立于2015年12月,隶属于Linux  Foundation,是非营利性组织。 

CNCF云原生计算基金会)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。请长按以下二维码进行关注。

本文分享自微信公众号 - CNCF(lf_cncf)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部