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.
For this installation you need few items.
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
Configure istioctl client tool for your workstation.
Confirm istioctl version:
Enabling istioctl completion for Bash
Verify auto completion.
Create a namespace where all istio related services will be deployed.
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
Create Kiali Secret
Create Jaeger Secret.
List secrets created.
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.
The contents are. – Ref Global Mesh Options
Validate configuration by performing dry run.
Install istio using the following command:
Check deployed pods to confirm they are in running state:
You can list Service Endpoints with:
Add annotations to Ingress Service to get AWS Load Balancer. The annotations to be added are:
We’ll add annotations with kubectl command.
Confirm LB was created.
Accessing Dashboards:
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.
Click on “Create hosted zone” to add the domain to Route53.
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.
The type of record to add is NS. Once all are added it will look like this:
Confirm DNS propagation after updating. For some registries it may take up to 24 hours for updates to be pushed.
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:
When don hit the “Define simple record” button.
Verify details and click “Create records“
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.
Enable automatic sidecar injection by adding istio-injection=enabled label on the namespace:
Confirm label is added to the namespace.
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.
Deploy application using kubectl command:
Confirm pods are running:
Confirm all services are correctly defined.
To confirm that the Bookinfo application is running, send a request to it by a curl command from some pod, for example from ratings:
Expected command output:
Download gateway file.
Edit it to set host value.
Define the ingress gateway for the application:
Test access to the application with curl or Web browser.
Curl:
From web browser.
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.
> ~/.bashrc — Zsh — mkdir -p ~/completions && istioctl collateral –zsh -o ~/completions source ~/completions/_istioctl echo “source ~/completions/_istioctl” >>~/.zshrc Verify auto completion. $ istioctl
Install Istio Service Mesh in EKS Kubernetes Cluster
Step 1: Install istioctl in your Local machine / Bastion
cd ~/
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.8 sh -
sudo cp istio-1.6.8/bin/istioctl /usr/local/bin/
sudo chmod +x /usr/local/bin/istioctl
$ istioctl version
1.6.8
--- 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
$ istioctl
Step 2: Create Istio Namespace
$ kubectl create namespace istio-system
namespace/istio-system created
Step 3: Create required Secrets
GRAFANA_USERNAME=$(echo -n "grafana" | base64)
GRAFANA_PASSPHRASE=$(echo -n "GrafanaP@ssw0rd" | base64) # Replace GrafanaP@ssw0rd with your password
cat <
KIALI_USERNAME=$(echo -n "kiali" | base64)
KIALI_PASSPHRASE=$(echo -n "KialiP@ssw0rd" | base64) # Replace KialiP@ssw0rd with your password
cat <
JAEGER_USERNAME=$(echo -n "jaeger" | base64)
JAEGER_PASSPHRASE=$(echo -n "JaegerP@ssw0rd" | base64) # Replace JaegerP@ssw0rd with your password
cat <
$ 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
$ vim istio-control-plane-eks.yml
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
$ istioctl manifest apply -f istio-control-plane-eks.yml --dry-run
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Addons installed
- Pruning removed resources
......
$ istioctl manifest apply -f istio-control-plane-eks.yml
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Addons installed
✔ Installation complete
$ 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
$ kubectl get svc -n istio-system
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-internal: "0.0.0.0/0"
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
$ 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
# 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
$ 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.
Step 6: Enable automatic sidecar injection for namespace
$ kubectl create ns demo
namespace/demo created
$ kubectl label namespace demo istio-injection=enabled
namespace/demo labeled
$ kubectl get namespace demo -L istio-injection
NAME STATUS AGE ISTIO-INJECTION
demo Active 2m20s enabled
Step 7: Deploy test Application with Istio gateway
wget https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/platform/kube/bookinfo.yaml
$ 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
$ 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
$ 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
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 "
wget https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml
$ 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
$ kubectl apply -f ./bookinfo-gateway.yaml -n demo
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
$ curl -s http://bookinfo.cloud.hirebestengineers.com/productpage | grep -o "
$ 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