Managing Traffic Flow with Anthos Service Mesh
With Anthos Service Mesh, you can manage service discovery, traffic routing, and load balancing for your services without having to update code in your services. Anthos Service Mesh simplifies configuration of service-level properties like timeouts and retries, and makes it straightforward to set up tasks like staged rollouts with percentage-based traffic splits.
Anthos Service Mesh’s traffic management model relies on the following two components:
- Control plane: manages and configures the Envoy proxies to route traffic and enforce policies.
- Data plane: encompasses all network communication between microservices performed at runtime by the Envoy proxies.
These components enable mesh traffic management features including:
- Service discovery
- Load balancing
- Traffic routing and control
Tasks:
- Configure and use Istio Gateways
- Apply default destination rules, for all available versions
- Apply virtual services to route by default to only one version
- Route to a specific version of a service based on user identity
- Shift traffic gradually from one version of a microservice to another
- Use the Anthos Service Mesh dashboard to view routing to multiple versions
- Setup networking best practices such as retries, circuit breakers and timeouts
Review Traffic Management use cases
Different traffic management capabilities are enabled by using different configuration options.
traffic splitting
Route traffic to multiple versions of a service.
timeouts
Set a timeout, the amount of time Istio waits for a response to a request. The timeout for HTTP requests is 15 seconds, but it can be overridden.
retries
A retry is an attempt to complete an operation multiple times if it fails. Adjust the maximum number of retry attempts, or the number of attempts possible within the default or overridden timeout period.
fault injection: inserting delays
Fault injection is a testing method that introduces errors into a system to ensure that it can withstand and recover from error conditions.
fault injection: inserting aborts
For example, returns an HTTP 400 error code for 10% of the requests to the ratings service “v1”.
conditional routing: based on source labels
A rule can indicate that it only applies to calls from workloads (pods) implementing the version v2 of the reviews service.
conditional routing: based on request headers
For example, a rule only applies to an incoming request if it includes a custom “end-user” header that contains the string “pradeep”.
Welcome to Cloud Shell! Type "help" to get started.
Your Cloud Platform project in this session is set to qwiklabs-gcp-02-0514bbab990a.
Use “gcloud config set project [PROJECT_ID]” to change to a different project.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ CLUSTER_ZONE=us-central1-f
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ export CLUSTER_NAME=gke
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ export GCLOUD_PROJECT=$(gcloud config get-value project)
gcloud container clusters get-credentials $CLUSTER_NAME \
--zone $CLUSTER_ZONE --project $GCLOUD_PROJECT
Your active configuration is: [cloudshell-21403]
Fetching cluster endpoint and auth data.
kubeconfig entry generated for gke.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ gcloud container clusters list
NAME: gke
LOCATION: us-central1-f
MASTER_VERSION: 1.28.7-gke.1026000
MASTER_IP: 35.222.53.61
MACHINE_TYPE: e2-standard-4
NODE_VERSION: 1.28.7-gke.1026000
NUM_NODES: 3
STATUS: RUNNING
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istiod-asm-1157-23-79bf57569-528dp 1/1 Running 0 6h43m
istiod-asm-1157-23-79bf57569-nvnp6 1/1 Running 0 6h43m
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get service -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istiod ClusterIP 10.108.150.172 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 6h43m
istiod-asm-1157-23 ClusterIP 10.108.159.127 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 6h43m
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-cf74bb974-fz5g5 2/2 Running 0 6h43m
productpage-v1-87d54dd59-pntxh 2/2 Running 0 6h43m
ratings-v1-7c4bbf97db-kcclm 2/2 Running 0 6h43m
reviews-v1-5fd6d4f8f8-lmpl5 2/2 Running 0 6h43m
reviews-v2-6f9b55c5db-kfzp5 2/2 Running 0 6h43m
reviews-v3-7d99fd7978-gldjg 2/2 Running 0 6h43m
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.108.148.244 <none> 9080/TCP 6h43m
kubernetes ClusterIP 10.108.144.1 <none> 443/TCP 7h5m
productpage ClusterIP 10.108.145.43 <none> 9080/TCP 6h43m
ratings ClusterIP 10.108.156.53 <none> 9080/TCP 6h43m
reviews ClusterIP 10.108.148.105 <none> 9080/TCP 6h43m
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Install Gateways to enable ingress
In a Kubernetes environment, the Kubernetes Ingress Resource is used to specify services that should be exposed outside the cluster. In Anthos Service Mesh, a better approach, which also works in Kubernetes and other environments, is to use a Gateway resource. A Gateway allows mesh features such as monitoring, mTLS, and advanced routing capabilities rules to be applied to traffic entering the cluster.
Gateways overcome Kubernetes Ingress shortcomings by separating the L4-L6 spec from L7. The Gateway configures the L4-L6 functions, such as the ports to expose, or the protocol to use. Then service owners bind VirtualService to configure L7 traffic routing options, such as routing based on paths, headers, weights, etc.
There are two options for deploying gateways, either shared or dedicated. Shared gateways use a single centralized gateway is that used by many applications, possibly across many namespaces. In the example below, the Gateway in the ingress namespace delegates ownership of routes to application namespaces, but retains control over TLS configuration. This works well when using shared TLS certificates or shared infrastructure. In this lab we will use this option.
Dedicated gateways give full control and ownership to a single namespace, since an application namespace has its own dedicated gateway. This works well for applications that require isolation for security or performance.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl create namespace ingress
namespace/ingress created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl label namespace ingress \
istio.io/rev=$(kubectl -n istio-system get pods -l app=istiod -o json | jq -r '.items[0].metadata.labels["istio.io/rev"]') \
--overwrite
namespace/ingress labeled
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages
kubectl apply -n ingress -f anthos-service-mesh-packages/samples/gateways/istio-ingressgateway
Cloning into 'anthos-service-mesh-packages'...
remote: Enumerating objects: 11990, done.
remote: Counting objects: 100% (1395/1395), done.
remote: Compressing objects: 100% (482/482), done.
remote: Total 11990 (delta 1044), reused 1237 (delta 911), pack-reused 10595
Receiving objects: 100% (11990/11990), 3.02 MiB | 22.08 MiB/s, done.
Resolving deltas: 100% (8230/8230), done.
horizontalpodautoscaler.autoscaling/istio-ingressgateway created
deployment.apps/istio-ingressgateway created
poddisruptionbudget.policy/istio-ingressgateway created
role.rbac.authorization.k8s.io/istio-ingressgateway created
rolebinding.rbac.authorization.k8s.io/istio-ingressgateway created
service/istio-ingressgateway created
serviceaccount/istio-ingressgateway created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get pod,service -n ingress
NAME READY STATUS RESTARTS AGE
pod/istio-ingressgateway-59c87f6556-8gcq4 1/1 Running 0 61s
pod/istio-ingressgateway-59c87f6556-jqp47 1/1 Running 0 61s
pod/istio-ingressgateway-59c87f6556-xxcqb 1/1 Running 0 61s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-ingressgateway LoadBalancer 10.108.155.2 35.193.148.208 15021:30753/TCP,80:31324/TCP,443:32316/TCP 63s
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
namespace: ingress
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
EOF - "*":
gateway.networking.istio.io/bookinfo-gateway created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- ingress/bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
EOF number: 9080ageroducts
virtualservice.networking.istio.io/bookinfo configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get gateway,virtualservice
NAME AGE
gateway.networking.istio.io/bookinfo-gateway 6h50m
NAME GATEWAYS HOSTS AGE
virtualservice.networking.istio.io/bookinfo ["ingress/bookinfo-gateway"] ["*"] 6h50m
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ export GATEWAY_URL=$(kubectl get svc -n ingress istio-ingressgateway \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo The gateway address is $GATEWAY_URL
The gateway address is 35.193.148.208
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ sudo apt install siege
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
siege
0 upgraded, 1 newly installed, 0 to remove and 9 not upgraded.
Need to get 102 kB of archives.
After this operation, 269 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 siege amd64 4.0.7-1build3 [102 kB]
Fetched 102 kB in 1s (78.4 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package siege.
(Reading database ... 121585 files and directories currently installed.)
Preparing to unpack .../siege_4.0.7-1build3_amd64.deb ...
Unpacking siege (4.0.7-1build3) ...
Setting up siege (4.0.7-1build3) ...
Processing triggers for man-db (2.10.2-1) ...
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ siege http://${GATEWAY_URL}/productpage
New configuration template added to /home/student_01_7fdd866025d9/.siege
Run siege -C to view the current settings in that file
Welcome to Cloud Shell! Type "help" to get started.
Your Cloud Platform project in this session is set to qwiklabs-gcp-02-0514bbab990a.
Use “gcloud config set project [PROJECT_ID]” to change to a different project.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ CLUSTER_ZONE=us-central1-f
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ export CLUSTER_NAME=gke
export GCLOUD_PROJECT=$(gcloud config get-value project)
gcloud container clusters get-credentials $CLUSTER_NAME \
--zone $CLUSTER_ZONE --project $GCLOUD_PROJECT
export GATEWAY_URL=$(kubectl get svc istio-ingressgateway \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}' -n ingress)
Your active configuration is: [cloudshell-25975]
Fetching cluster endpoint and auth data.
kubeconfig entry generated for gke.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl exec -it \
$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') \
-c ratings -- curl productpage:9080/productpage \
| grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ curl -I http://${GATEWAY_URL}/productpage
HTTP/1.1 200 OK
server: istio-envoy
date: Sat, 27 Apr 2024 05:47:06 GMT
content-type: text/html; charset=utf-8
content-length: 4294
vary: Cookie
x-envoy-upstream-service-time: 17
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ echo http://${GATEWAY_URL}/productpage
http://35.193.148.208/productpage
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Congratulations! You exposed an HTTP endpoint for the Bookinfo productpage service to external traffic. The Gateway configuration resources allow external traffic to enter the service mesh and make the traffic management and policy features available for edge services.
Use the Anthos Service Mesh dashboard view routing to multiple versions
There are a couple of items to note when it comes to viewing data in the Anthos Service Mesh dashboard.
The first is that, for most pages, it takes 1-2 minutes for the data to be available for display. That means that if you look at a page, it might not have the data you expect for 1-2 minutes. If you don’t see the data you want, wait for a minute or so and then refresh the page.
The Topology page also has a big initial delay before data is shown. It can take up to 5+ minutes for the initial set of data to be available. If you see a message that there is no data, wait a bit and then refresh the page and return to the Topology view.
In the previous paragraphs, you are instructed to wait AND to refresh the page. As it turns out, not only is the data a bit delayed in arriving, but many pages won’t show the available data without a page refresh. So if you expect the data to be available and you don’t see it, make sure to do a refresh of the page in your browser.
Apply default destination rules, for all available versions
In this task, you define all the available versions, called subsets, in destination rules.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/destination-rule-all.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get destinationrules
NAME HOST AGE
details details 19s
productpage productpage 20s
ratings ratings 19s
reviews reviews 20s
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get destinationrules -o yaml
apiVersion: v1
items:
- apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"details","namespace":"default"},"spec":{"host":"details","subsets":[{"labels":{"version":"v1"},"name":"v1"},{"labels":{"version":"v2"},"name":"v2"}]}}
creationTimestamp: "2024-04-27T05:52:02Z"
generation: 1
name: details
namespace: default
resourceVersion: "276477"
uid: 83461a5f-a6c6-4c15-9dd1-3f200fe4f1c9
spec:
host: details
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"productpage","namespace":"default"},"spec":{"host":"productpage","subsets":[{"labels":{"version":"v1"},"name":"v1"}]}}
creationTimestamp: "2024-04-27T05:52:01Z"
generation: 1
name: productpage
namespace: default
resourceVersion: "276457"
uid: 399b55d0-80ff-4514-8944-204dec7d442a
spec:
host: productpage
subsets:
- labels:
version: v1
name: v1
- apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"ratings","namespace":"default"},"spec":{"host":"ratings","subsets":[{"labels":{"version":"v1"},"name":"v1"},{"labels":{"version":"v2"},"name":"v2"},{"labels":{"version":"v2-mysql"},"name":"v2-mysql"},{"labels":{"version":"v2-mysql-vm"},"name":"v2-mysql-vm"}]}}
creationTimestamp: "2024-04-27T05:52:02Z"
generation: 1
name: ratings
namespace: default
resourceVersion: "276474"
uid: 9ab4d168-17d4-4d2a-8115-82311105eaff
spec:
host: ratings
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v2-mysql
name: v2-mysql
- labels:
version: v2-mysql-vm
name: v2-mysql-vm
- apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"reviews","namespace":"default"},"spec":{"host":"reviews","subsets":[{"labels":{"version":"v1"},"name":"v1"},{"labels":{"version":"v2"},"name":"v2"},{"labels":{"version":"v3"},"name":"v3"}]}}
creationTimestamp: "2024-04-27T05:52:01Z"
generation: 1
name: reviews
namespace: default
resourceVersion: "276467"
uid: a18742b6-7158-4e76-aed4-83547751160e
spec:
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
kind: List
metadata:
resourceVersion: ""
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Apply virtual services to route by default to only one version
In this task, you apply virtual services for each service that routes all traffic to v1 of the service workload.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get virtualservices
NAME GATEWAYS HOSTS AGE
bookinfo ["ingress/bookinfo-gateway"] ["*"] 7h
details ["details"] 18s
productpage ["productpage"] 19s
ratings ["ratings"] 18s
reviews ["reviews"] 19s
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ echo $GATEWAY_URL
35.193.148.208
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Test the new routing configuration using the Bookinfo UI.
- Open the Bookinfo site in your browser. The URL is
http://[GATEWAY_URL]/productpage
, whereGATEWAY_URL
is the External IP address of the ingress. - Refresh the page a few times to issue multiple requests.
Notice that the Book Reviews part of the page displays with no rating stars, no matter how many times you refresh. This is because you configured the mesh to route all traffic for the reviews service to the version reviews:v1 and this version of the service does not access the star ratings service.
Route to a specific version of a service based on user identity
In this task, you change the route configuration so that all traffic from a specific user is routed to a specific service version. In this case, all traffic from user pradeep
will be routed to the service reviews:v2
, the version that includes the star ratings feature.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
virtualservice.networking.istio.io/reviews configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl get virtualservice reviews
NAME GATEWAYS HOSTS AGE
reviews ["reviews"] 3m44s
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
curl -c cookies.txt -F "username=jason" -L -X \
POST http://$GATEWAY_URL/login
cookie_info=$(grep -Eo "session.*" ./cookies.txt)
cookie_name=$(echo $cookie_info | cut -d' ' -f1)
cookie_value=$(echo $cookie_info | cut -d' ' -f2)
siege -c 5 http://$GATEWAY_URL/productpage \
--header "Cookie: $cookie_name=$cookie_value"
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io "productpage" deleted
virtualservice.networking.istio.io "reviews" deleted
virtualservice.networking.istio.io "ratings" deleted
virtualservice.networking.istio.io "details" deleted
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Shift traffic gradually from one version of a microservice to another
In this task, you gradually migrate traffic from one version of a microservice to another. For example, you might use this approach to migrate traffic from an older version to a new version.
You will send 50% of traffic to reviews:v1 and 50% to reviews:v3. Then, you will complete the migration by sending 100% of traffic to reviews:v3.
In Anthos Service Mesh, you accomplish this goal by configuring a sequence of rules that route a percentage of traffic to one service or another.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
tudent_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f \
https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
virtualservice.networking.istio.io/reviews configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking//virtual-service-reviews-v3.yaml
virtualservice.networking.istio.io/reviews configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io "productpage" deleted
virtualservice.networking.istio.io "reviews" deleted
virtualservice.networking.istio.io "ratings" deleted
virtualservice.networking.istio.io "details" deleted
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Add timeouts to avoid waiting indefinitely for service replies
A timeout for HTTP requests can be specified using the timeout field of the route rule. By default, the request timeout is disabled, but in this task you override the reviews service timeout to 1 second. To see its effect, however, you also introduce an artificial 2 second delay in calls to the ratings service. We will start by introducing the delay.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
EOF
virtualservice.networking.istio.io/reviews configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percent: 100
fixedDelay: 2s
route:
- destination:
host: ratings
subset: v1
EOF
virtualservice.networking.istio.io/ratings configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
timeout: 0.5s
EOF
virtualservice.networking.istio.io/reviews configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
retries:
attempts: 1
perTryTimeout: 2s
EOF
virtualservice.networking.istio.io/productpage configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io "productpage" deleted
virtualservice.networking.istio.io "reviews" deleted
virtualservice.networking.istio.io "ratings" deleted
virtualservice.networking.istio.io "details" deleted
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Add circuit breakers to enhance your microservices’ resiliency
This task shows you how to configure circuit breaking for connections, requests, and outlier detection.
Circuit breaking is an important pattern for creating resilient microservice applications. Circuit breaking allows you to write applications that limit the impact of failures, latency spikes, and other undesirable effects of network peculiarities.
In this task, you will configure circuit breaking rules and then test the configuration by intentionally “tripping” the circuit breaker.
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
virtualservice.networking.istio.io/productpage created
virtualservice.networking.istio.io/reviews created
virtualservice.networking.istio.io/ratings created
virtualservice.networking.istio.io/details created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
EOF maxEjectionPercent: 100
destinationrule.networking.istio.io/productpage configured
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ siege -c 5 http://$GATEWAY_URL/productpage \
> --header "Cookie: $cookie_name=$cookie_value"~
^C
{ "transactions": 3231,
"availability": 99.60,
"elapsed_time": 514.82,
"data_transferred": 169.53,
"response_time": 0.80,
"transaction_rate": 6.28,
"throughput": 0.33,
"concurrency": 4.99,
"successful_transactions": 3231,
"failed_transactions": 13,
"longest_transaction": 2.47,
"shortest_transaction": 0.41
}
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Create a client to send traffic to the productpage service.
The client is a simple load-testing client called fortio. Fortio lets you control the number of connections, concurrency, and delays for outgoing HTTP calls. You will use this client to “trip” the circuit breaker policies you set in the DestinationRule:
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.9/samples/httpbin/sample-client/fortio-deploy.yaml
service/fortio created
deployment.apps/fortio-deploy created
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ export FORTIO_POD=$(kubectl get pods -lapp=fortio -o 'jsonpath={.items[0].metadata.name}')
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio curl -quiet http://${GATEWAY_URL}/productpage
HTTP/1.1 200 OK
server: envoy
date: Sat, 27 Apr 2024 06:09:12 GMT
content-type: text/html; charset=utf-8
content-length: 4294
vary: Cookie
x-envoy-upstream-service-time: 26
<!DOCTYPE html>
<html>
<head>
<title>Simple Bookstore App</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="static/bootstrap/css/bootstrap-theme.min.css">
</head>
<body>
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">BookInfo Sample</a>
</div>
<button type="button" class="btn btn-default navbar-btn navbar-right" data-toggle="modal" href="#login-modal">Sign
in</button>
</div>
</nav>
<!---
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header pull-left">
<a class="navbar-brand" href="#">Microservices Fabric BookInfo Demo</a>
</div>
<div class="navbar-header pull-right">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<button type="button" class="btn btn-default navbar-btn pull-right" data-toggle="modal" data-target="#login-modal">Sign in</button>
</div>
</div>
</div>
-->
<div id="login-modal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Please sign in</h4>
</div>
<div class="modal-body">
<form method="post" action='login' name="login_form">
<p><input type="text" class="form-control" name="username" id="username" placeholder="User Name"></p>
<p><input type="password" class="form-control" name="passwd" placeholder="Password"></p>
<p>
<button type="submit" class="btn btn-primary">Sign in</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</p>
</form>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<h3 class="text-center text-primary">The Comedy of Errors</h3>
<p>Summary: <a href="https://en.wikipedia.org/wiki/The_Comedy_of_Errors">Wikipedia Summary</a>: The Comedy of Errors is one of <b>William Shakespeare's</b> early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play.</p>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4 class="text-center text-primary">Book Details</h4>
<dl>
<dt>Type:</dt>paperback
<dt>Pages:</dt>200
<dt>Publisher:</dt>PublisherA
<dt>Language:</dt>English
<dt>ISBN-10:</dt>1234567890
<dt>ISBN-13:</dt>123-1234567890
</dl>
</div>
<div class="col-md-6">
<h4 class="text-center text-primary">Book Reviews</h4>
<blockquote>
<p>An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!</p>
<small>Reviewer1</small>
</blockquote>
<blockquote>
<p>Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.</p>
<small>Reviewer2</small>
</blockquote>
<dl>
<dt>Reviews served by:</dt>
<u>reviews-v1-5fd6d4f8f8-lmpl5</u>
</dl>
</div>
</div>
</div>
<!-- Latest compiled and minified JavaScript -->
<script src="static/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="static/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript">
$('#login-modal').on('shown.bs.modal', function () {
$('#username').focus();
});
</script>
</body>
</html>
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://${GATEWAY_URL}/productpage
{"ts":1714198196.786403,"level":"info","r":1,"file":"logger.go","line":254,"msg":"Log level is now 3 Warning (was 2 Info)"}
Fortio 1.60.3 running at 0 queries per second, 4->4 procs, for 20 calls: http://35.193.148.208/productpage
Starting at max qps with 2 thread(s) [gomax 4] for exactly 20 calls (10 per thread + 0)
{"ts":1714198196.793022,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.795846,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.798241,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.800698,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.802598,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.805004,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.807610,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.810159,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.812100,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.814339,"level":"warn","r":8,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198196.816127,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.818248,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.820075,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.821870,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.824100,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.826122,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.828159,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.829959,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198196.831755,"level":"warn","r":7,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
Ended after 44.034415ms : 20 calls. qps=454.19
Aggregated Function Time : count 20 avg 0.0034918101 +/- 0.005218 min 0.001785869 max 0.026026445 sum 0.069836203
# range, mid point, percentile, count
>= 0.00178587 <= 0.002 , 0.00189293 , 35.00, 7
> 0.002 <= 0.003 , 0.0025 , 90.00, 11
> 0.005 <= 0.006 , 0.0055 , 95.00, 1
> 0.025 <= 0.0260264 , 0.0255132 , 100.00, 1
# target 50% 0.00227273
# target 75% 0.00272727
# target 90% 0.003
# target 99% 0.0258212
# target 99.9% 0.0260059
Error cases : count 19 avg 0.0023057767 +/- 0.0007294 min 0.001785869 max 0.005152399 sum 0.043809758
# range, mid point, percentile, count
>= 0.00178587 <= 0.002 , 0.00189293 , 36.84, 7
> 0.002 <= 0.003 , 0.0025 , 94.74, 11
> 0.005 <= 0.0051524 , 0.0050762 , 100.00, 1
# target 50% 0.00222727
# target 75% 0.00265909
# target 90% 0.00291818
# target 99% 0.00512344
# target 99.9% 0.0051495
# Socket and IP used for each connection:
[0] 9 socket used, resolved to 35.193.148.208:80, connection timing : count 9 avg 0.00025037311 +/- 7.468e-05 min 0.000148124 max 0.00038296 sum 0.002253358
[1] 10 socket used, resolved to 35.193.148.208:80, connection timing : count 10 avg 0.0003256097 +/- 0.0001156 min 0.000153109 max 0.00048716 sum 0.003256097
Connection time (s) : count 19 avg 0.00028997132 +/- 0.0001053 min 0.000148124 max 0.00048716 sum 0.005509455
Sockets used: 19 (for perfect keepalive, would be 2)
Uniform: false, Jitter: false, Catchup allowed: true
IP addresses distribution:
35.193.148.208:80: 19
Code 200 : 1 (5.0 %)
Code 503 : 19 (95.0 %)
Response Header Sizes : count 20 avg 9.1 +/- 39.67 min 0 max 182 sum 182
Response Body/Total Sizes : count 20 avg 401.45 +/- 934.8 min 187 max 4476 sum 8029
All done 20 calls (plus 0 warmup) 3.492 ms avg, 454.2 qps
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Bring the number of concurrent connections up to 3:
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://${GATEWAY_URL}/productpage
{"ts":1714198247.981977,"level":"info","r":1,"file":"logger.go","line":254,"msg":"Log level is now 3 Warning (was 2 Info)"}
Fortio 1.60.3 running at 0 queries per second, 4->4 procs, for 30 calls: http://35.193.148.208/productpage
Starting at max qps with 3 thread(s) [gomax 4] for exactly 30 calls (10 per thread + 0)
{"ts":1714198247.986388,"level":"warn","r":19,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198247.988333,"level":"warn","r":19,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198248.002132,"level":"warn","r":20,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198248.011439,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.014434,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.016551,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.018328,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.020151,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.022431,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.024660,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.026743,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.028833,"level":"warn","r":21,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":2,"run":0}
{"ts":1714198248.067171,"level":"warn","r":19,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198248.126482,"level":"warn","r":20,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
{"ts":1714198248.186654,"level":"warn","r":19,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198248.189237,"level":"warn","r":19,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":0,"run":0}
{"ts":1714198248.245309,"level":"warn","r":20,"file":"http_client.go","line":1104,"msg":"Non ok http code","code":503,"status":"HTTP/1.1 503","thread":1,"run":0}
Ended after 557.781663ms : 30 calls. qps=53.784
Aggregated Function Time : count 30 avg 0.032055648 +/- 0.0412 min 0.001781338 max 0.122483374 sum 0.961669437
# range, mid point, percentile, count
>= 0.00178134 <= 0.002 , 0.00189067 , 10.00, 3
> 0.002 <= 0.003 , 0.0025 , 53.33, 13
> 0.018 <= 0.02 , 0.019 , 60.00, 2
> 0.02 <= 0.025 , 0.0225 , 63.33, 1
> 0.025 <= 0.03 , 0.0275 , 70.00, 2
> 0.06 <= 0.07 , 0.065 , 80.00, 3
> 0.07 <= 0.08 , 0.075 , 83.33, 1
> 0.08 <= 0.09 , 0.085 , 86.67, 1
> 0.1 <= 0.12 , 0.11 , 96.67, 3
> 0.12 <= 0.122483 , 0.121242 , 100.00, 1
# target 50% 0.00292308
# target 75% 0.065
# target 90% 0.106667
# target 99% 0.121738
# target 99.9% 0.122409
Error cases : count 17 avg 0.0032099762 +/- 0.003861 min 0.001781338 max 0.018593014 sum 0.054569595
# range, mid point, percentile, count
>= 0.00178134 <= 0.002 , 0.00189067 , 17.65, 3
> 0.002 <= 0.003 , 0.0025 , 94.12, 13
> 0.018 <= 0.018593 , 0.0182965 , 100.00, 1
# target 50% 0.00242308
# target 75% 0.00275
# target 90% 0.00294615
# target 99% 0.0184922
# target 99.9% 0.0185829
# Socket and IP used for each connection:
[0] 6 socket used, resolved to 35.193.148.208:80, connection timing : count 6 avg 0.00030060767 +/- 6.854e-05 min 0.00016685 max 0.000387157 sum 0.001803646
[1] 4 socket used, resolved to 35.193.148.208:80, connection timing : count 4 avg 0.00025245275 +/- 7.65e-05 min 0.000178073 max 0.000360274 sum 0.001009811
[2] 9 socket used, resolved to 35.193.148.208:80, connection timing : count 9 avg 0.00025858056 +/- 7.605e-05 min 0.000168617 max 0.000439194 sum 0.002327225
Connection time (s) : count 19 avg 0.00027056221 +/- 7.667e-05 min 0.00016685 max 0.000439194 sum 0.005140682
Sockets used: 19 (for perfect keepalive, would be 3)
Uniform: false, Jitter: false, Catchup allowed: true
IP addresses distribution:
35.193.148.208:80: 19
Code 200 : 13 (43.3 %)
Code 503 : 17 (56.7 %)
Response Header Sizes : count 30 avg 79 +/- 90.34 min 0 max 183 sum 2370
Response Body/Total Sizes : count 30 avg 2075.0667 +/- 2100 min 187 max 4477 sum 62252
All done 30 calls (plus 0 warmup) 32.056 ms avg, 53.8 qps
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
Now you start to see the expected circuit breaking behavior. Only 43.3% of the requests succeeded and the rest were trapped by circuit breaking:
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ history
1 CLUSTER_ZONE=us-central1-f
2 export CLUSTER_NAME=gke
3 export GCLOUD_PROJECT=$(gcloud config get-value project)
4 gcloud container clusters get-credentials $CLUSTER_NAME --zone $CLUSTER_ZONE --project $GCLOUD_PROJECT
5 gcloud container clusters list
6 kubectl get pods -n istio-system
7 kubectl get service -n istio-system
8 kubectl get pods
9 kubectl get services
10 kubectl create namespace ingress
11 kubectl label namespace ingress istio.io/rev=$(kubectl -n istio-system get pods -l app=istiod -o json | jq -r '.items[0].metadata.labels["istio.io/rev"]') --overwrite
12 git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages
13 kubectl apply -n ingress -f anthos-service-mesh-packages/samples/gateways/istio-ingressgateway
14 kubectl get pod,service -n ingress
15 cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
namespace: ingress
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
EOF
16 cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- ingress/bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
EOF
17 kubectl get gateway,virtualservice
18 export GATEWAY_URL=$(kubectl get svc -n ingress istio-ingressgateway \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
19 echo The gateway address is $GATEWAY_URL
20 sudo apt install siege
21 siege http://${GATEWAY_URL}/productpage
22 curl -c cookies.txt -F "username=jason" -L -X POST http://$GATEWAY_URL/login
23 cookie_info=$(grep -Eo "session.*" ./cookies.txt)
24 cookie_name=$(echo $cookie_info | cut -d' ' -f1)
25 cookie_value=$(echo $cookie_info | cut -d' ' -f2)
26 siege -c 5 http://$GATEWAY_URL/productpage --header "Cookie: $cookie_name=$cookie_value"~
27 export FORTIO_POD=$(kubectl get pods -lapp=fortio -o 'jsonpath={.items[0].metadata.name}')
28 kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio curl -quiet http://${GATEWAY_URL}/productpage
29 kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://${GATEWAY_URL}/productpage
30 kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://${GATEWAY_URL}/productpage
31 history
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$ history
1 CLUSTER_ZONE=us-central1-f
2 export CLUSTER_NAME=gke
3 export GCLOUD_PROJECT=$(gcloud config get-value project)
4 gcloud container clusters get-credentials $CLUSTER_NAME --zone $CLUSTER_ZONE --project $GCLOUD_PROJECT
5 gcloud container clusters list
6 kubectl get pods -n istio-system
7 kubectl get service -n istio-system
8 kubectl get pods
9 kubectl get services
10 kubectl create namespace ingress
11 kubectl label namespace ingress istio.io/rev=$(kubectl -n istio-system get pods -l app=istiod -o json | jq -r '.items[0].metadata.labels["istio.io/rev"]') --overwrite
12 git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages
13 kubectl apply -n ingress -f anthos-service-mesh-packages/samples/gateways/istio-ingressgateway
14 kubectl get pod,service -n ingress
15 cat <<EOF | kubectl apply -f -
16 apiVersion: networking.istio.io/v1alpha3
17 kind: Gateway
18 metadata:
19 name: bookinfo-gateway
20 namespace: ingress
21 spec:
22 selector:
23 istio: ingressgateway
24 servers:
25 - port:
26 number: 80
27 name: http
28 protocol: HTTP
29 hosts:
30 - "*"
31 EOF
32 cat <<EOF | kubectl apply -f -
33 apiVersion: networking.istio.io/v1alpha3
34 kind: VirtualService
35 metadata:
36 name: bookinfo
37 spec:
38 hosts:
39 - "*"
40 gateways:
41 - ingress/bookinfo-gateway
42 http:
43 - match:
44 - uri:
45 exact: /productpage
46 - uri:
47 prefix: /static
48 - uri:
49 exact: /login
50 - uri:
51 exact: /logout
52 - uri:
53 prefix: /api/v1/products
54 route:
55 - destination:
56 host: productpage
57 port:
58 number: 9080
59 EOF
60 kubectl get gateway,virtualservice
61 export GATEWAY_URL=$(kubectl get svc -n ingress istio-ingressgateway \
62 -o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
63 echo The gateway address is $GATEWAY_URL
64 sudo apt install siege
65 CLUSTER_ZONE=us-central1-f
66 export CLUSTER_NAME=gke
67 export GCLOUD_PROJECT=$(gcloud config get-value project)
68 gcloud container clusters get-credentials $CLUSTER_NAME --zone $CLUSTER_ZONE --project $GCLOUD_PROJECT
69 export GATEWAY_URL=$(kubectl get svc istio-ingressgateway \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}' -n ingress)
70 kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"
71 curl -I http://${GATEWAY_URL}/productpage
72 echo http://${GATEWAY_URL}/productpage
73 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/destination-rule-all.yaml
74 kubectl get destinationrules
75 kubectl get destinationrules -o yaml
76 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
77 kubectl get virtualservices
78 echo $GATEWAY_URL
79 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
80 kubectl get virtualservice reviews
81 kubectl delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
82 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
83 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
84 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking//virtual-service-reviews-v3.yaml
85 kubectl delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
86 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
87 kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
EOF
88 kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percent: 100
fixedDelay: 2s
route:
- destination:
host: ratings
subset: v1
EOF
89 kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
timeout: 0.5s
EOF
90 kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
retries:
attempts: 1
perTryTimeout: 2s
EOF
91 kubectl delete -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
92 kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/virtual-service-all-v1.yaml
93 kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
EOF
94 history
student_01_7fdd866025d9@cloudshell:~ (qwiklabs-gcp-02-0514bbab990a)$