Add microservices tutorial - first modules (#5111)

* Add intro, fix broken links/titles, set 80 columns

* Clarified, expanded wording and made it consistent

* Fixed curl case

* Removed tutorial node and moved to examples node

* Fixed PR comments
This commit is contained in:
Adam Miller 2019-10-15 12:02:38 -07:00 committed by Istio Automation
parent 31d21ffbb4
commit 8a29b55cf5
7 changed files with 461 additions and 0 deletions

View File

@ -313,6 +313,7 @@ Kuat
Kube
Kubecon
kubeconfig
kubectl
Kubelet
kubelet
Kubernetes
@ -370,6 +371,7 @@ netmask
networking.istio.io
nginx
NLBs
Node.js
nodePorts
non-sandboxed
normalization

View File

@ -0,0 +1,5 @@
---
---
{{< warning >}}
This is work in progress. We will add its sections in pieces. Your feedback is welcome at [discuss.istio.io](https://discuss.istio.io).
{{< /warning >}}

View File

@ -0,0 +1,17 @@
---
title: Learn Microservices using Kubernetes and Istio
description: This modular tutorial provides new users with hands-on experience using Istio for common microservices scenarios, one step at a time.
weight: 40
icon: classroom
simple_list: true
content_above: true
---
It is intended for self-guided users or instructors who train
others. It begins with the steps to set up a cluster to
control an example microservice running on a local computer, and culminates into
demonstrating several crucial microservice management tasks using Istio.
For the best experience, follow the modules in the order provided.
{{< boilerplate work-in-progress >}}

View File

@ -0,0 +1,30 @@
---
title: Prerequisites
overview: Check the prerequisites for this tutorial.
weight: 2
---
{{< boilerplate work-in-progress >}}
For this tutorial you need a Kubernetes cluster with a namespace for the
tutorial's modules and a local computer to run the commands. If you have your
own cluster, ensure your cluster satisfies the prerequisites.
If you are in a workshop and the instructors provide a cluster, let
them handle the cluster prerequisites, while you skip ahead to setup your local
computer.
## Kubernetes cluster
Ensure the following conditions are met:
- You have administrator privileges on a Kubernetes cluster.
- You can create a namespace in the cluster for each participant.
## Local computer
Ensure the following conditions are met:
- You have write access to the local computer's `/etc/hosts` file.
- You have the ability and permission to download, install and run command line tools on the local computer.
- You have Internet connectivity for the duration of the tutorial.

View File

@ -0,0 +1,228 @@
---
title: Setup a Kubernetes Cluster
overview: Set up your Kubernetes cluster for the tutorial.
weight: 2
---
{{< boilerplate work-in-progress >}}
In this module, you set up a Kubernetes cluster that has Istio installed and a
namespace to use throughout the tutorial.
{{< warning >}}
If you are in a workshop and the instructors provide a cluster for you,
proceed to [setting up your local computer](/docs/examples/microservices-istio/setup-local-computer).
{{</ warning >}}
1. Ensure you have access to a [Kubernetes cluster](https://kubernetes.io/docs/tutorials/kubernetes-basics/).
You can use the [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/docs/quickstart) or the
[IBM Cloud Kubernetes Service](https://cloud.ibm.com/docs/containers?topic=containers-getting-started).
1. Connect to your cluster and create an environment variable to store the name
of a namespace that you will use when you run the tutorial commands.
You can use any name, for example `tutorial`.
{{< text bash >}}
$ export NAMESPACE=tutorial
{{< /text >}}
1. Create the namespace:
{{< text bash >}}
$ kubectl create namespace $NAMESPACE
{{< /text >}}
{{< tip >}}
If you are an instructor, you should allocate a separate namespace per each
participant. The tutorial supports work in multiple namespaces
simultaneously by multiple participants.
{{< /tip >}}
1. Install Istio with strict mutual TLS enabled by selecting the `strict mutual
TLS` tab when you follow [the Kubernetes installation steps](/docs/setup/install/kubernetes/#installation-steps).
1. [Enable Envoy's access logging](/docs/tasks/observability/logs/access-log/#enable-envoy-s-access-logging).
1. Create a Kubernetes Ingress resource for these common Istio services using
the `kubectl` command shown. It is not necessary to be familiar with each of
these services at this point in the tutorial.
- [Grafana](https://grafana.com/docs/guides/getting_started/)
- [Jaeger](https://www.jaegertracing.io/docs/1.13/getting-started/)
- [Prometheus](https://prometheus.io/docs/prometheus/latest/getting_started/)
- [Kiali](https://www.kiali.io/documentation/getting-started/)
The `kubectl` command can accept an in-line configuration to create the
Ingress resources for each service:
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: istio-system
namespace: istio-system
spec:
rules:
- host: my-istio-dashboard.io
http:
paths:
- path: /
backend:
serviceName: grafana
servicePort: 3000
- host: my-istio-tracing.io
http:
paths:
- path: /
backend:
serviceName: tracing
servicePort: 80
- host: my-istio-logs-database.io
http:
paths:
- path: /
backend:
serviceName: prometheus
servicePort: 9090
- host: my-kiali.io
http:
paths:
- path: /
backend:
serviceName: kiali
servicePort: 20001
EOF
{{< /text >}}
1. Create a role to provide read access to the `istio-system` namespace. This
role is required to limit permissions of the participants in the steps
below.
{{< text bash >}}
$ kubectl apply -f - <<EOF
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: istio-system-access
namespace: istio-system
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["*"]
verbs: ["get", "list"]
EOF
{{< /text >}}
1. Create a service account for each participant:
{{< text bash >}}
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: ${NAMESPACE}-user
namespace: $NAMESPACE
EOF
{{< /text >}}
1. Limit each participant's permissions. During the tutorial, participants only
need to create resources in their namespace and to read resources from
`istio-system` namespace. It is a good practice, even if using your own
cluster, to avoid interfering with other namespaces in
your cluster.
Create a role to allow read-write access to each participant's namespace.
Bind the participant's service account to this role and to the role for
reading resources from `istio-system`:
{{< text bash >}}
$ kubectl apply -f - <<EOF
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: ${NAMESPACE}-access
namespace: $NAMESPACE
rules:
- apiGroups: ["", "extensions", "apps", "networking.k8s.io", "networking.istio.io", "authentication.istio.io",
"rbac.istio.io", "config.istio.io"]
resources: ["*"]
verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: ${NAMESPACE}-access
namespace: $NAMESPACE
subjects:
- kind: ServiceAccount
name: ${NAMESPACE}-user
namespace: $NAMESPACE
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ${NAMESPACE}-access
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: ${NAMESPACE}-istio-system-access
namespace: istio-system
subjects:
- kind: ServiceAccount
name: ${NAMESPACE}-user
namespace: $NAMESPACE
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: istio-system-access
EOF
{{< /text >}}
1. Each participant needs to use their own Kubernetes configuration file. This configuration file specifies
the cluster details, the service account, the credentials and the namespace of the participant.
The `kubectl` command uses the configuration file to operate on the cluster.
Generate a Kubernetes configuration file for each participant:
{{< text bash >}}
$ cat <<EOF > ./${NAMESPACE}-user-config.yaml
apiVersion: v1
kind: Config
preferences: {}
clusters:
- cluster:
certificate-authority-data: $(kubectl get secret $(kubectl get sa ${NAMESPACE}-user -n $NAMESPACE -o jsonpath={.secrets..name}) -n $NAMESPACE -o jsonpath='{.data.ca\.crt}')
server: $(kubectl config view -o jsonpath="{.clusters[?(.name==\"$(kubectl config view -o jsonpath="{.contexts[?(.name==\"$(kubectl config current-context)\")].context.cluster}")\")].cluster.server}")
name: ${NAMESPACE}-cluster
users:
- name: ${NAMESPACE}-user
user:
as-user-extra: {}
client-key-data: $(kubectl get secret $(kubectl get sa ${NAMESPACE}-user -n $NAMESPACE -o jsonpath={.secrets..name}) -n $NAMESPACE -o jsonpath='{.data.ca\.crt}')
token: $(kubectl get secret $(kubectl get sa ${NAMESPACE}-user -n $NAMESPACE -o jsonpath={.secrets..name}) -n $NAMESPACE -o jsonpath={.data.token} | base64 --decode)
contexts:
- context:
cluster: ${NAMESPACE}-cluster
namespace: ${NAMESPACE}
user: ${NAMESPACE}-user
name: ${NAMESPACE}
current-context: ${NAMESPACE}
EOF
{{< /text >}}
1. If you are setting up the cluster for yourself, copy the
`${NAMESPACE}-user-config.yaml` file mentioned in the previous steps to your
local computer, where `${NAMESPACE}` is the name of the namespace you
provided in the previous steps. For example, `tutorial-user-config.yaml`.
You will need this file later in the tutorial.
If you are an instructor, send the generated configuration files to each
participant who should copy it to their local computer.
Congratulations, you configured your cluster for the tutorials!
You are ready to [setup a local computer](/docs/examples/microservices-istio/setup-local-computer).

View File

@ -0,0 +1,50 @@
---
title: Setup a Local Computer
overview: Set up your local computer for the tutorial.
weight: 3
---
{{< boilerplate work-in-progress >}}
In this module you prepare your local computer for the tutorial.
1. On your local computer, locate the `${NAMESPACE}-user-config.yaml` file you
created earlier in the tutorial, where `${NAMESPACE}` is the name of your
namespace. For example `tutorial-user-config.yaml`.
1. Install [curl](https://curl.haxx.se/download.html).
1. Install [Node.js](https://nodejs.org/en/download/).
1. Install [Docker](https://docs.docker.com/install/).
1. Install [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
1. Set the `KUBECONFIG` environment variable for the `${NAMESPACE}-user-config.yaml`
configuration file:
{{< text bash >}}
$ export KUBECONFIG=./${NAMESPACE}-user-config.yaml
{{< /text >}}
1. Verify that the configuration took effect by printing the current namespace:
{{< text bash >}}
$ kubectl config view -o jsonpath="{.contexts[?(@.name==\"$(kubectl config current-context)\")].context.namespace}"
tutorial
{{< /text >}}
You should see the name of your namespace in the output.
1. Download one of the [Istio release archives](https://github.com/istio/istio/releases) and extract
the `istioctl` command line tool from the `bin` directory, and verify that you
can run `istioctl` with the following command:
{{< text bash >}}
$ istioctl version
version.BuildInfo{Version:"release-1.1-20190214-09-16", GitRevision:"6113e155ac85e2485e30dfea2b80fd97afd3130a", User:"root", Host:"4496ae63-3039-11e9-86e9-0a580a2c0304", GolangVersion:"go1.10.4", DockerHub:"gcr.io/istio-release", BuildStatus:"Clean", GitTag:"1.1.0-snapshot.6-6-g6113e15"}
{{< /text >}}
Congratulations, you configured your local computer!
You are ready to [run a single service locally](/docs/examples/microservices-istio/single/).

View File

@ -0,0 +1,129 @@
---
title: Run a Microservice Locally
overview: Learn how to work on a single service on your local machine.
weight: 10
---
{{< boilerplate work-in-progress >}}
Before the advent of microservice architecture, development teams built,
deployed and ran the whole application as one large chunk of software. To test a
small change in their module not merely by unit testing, the developers had to
build the whole application. Therefore the builds took large amount of time.
After the build, the developers deployed their version of the application into a
test server. The developers ran the server either on a remote machine, or on their
local computer. In the latter case, the developers had to install and operate a
rather complex environment on their local computer.
In the era of microservice architecture, the developers write, build, test and
run small software services. Builds are fast. With modern frameworks like
[Node.js](https://nodejs.org/en/) there is no need to install and operate
complex server environments to test a single service, since the service runs as
a regular process. You do not have to deploy your service to some environment to
merely test it, so you just build your service and run it immediately on your
local computer.
This module covers the different aspects involved in developing a single service
on a local machine. You don't need to write code though. Instead, you build,
run, and test an existing service: `ratings`.
The `ratings` service is a small web app written in
[Node.js](https://nodejs.org/en/) that can run on its own. It performs similar
actions to those of other web apps:
- Listen to the port it receives as a parameter.
- Expect `HTTP GET` requests on the `/ratings/{productID}` path and return the
ratings of the product matching the value the client specifies for `productID`.
- Expect `HTTP POST` requests on the `/ratings/{productID}` path and update the
ratings of the product matching the value you specify for `productID`.
Follow these steps to download the code of the app, install its dependencies,
and run it locally:
1. Download
[the service's code]({{< github_blob >}}/samples/bookinfo/src/ratings/ratings.js)
and
[the package file]({{< github_blob >}}/samples/bookinfo/src/ratings/package.json)
into a separate directory:
{{< text bash >}}
$ mkdir ratings
$ cd ratings
$ curl -s {{< github_file >}}/samples/bookinfo/src/ratings/ratings.js -o ratings.js
$ curl -s {{< github_file >}}/samples/bookinfo/src/ratings/package.json -o package.json
{{< /text >}}
1. Skim the service's code and note the following elements on the code:
- The web server's features:
- listening to a port
- handling requests and responses
- The aspects related to HTTP:
- headers
- path
- status code
{{< tip >}}
In Node.js, the web server's functionality is embedded in the code of the application. A Node.js
web application runs as a standalone process.
{{< /tip >}}
1. Node.js applications are written in JavaScript, which means that there is no
explicit compilation step. Instead, they use [just-in-time compilation](https://en.wikipedia.org/wiki/Just-in-time_compilation). To build a Node.js application, then means to install its dependencies. Install
the dependencies of the `ratings` service in the same folder where you
stored the service code and the package file:
{{< text bash >}}
$ npm install
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN ratings No description
npm WARN ratings No repository field.
npm WARN ratings No license field.
added 24 packages in 2.094s
{{< /text >}}
1. Run the service, passing `9080` as a parameter. The application then listens on port 9080.
{{< text bash >}}
$ npm start 9080
> @ start /tmp/ratings
> node ratings.js "9080"
Server listening on: http://0.0.0.0:9080
{{< /text >}}
{{< tip >}}
The `ratings` service is a web app and you can communicate with it as you would
with any other web app. You can use a browser or a command line web client like
[`curl`](https://curl.haxx.se) or [`Wget`](https://www.gnu.org/software/wget/).
Since you run the `ratings` service locally, you can also access it via the
`localhost` hostname.
{{< /tip >}}
1. Open [http://localhost:9080/ratings/7](http://localhost:9080/ratings/7) in
your browser or access `ratings` using the `curl` command:
{{< text bash >}}
$ curl localhost:9080/ratings/7
{"id":7,"ratings":{"Reviewer1":5,"Reviewer2":4}}
{{< /text >}}
1. Use the `POST` method of the `curl` command to set the ratings for the
product to `1`:
{{< text bash >}}
$ curl -X POST localhost:9080/ratings/7 -d '{"Reviewer1":1,"Reviewer2":1}'
{"id":7,"ratings":{"Reviewer1":1,"Reviewer2":1}}
{{< /text >}}
1. Check the updated ratings:
{{< text bash >}}
$ curl localhost:9080/ratings/7
{"id":7,"ratings":{"Reviewer1":1,"Reviewer2":1}}
{{< /text >}}
1. Use `Ctrl-C` in the terminal running the service to stop it.
Congratulations, you can now build, test, and run a service on your local computer!
You are ready to learn how to package the service into a container.