1. Overview
In the first part of the lab, you created an ASP.NET Core application, containerized, and deployed it to Google Kubernetes Engine (GKE) and configured its traffic to be managed by Istio.
This second part of the lab assumes that you already have your Kubernetes cluster and the application from the first lab running. You will see how Istio can help to manage, monitor, and secure your services with minimal code changes. Specifically, you explore features of Istio such as metrics, tracing, service visualization, dynamic traffic management, fault injection, and more.
What you'll learn
- How to query metrics with Prometheus.
- How to visualize metrics with Grafana.
- How to create a new version of your service.
- How to pin a service to a specific version.
- How to split traffic between different versions.
- How to inject faults in service calls.
What you'll need
How will you use this tutorial?
How would rate your experience with Google Cloud Platform?
2. Setup and Requirements
Self-paced environment setup
- Sign in to Cloud Console and create a new project or reuse an existing one. (If you don't already have a Gmail or G Suite account, you must create one.)
Remember the project ID, a unique name across all Google Cloud projects (the name above has already been taken and will not work for you, sorry!). It will be referred to later in this codelab as PROJECT_ID
.
- Next, you'll need to enable billing in Cloud Console in order to use Google Cloud resources.
Running through this codelab shouldn't cost much, if anything at all. Be sure to to follow any instructions in the "Cleaning up" section which advises you how to shut down resources so you don't incur billing beyond this tutorial. New users of Google Cloud are eligible for the $300USD Free Trial program.
Start Cloud Shell
While Google Cloud can be operated remotely from your laptop, in this codelab you use Google Cloud Shell, a command line environment running in Google Cloud.
Activate Cloud Shell
- From the Cloud Console, click Activate Cloud Shell .
If you've never started Cloud Shell before, you'll be presented with an intermediate screen (below the fold) describing what it is. If that's the case, click Continue (and you won't ever see it again). Here's what that one-time screen looks like:
It should only take a few moments to provision and connect to Cloud Shell.
This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory and runs in Google Cloud, greatly enhancing network performance and authentication. Much, if not all, of your work in this codelab can be done with simply a browser or your Chromebook.
Once connected to Cloud Shell, you should see that you are already authenticated and that the project is already set to your project ID.
- Run the following command in Cloud Shell to confirm that you are authenticated:
gcloud auth list
Command output
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
Command output
[core] project = <PROJECT_ID>
If it is not, you can set it with this command:
gcloud config set project <PROJECT_ID>
Command output
Updated property [core/project].
3. Test the application
Before you start the lab, make sure the application is still working from the previous lab. As a reminder, this is how you see the external IP and port of the gateway, which are listed under EXTERNAL-IP
:
kubectl get svc istio-ingressgateway -n istio-system
To view the application, you can open your browser and navigate to http://<gatewayurl>
:
If you don't see the application, go back to the previous lab to make sure you followed all the steps and both the application and Istio are installed and running properly.
At this point, you might be wondering "What's the benefit of Istio?". By letting Istio manage your application's traffic, you get features like metrics, tracing, dynamic traffic management, service visualization, fault injection, and more for free.
You'll start with exploring metrics in the next step.
4. Metrics with Grafana and Prometheus
By default, Istio generates some metrics. You can use add-ons to query and visualize these default metrics.
Prometheus
Prometheus is an open-source monitoring solution. You can use Prometheus to query metrics generated by Istio but you need to first install Prometheus add-on.
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml
Verify that Prometheus is running:
kubectl get svc prometheus -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prometheus ClusterIP 10.31.243.62 <none> 9090/TCP 1d
Send some traffic to the application by visiting http://<gatewayurl>
a few times or running the curl command.
Setup port forwarding for the Prometheus UI:
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 8080:9090
You can now execute a query by clicking on the Web Preview button in the top-right corner of Cloud Shell and click Preview on port 8080:
You'll see the Prometheus UI in a new tab:
To learn more about Prometheus, see Querying Metrics with Prometheus.
Grafana
Grafana is another add-on for visualizing metrics.
Install Grafana. Replace istio-version
with your current Istio version,for example, 1.0.3-gke.3
:
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/grafana.yaml
Verify that Grafana is running:
kubectl get svc grafana -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana ClusterIP 10.31.248.230 <none> 3000/TCP 1d
Send some traffic to the application by visiting http://<gatewayurl>
a few times or running the curl command.
Setup port forwarding for the Grafana UI:
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 8080:3000
You can view Grafana dashboards by visiting Web Preview:
To learn more about Granfana, see Visualizing Metrics with Grafana.
5. Create a new version of the application
At some point, the application that you've deployed to production will require bug fixes or additional features. Let's see how that process looks like.
First, let's modify the application. Open the code editor from Cloud Shell.
Navigate to Index.cshtml
under HelloWorldAspNetCore > Views > Home
and update one of the carousel messages.
Find the following line:
Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core
And change it to this:
Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core on Google Cloud
Save the changes and then go back to Cloud Shell. Inside HelloWorldAspNetCore,
build the docker image:
docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 .
And push to the Container Registry:
docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2
After you push the container image, you can deploy the new version in the next step.
6. Create the new deployment
To deploy the new version, you first need to create a new deployment for it in Kubernetes. Add the following at the end of the aspnetcore.yaml
file:
--- apiVersion: apps/v1 kind: Deployment metadata: name: aspnetcore-v2 spec: replicas: 1 selector: matchLabels: app: aspnetcore version: v2 template: metadata: labels: app: aspnetcore version: v2 spec: containers: - name: aspnetcore image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 8080
Deploy the new version to the default namespace with kubectl
:
kubectl apply -f aspnetcore.yaml
service "aspnetcore" unchanged deployment.extensions "aspnetcore-v1" unchanged deployment.extensions "aspnetcore-v2" created
Verify that the expected pods are running:
kubectl get pods
NAME READY STATUS RESTARTS AGE aspnetcore-v1-6cf64748-mddb 2/2 Running 0 34s aspnetcore-v2-5d765db-l9xmg 2/2 Running 0 1m
Now, test the application again. Get the external IP of the gateway:
kubectl get svc istio-ingressgateway -n istio-system
It's listed under EXTERNAL-IP. Open up an incognito browser and visit http://<replace-with-external-ip>
When you refresh, sometimes, you'll see the message "Learn about building Web apps with ASP.NET Core":
Other times, you'll see the message "Learn about building Web apps with ASP.NET Core on Google Cloud":
This is because both v1
and v2
deployments are exposed behind the same Kubernetes service (aspnetcore-service
) and the VirtualService you created in the previous lab (aspnetcore-virtualservice
) uses that service as a host.
In the next step, you pin the service to the v2
deployment using a DestinationRule.
7. Pin your service to the new version
In this step, you pin your service to use the v2
deployment and you can do that with a DestinationRule. A DestinationRule configures the set of policies to be applied to a request after a VirtualService routing operation has occurred.
A DestinationRule also defines addressable subsets, meaning named versions, of the corresponding destination host. These subsets are used in VirtualService route specifications when sending traffic to specific versions of the service.
Create a new file called aspnetcore-destinationrule.yaml
:
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: aspnetcore-destinationrule spec: host: aspnetcore-service trafficPolicy: tls: mode: ISTIO_MUTUAL subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
Next, create the DestinationRule. This creates two subsets (v1 and v2) that you can use from the VirtualService:
kubectl apply -f aspnetcore-destinationrule.yaml
destinationrule.networking.istio.io "aspnetcore-destionationrule" created
Now, go back to aspnetcore-virtualservice.yaml
file to update the VirtualService to use the v2
subset:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: aspnetcore-virtualservice spec: hosts: - "*" gateways: - aspnetcore-gateway http: - route: - destination: host: aspnetcore-service subset: v2
Update the VirtualService:
kubectl apply -f aspnetcore-virtualservice.yaml
Open up your browser and visit http://<replace-with-external-ip>.
Even after multiple refreshes, you should see the message "Learn about building Web apps with ASP.NET Core on Google Cloud":
8. Split traffic between versions
Sometimes, you might want to split traffic between versions for testing. For example, you might want to send 75% of the traffic to the v1 and 25% of the traffic to the v2 version of the service. You can easily achieve this with Istio. Create a new aspnetcore-virtualservice-weights.yaml
file to refer to the two subsets with different weights:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: aspnetcore-virtualservice spec: hosts: - "*" gateways: - aspnetcore-gateway http: - route: - destination: host: aspnetcore-service subset: v1 weight: 75 - destination: host: aspnetcore-service subset: v2 weight: 25
Update the VirtualService:
kubectl apply -f aspnetcore-virtualservice-weights.yaml
Now, when you refresh the browser, you should see the v1 vs. v2 versions served with roughly a 3:1 ratio.
To learn more, see traffic splitting in Istio.
9. Inject faults
Another useful development task to do for testing is to inject faults or delays into the traffic and see how services behave in response.
For example, you might want to return a bad request (HTTP 400) response for 50% of the traffic to the v1 version. Create aspnetcore-virtualservice-fault-abort.yaml
file to match the following:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: aspnetcore-virtualservice spec: hosts: - "*" gateways: - aspnetcore-gateway http: - fault: abort: percentage: value: 50 httpStatus: 400 route: - destination: host: aspnetcore-service subset: v1
Update the VirtualService:
kubectl apply -f aspnetcore-virtualservice-fault-abort.yaml
Now, when you refresh the browser, you should see that half of the time, the v1 service returns a HTTP 400s response code.
Or maybe you want to add 5 seconds delay to the requests. Create aspnetcore-virtualservice-fault-delay.yaml
file to match the following:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: aspnetcore-virtualservice spec: hosts: - "*" gateways: - aspnetcore-gateway http: - fault: delay: fixedDelay: 5s percentage: value: 100 route: - destination: host: aspnetcore-service subset: v1
Update the VirtualService:
kubectl apply -f aspnetcore-virtualservice-fault-delay.yaml
Now, when you refresh the browser, you should see that requests are delayed by 5 seconds.
To learn more about Istio features such as timeouts, retries, conditional rules, circuit breakers and more, see traffic management features.
10. Congratulations!
Hopefully, this lab gave you an overview of what Istio can do for your services out of the box. To learn more about Istio and GKE.
Next Steps
- Learn more about Istio.
- Learn more about Kubernetes.
- Learn more about Google Kubernetes Engine.
- Learn more about .NET on Google Cloud Platform.
License
This work is licensed under a Creative Commons Attribution 2.0 Generic License.
11. Cleanup
You can delete the app and uninstall Istio or you can simply delete the Kubernetes cluster.
Delete the application
To delete the application:
kubectl delete -f aspnetcore-gateway.yaml kubectl delete -f aspnetcore-virtualservice.yaml kubectl delete -f aspnetcore-destinationrule.yaml kubectl delete -f aspnetcore.yaml
To confirm that the application is gone:
kubectl get gateway kubectl get virtualservices kubectl get destinationrule kubectl get pods
Uninstall Istio
To delete Istio:
kubectl delete -f install/kubernetes/istio-demo-auth.yaml
To confirm that Istio is gone:
kubectl get pods -n istio-system
Delete Kubernetes cluster
gcloud container clusters delete hello-dotnet-cluster