22. 故障注入

使用 Service Mesh InterfaceTraffic Split API 很容易将故障注入应用程序。 TrafficSplit 允许您将一定比例的流量重定向到特定后端。 这个后端是完全灵活的,可以返回任何你想要的响应——500s超时甚至疯狂的有效载荷

books demo 是展示这种行为的好方法。整体拓扑如下:

Topology
Topology

在本指南中,您将把一些请求从 webapp 拆分到 books。 大多数请求最终会到达正确的 books 目的地,但其中一些将被重定向到有问题的后端。 此后端将为每个请求返回 500s 并将故障注入 webapp 服务。 不需要更改代码,并且由于此方法是配置驱动的, 因此可以将其添加到集成测试CI 管道中。 如果你真的过着混沌工程(chaos engineering)lifestyle,甚至可以在生产中使用故障注入

前提条件

要使用本指南,您需要在集群上安装 Linkerd 及其 Viz 扩展。 如果您还没有这样做,请按照安装 Linkerd 指南进行操作。

设置服务

首先,将 books 示例应用程序添加到您的集群:

kubectl create ns booksapp && \
  linkerd inject https://run.linkerd.io/booksapp.yml | \
  kubectl -n booksapp apply -f -

由于此清单在其他地方用作 demo,因此已配置错误率(error rate)。 为了展示故障注入的工作原理,需要去除错误率,以便有一个可靠的基线(reliable baseline)。 要将 booksapp成功率提高到 100%,请运行:

kubectl -n booksapp patch deploy authors \
  --type='json' \
  -p='[{"op":"remove", "path":"/spec/template/spec/containers/0/env/2"}]'

过了一会儿,统计数据会显示 100%成功率。您可以通过运行以下命令来验证这一点:

linkerd viz -n booksapp stat deploy

输出最终看起来有点像:

NAME      MESHED   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99   TCP_CONN
authors      1/1   100.00%   7.1rps           4ms          26ms          33ms          6
books        1/1   100.00%   8.6rps           6ms          73ms          95ms          6
traffic      1/1         -        -             -             -             -          -
webapp       3/3   100.00%   7.9rps          20ms          76ms          95ms          9

创建有问题的后端

将故障注入到 booksapp 中需要一个配置为返回错误的服务。 为此,您可以启动 NGINX 并通过运行以下命令将其配置为返回 500s

cat <<EOF | linkerd inject - | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: error-injector
  namespace: booksapp
data:
 nginx.conf: |-
    events {}
    http {
        server {
          listen 8080;
            location / {
                return 500;
            }
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: error-injector
  namespace: booksapp
  labels:
    app: error-injector
spec:
  selector:
    matchLabels:
      app: error-injector
  replicas: 1
  template:
    metadata:
      labels:
        app: error-injector
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          volumeMounts:
            - name: nginx-config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
      volumes:
        - name: nginx-config
          configMap:
            name: error-injector
---
apiVersion: v1
kind: Service
metadata:
  name: error-injector
  namespace: booksapp
spec:
  ports:
  - name: service
    port: 8080
  selector:
    app: error-injector
EOF

注入故障

随着 booksappNGINX 的运行,现在是时候在现有的后端(backend)books 和 新创建的 error-injector 之间部分地分割流量了。 这是通过向集群添加 TrafficSplit 配置来实现的:

cat <<EOF | kubectl apply -f -
apiVersion: split.smi-spec.io/v1alpha1
kind: TrafficSplit
metadata:
  name: error-split
  namespace: booksapp
spec:
  service: books
  backends:
  - service: books
    weight: 900m
  - service: error-injector
    weight: 100m
EOF

Linkerd 看到流向 books 服务的流量时, 它会向原始服务发送 9⁄10 个请求,向错误注入器(error injector)发送 1⁄10 个请求。 您可以通过运行 stat 并显式过滤来自 webapp 的请求来查看它的样子:

linkerd viz -n booksapp routes deploy/webapp --to service/books

与之前的 stat 命令只查看服务器收到的请求不同, 这个 routes 命令过滤到所有由 webapp 发出的 发往 books 服务本身的请求。输出应显示 90% 的成功率:

ROUTE       SERVICE   SUCCESS      RPS   LATENCY_P50   LATENCY_P95   LATENCY_P99
[DEFAULT]     books    90.08%   2.0rps           5ms          69ms          94ms

清理

要从集群中删除本指南中的所有内容,请运行:

kubectl delete ns booksapp