Istio 導入への道 - Fault Injection 編

Istio シリーズです。

今回は Fault Injection です。前回の VirtualService に設定を入れることでわざと 503 とか 500 エラーを返したり、delay を入れたりすることができます。

500 Internal Server Error を返す

現在の設定を確認。QueryString に v=1 があれば v1 に、それ意外は v2 に送られます。

$ kubectl get vs httpbin-virtual-service -o yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  annotations:
...
(省略)
...
spec:
  hosts:
  - httpbin-service
  http:
  - match:
    - name: v1
      queryParams:
        v:
          exact: "1"
    route:
    - destination:
        host: httpbin-service
        subset: v1
  - route:
    - destination:
        host: httpbin-service
        subset: v2

route のレベルに fault を入れます。v1 のところに入れてみます。(HTTPFaultInjection.Abort)

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: httpbin-virtual-service
spec:
  hosts:
  - httpbin-service
  http:
  - match:
    - name: v1
      queryParams:
        v:
          exact: "1"
    fault:
      abort:
        httpStatus: 500
        percentage:
          value: 50
    route:
    - destination:
        host: httpbin-service
        subset: v1
  - route:
    - destination:
        host: httpbin-service
        subset: v2
EOF

v1 の場合に、50% の割合で 500 Internal Server Error を返すようにしました。

root@ubuntu-deployment-cc86cc647-vsvbh:/# curl -sv http://httpbin-service/headers\?v=1
*   Trying 10.109.118.31...
* TCP_NODELAY set
* Connected to httpbin-service (10.109.118.31) port 80 (#0)
> GET /headers?v=1 HTTP/1.1
> Host: httpbin-service
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 500 Internal Server Error
< content-length: 18
< content-type: text/plain
< date: Sun, 08 Mar 2020 01:53:15 GMT
< server: envoy
< 
* Connection #0 to host httpbin-service left intact
fault filter abort

curl を実行した Pod 側で istio-proxy のログを確認してみると response_flagsFI (Fault Injection) と入っています。また、宛先の Pod 側ではログが出ていないため、リクエストは送られていないようです。まあそうでしょう。curl 側のログも upstream の項目が空です。

{
  "authority": "httpbin-service",
  "bytes_received": "0",
  "bytes_sent": "18",
  "downstream_local_address": "10.109.118.31:80",
  "downstream_remote_address": "172.17.0.9:60170",
  "duration": "5",
  "istio_policy_status": "-",
  "method": "GET",
  "path": "/headers?v=1",
  "protocol": "HTTP/1.1",
  "request_id": "76435924-cdea-4fdb-ae52-bc5db43946fc",
  "requested_server_name": "-",
  "response_code": "500",
  "response_flags": "FI",
  "route_name": "-",
  "start_time": "2020-03-08T01:53:15.360Z",
  "upstream_cluster": "-",
  "upstream_host": "-",
  "upstream_local_address": "-",
  "upstream_service_time": "-",
  "upstream_transport_failure_reason": "-",
  "user_agent": "curl/7.58.0",
  "x_forwarded_for": "-"
}

percentage で 50 と指定しているため全てが 500 Error になるわけではなく、リクエストの半分です。percentage の型は double で小数で 1% 未満も指定可能です。もちろんこの設定では v2 側へのアクセス時には 500 Error は返されません。本当に Upstream 側で返されれば別でしょうが。

Delay を挿入する

次に v2 側に delay を入れてみます。(HTTPFaultInjection.Delay)

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: httpbin-virtual-service
spec:
  hosts:
  - httpbin-service
  http:
  - match:
    - name: v1
      queryParams:
        v:
          exact: "1"
    fault:
      abort:
        httpStatus: 500
        percentage:
          value: 50
    route:
    - destination:
        host: httpbin-service
        subset: v1
  - route:
    - destination:
        host: httpbin-service
        subset: v2
    fault:
      delay:
        fixedDelay: 5s
        percentage:
          value: 50
EOF

これで v2 へリクエストを送る際に 50% の割合で5秒の delay が挿入されます。ログを確認してみます。

curl を実行している側の Pod の istio-proxy のログです。"response_flags": "DI" となっており、Delay が挿入されていることがわかります。"start_time": "2020-03-08T02:11:04.369Z" を宛先側のログと比較してみます。

{
  "authority": "httpbin-service",
  "bytes_received": "0",
  "bytes_sent": "521",
  "downstream_local_address": "10.109.118.31:80",
  "downstream_remote_address": "172.17.0.9:47376",
  "duration": "5004",
  "istio_policy_status": "-",
  "method": "GET",
  "path": "/headers",
  "protocol": "HTTP/1.1",
  "request_id": "71da7efc-29a0-4e03-b23b-bfbf1638c273",
  "requested_server_name": "-",
  "response_code": "200",
  "response_flags": "DI",
  "route_name": "-",
  "start_time": "2020-03-08T02:11:04.369Z",
  "upstream_cluster": "outbound|80|v2|httpbin-service.default.svc.cluster.local",
  "upstream_host": "172.17.0.8:80",
  "upstream_local_address": "172.17.0.9:54576",
  "upstream_service_time": "2",
  "upstream_transport_failure_reason": "-",
  "user_agent": "curl/7.58.0",
  "x_forwarded_for": "-"
}

宛先側の Pod の istio-proxy のログです。"start_time": "2020-03-08T02:11:09.371Z" と開始が5秒遅れていることが確認できます。送信元側で待ってから送っているようです。

{
  "authority": "httpbin-service",
  "bytes_received": "0",
  "bytes_sent": "521",
  "downstream_local_address": "172.17.0.8:80",
  "downstream_remote_address": "172.17.0.9:54576",
  "duration": "2",
  "istio_policy_status": "-",
  "method": "GET",
  "path": "/headers",
  "protocol": "HTTP/1.1",
  "request_id": "71da7efc-29a0-4e03-b23b-bfbf1638c273",
  "requested_server_name": "outbound_.80_.v2_.httpbin-service.default.svc.cluster.local",
  "response_code": "200",
  "response_flags": "-",
  "route_name": "default",
  "start_time": "2020-03-08T02:11:09.371Z",
  "upstream_cluster": "inbound|80|http|httpbin-service.default.svc.cluster.local",
  "upstream_host": "127.0.0.1:80",
  "upstream_local_address": "127.0.0.1:50500",
  "upstream_service_time": "1",
  "upstream_transport_failure_reason": "-",
  "user_agent": "curl/7.58.0",
  "x_forwarded_for": "-"
}

は OutlierDetection / 異常値検出 かな。


Istio 導入への道シリーズ

Built with Hugo
テーマ StackJimmy によって設計されています。