Install Istio Service Mesh in EKS Kubernetes Cluster

Posted on 161 views

The work of Istio service mesh is to provide access control, traffic monitoring, security, discovery, Load balancing and many other useful features to services in a Kubernetes Cluster. There are no changes in your code for you to enjoy these services. Istio does it all for you. In this guide we will look at how you can install Istio Service Mesh in an EKS Kubernetes Cluster.

In a nutshell Istio deploys a proxy (called a sidecar) next to each service deployed in a namespace that is part of the mesh. Any traffic meant for a service has to go through sidecar proxy. Istio policies are then use to route traffic on to the service. With Istio you can also simplify DevOps techniques such as circuit breakers, canary deployments and fault injection.

This is how traffic flows in Istio.

The work of Istio service mesh is to provide access control, traffic monitoring, security, discovery, Load balancing and many other useful features to services in a Kubernetes Cluster. There are no changes in your code for you to enjoy these services. Istio does it all for you. In this guide we will look at how you can install Istio Service Mesh in an EKS Kubernetes Cluster.  In a nutshell Istio deploys a proxy (called a sidecar) next to each service deployed in a namespace that is part of the mesh. Any traffic meant for a service has to go through sidecar proxy. Istio policies are then use to route traffic on to the service. With Istio you can also simplify DevOps techniques such as circuit breakers, canary deployments and fault injection. This is how traffic flows in Istio.  istio service mesh flow Install Istio Service Mesh in EKS Kubernetes Cluster For this installation you need few items. Working EKS Kubernetes Cluster deployed in AWS Access to the cluster as user with Admin privileges Route53 hosted zone if you want to use Gateway and Virtual Services with domain names Step 1: Install istioctl in your Local machine / Bastion Depending on where kubectl is installed and working place istioctl in the same machine. This can be your local workstation machine if API server is accessible from the machine. For private EKS cluster deployed in AWS this will be Bastion server.  Download and extract istioctl – Works for Linux and macOS. We will install version 1.6.8  cd ~/ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.8 sh - Configure istioctl client tool for your workstation.  sudo cp istio-1.6.8/bin/istioctl /usr/local/bin/ sudo chmod +x /usr/local/bin/istioctl Confirm istioctl version:  $ istioctl version 1.6.8 Enabling istioctl completion for Bash  --- Bash --- mkdir -p ~/completions && istioctl collateral --bash -o ~/completions source ~/completions/istioctl.bash echo > ~/.bashrc — Zsh — mkdir -p ~/completions && istioctl collateral –zsh -o ~/completions source ~/completions/_istioctl echo “source ~/completions/_istioctl” >>~/.zshrc Verify auto completion. $ istioctl analyze dashboard install operator proxy-status validate authz deregister kube-inject profile register verify-install convert-ingress experimental manifest proxy-config upgrade version Step 2: Create Istio Namespace Create a namespace where all istio related services will be deployed. $ kubectl create namespace istio-system namespace/istio-system created Step 3: Create required Secrets We’ll be installing Grafana, Kiali and Jaeger as part of Istio installation. In our setup, each of these components requires credentials that must be provided as a Secret. Let us create these secrets in istio-system namespace. Create Grafana Secret GRAFANA_USERNAME=$(echo -n “grafana” | base64) GRAFANA_PASSPHRASE=$(echo -n “[email protected]” | base64) # Replace [email protected] with your password cat <. Step 5: Configure Route53 DNS I’ll delegate subdomain cloud.hirebestengineers.com to AWS Route53 to be used in Istio Gateways. Access Route53 console to create hosted zone if you don’t have one already. eks route53 configuration 01 Click on “Create hosted zone” to add the domain to Route53. eks route53 configuration 02 You’ll be provided with DNS Server entries to update in your registrar for the domain DNS entries to be resolved and managed on Route53. Since I use Cloudflare to manage my DNS I’ll update the settings accordingly from the Admin console. Notice that I use subdomain on Route53 and not the actual domain name. eks route53 configuration 03 The type of record to add is NS. Once all are added it will look like this: eks route53 configuration 05 Confirm DNS propagation after updating. For some registries it may take up to 24 hours for updates to be pushed. $ dig NS cloud.hirebestengineers.com +short ns-1335.awsdns-38.org. ns-1879.awsdns-42.co.uk. ns-454.awsdns-56.com. ns-643.awsdns-16.net. Create a record on route53 that points to the Load Balancer used by Istio Ingress. For me the record will be *.cloud.hirebestengineers.com Click Create Record > Simple routing >Define simple record and set: Record name Value/Route traffic to: Select Network Load Balancer, set region and Load balancer ID Record type: A When don hit the “Define simple record” button. eks route53 configuration 06 Verify details and click “Create records“ eks route53 configuration 07 Step 6: Enable automatic sidecar injection for namespace Sidecars can be automatically added to applicable Kubernetes pods using a mutating webhook admission controller provided by Istio. I’ll create a demo namespace for this project. $ kubectl create ns demo namespace/demo created Enable automatic sidecar injection by adding istio-injection=enabled label on the namespace: $ kubectl label namespace demo istio-injection=enabled namespace/demo labeled Confirm label is added to the namespace. $ kubectl get namespace demo -L istio-injection NAME STATUS AGE ISTIO-INJECTION demo Active 2m20s enabled Step 7: Deploy test Application with Istio gateway We will use example in Istio Website – Bookinfo Application. This example deploys a sample application composed of four separate microservices used to demonstrate various Istio features. Download application manifest file. wget https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml Deploy application using kubectl command: $ kubectl apply -f bookinfo.yaml -n demo service/details created serviceaccount/bookinfo-details created deployment.apps/details-v1 created service/ratings created serviceaccount/bookinfo-ratings created deployment.apps/ratings-v1 created service/reviews created serviceaccount/bookinfo-reviews created deployment.apps/reviews-v1 created deployment.apps/reviews-v2 created deployment.apps/reviews-v3 created service/productpage created serviceaccount/bookinfo-productpage created deployment.apps/productpage-v1 created Confirm pods are running: $ kubectl get pods -n demo NAME READY STATUS RESTARTS AGE details-v1-5974b67c8-tqsj9 2/2 Running 0 86s productpage-v1-64794f5db4-hg7n6 2/2 Running 0 76s ratings-v1-c6cdf8d98-4dl8h 2/2 Running 0 84s reviews-v1-7f6558b974-64wrw 2/2 Running 0 81s reviews-v2-6cb6ccd848-fp2tl 2/2 Running 0 80s reviews-v3-cc56b578-dpgh2 2/2 Running 0 79s Confirm all services are correctly defined. $ kubectl get svc -n demo kubectl get svc -n demo NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE details ClusterIP 10.100.229.76 9080/TCP 4m28s productpage ClusterIP 10.100.23.164 9080/TCP 4m18s ratings ClusterIP 10.100.172.229 9080/TCP 4m26s reviews ClusterIP 10.100.18.183 9080/TCP 4m23s To confirm that the Bookinfo application is running, send a request to it by a curl command from some pod, for example from ratings: kubectl -n demo exec “$(kubectl get pod -n demo -l app=ratings -o jsonpath=’.items[0].metadata.name’)” -c ratings — curl productpage:9080/productpage | grep -o “.*” Expected command output: Simple Bookstore App Download gateway file. wget https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml Edit it to set host value. $ vim bookinfo-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # use istio default controller servers: – port: number: 80 name: http protocol: HTTP hosts: – “bookinfo.cloud.hirebestengineers.com” — apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: bookinfo spec: hosts: – “bookinfo.cloud.hirebestengineers.com” gateways: – bookinfo-gateway http: – match: – uri: exact: /productpage – uri: prefix: /static – uri: exact: /login – uri: exact: /logout – uri: prefix: /api/v1/products route: – destination: host: productpage port: number: 9080 Define the ingress gateway for the application: $ kubectl apply -f ./bookinfo-gateway.yaml -n demo gateway.networking.istio.io/bookinfo-gateway created virtualservice.networking.istio.io/bookinfo created Test access to the application with curl or Web browser. Curl: $ curl -s http://bookinfo.cloud.hirebestengineers.com/productpage | grep -o “.*Simple Bookstore App From web browser. eks route53 configuration 08 You can use this sample application to experiment with Istio’s features such as traffic routing, fault injection, rate limiting, etc. Also check Istio Tasks to learn more. If you’re a beginner Configuring Request Routing is a good place to start as well. Cleaning Bookinfo application. $ kubectl delete -f ./bookinfo-gateway.yaml -n demo gateway.networking.istio.io “bookinfo-gateway” deleted virtualservice.networking.istio.io “bookinfo” deleted $ kubectl delete -f ./bookinfo.yaml -n demo service “details” deleted serviceaccount “bookinfo-details” deleted deployment.apps “details-v1” deleted service “ratings” deleted serviceaccount “bookinfo-ratings” deleted deployment.apps “ratings-v1” deleted service “reviews” deleted serviceaccount “bookinfo-reviews” deleted deployment.apps “reviews-v1” deleted deployment.apps “reviews-v2” deleted deployment.apps “reviews-v3” deleted service “productpage” deleted serviceaccount “bookinfo-productpage” deleted deployment.apps “productpage-v1” deleted $ kubectl get all -n demo No resources found in demo namespace. $ kubectl delete ns demo namespace “demo” deleted” width=”700″ height=”381″ />

Install Istio Service Mesh in EKS Kubernetes Cluster

For this installation you need few items.

  • Working EKS Kubernetes Cluster deployed in AWS
  • Access to the cluster as user with Admin privileges
  • Route53 hosted zone if you want to use Gateway and Virtual Services with domain names

Step 1: Install istioctl in your Local machine / Bastion

Depending on where kubectl is installed and working place istioctl in the same machine. This can be your local workstation machine if API server is accessible from the machine. For private EKS cluster deployed in AWS this will be Bastion server.

Download and extract istioctl – Works for Linux and macOS. We will install version 1.6.8

cd ~/
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.8 sh -

Configure istioctl client tool for your workstation.

sudo cp istio-1.6.8/bin/istioctl /usr/local/bin/
sudo chmod +x /usr/local/bin/istioctl

Confirm istioctl version:

$ istioctl version
1.6.8

Enabling istioctl completion for Bash

--- Bash ---
mkdir -p ~/completions && istioctl collateral --bash -o ~/completions
source ~/completions/istioctl.bash
echo "source ~/completions/istioctl.bash" >> ~/.bashrc

--- Zsh ---
mkdir -p ~/completions && istioctl collateral --zsh -o ~/completions
source ~/completions/_istioctl
echo "source ~/completions/_istioctl" >>~/.zshrc

Verify auto completion.

$ istioctl 
analyze          dashboard        install          operator         proxy-status     validate
authz            deregister       kube-inject      profile          register         verify-install
convert-ingress  experimental     manifest         proxy-config     upgrade          version

Step 2: Create Istio Namespace

Create a namespace where all istio related services will be deployed.

$ kubectl create namespace istio-system
namespace/istio-system created

Step 3: Create required Secrets

We’ll be installing GrafanaKiali and Jaeger as part of Istio installation. In our setup, each of these components requires credentials that must be provided as a Secret.

Let us create these secrets in istio-system namespace.

Create Grafana Secret

GRAFANA_USERNAME=$(echo -n "grafana" | base64)
GRAFANA_PASSPHRASE=$(echo -n "GrafanaP@ssw0rd" | base64) # Replace GrafanaP@ssw0rd with your password

cat <

Create Kiali Secret

KIALI_USERNAME=$(echo -n "kiali" | base64)
KIALI_PASSPHRASE=$(echo -n "KialiP@ssw0rd" | base64) # Replace KialiP@ssw0rd with your password

cat <

Create Jaeger Secret.

JAEGER_USERNAME=$(echo -n "jaeger" | base64)
JAEGER_PASSPHRASE=$(echo -n "JaegerP@ssw0rd" | base64) # Replace JaegerP@ssw0rd with your password

cat <

List secrets created.

$ kubectl get secret -n istio-system
NAME                  TYPE                                  DATA   AGE
default-token-kwrcj   kubernetes.io/service-account-token   3      16m
grafana               Opaque                                2      4m59s
jaeger                Opaque                                2      47s
kiali                 Opaque                                2      3m7s

Step 4: Create Istio Control Plane Configuration

Now that we’ve successfully created the Secrets required we can create Istio Control plane configuration file.

I’ll name the file istio-control-plane-eks.yml. This file will hold the Istio control plane spec details for configuring Istio.

$ vim istio-control-plane-eks.yml

The contents are. – Ref Global Mesh Options

apiVersion: install.istio.io/v1alpha2
kind: IstioControlPlane
spec:
  profile: default
  values:
    meshConfig:
      disablePolicyChecks: false
      # File address for the proxy access log (e.g. /dev/stdout).
      accessLogFile: "/dev/stdout"
      # Set the default behavior of the sidecar for handling outbound traffic from the application
      outboundTrafficPolicy:
        mode: "ALLOW_ANY"
      # Enable mutual TLS automatically for service to service communication within the mesh
      enableAutoMtls: false
      disablePolicyChecks: false
    gateways:
      # Enable egress gateway
      istio-egressgateway:
        enabled: true
        autoscaleEnabled: true
      # Enable Ingress gateway
      istio-ingressgateway:
        enabled: true
        autoscaleEnabled: true
    global:
      # Ensure that the Istio pods are only scheduled to run on Linux nodes
      defaultNodeSelector:
        beta.kubernetes.io/os: linux
      # Enable mutual TLS for the control plane
      controlPlaneSecurityEnabled: true
    grafana:
      # Enable Grafana deployment for analytics and monitoring dashboards
      enabled: true
      security:
        # Enable authentication for Grafana
        enabled: true
    kiali:
      # Enable the Kiali deployment for a service mesh observability dashboard
      enabled: true
    tracing:
      # Enable the Jaeger deployment for tracing
      enabled: true
      provider: jaeger # zipkin / jaeger

Validate configuration by performing dry run.

$ istioctl manifest apply -f istio-control-plane-eks.yml --dry-run
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Addons installed
- Pruning removed resources
......

Install istio using the following command:

$ istioctl manifest apply -f istio-control-plane-eks.yml
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Addons installed
✔ Installation complete

Check deployed pods to confirm they are in running state:

$ kubectl get pods -n istio-system
NAME                                    READY   STATUS    RESTARTS   AGE
grafana-86897cb4f5-wg29n                1/1     Running   0          3h34m
istio-egressgateway-8667d76d75-2t96d    1/1     Running   0          51s
istio-ingressgateway-5d78f74886-8xpx5   1/1     Running   0          3h35m
istio-tracing-57d7cfd779-xbtd8          1/1     Running   0          3h34m
istiod-58f84ffddc-khncg                 1/1     Running   0          3h35m
kiali-7c974669b4-ckfh4                  1/1     Running   0          3h34m
prometheus-6946fd87b4-ldzt2             2/2     Running   0          3h34m

You can list Service Endpoints with:

$ kubectl get svc -n istio-system

Add annotations to Ingress Service to get AWS Load Balancer. The annotations to be added are:

service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-internal: "0.0.0.0/0"

We’ll add annotations with kubectl command.

kubectl annotate svc istio-ingressgateway service.beta.kubernetes.io/aws-load-balancer-type="nlb" -n istio-system
kubectl annotate svc istio-ingressgateway service.beta.kubernetes.io/aws-load-balancer-internal="0.0.0.0/0" -n istio-system

Confirm LB was created.

$ kubectl get svc istio-ingressgateway  -n istio-system
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP                                                                     PORT(S)                                                      AGE
istio-ingressgateway   LoadBalancer   10.100.49.28   a75fa02249f79436290b35e8a00a00b5-8e63bc91906eba93.elb.eu-west-1.amazonaws.com   15021:31022/TCP,80:32766/TCP,443:32512/TCP,15443:31919/TCP   3h31m

Accessing Dashboards:

# Grafana
$ istioctl dashboard grafana

# Kiali
$ istioctl dashboard kiali

# Jaeger
$ istioctl dashboard jaeger

# Prometheus
$ istioctl dashboard prometheus

# Zipkin
$ istioctl dashboard zipkin

# Envoy
$ istioctl dashboard envoy .

Step 5: Configure Route53 DNS

I’ll delegate subdomain cloud.hirebestengineers.com to AWS Route53 to be used in Istio Gateways.

Access Route53 console to create hosted zone if you don’t have one already.

eks-route53-configuration-01-1024x848

Click on “Create hosted zone” to add the domain to Route53.

eks-route53-configuration-02-1024x435

You’ll be provided with DNS Server entries to update in your registrar for the domain DNS entries to be resolved and managed on Route53.

Since I use Cloudflare to manage my DNS I’ll update the settings accordingly from the Admin console. Notice that I use subdomain on Route53 and not the actual domain name.

eks-route53-configuration-03-1024x312

The type of record to add is NS. Once all are added it will look like this:

eks-route53-configuration-05-1024x313

Confirm DNS propagation after updating. For some registries it may take up to 24 hours for updates to be pushed.

$ dig NS cloud.hirebestengineers.com +short
ns-1335.awsdns-38.org.
ns-1879.awsdns-42.co.uk.
ns-454.awsdns-56.com.
ns-643.awsdns-16.net.

Create a record on route53 that points to the Load Balancer used by Istio Ingress. For me the record will be *.cloud.hirebestengineers.com

Click Create Record > Simple routing >Define simple record and set:

  • Record name
  • Value/Route traffic to: Select Network Load Balancer, set region and Load balancer ID
  • Record type: A

When don hit the “Define simple record” button.

eks-route53-configuration-06-1024x827

Verify details and click “Create records

eks-route53-configuration-07-1024x522

Step 6: Enable automatic sidecar injection for namespace

Sidecars can be automatically added to applicable Kubernetes pods using a mutating webhook admission controller provided by Istio.

I’ll create a demo namespace for this project.

$ kubectl create ns demo
namespace/demo created

Enable automatic sidecar injection by adding istio-injection=enabled label on the namespace:

$ kubectl label namespace demo istio-injection=enabled
namespace/demo labeled

Confirm label is added to the namespace.

$ kubectl get namespace demo -L istio-injection
NAME   STATUS   AGE     ISTIO-INJECTION
demo   Active   2m20s   enabled

Step 7: Deploy test Application with Istio gateway

We will use example in Istio Website – Bookinfo Application. This example deploys a sample application composed of four separate microservices used to demonstrate various Istio features.

Download application manifest file.

wget https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml

Deploy application using kubectl command:

$ kubectl apply -f bookinfo.yaml -n demo

service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created

Confirm pods are running:

$ kubectl get pods -n demo
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-5974b67c8-tqsj9        2/2     Running   0          86s
productpage-v1-64794f5db4-hg7n6   2/2     Running   0          76s
ratings-v1-c6cdf8d98-4dl8h        2/2     Running   0          84s
reviews-v1-7f6558b974-64wrw       2/2     Running   0          81s
reviews-v2-6cb6ccd848-fp2tl       2/2     Running   0          80s
reviews-v3-cc56b578-dpgh2         2/2     Running   0          79s

Confirm all services are correctly defined.

$ kubectl get svc -n demo
kubectl get svc -n demo
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.100.229.76            9080/TCP   4m28s
productpage   ClusterIP   10.100.23.164            9080/TCP   4m18s
ratings       ClusterIP   10.100.172.229           9080/TCP   4m26s
reviews       ClusterIP   10.100.18.183            9080/TCP   4m23s

To confirm that the Bookinfo application is running, send a request to it by a curl command from some pod, for example from ratings:

kubectl -n demo exec "$(kubectl get pod  -n demo -l app=ratings -o jsonpath='.items[0].metadata.name')" -c ratings -- curl productpage:9080/productpage | grep -o ".*"

Expected command output:

Simple Bookstore App

Download gateway file.

wget https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml

Edit it to set host value.

$ vim bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "bookinfo.cloud.hirebestengineers.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "bookinfo.cloud.hirebestengineers.com"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

Define the ingress gateway for the application:

$ kubectl apply -f ./bookinfo-gateway.yaml -n demo

gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created

Test access to the application with curl or Web browser.

Curl:

$ curl -s http://bookinfo.cloud.hirebestengineers.com/productpage  |  grep -o ".*"
Simple Bookstore App

From web browser.

eks-route53-configuration-08-1024x298

You can use this sample application to experiment with Istio’s features such as traffic routing, fault injection, rate limiting, etc. Also check Istio Tasks to learn more. If you’re a beginner Configuring Request Routing is a good place to start as well.

Cleaning Bookinfo application.

$ kubectl delete -f ./bookinfo-gateway.yaml -n demo
gateway.networking.istio.io "bookinfo-gateway" deleted
virtualservice.networking.istio.io "bookinfo" deleted

$ kubectl delete -f ./bookinfo.yaml -n demo
service "details" deleted
serviceaccount "bookinfo-details" deleted
deployment.apps "details-v1" deleted
service "ratings" deleted
serviceaccount "bookinfo-ratings" deleted
deployment.apps "ratings-v1" deleted
service "reviews" deleted
serviceaccount "bookinfo-reviews" deleted
deployment.apps "reviews-v1" deleted
deployment.apps "reviews-v2" deleted
deployment.apps "reviews-v3" deleted
service "productpage" deleted
serviceaccount "bookinfo-productpage" deleted
deployment.apps "productpage-v1" deleted

$ kubectl get all -n demo
No resources found in demo namespace.

$ kubectl delete ns demo
namespace "demo" deleted
coffee

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.