break up bookinfo sample into tasks (#68)

* break up bookinfo sample into tasks

* address review comments
This commit is contained in:
Frank Budinsky 2017-04-26 15:47:13 -04:00 committed by GitHub
parent afd2a5e455
commit d05e3c29c5
4 changed files with 381 additions and 280 deletions

View File

@ -1,7 +1,7 @@
---
category: Samples
title: BookInfo
overview: This sample deploys a simple app that displays information about a book, similar to a single catalog entry of an online book store.
overview: This sample deploys a simple application composed of four separate microservices which will be used to demonstrate various features of the Istio service mesh.
order: 10
@ -10,8 +10,17 @@ layout: docs
type: markdown
---
This sample deploys a simple application composed of four separate microservices which will be used
to demonstrate various features of the Istio service mesh.
## Before you begin
In this sample, we will deploy a simple app that displays information about a
Setup Istio by following the instructions in the
[Installation guide](/docs/tasks/installing-istio.html).
## Overview
In this sample we will deploy a simple application that displays information about a
book, similar to a single catalog entry of an online book store. Displayed
on the page is a description of the book, book details (ISBN, number of
pages, and so on), and a few book reviews.
@ -35,23 +44,26 @@ The end-to-end architecture of the application is shown below.
This application is polyglot, i.e., the microservices are written in different languages.
1. Follow the Istio [Installation]({{site.bareurl}}/docs/tasks/istio-installation.html) guide.
## Start the application
## Start the Application
1. Change your current working directory to the bookinfo application directory:
```bash
cd demos/apps/bookinfo
```
```bash
cd demos/apps/bookinfo
```
1. Bring up the application containers:
```bash
kubectl apply -f <(istioctl kube-inject -f bookinfo.yaml)
```
```bash
kubectl apply -f <(istioctl kube-inject -f bookinfo.yaml)
```
The above command launches four microservices and creates the gateway
ingress resource and as illustrated in the diagram above.
The reviews microservice has 3 versions: v1, v2, and v3. Note that in a
realistic deployment, new versions of a microservice are deployed
over time instead of deploying all versions
simultaneously.
ingress resource as illustrated in the diagram above.
The reviews microservice has 3 versions: v1, v2, and v3.
> Note that in a realistic deployment, new versions of a microservice are deployed
over time instead of deploying all versions simultaneously.
Notice that the `istioctl kube-inject` command is used to modify the `bookinfo.yaml`
file before creating the deployments. This injects Envoy into kubernetes resources
@ -61,255 +73,80 @@ kubectl apply -f <(istioctl kube-inject -f bookinfo.yaml)
like this:
![Bookinfo app]({{site.bareurl}}/docs/samples/img/bookinfo/withistio.svg)
1. Confirm all services and pods are correctly defined and running:
```bash
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details 10.0.0.31 <none> 9080/TCP 6m
istio-ingress 10.0.0.122 <pending> 80:31565/TCP 8m
istio-manager 10.0.0.189 <none> 8080/TCP 8m
istio-mixer 10.0.0.132 <none> 9091/TCP,42422/TCP 8m
kubernetes 10.0.0.1 <none> 443/TCP 14d
productpage 10.0.0.120 <none> 9080/TCP 6m
ratings 10.0.0.15 <none> 9080/TCP 6m
reviews 10.0.0.170 <none> 9080/TCP 6m
```
```bash
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details 10.0.0.31 <none> 9080/TCP 6m
istio-ingress 10.0.0.122 <pending> 80:31565/TCP 8m
istio-manager 10.0.0.189 <none> 8080/TCP 8m
istio-mixer 10.0.0.132 <none> 9091/TCP,42422/TCP 8m
kubernetes 10.0.0.1 <none> 443/TCP 14d
productpage 10.0.0.120 <none> 9080/TCP 6m
ratings 10.0.0.15 <none> 9080/TCP 6m
reviews 10.0.0.170 <none> 9080/TCP 6m
```
and
```bash
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-1520924117-48z17 2/2 Running 0 6m
istio-ingress-3181829929-xrrk5 1/1 Running 0 8m
istio-manager-175173354-d6jm7 2/2 Running 0 8m
istio-mixer-3883863574-jt09j 2/2 Running 0 8m
productpage-v1-560495357-jk1lz 2/2 Running 0 6m
ratings-v1-734492171-rnr5l 2/2 Running 0 6m
reviews-v1-874083890-f0qf0 2/2 Running 0 6m
reviews-v2-1343845940-b34q5 2/2 Running 0 6m
reviews-v3-1813607990-8ch52 2/2 Running 0 6m
```
```bash
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-1520924117-48z17 2/2 Running 0 6m
istio-ingress-3181829929-xrrk5 1/1 Running 0 8m
istio-manager-175173354-d6jm7 2/2 Running 0 8m
istio-mixer-3883863574-jt09j 2/2 Running 0 8m
productpage-v1-560495357-jk1lz 2/2 Running 0 6m
ratings-v1-734492171-rnr5l 2/2 Running 0 6m
reviews-v1-874083890-f0qf0 2/2 Running 0 6m
reviews-v2-1343845940-b34q5 2/2 Running 0 6m
reviews-v3-1813607990-8ch52 2/2 Running 0 6m
```
1. Determine the gateway ingress URL:
If your cluster is running in an environment that supports external loadbalancers,
use the ingress' external address:
```bash
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
gateway * 130.211.10.121 80 1d
$ export GATEWAY_URL=130.211.10.121:80
```
If your cluster is running in an environment that supports external loadbalancers,
use the ingress' external address:
```bash
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
gateway * 130.211.10.121 80 1d
$ export GATEWAY_URL=130.211.10.121:80
```
If loadbalancers are not supported, use the service NodePort instead:
```bash
$ export GATEWAY_URL=$(kubectl get po -l infra=istio-ingress-controller -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc istio-ingress-controller -o jsonpath={.spec.ports[0].nodePort})
```
If loadbalancers are not supported, use the service NodePort instead:
```bash
$ export GATEWAY_URL=$(kubectl get po -l infra=istio-ingress-controller -o jsonpath={.items[0].status.hostIP}):$(kubectl get svc istio-ingress-controller -o jsonpath={.spec.ports[0].nodePort})
```
1. Confirm that the bookinfo application is running with the following `curl` command:
```bash
$ curl -o /dev/null -s -w "%{http_code}\n" http://$GATEWAY_URL/productpage
200
```
```bash
$ curl -o /dev/null -s -w "%{http_code}\n" http://$GATEWAY_URL/productpage
200
```
## Traffic Management
## What's next
### Content Based Routing
Now that you have the bookinfo sample up and running, you can use Istio to control traffic routing,
inject faults, rate limit services, etc..
Since we have 3 versions of the reviews microservice running, we need to set the default route.
Otherwise if you access the application several times, you would notice that sometimes the output contains
star ratings. This is because without an explicit default version set, Istio will
route requests to all available versions of a service in a random fashion.
* To get started, check out the [request routing task](/docs/tasks/request-routing.html)
1. Set the default version for all microservices to v1.
```bash
istioctl create -f route-rule-all-v1.yaml
```
You can display the routes that are defined with the following command:
```yaml
$ istioctl get route-rules -o yaml
kind: route-rule
name: ratings-default
namespace: default
spec:
destination: ratings.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
kind: route-rule
name: reviews-default
namespace: default
spec:
destination: reviews.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
kind: route-rule
name: details-default
namespace: default
spec:
destination: details.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
kind: route-rule
name: productpage-default
namespace: default
spec:
destination: productpage.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
```
Since rule propagation to the proxies is asynchronous, you should wait a few seconds for the rules
to propagate to all pods before attempting to access the application.
1. Open the Bookinfo URL (http://$GATEWAY_URL/productpage) in your browser
* When you're finished experimenting with the bookinfo sample, you can uninstall it as follows:
You should see the bookinfo application productpage displayed.
Notice that the `productpage` is displayed with no rating stars since `reviews:v1` does not access the ratings service.
1. Route a specific user to `reviews:v2`
Lets enable the ratings service for test user "jason" by routing productpage traffic to
`reviews:v2` instances.
```bash
istioctl create -f route-rule-reviews-test-v2.yaml
```
Confirm the rule is created:
```yaml
$ istioctl get route-rule reviews-test-v2
destination: reviews.default.svc.cluster.local
match:
httpHeaders:
Cookie:
regex: ^(.*?;)?(user=jason)(;.*)?$
precedence: 2
route:
- tags:
version: v2
```
Log in as user "jason" at the `productpage` web page. You should now see ratings (1-5 stars) next
to each review.
1. Delete the routing rules and terminate the application pods
### Fault Injection
```bash
./cleanup.sh
```
To test our bookinfo application microservices for resiliency, we will _inject a 7s delay_
between the reviews:v2 and ratings microservices. Since the _reviews:v2_ service has a
10s timeout for its calls to the ratings service, we expect the end-to-end flow to
continue without any errors.
1. Inject the delay
Create a fault injection rule, to delay traffic coming from user "jason" (our test user).
```bash
istioctl create -f destination-ratings-test-delay.yaml
```
Confirm the rule is created:
```yaml
$ istioctl get route-rule ratings-test-delay
destination: ratings.default.svc.cluster.local
httpFault:
delay:
fixedDelaySeconds: 7
percent: 100
match:
httpHeaders:
Cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
precedence: 2
route:
- tags:
version: v1
```
Allow several seconds to account for rule propagation delay to all pods.
1. Observe application behavior
If the application's front page was set to correctly handle delays, we expect it
to load within approximately 7 seconds. To see the web page response times, open the
*Developer Tools* menu in IE, Chrome or Firefox (typically, key combination _Ctrl+Shift+I_
or _Alt+Cmd+I_) and reload the `productpage` web page.
You will see that the webpage loads in about 6 seconds. The reviews section will show
*Sorry, product reviews are currently unavailable for this book*.
The reason that the entire reviews service has failed is because our bookinfo application
has a bug. The timeout between the productpage and reviews service is less (3s + 1 retry = 6s total)
than the timeout between the reviews and ratings service (10s). These kinds of bugs can occur in
typical enterprise applications where different teams develop different microservices
independently. Istio's fault injection rules help you identify such anomalies without
impacting end users.
> Notice that we are restricting the failure impact to user "jason" only. If you login
> as any other user, you would not experience any delays.
**Fixing the bug:** At this point we would normally fix the problem by either increasing the
productpage timeout or decreasing the reviews to ratings service timeout,
terminate and restart the fixed microservice, and then confirm that the `productpage`
returns its response without any errors.
(Left as an exercise for the reader - change the delay rule to
use a 2.8 second delay and then run it against the v3 version of reviews.)
However, we already have this fix running in v3 of the reviews service, so
we can next demonstrate deployment of a new version.
### Percentage-based Traffic Split
Now that we have tested the reviews service, fixed the bug and deployed a
new version (`reviews:v3`), lets route all user traffic from `reviews:v1`
to `reviews:v3` in two steps.
1. First, transfer 50% of traffic from `reviews:v1` to `reviews:v3` with the following command:
```bash
istioctl replace -f route-rule-reviews-50-v3.yaml
```
Notice that we are using `istioctl replace` instead of `create`.
2. To see the new version you need to either Log out as test user "jason" or delete the test rules
that we created exclusively for him:
```bash
istioctl delete route-rule reviews-test-v2
istioctl delete route-rule ratings-test-delay
```
You should now see *red* colored star ratings approximately 50% of the time when you refresh
the `productpage`.
Note: With the Envoy sidecar implementation, you may need to refresh the `productpage` multiple times
to see the proper distribution. You can modify the rules to route 90% of the traffic to v3 to see red stars more often.
3. When version v3 of the reviews microservice is stable, route 100% of the traffic to `reviews:v3`:
```bash
istioctl replace -f route-rule-reviews-v3.yaml
```
You can now log in to the `productpage` as any user and you should always see book reviews
with *red* colored star ratings for each review.
## Policy Enforcement
### Rate Limiting [WIP]
1. Now we'll pretend that `ratings` is an external service for which we are paying (like going to rotten tomatoes),
so we will set a rate limit on the service such that the load remains under the Free quota (5q/s):
```bash
# (TODO) istioctl create -f mixer-rule-ratings-ratelimit.yaml
kubectl apply -f ../../mixer-config-quota-bookinfo.yaml
```
2. We now generate load on the `productpage` with the following command:
```bash
while true; do curl -s -o /dev/null http://$GATEWAY_URL/productpage; done
```
If you now refresh the `productpage` you'll see that while the load generator is running
(i.e., generating more than 5 req/s), we stop seeing stars.
## Cleanup
1. Delete the routing rules and terminate the application pods:
```bash
./cleanup.sh
```
1. Confirm shutdown
```bash
istioctl get route-rules #-- there should be no more routing rules
kubectl get pods #-- the bookinfo pods should be deleted
```
```bash
istioctl get route-rules #-- there should be no more routing rules
kubectl get pods #-- the bookinfo pods should be deleted
```

View File

@ -1,7 +1,7 @@
---
category: Tasks
title: Fault Injection
overview: This task shows how to inject failures and test the resiliency of your application.
overview: This task shows how to inject delays and test the resiliency of your application.
order: 60
@ -10,29 +10,94 @@ layout: docs
type: markdown
---
This task shows how to do X in a Kubernetes cluster. You'll learn
how to ...
This task shows how to inject delays and test the resiliency of your application.
## Before you begin
* Do this.
* Do this too.
## Doing ...
* Setup Istio by following the instructions in the
[Installation guide](/docs/tasks/installing-istio.html).
1. Do this.
1. Do this next. Possibly read this [related explanation](...).
* Deploy the [bookinfo](/docs/samples/bookinfo.html) sample application.
* Initialize the application version routing by either first doing the
[request routing](/docs/tasks/request-routing.html) task or by running following
commands:
```bash
$ istioctl create -f route-rule-all-v1.yaml
$ istioctl create -f route-rule-reviews-test-v2.yaml
```
### Fault Injection
## Understanding ...
To test our bookinfo application microservices for resiliency, we will _inject a 7s delay_
between the reviews:v2 and ratings microservices. Since the _reviews:v2_ service has a
10s timeout for its calls to the ratings service, we expect the end-to-end flow to
continue without any errors.
Here's an interesting thing to know about the steps you just did.
1. Create a fault injection rule to delay traffic coming from user "jason" (our test user)
```bash
istioctl create -f destination-ratings-test-delay.yaml
```
Confirm the rule is created:
```yaml
$ istioctl get route-rule ratings-test-delay
destination: ratings.default.svc.cluster.local
httpFault:
delay:
fixedDelaySeconds: 7
percent: 100
match:
httpHeaders:
Cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
precedence: 2
route:
- tags:
version: v1
```
Allow several seconds to account for rule propagation delay to all pods.
1. Observe application behavior
If the application's front page was set to correctly handle delays, we expect it
to load within approximately 7 seconds. To see the web page response times, open the
*Developer Tools* menu in IE, Chrome or Firefox (typically, key combination _Ctrl+Shift+I_
or _Alt+Cmd+I_) and reload the `productpage` web page.
You will see that the webpage loads in about 6 seconds. The reviews section will show
*Sorry, product reviews are currently unavailable for this book*.
## Understanding what happened
The reason that the entire reviews service has failed is because our bookinfo application
has a bug. The timeout between the productpage and reviews service is less (3s + 1 retry = 6s total)
than the timeout between the reviews and ratings service (10s). These kinds of bugs can occur in
typical enterprise applications where different teams develop different microservices
independently. Istio's fault injection rules help you identify such anomalies without
impacting end users.
> Notice that we are restricting the failure impact to user "jason" only. If you login
> as any other user, you would not experience any delays.
**Fixing the bug:** At this point we would normally fix the problem by either increasing the
productpage timeout or decreasing the reviews to ratings service timeout,
terminate and restart the fixed microservice, and then confirm that the `productpage`
returns its response without any errors.
However, we already have this fix running in v3 of the reviews service, so we can simply
fix the problem by migrating all
traffic to `reviews:v3` as described in the [request routing task](/docs/tasks/request-routing.html).
(Left as an exercise for the reader - change the delay rule to
use a 2.8 second delay and then run it against the v3 version of reviews.)
## What's next
* Learn more about [this](...).
* See this [related task](...).
* Learn more about [fault injection](/docs/concepts/fault-injection.html).
* Limit requests to the bookinfo `ratings` service with Istio [rate limiting](/docs/tasks/rate-limiting.html).

View File

@ -0,0 +1,63 @@
---
category: Tasks
title: Rate Limiting
overview: This task shows you how to use Istio to dynamically limit the traffic to a service.
order: 40
bodyclass: docs
layout: docs
type: markdown
---
This task shows you how to use Istio to dynamically limit the traffic to a service.
## Before you begin
* Setup Istio by following the instructions in the
[Installation guide](/docs/tasks/installing-istio.html).
* Deploy the [bookinfo](/docs/samples/bookinfo.html) sample application.
* Initialize the application version routing by either first doing the
[request routing](/docs/tasks/request-routing.html) task or by running following
commands:
```bash
$ istioctl create -f route-rule-all-v1.yaml
$ istioctl replace -f route-rule-reviews-v3.yaml
```
### Rate Limiting [WIP]
We will pretend that `ratings` is an external service for which we are paying
(like going to rotten tomatoes), so we will set a rate limit on the service
such that the load remains under the Free quota (5q/s).
1. Configure mixer with the rate limit:
```bash
# (TODO) istioctl create -f mixer-rule-ratings-ratelimit.yaml
kubectl apply -f ../../mixer-config-quota-bookinfo.yaml
```
2. Generate load on the `productpage` with the following command:
```bash
while true; do curl -s -o /dev/null http://$GATEWAY_URL/productpage; done
```
If you now refresh the `productpage` (http://$GATEWAY_URL/productpage)
you'll see that while the load generator is running
(i.e., generating more than 5 req/s), we stop seeing stars.
## Understanding ...
Here's an interesting thing to know about the steps you just did.
## What's next
* Learn more about [this](...).
* See this [related task](...).

View File

@ -10,29 +10,165 @@ layout: docs
type: markdown
---
This task shows how to do X in a Kubernetes cluster. You'll learn
how to ...
This task shows you how to configure dynamic request routing based on weights and HTTP headers.
## Before you begin
* Do this.
* Do this too.
## Doing ...
* Setup Istio by following the instructions in the
[Installation guide](/docs/tasks/installing-istio.html).
1. Do this.
1. Do this next. Possibly read this [related explanation](...).
* Deploy the [bookinfo](/docs/samples/bookinfo.html) sample application.
## Content Based Routing
Because the bookinfo sample deploys 3 versions of the reviews microservice,
we need to set a default route.
Otherwise if you access the application several times, you would notice that sometimes the output contains
star ratings.
This is because without an explicit default version set, Istio will
route requests to all available versions of a service in a random fashion.
## Understanding ...
1. Set the default version for all microservices to v1.
Here's an interesting thing to know about the steps you just did.
```bash
istioctl create -f route-rule-all-v1.yaml
```
You can display the routes that are defined with the following command:
```yaml
$ istioctl get route-rules -o yaml
kind: route-rule
name: ratings-default
namespace: default
spec:
destination: ratings.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
kind: route-rule
name: reviews-default
namespace: default
spec:
destination: reviews.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
kind: route-rule
name: details-default
namespace: default
spec:
destination: details.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
kind: route-rule
name: productpage-default
namespace: default
spec:
destination: productpage.default.svc.cluster.local
precedence: 1
route:
- tags:
version: v1
weight: 100
---
```
Since rule propagation to the proxies is asynchronous, you should wait a few seconds for the rules
to propagate to all pods before attempting to access the application.
1. Open the Bookinfo URL (http://$GATEWAY_URL/productpage) in your browser
You should see the bookinfo application productpage displayed.
Notice that the `productpage` is displayed with no rating stars since `reviews:v1` does not access the ratings service.
1. Route a specific user to `reviews:v2`
Lets enable the ratings service for test user "jason" by routing productpage traffic to
`reviews:v2` instances.
```bash
istioctl create -f route-rule-reviews-test-v2.yaml
```
Confirm the rule is created:
```yaml
$ istioctl get route-rule reviews-test-v2
destination: reviews.default.svc.cluster.local
match:
httpHeaders:
Cookie:
regex: ^(.*?;)?(user=jason)(;.*)?$
precedence: 2
route:
- tags:
version: v2
```
1. Log in as user "jason" at the `productpage` web page.
You should now see ratings (1-5 stars) next to each review. Notice that if you log in as
any other user, you will continue to see `reviews:v1`.
## Understanding what happened
In this task, you used Istio to send 100% of the traffic to the v1 version of each of the bookinfo
services. You then set a rule to selectively send traffic to version v2 of the reviews service based
a header (i.e., a user cookie) in a request.
Once the v2 version has been tested to our satisfaction, we could use Istio to send traffic from
all users to v2, optionally in a gradual fashion by using a sequence of rules with weights less
than 100 to migrate traffic in steps, for example 10, 20, 30, ... 100%.
If you now proceed to the [fault injection task](/docs/tasks/fault-injection.html), you will see
that with simple testing, the v2 version of the reviews service has a bug, which is fixed in v3.
So after exploring that task, you can route all user traffic from `reviews:v1`
to `reviews:v3` in two steps as follows:
1. First, transfer 50% of traffic from `reviews:v1` to `reviews:v3` with the following command:
```bash
istioctl replace -f route-rule-reviews-50-v3.yaml
```
Notice that we are using `istioctl replace` instead of `create`.
2. To see the new version you need to either Log out as test user "jason" or delete the test rules
that we created exclusively for him:
```bash
istioctl delete route-rule reviews-test-v2
istioctl delete route-rule ratings-test-delay
```
You should now see *red* colored star ratings approximately 50% of the time when you refresh
the `productpage`.
> Note: With the Envoy sidecar implementation, you may need to refresh the `productpage` multiple times
> to see the proper distribution. You can modify the rules to route 90% of the traffic to v3 to see red stars more often.
3. When version v3 of the reviews microservice is stable, route 100% of the traffic to `reviews:v3`:
```bash
istioctl replace -f route-rule-reviews-v3.yaml
```
You can now log in to the `productpage` as any user and you should always see book reviews
with *red* colored star ratings for each review.
## What's next
* Learn more about [this](...).
* See this [related task](...).
* Learn more about [request routing](/docs/concepts/rules-configuration.html).
* Test the bookinfo application resiliency by [injecting faults](/docs/tasks/fault-injection.html).