diff --git a/.spelling b/.spelling index 257dec141f..47dbfe974a 100644 --- a/.spelling +++ b/.spelling @@ -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 diff --git a/content/en/boilerplates/work-in-progress.md b/content/en/boilerplates/work-in-progress.md new file mode 100644 index 0000000000..fa799d116a --- /dev/null +++ b/content/en/boilerplates/work-in-progress.md @@ -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 >}} diff --git a/content/en/docs/examples/microservices-istio/_index.md b/content/en/docs/examples/microservices-istio/_index.md new file mode 100644 index 0000000000..968e9b762e --- /dev/null +++ b/content/en/docs/examples/microservices-istio/_index.md @@ -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 >}} diff --git a/content/en/docs/examples/microservices-istio/prereq/index.md b/content/en/docs/examples/microservices-istio/prereq/index.md new file mode 100644 index 0000000000..fcc004be8b --- /dev/null +++ b/content/en/docs/examples/microservices-istio/prereq/index.md @@ -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. diff --git a/content/en/docs/examples/microservices-istio/setup-kubernetes-cluster/index.md b/content/en/docs/examples/microservices-istio/setup-kubernetes-cluster/index.md new file mode 100644 index 0000000000..49d8327071 --- /dev/null +++ b/content/en/docs/examples/microservices-istio/setup-kubernetes-cluster/index.md @@ -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). +{{}} + +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 - <}} + +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 - <}} + +1. Create a service account for each participant: + + {{< text bash >}} + $ kubectl apply -f - <}} + +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 - <}} + +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 < ./${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). diff --git a/content/en/docs/examples/microservices-istio/setup-local-computer/index.md b/content/en/docs/examples/microservices-istio/setup-local-computer/index.md new file mode 100644 index 0000000000..3a86e4a981 --- /dev/null +++ b/content/en/docs/examples/microservices-istio/setup-local-computer/index.md @@ -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/). diff --git a/content/en/docs/examples/microservices-istio/single/index.md b/content/en/docs/examples/microservices-istio/single/index.md new file mode 100644 index 0000000000..0d05c97bb4 --- /dev/null +++ b/content/en/docs/examples/microservices-istio/single/index.md @@ -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.