[Yandex Cloud documentation](../../index.md) > [Tutorials](../index.md) > [Container infrastructure](index.md) > Managed Service for Kubernetes > Using Cloud Marketplace products > Using Istio

# Using Istio in Yandex Managed Service for Kubernetes

# Using Istio


[Istio](https://istio.io/latest/about/service-mesh/) implements a _service mesh_, a low-latency infrastructure layer that manages large-scale network communications between services in a Managed Service for Kubernetes cluster.

To explore Istio use cases:

1. [Install Istio](#istio-install).
1. [Install a test application](#test-application).
1. [View a service network diagram on the Kiali dashboard](#visualization-service-network).
1. [Route requests](#request-routing).
1. [Simulate a service failure](#injection-failures).
1. [Redistribute traffic](#traffic-redistribution).
1. [Set up mutual TLS authentication](#mutual-tls).
1. [View Istio metrics on the Prometheus dashboard](#viewing-metrics-prometheus).
1. [View Istio metrics on the Grafana dashboard](#viewing-metrics-grafana).

If you no longer need the resources you created, [delete them](#clear-out).


## Required paid resources {#paid-resources}

The support cost for this solution includes:

* Fee for using the master and outgoing traffic in a Managed Service for Kubernetes cluster (see [Managed Service for Kubernetes pricing](../../managed-kubernetes/pricing.md)).
* Fee for using computing resources, OS, and storage in cluster nodes (VMs) (see [Compute Cloud pricing](../../compute/pricing.md)).
* Fee for a public IP address assigned to cluster nodes (see [Virtual Private Cloud pricing](../../vpc/pricing.md#prices-public-ip)).


## Getting started {#before-you-begin}

1. Create a Kubernetes cluster and [node group](../../managed-kubernetes/concepts/index.md#node-group).

    {% list tabs group=instructions %}

    - Manually {#manual}

        1. If you do not have a [network](../../vpc/concepts/network.md#network) yet, [create one](../../vpc/operations/network-create.md).
        1. If you do not have any [subnets](../../vpc/concepts/network.md#subnet) yet, [create them](../../vpc/operations/subnet-create.md) in the [availability zones](../../overview/concepts/geo-scope.md) where the new Kubernetes cluster and node group will reside.
        1. [Create these service accounts](../../iam/operations/sa/create.md):

            * Service account with the `k8s.clusters.agent` and `vpc.publicAdmin` [roles](../../managed-kubernetes/security/index.md#yc-api) for the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create a Kubernetes cluster. This service account will be used to create resources for your Kubernetes cluster.
            * Service account with the [container-registry.images.puller](../../container-registry/security/index.md#container-registry-images-puller) [role](../../iam/concepts/access-control/roles.md). Nodes will use this account to pull the required [Docker images](../../container-registry/concepts/docker-image.md) from the [registry](../../container-registry/concepts/registry.md).

            {% note tip %}

            You can use the same [service account](../../iam/concepts/users/service-accounts.md) to manage your Kubernetes cluster and its node groups.

            {% endnote %}

        1. [Create security groups](../../managed-kubernetes/operations/connect/security-groups.md) for the Managed Service for Kubernetes cluster and its node groups.

            {% note warning %}
            
            The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
            
            {% endnote %}

        1. [Create a Kubernetes cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-create.md) and [node group](../../managed-kubernetes/operations/node-group/node-group-create.md) with at least 6 GB of RAM and the security groups you created earlier.

    - Terraform {#tf}

        1. If you do not have Terraform yet, [install it](../infrastructure-management/terraform-quickstart.md#install-terraform).
        1. [Get the authentication credentials](../infrastructure-management/terraform-quickstart.md#get-credentials). You can add them to environment variables or specify them later in the provider configuration file.
        1. [Configure and initialize a provider](../infrastructure-management/terraform-quickstart.md#configure-provider). There is no need to create a provider configuration file manually, you can [download it](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
        1. Place the configuration file in a separate working directory and [specify the parameter values](../infrastructure-management/terraform-quickstart.md#configure-provider). If you did not add the authentication credentials to environment variables, specify them in the configuration file.

        1. Download the [k8s-cluster.tf](https://github.com/yandex-cloud-examples/yc-mk8s-cluster-infrastructure/blob/main/k8s-cluster.tf) cluster configuration file to the same working directory. This file describes:

            * [Network](../../vpc/concepts/network.md#network).
            * [Subnet](../../vpc/concepts/network.md#subnet).
            * Kubernetes cluster.
            * [Service account](../../iam/concepts/users/service-accounts.md) for the Managed Service for Kubernetes cluster and node group.
            * [Security groups](../../vpc/concepts/security-groups.md) which contain [rules](../../managed-kubernetes/operations/connect/security-groups.md) required for the Managed Service for Kubernetes cluster and its node groups.

                {% note warning %}
                
                The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
                
                {% endnote %}

        1. In the `k8s-cluster.tf` file, specify the following:

            * [Folder ID](../../resource-manager/operations/folder/get-id.md).
            * Kubernetes version for the Kubernetes cluster and node groups.
            * RAM for your node group, which must be at least 6 GB and a multiple of the vCPU count.
            * Kubernetes cluster CIDR.
            * Name of the Managed Service for Kubernetes cluster service account.

        1. Validate your Terraform configuration files using this command:

            ```bash
            terraform validate
            ```

            Terraform will display any configuration errors detected in your files.

        1. Create the required infrastructure:

            1. Run this command to view the planned changes:
            
               ```bash
               terraform plan
               ```
            
               If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
            
            1. If everything looks correct, apply the changes:
               1. Run this command:
            
                  ```bash
                  terraform apply
                  ```
            
               1. Confirm updating the resources.
               1. Wait for the operation to complete.

            All the required resources will be created in the specified folder. You can check resource availability and their settings in the [management console](https://console.yandex.cloud).

    {% endlist %}

    {% note warning %}
    
    Do not change or delete Virtual Private Cloud resources used by the Managed Service for Kubernetes cluster. This may cause cluster errors or make it impossible to delete later.
    
    {% endnote %}

1. [Install kubect](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [configure it to work with the new cluster](../../managed-kubernetes/operations/connect/index.md#kubectl-connect).

## Install Istio {#istio-install}

1. [Install](../../managed-kubernetes/operations/applications/istio.md#marketplace-install) [Istio](https://yandex.cloud/en/marketplace/products/yc/istio) from Yandex Cloud Marketplace. When installing the app:

    1. Create a new [namespace](../../managed-kubernetes/concepts/index.md#namespace) called `istio-system`.
    1. Install Istio add-ons: Kiali, Prometheus, Grafana, Loki, and Jaeger.

1. Make sure all [pods](../../managed-kubernetes/concepts/index.md#pod) of Istio and its add-ons switched to `Running`:

    ```bash
    kubectl get pods -n istio-system
    ```

    Result:

    ```text
    NAME                                    READY   STATUS    RESTARTS   AGE
    grafana-75c6d4fcf7-v4sfp                1/1     Running   0          2h
    istio-ingressgateway-6496999d57-hdbnf   1/1     Running   0          2h
    istiod-665dbb97c9-s6xxk                 1/1     Running   0          2h
    jaeger-5468d9c886-x2bq8                 1/1     Running   0          2h
    kiali-6854cc8574-26t65                  1/1     Running   0          2h
    loki-0                                  1/1     Running   0          2h
    prometheus-54f86f6676-vmqqr             2/2     Running   0          2h
    ```

## Install a test application {#test-application}

1. Create a new namespace called `todoapp`:

    ```bash
    kubectl create namespace todoapp
    ```

1. Add the `istio-injection` label to the `todoapp` namespace:

    ```bash
    kubectl label namespace todoapp istio-injection=enabled
    ```

1. Install the `todoapp` test application:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/todoapp.yaml -n todoapp
    ```

    Result:

    ```text
    deployment.apps/todoapp-v1 created
    deployment.apps/todoapp-v2 created
    deployment.apps/recommender-v1 created
    deployment.apps/todoapp-redis-v1 created
    service/todoapp created
    service/recommender created
    service/todoapp-redis created
    ```

1. Check the pod status:

    ```bash
    kubectl get pods -n todoapp
    ```

    Result:

    ```text
    NAME                                READY   STATUS    RESTARTS   AGE
    recommender-v1-7865c4cfbb-hsp2k     2/2     Running   0          60s
    recommender-v1-7865c4cfbb-vqt68     2/2     Running   0          59s
    todoapp-redis-v1-dbdf4d44-48952     2/2     Running   0          59s
    todoapp-v1-6d4b78b6c9-gfkxd         2/2     Running   0          60s
    todoapp-v1-6d4b78b6c9-jc962         2/2     Running   0          60s
    todoapp-v2-7dd69b445f-2rznm         2/2     Running   0          60s
    todoapp-v2-7dd69b445f-gr4vn         2/2     Running   0          60s
    ```

    Make sure all pods switched to `Running` and `READY=2/2`.

1. Check the status of services:

    ```bash
    kubectl get services -n todoapp
    ```

    Result:

    ```text
    NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    recommender     ClusterIP   10.96.255.93    <none>        80/TCP     80s
    todoapp         ClusterIP   10.96.232.143   <none>        80/TCP     80s
    todoapp-redis   ClusterIP   10.96.174.100   <none>        6379/TCP   80s
    ```

1. Make sure the web app is up and running:

    ```bash
    kubectl exec "$(kubectl get pod -l app=recommender -n todoapp -o jsonpath='{.items[0].metadata.name}')" -n todoapp \
       -- curl --silent --show-error todoapp:80 | grep -o "<title>.*</title>"
    ```

    Result:

    ```text
    <title>Todoapp</title>
    ```

1. Publish the app:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/todoapp-gateway.yaml -n todoapp
    ```

    Result:

    ```text
    gateway.networking.istio.io/todoapp-gateway created
    virtualservice.networking.istio.io/todoapp-vs created
    ```

1. Get the ingress gateway IP address to access the app:

    ```bash
    kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
    ```

1. To run the web app, paste the obtained IP address into the address bar of your browser.

    {% note info %}
    
    If you cannot access the resource at the specified URL, [make sure](../../managed-kubernetes/operations/connect/security-groups.md) the security groups for the Managed Service for Kubernetes cluster and its node groups are configured correctly. If a rule is missing, [add it](../../vpc/operations/security-group-add-rule.md).
    
    {% endnote %}

    Each time the page is refreshed, its content will be updated. Depending on the version of the pod serving your request, you will see:

    * Pod `v1`: To-do list panel.
    * Pod `v2`: To-do list and recommendations panels.

## View a service network diagram on the Kiali dashboard {#visualization-service-network}

1. Make sure `kiali` is installed and available in your Managed Service for Kubernetes cluster:

    ```bash
    kubectl get service kiali -n istio-system
    ```

    Result:

    ```text
    NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)              AGE
    kiali   ClusterIP   10.96.207.108   <none>        20001/TCP,9090/TCP   15d
    ```

1. Set up `kiali` port forwarding to your local computer:

    ```bash
    kubectl port-forward service/kiali 8080:20001 -n istio-system
    ```

1. To open the Kiali dashboard, paste `http://localhost:8080` into the address bar of your browser.

    The Kiali dashboard visualizes various information, including the service mesh diagram, Istio configuration, service configurations and statuses, as well as metrics, traces, and pod logs.

1. To generate traffic, use your [test app](#test-application). For example, add a to-do list.

1. Open the Kiali dashboard, go to **Graph**, and select the **todoapp** namespace. On the diagram, you will see the test application components running within the Istio service mesh.

    {% note tip %}

    Use the Kiali dashboard to monitor changes in the next steps of this tutorial. For example, you can see how the display of services or traffic distribution changes.

    {% endnote %}

## Route requests {#request-routing}

`todoapp` service pods run concurrently in the `v1` and `v2` versions. When you refresh the [test app](#test-application) page, the recommendations panel is sometimes not displayed, as only the `todoapp` `v2` pods send requests to the recommendations service and show the results.

Use routing to direct users to a specific service version:

1. Route all requests to `v1`:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/virtualservice-route-v1.yaml -n todoapp
    ```

    Result:

    ```text
    destinationrule.networking.istio.io/todoapp-dr created
    virtualservice.networking.istio.io/todoapp-vs configured
    ```

1. Refresh the test app page several times. Now, the `v1` pods process all requests. The page only shows the to-do list panel.

1. Route all requests to `v2`:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/virtualservice-route-v2.yaml -n todoapp
    ```

    Result:

    ```text
    destinationrule.networking.istio.io/todoapp-dr unchanged
    virtualservice.networking.istio.io/todoapp-vs configured
    ```

1. Refresh the test app page several times. Now, the `v2` pods process all requests. The page shows the to-do list and recommendations panels.

To cancel routing, run this command:

```bash
kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/todoapp-gateway.yaml -n todoapp
```

Result:

```text
gateway.networking.istio.io/todoapp-gateway unchanged
virtualservice.networking.istio.io/todoapp-vs configured
```

## Simulate a service failure {#injection-failures}

With Istio, you can test your app's reliability by simulating service failures.
When accessing `recommender`, there is a 3-second timeout. If the service does not respond within this time, the recommendations panel is not shown.

You can simulate a failure by specifying a timeout longer than 3 seconds in the `VirtualService` resource configuration. For example, this code section implements a 50-percent probability of a 5-second delay:

```yaml
fault:
  delay:
    percentage:
      value: 50.0
    fixedDelay: 5s
```

To simulate a failure of your [test app](#test-application):

1. Apply the `VirtualService` configuration:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/virtualservice-delay.yaml -n todoapp
    ```

    Result:

    ```text
    destinationrule.networking.istio.io/recommender-dr created
    virtualservice.networking.istio.io/recommender-vs created
    ```

1. Refresh the test app page several times. When a response delay occurs, the recommendations panel does not show up, even though the `v2` pod is handling the request. The app correctly handles a `recommender` failure.

To roll back the `VirtualService` configuration, run this command:

```bash
kubectl delete -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/virtualservice-delay.yaml -n todoapp
```

Result:

```text
destinationrule.networking.istio.io "recommender-dr" deleted
virtualservice.networking.istio.io "recommender-vs" deleted
```

## Redistribute traffic {#traffic-redistribution}

When upgrading the microservice version, you can redistribute traffic between its versions without affecting the number of application pods. You can manage traffic routes using the `weight` parameter for the `VirtualService` resource.

To redistribute traffic in your [test app](#test-application):

1. Set the weight for `v1` and `v2` to 50%:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/virtualservice-weight-v2-50.yaml -n todoapp
    ```

    Result:

    ```text
    destinationrule.networking.istio.io/todoapp-dr unchanged
    virtualservice.networking.istio.io/todoapp-vs configured
    ```

1. Refresh the test app page several times. The app is handled by the `v1` and `v2` pods in roughly equal proportions.

1. Increase the weight for `v2` to 100%:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/virtualservice-weight-v2-100.yaml -n todoapp
    ```

    Result:

    ```text
    destinationrule.networking.istio.io/todoapp-dr unchanged
    virtualservice.networking.istio.io/todoapp-vs configured
    ```

1. Refresh the test app page several times. The app is only handled by the `v2` pods.

## Set up mutual TLS authentication {#mutual-tls}

By default, applications with Istio sidecars communicate securely using mutual TLS.

You can configure a strict authentication policy, disallowing unencrypted traffic from applications without Istio sidecars.

To test your [test app](#test-application) in different modes:

1. Set up an authentication policy:

    ```bash
    kubectl apply -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/peerauthentication.yaml -n todoapp
    ```

    Result:

    ```text
    peerauthentication.security.istio.io/default created
    ```

1. Try creating a pod in the `default` namespace to test a connection to `todoapp`:

    ```bash
    kubectl run -i -n default \
       --rm \
       --restart=Never curl \
       --image=curlimages/curl \
       --command \
       -- sh -c 'curl --insecure http://todoapp.todoapp.svc.cluster.local'
    ```

    Result:

    ```text
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
    curl: (56) Recv failure: Connection reset by peer
    pod "curl" deleted
    pod default/curl terminated (Error)
    ```

1. Delete the authentication policy:

    ```bash
    kubectl delete -f https://raw.githubusercontent.com/yandex-cloud-examples/yc-mk8s-todo-app/main/kube/peerauthentication.yaml -n todoapp
    ```

    Result:

    ```text
    peerauthentication.security.istio.io "default" deleted
    ```

1. Try creating a pod once again:

    ```bash
    kubectl run -i -n default \
       --rm \
       --restart=Never curl \
       --image=curlimages/curl \
       --command \
       -- sh -c 'curl --insecure http://todoapp.todoapp.svc.cluster.local'
    ```

    Result:

    ```text
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  2658  100  2658    0     0   147k      0 --:--:-- --:--:-- --:--:--  152k
    <!DOCTYPE html>
    <html lang="ru">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Todoapp</title>
    ...
    ```

## View Istio metrics on the Prometheus dashboard {#viewing-metrics-prometheus}

1. Make sure `prometheus` is installed and available in your Managed Service for Kubernetes cluster:

    ```bash
    kubectl get service prometheus -n istio-system
    ```

    Result:

    ```text
    NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    prometheus   ClusterIP   10.96.147.249   <none>        9090/TCP   15d
    ```

1. Set up `prometheus` port forwarding to your local computer:

    ```bash
    kubectl port-forward service/prometheus 9090:9090 -n istio-system
    ```

1. To open the Prometheus dashboard, paste `http://localhost:9090` into the address bar of your browser.

1. Enter the following request in the **Expression** field:

    ```bash
    istio_requests_total{destination_service="recommender.todoapp.svc.cluster.local"}
    ```

1. Go to the **Graph** tab showing Istio metrics.

## View Istio metrics on the Grafana dashboard {#viewing-metrics-grafana}

1. Make sure `grafana` is installed and available in your Managed Service for Kubernetes cluster:

    ```bash
    kubectl get service grafana -n istio-system
    ```

    Result:

    ```text
    NAME      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
    grafana   ClusterIP   10.96.205.86   <none>        3000/TCP   15d
    ```

1. Set up `grafana` port forwarding to your local computer:

    ```bash
    kubectl port-forward service/grafana 3000:3000 -n istio-system
    ```

1. To open the Grafana dashboard, paste `http://localhost:3000` into the address bar of your browser.

1. In the list of dashboards, find and open the **Istio Mesh Dashboard**. It shows request metrics for your test app's services.

## Delete the resources you created {#clear-out}

Delete the resources you no longer need to avoid paying for them:

{% list tabs group=instructions %}

- Manually {#manual}

    1. [Delete the Kubernetes cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-delete.md).
    1. [Delete the created subnets](../../vpc/operations/subnet-delete.md) and [networks](../../vpc/operations/network-delete.md).
    1. [Delete the created service accounts](../../iam/operations/sa/delete.md).

- Terraform {#tf}

    1. In the terminal window, go to the directory containing the infrastructure plan.
    
        {% note warning %}
    
        Make sure the directory has no Terraform manifests with the resources you want to keep. Terraform deletes all resources that were created using the manifests in the current directory.
    
        {% endnote %}
    
    1. Delete resources:
    
        1. Run this command:
    
            ```bash
            terraform destroy
            ```
    
        1. Confirm deleting the resources and wait for the operation to complete.
    
        All the resources described in the Terraform manifests will be deleted.

{% endlist %}