(#6586) move istio.io test for circuit breaking to istio.io repository (#6609)

* (#6586) move istio.io test for circuit breaking to istio.io repository

* (#6586) add verification for output metrics

* (#6586) widened bounds for both before and after tripping and use ruby for evaluation

* (#6586) fix istioio package import
This commit is contained in:
Suchith J N 2020-03-12 21:35:43 +05:30 committed by GitHub
parent 782a7dba4c
commit 798328b911
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 246 additions and 0 deletions

View File

@ -0,0 +1,48 @@
// Copyright 2020 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package trafficmanagement
import (
"testing"
"istio.io/istio.io/pkg/test/istioio"
"istio.io/istio/pkg/test/framework"
)
func TestCircuitBreaker(t *testing.T) {
framework.
NewTest(t).
Run(istioio.NewBuilder("tasks__traffic_management__circuit_breaking").
Add(
istioio.Script{Input: istioio.Path("scripts/circuitbreaker_test_setup.txt")},
istioio.MultiPodWait("istio-io-circuitbreaker"),
istioio.Script{
Input: istioio.Evaluate(istioio.Path("scripts/trip_circuitbreaker.txt"), map[string]interface{}{
"isSnippet": false,
"inputTerminalFlag": "",
"beforeCircuitBreakVerify": " 2>&1 | verify_circuit_breaking 60 100 0 40",
"afterCircuitBreakVerify": " 2>&1 | verify_circuit_breaking 20 80 20 80",
"outputRedirectionCmd": "2>&1",
}),
SnippetInput: istioio.Evaluate(istioio.Path("scripts/trip_circuitbreaker.txt"), map[string]interface{}{
"isSnippet": true,
"inputTerminalFlag": "-it",
"beforeCircuitBreakVerify": "",
"afterCircuitBreakVerify": "",
"outputRedirectionCmd": "",
}),
}).
Defer(istioio.Script{Input: istioio.Path("scripts/circuitbreaker_test_cleanup.txt")}).
Build())
}

View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Copyright 2020 Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
set -u
set -o pipefail
# $snippet cleanup.sh syntax="bash"
$ kubectl delete destinationrule httpbin -n istio-io-circuitbreaker
$ kubectl delete deploy httpbin fortio-deploy -n istio-io-circuitbreaker
$ kubectl delete svc httpbin -n istio-io-circuitbreaker
$ kubectl delete ns istio-io-circuitbreaker
# $endsnippet

View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Copyright 2020 Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
set -u
set -o pipefail
cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: istio-io-circuitbreaker
labels:
istio-injection: enabled
EOF
# $snippet deploy_httpbin.sh syntax="bash"
$ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n istio-io-circuitbreaker
# $endsnippet
# $snippet deploy_httpbin_destination_rule.sh syntax="bash"
$ cat<<EOF | kubectl -n istio-io-circuitbreaker apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
EOF
$ kubectl get destinationrule httpbin -n istio-io-circuitbreaker -o yaml
# $verify verifier="contains"
spec:
host: httpbin
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
tcp:
maxConnections: 1
outlierDetection:
baseEjectionTime: 3m
consecutiveErrors: 1
interval: 1s
maxEjectionPercent: 100
# $endsnippet
# $snippet deploy_fortio.sh syntax="bash"
$ kubectl apply -f @samples/httpbin/sample-client/fortio-deploy.yaml@ -n istio-io-circuitbreaker
# $endsnippet

View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
# Copyright 2020 Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
set -u
set -o pipefail
# $snippet test_fortio_httpbin_interaction.sh syntax="bash" outputis="text"
$ FORTIO_POD=$(kubectl get pods -n istio-io-circuitbreaker | grep fortio | awk '{ print $1 }')
$ kubectl -n istio-io-circuitbreaker exec {{ .inputTerminalFlag }} $FORTIO_POD -c fortio /usr/bin/fortio -- load -curl http://httpbin:8000/get
# $verify verifier="contains"
200 OK
# $endsnippet
function ruby_eval() {
ruby -e "p $1"
}
# check_percentage_bounds take 4 arguments as input. It must be invoked as follows
#
# $ check_percentage_bounds <percentage-lower-bound-200> <percentage-upper-bound-200> \
# <percentage-upper-bound-503> <percentage-upper-bound-503>
#
# Percentage of requests with status 200 must be between "percentage-lower-bound-200" and
# "percentage-upper-bound-200" inclusive. Same for 503. If bounds are breached then the
# function exits with status 1
function check_percentage_bounds() {
local lower_bounds=( ["200"]=${1:-"100"} ["503"]=${3:-"0"} )
local upper_bounds=( ["200"]=${2:-"100"} ["503"]=${4:-"0"} )
readarray -t code_lines < <(grep -E "^Code ([1-5][0-9]{2,}) : [0-9]+ \(([0-9\.]+) %\)$")
for code_line in "${code_lines[@]}"; do
local status_code=$(echo $code_line | cut -d' ' -f2)
local percentage_req=$(echo $code_line | cut -d' ' -f5 | sed "s/[\(]//g")
local status_lower_bound=${lower_bounds[$status_code]}
local status_upper_bound=${upper_bounds[$status_code]}
local is_lower_bound_breached=$(ruby_eval "$percentage_req < $status_lower_bound")
local is_upper_bound_breached=$(ruby_eval "$percentage_req > $status_upper_bound")
if [[ $is_lower_bound_breached == "true" || $is_upper_bound_breached == "true" ]]; then
echo "either lower bound or upper bound is breached"
echo "status=$status_code actual=$percentage_req, low=$status_lower_bound high=$status_upper_bound"
exit 1
fi
done
}
function verify_circuit_breaking() {
local fortio_output=`cat` # preserve output
echo "$fortio_output" | check_percentage_bounds $1 $2 $3 $4
if (($? != 0)); then
exit 1;
fi
echo "$fortio_output"
}
# $snippet almost_trip_circuit_breaker.sh syntax="bash" outputis="text"
$ kubectl -n istio-io-circuitbreaker exec {{ .inputTerminalFlag }} $FORTIO_POD -c fortio /usr/bin/fortio -- \
load -c 2 -qps 0 -n 20 -loglevel warning http://httpbin:8000/get {{ .beforeCircuitBreakVerify }}
# $endsnippet
# $snippet trip_circuit_breaker.sh syntax="bash" outputis="text"
$ kubectl -n istio-io-circuitbreaker exec {{ .inputTerminalFlag }} $FORTIO_POD -c fortio /usr/bin/fortio -- \
load -c 3 -qps 0 -n 30 -loglevel warning http://httpbin:8000/get {{ .afterCircuitBreakVerify }}
# $endsnippet
# $snippet print_statistics_after_tripping.sh syntax="bash" outputis="text"
$ kubectl -n istio-io-circuitbreaker exec {{ .inputTerminalFlag }} $FORTIO_POD -c istio-proxy -- \
pilot-agent request GET stats | grep httpbin | grep pending {{ .outputRedirectionCmd }}
# $verify
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.circuit_breakers.default.rq_pending_open: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.circuit_breakers.high.rq_pending_open: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_active: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_failure_eject: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_overflow: ?
cluster.outbound|8000||httpbin.istio-io-circuitbreaker.svc.cluster.local.upstream_rq_pending_total: ?
# $endsnippet