Let's look at deploying the TeaStore application by Descartes Research across two different cloud providers, AWS and GCP, in a Multi-Cluster Single Mesh style architecture.
But why go through such lengths, when in practice we should be keeping it simple by using as few clusters as possible? The immediate answer, from an app dev mindset, is to separate the non-production from the production services, by placing them in different clusters. There are other reasons for joining the multi-cluster, multi-cloud bandwagon and these are, not limited to, the following:
- Isolation: Services' Control and Data plane separation (++
reliability
& ++security
) - Location: Address
availability
and latency of critical services - Scale:
Scaling
services beyond the practical limits of a single cluster - Compliance: Governance,
risk
management and compliance regulations
Istio's Split Horizon Endpoint Discovery Service (EDS) and Server Name Indication (SNI) Based routing features allows a Multi-Cluster Single Mesh architecture without the need of a flat network or a VPN between the cluster (or the Clouds, if the clusters reside in different Clouds). This is achieved by enabling the Kubernetes control planes running a remote Istio configuration to connect to a single Istio control plane. Once one, or more, Kubernetes clusters are connected to the (single) Istio control plane the Envoy communicates with the Istio control plane in order to form a mesh network across those clusters. If you wish to know more, please check this amazing blog post by BanzaiCloud. The picture below, from that amazing blog post, allows to better visualise the Istio architecture in a hybrid and multi-cloud single mesh without flat network or VPN deployment.
For this multi-cloud and multi-cluster deployment we will be using Cisco's Service Mesh Manager (SMM) (previously BanzaiCloud Backyards). If you are following this demo you will need SMM access, if you are part of Cisco please reach out to Roger Dickinson, otherwise if you are new to Service Mesh Manager and would like to evaluate it, contact the SMM team to discuss your needs and requirements, and organize a live demo.
Alternatively, there is an open-source Istio Operator developed by BanzaiCloud. If you wish to implement the service mesh this way then the BanzaiCloud's Istio Split Horizon EDS Multi Cluster Federation Example is a great way to start! For further info, the amazing blog post by BanzaiCloud mentioned above is also super helpful.
Since we will be deploying different clusters in different clouds, I would highly recommend that you use kubectx to easily switch between clusters - kubectx
will be widely used in this deployment. To install on a macOS, with homebrew
, simply:
brew install kubectx
If you need to install on another OS, please check the installation guide.
If you followed the single cluster deployment above you should already have the Google Cloud SDK installed, with the gcloud
command-line tool and kubectl
ready to go. If not, please install those and follow the guide above, up to point 3. only.
- Create a cluster, called
smm-gke
, in GKE with 4 nodes:gcloud container clusters create smm-gke \ --project=${PROJECT_ID} --zone=europe-west2-a --node-locations=europe-west2-a \ --enable-autoupgrade --enable-autoscaling \ --num-nodes=4 --min-nodes=4 --max-nodes=6 --machine-type=e2-standard-2
Please Note: This cluster gets deployed in London, zone europe-west2-a
, if you wish to deploy elsewhere, please check the available regions and zones here. Similarly, if you wish to change the machine-type
please check here.
- Rename the
kubectl
context withkubectx
:$ kubectx gke_cleur-sad-dev-rmke_europe-west2_smm-gke
kubectx smm-gke=gke_cleur-sad-dev-rmke_europe-west2_smm-gke
If you ever need to rezise this cluster you can do it with the following command.
gcloud container clusters resize smm-gke --num-nodes=4
In order to create a cluster on AWS EKS you will need to:
-
Install the AWS CLI v2
-
Configure AWS CLI with your
Access Key ID
,Secret Access Key
,aws region
andoutput format
. The good news is, you don't need to know AWS to create the cluster as we will be using an amazing open-source tool called eksctl.eksctl
is a simple CLI tool for creating clusters on EKS, so easy that you can create a cluster in minutes with just one command. Using CloudFormation,eksctl
abstracts the heavy lifting from you in having to create VPCs, IAM Roles and Security Groups on AWS. -
Create a cluster called
smm-eks
, in EKS with 2 nodes:eksctl create cluster \ --name smm-eks \ --node-type m5.large \ --nodes 8 \ --nodes-min 2 \ --nodes-max 10 \ --region eu-west-2
Please Note: Similarly to GKE above, this cluster gets deployed in London, zone eu-west-2
, if you wish to deploy elsewhere, please check the available regions and zones here. If you wish to change the node-type
you can find more information here.
Once you run the eksctl
command, it does take a while to create the cluster, considerably longer when compared with GKE, so just hang in there. You will see the following on your terminal as the cluster gets created - you can spot some of the eksctl
CloudFormation magic.
- Rename the
kubectl
context withkubectx
:$ kubectx smm-gke peolivei@cisco.com@smm-eks.eu-west-2.eksctl.io
kubectx smm-eks=peolivei@cisco.com@smm-eks.eu-west-2.eksctl.io
You can confirm with kubectx
that the context name has updated and that you now have both smm-gke
and smm-eks
contexts set.
$ kubectx
smm-eks
smm-gke
If you ever need to resize this cluster, you will need to find the nodegroup
name first:
eksctl get nodegroup --cluster=smm-eks
Then you can resize it and if you need to increase the maximum number of nodes, you can use the -M
flag as well. The example below increases the number of nodes on the EKS cluster to 10, as well as increasing the maximum number of nodes to 12.
eksctl scale nodegroup --name=<node-group-name> --cluster=smm-eks --nodes=10 -M=12
All of the instructions layed out here are based on the SMM Documentation, so please check it out for further information.
-
You will need access to the SMM binaries in order to install this. Please check that you do.
AWS_REGION=us-east-2 aws ecr list-images --registry-id 033498657557 --repository-name banzaicloud/istio-proxyv2
If you don't and you are Cisco internal then you can request it, otherwise if you are new to Service Mesh Manager and would like to evaluate it, contact the SMM team to discuss your needs and requirements, and organize a live demo.
-
Download the SMM tool (v1.8.0 was the latest version at the time of writing) to the current directory
aws s3 cp s3://cisco-eti-banzai-binaries/smm-cli/1.8.0/dist/smm_1.8.0_darwin_amd64.tar.gz ./
-
Install the SMM tool and add it to
$PATH
tar -xvzf smm_1.8.0_darwin_amd64.tar.gz mkdir bin mv smm bin/ export PATH=$PWD/bin:$PATH smm -h
Please Note: If you close your terminal you will need to add the SMM tool to your
$PATH
again!
-
Install SMM on the primary cluster (EKS) using a
cluster-name
flag to make sure there are no naming issues with weird characters, like_-/.\
kubectx smm-eks smm install -a --cluster-name primaryclustereks
This might take a while and it will be finished once you get all the green ticks.
-
Grab the
kubeconfig
of the peer cluster (GKE)cp ~/.kube/config ~/.kube/config_backup rm ~/.kube/config gcloud container clusters get-credentials smm-gke mv ~/.kube/config . mv ~/.kube/config_backup ~/.kube/config mv config gke-peer-kubeconfig
-
Attach the peer cluster (GKE) to the service mesh
smm istio cluster attach gke-peer-kubeconfig --name=peerclustergke
-
Wait until the peer cluster is attached. Attaching the peer cluster takes some time.
smm istio cluster status
The process is finished when you see
Available
in theStatus
field of both clusters. -
You can view the
IstioControlPlane
resource, theIstioMeshGateway
, as well as thepods
andservices
created by SMMkubectl get icp -n istio-system kubectl get IstioMeshGateway -n istio-system kubectl get svc -n istio-system kubectl get pods -n smm-system
-
Open the SMM Dashboard and look around! For now there isn't an application deployed yet, but once there is, the
Topology
section is quite the mind blow.smm dashboard
- Detach the peer cluster - this is very important, do not proceed to the next step without completing this one!
smm istio cluster detach gke-peer-kubeconfig
- Unninstall all SMM components using the SMM tool
smm uninstall -a
- Delete remaining CRDs
kubectx smm-eks kubectl get crd |grep -i -e istio.banzaicloud.io -e sre -e backyards -e istio.io -e cisco.com -e banzaicloud.io -e cert-manager|cut -d ' ' -f 1 |xargs kubectl delete crd kubectx smm-gke kubectl get crd |grep -i -e istio.banzaicloud.io -e sre -e backyards -e istio.io -e cisco.com -e banzaicloud.io -e cert-manager|cut -d ' ' -f 1 |xargs kubectl delete crd
- Delete remaining Mutating and Validating Webhooks
kubectx smm-eks kubectl get mutatingwebhookconfiguration |grep -i -e istio|cut -d ' ' -f 1 |xargs kubectl delete mutatingwebhookconfiguration kubectl get validatingwebhookconfiguration |grep -i -e istio|cut -d ' ' -f 1 |xargs kubectl delete validatingwebhookconfiguration kubectx smm-gke kubectl get mutatingwebhookconfiguration |grep -i -e istio|cut -d ' ' -f 1 |xargs kubectl delete mutatingwebhookconfiguration kubectl get validatingwebhookconfiguration |grep -i -e istio|cut -d ' ' -f 1 |xargs kubectl delete validatingwebhookconfiguration
Before deploying the application, I highly recommend that you deploy the AppDynamics Cluster Agent which collects metrics and metadata for the entire cluster, including every node and namespace down to the container level. Since the all of the TeaStore app microservices are written in JAVA we can also Auto-Instrument these with AppDynamics APM Java Agents using the cluster agent. Please Note: Since we have two clusters we will need to install a cluster agent on each and this installation requires Helm. For more info, please check the documentation.
-
Let's start with the primary cluster. Create the
appdynamics
namespacekubectx smm-eks kubectl create ns appdynamics
-
Add your AppDynamics controller credentials to the values file
values-ca.yaml.tpl
, between lines 1-6 under multiCloudDeployments/control/AppDynamics folder. Save it and rename it asvalues-ca.yaml
-
Add the cluster agent chart repository to Helm
helm repo add appdynamics-charts https://appdynamics.github.io/appdynamics-charts
-
Deploy the cluster agent on the
appdynamics
namespacehelm install -f multiCloudDeployments/control/AppDynamics/values-ca.yaml cluster-agent appdynamics-charts/cluster-agent -n appdynamics
This will deploy the cluster agent with auto-intrumentation ON. If you check your
values-ca.yaml
file between lines 9-27, you can inspect the auto-instrumentation configuration. -
Check that the cluster agent is running
kubectl get pods -n appdynamics
Once this is running it takes about 15/20mins for all the data to be populated on your AppDynamics Controller Dashboard and you can view it under
Servers
>Clusters
. -
Deploy the same thing on the peer cluster. Similarly as before, add your AppDynamics controller credentials to the values file
values-ca.yaml.tpl
, between lines 1-6 under multiCloudDeployments/peer/AppDynamics folderkubectx smm-gke kubectl create ns appdynamics helm repo add appdynamics-charts https://appdynamics.github.io/appdynamics-charts helm install -f multiCloudDeployments/peer/AppDynamics/values-ca.yaml cluster-agent appdynamics-charts/cluster-agent -n appdynamics kubectl get pods -n appdynamics
If you ever need to change the AppDynamics cluster agent configuration you can edit the values-ca.yaml
files and then use helm to upgrade the deployment. Below is an example on how you would upgrade the AppDynamics cluster agent on the primary cluster, after you edit and save the values-ca.yaml
under the multiCloudDeployments/control/AppDynamics folder.
kubectx smm-eks
helm upgrade -f multiCloudDeployments/control/AppDynamics/values-ca.yaml cluster-agent appdynamics-charts/cluster-agent -n appdynamics
To test and use our multi-cloud extended service mesh that we just deployed with Cisco SMM we will be using TeaStore. We will deploy different components of the application in each cluster.
In this cluster we will be installing the following microservices:
- DB
- Registry
- Persistence
- WebUI v1
- Image v1
- Image v2
-
Create a
tea-store
namespacekubectx smm-eks kubectl create tea-store
-
Apply SMM side-car proxy auto-injection to the
tea-store
namespacesmm sp ai on --namespace=tea-store
Please Note The SMM side-car proxy auto-injection just needs to be activated once via the SMM tool. This is propagated throughout the mesh on both clusters.
-
Deploy all the TeaStore microservices mentioned above
kubectl apply -f multiCloudDeployments/control/Tea-Store/deployments.yaml -n tea-store
-
Deploy all the TeaStore microservices services. Please Note that for service discover purposes all services need to be deployed on both clusters
kubectl apply -f multiCloudDeployments/control/Tea-Store/services.yaml -n tea-store
-
Check that all pods are running. If you describe one of the pods you will see that the AppDynamics JAVA agent was installed via an init container and that the
istio-proxy
container is attached.kubectl get pods -n tea-store kubectl describe pods <pod-name> tea-store
As part of our deployment we will be leveraging K8s horizontal pod autoscaling (hpa). The idea being that as user traffic increases, k8s will increase the number of replicas of particular pods. In this case we will target teastore-webui
and teastore-persistence
and will increase the number of replicas up to 3
and 2
, respectively, if the %CPU
of the pods go above 95%
kubectl autoscale deployment teastore-webui --cpu-percent=95 --min=1 --max=3 -n tea-store
kubectl autoscale deployment teastore-persistence --cpu-percent=95 --min=1 --max=2 -n tea-store
You can then check the status of the hpa. This will be useful once we add the load generator in the upcoming sections.
kubectl get hpa -n tea-store
In this cluster we will be installing the following microservices:
- Auth
- Recommender
- WebUI v2
- Image v2
-
Create a
tea-store
namespacekubectx smm-gke kubectl create tea-store
-
Deploy all the TeaStore microservices mentioned above
kubectl apply -f multiCloudDeployments/peer/Tea-Store/deployments.yaml -n tea-store
-
Deploy all the TeaStore microservices services. Please Note that for service discover purposes all services need to be deployed on both clusters
kubectl apply -f multiCloudDeployments/peer/Tea-Store/services.yaml -n tea-store
-
Check that all pods are running
kubectl get pods -n tea-store
The application is now deployed and instrumented but so far there is no ingress defined so it is not exposed yet. For that we need to create an IstioMeshGateway
, as well as a Gateway
. For more information on how Istio ingress and egress gateways work and why would you need both a IstioMeshGateway and a Gateway, I would highly recommend reading this blog post.
Both these resources will be defined on the primary cluster, so the ingress for the application will effectively be deployed on EKS.
-
Deploy the
IstioMeshGateway
andGateway
for the TeaStore appkubectx smm-eks kubectl apply -f multiCloudDeployments/control/Tea-Store/istio/webui-mesh-gw.yaml
-
Deploy the istio ingress rule for the TeaStore app
kubectl apply -f multiCloudDeployments/control/Tea-Store/istio/webui-ingress.yaml
-
Define egress rules. This will mainly allow you to see the outbound calls to the AppDynamics controller on the SMM dashboard
kubectl apply -f multiCloudDeployments/control/Tea-Store/istio/egress-rules.yaml
-
Get the
External-IP
of theteastore-webui-mesh-gateway
kubectl get svc -n istio-system
You can now access the TeaStore App!! 🥳🥳🥳
-
(Optional) Have a look at the
IstioMeshGateway
andGateway
resources deployedkubectl get IstioMeshGateway -n istio-system kubectl get Gateway -A
Now, the application doesn't have much load, unless you start spamming it! Let's add a load generator so that you can start visualizing some cool stuff on both SMM and AppDynamics.
For stressing the TeaStore there is a Browse Profile template, tea-store-test.jmx
under the multiCloudDeployments/control/Tea-Store/jmeter-loadgenerator folder, that is used by the JMeter Load generator.
-
Provide the
hostname
of where your TeaStore application is hosted and how many users you want to simulate the load 1.1. (Line 13) Replace with your TeaStorehostname
. This could be internal within service mesh (ingress mesh gateway) or the external address. 1.2. (Line 23) Modify the number of users, if needed 1.3. Save the file! -
Create
jmeter
namespace and applySMM
sidecar-proxy auto injection to itkubectx smm-eks kubectl create ns jmeter smm sp ai on --namespace=jmeter
-
Make the script executable and launch
jmeter_cluster.sh
to start the deploymentchmod +x multiCloudDeployments/control/Tea-Store/jmeter-loadgenerator/jmeter_cluster_create.sh ./multiCloudDeployments/control/Tea-Store/jmeter-loadgenerator/jmeter_cluster_create.sh
-
After the test starts, you will see summary logs from the JMeter master pod 2.1 Let it run for a while to make sure there are no errors 2.2 Check the AppDynamics TeaStore Application Dashboard and make sure you can see the load 2.3 The loadgenerator is now running successfully and you can exit the pod by pressing
CTRL+C
Please note that the default option is that the thread group loops forever.
If you wish to stop the test and/or modify the load (by modifying the number of users), you will need to delete all the resources within the the jmeter
namespace - do not delete the namespace. For that you can use the jmeter_cluster_stop.sh
script.
- Make the script executable and launch
jmeter_cluster_stop.sh
to stop the deployment and delete all the resourceschmod +x multiCloudDeployments/control/Tea-Store/jmeter-loadgenerator/jmeter_cluster_stop.sh ./multiCloudDeployments/control/Tea-Store/jmeter-loadgenerator/jmeter_cluster_stop.sh
- Modify
tea-store-test.jmx
on lines 13 and/or 23, if needed. Save it! - Relaunch the jmeter start-up script
./multiCloudDeployments/control/Tea-Store/jmeter-loadgenerator/jmeter_cluster_create.sh
Now that the application has an ingress and there is a load generator creating traffic, you can visualise the application topology at a service mesh level with SMM and at the application level with AppDynamics
-
Deploy the SMM dashboard
smm dashboard
Make sure that you select the
tea-store
,jmeter
andistio-system
namespaces from the drop-down menu. -
Check the AppDynamics Application dashboard
Since you now have those tools available, go ahead and play with istio routing. There are a few manifests already under the multiCloudDeployments/control/Tea-Store/istio/routing folder. If you want to play with weighted traffic between versioned deployments (like webui
and image
v1
and v2
) you will need to apply the DestinationRule
resource.
Below is an example of how you can deploy an injection delay of 3s on 80% of image v1
's traffic.
kubectx smm-eks
kubectl apply -f multiCloudDeployments/control/Tea-Store/istio/routing/0-destinationRules.yaml -n tea-store
kubectl apply -f multiCloudDeployments/control/Tea-Store/istio/routing/3-injection-delay-image-v1.yaml -n tea-store
Go ahead and inspect both SMM and AppDynamics dashboards.
To eliminate the 3s delay just delete the teastore-image-injection-delay
virtualservice and the TeaStore app behaviour will go back to normal
kubectl delete virtualservice teastore-image-injection-delay -n tea-store
This demo includes a ThousandEyes enterprise agent that is deployed as a StatefulSet
. It also uses a persistent volume to preserve agent status across cluster re-deployments. This agent gives you inside-out visibility within the cluster, as well as the possibility of having network tests between the two clouds to track latency and any other issues that may occur.
To deploy the enterprise agent you will need to get your TE Agent Account Token
, which you can get by following this guide.
Once you have your TE Agent Account Token
add it to line 60 on te-agent.yaml.tpl
file on both multiCloudDeployments/control/ThousandEyes and multiCloudDeployments/peer/ThousandEyes folders. Save and rename the file as te-agent.yaml
, on both folders!
The enterprise agent must be deployed to a fixed K8s node to ensure that the agent's identity persists across pod re-deployments. This requires labeling the k8s node that ThousandEyes agent will be deployed to.
-
Label one of the nodes
kubectx smm-eks kubectl get nodes kubectl label nodes <node-name> tehost=host2
To check that the node has been labelled
kubectl get nodes -L tehost
If you wish to delete it
kubectl label node <node-name> tehost-
-
Create a
thousandeyes
namespacekubectl create ns thousandeyes
-
Deploy the enterprise agent on the
thousandeyes
namespacekubectl apply -f multiCloudDeployments/control/ThousandEyes/te-agent.yaml -n thousandeyes
-
Check that the agent is sucessfully running
kubectl get pods -n thousandeyes
If you want to check the logs of the enterprise agent you can use the following command:
kubectl -n thousandeyes exec -it te-agent-teastore-multicloud-eks-0 -- cat /var/log/agent/te-agent.log
-
Deploy the same enterprise agent but now on the peer cluster - you will still need to label a node!
kubectx smm-gke kubectl get nodes kubectl label nodes <node-name> tehost=host2 kubectl create ns thousandeyes kubectl apply -f multiCloudDeployments/peer/ThousandEyes/te-agent.yaml -n thousandeyes kubectl get pods -n thousandeyes
Once both agents are running on both clusters you should see them come online in the ThousandEyes Dashboard, as follows.
You can now create tests using those agents!
You can use ThousandEyes Cloud agents, deployed worldwide, to perform synthetic transaction tests against the TeaStore application. On the multiCloudDeployments/control/ThousandEyes/TransactionTests folder there is a sample transaction test example, Browse&Buy.js
, that you can import and use as your transaction test.
As the name of the file suggests this transaction test browses through the app, adds a few items to the cart, logs in and checks out. There are a few markers and screenshots added to the test too, so you will be able to visualize these on your ThousandEyes dashboard, as part of your test.
Please Note: If you are using the Browse&Buy.js
transaction test you need to set the Device Emulation
as Desktop Small
under Advanced Settings.
ThousandEyes natively supports sending alert notifications directly to AppDynamics. This allows you to correlate trigger events with clear events, and to create policies in AppDynamics based on specific properties like: alertState, alertType (HTTP, Network, Voice, etc) and testName. In AppDynamics, ThousandEyes alerts show up as custom events of type ThousandEyesAlert
and allow you to open the ThousandEyes app at the Views screen for the alert start time to have further visibility into the issue.
You can quickly and easily set-up the native alerts integration by following the steps in the official ThousandEyes Documentation.
ThousandEyes dashboard widgets can be embedded directly into an AppDynamics dashboard. To do this, simply use the URL from the Embed Widget menu in a widget that is part of an existing ThousandEyes dashboard.
Please Note: Only the URL is needed, not the full iframe code.
Paste the URL into an AppDynamics dashboard iFrame widget, under the URL to display field in an AppDynamics widget. Make sure Security Sandbox IFrame is unchecked.
If you wish to integrate Cisco's IWO, a real-time decision engine for application resource management across on-premises and public cloud environments, please check the iwo folder. There you will find a guide that shows you how to integrate IWO with the primary and peer clusters, as well as how to integrate it with AppDynamics and AWS billing.
If you wish to experiment with Cisco's SecureCN, a cloud native application security solution, you can request a free trial or talk to the SecureCN team for a deeper dive. Once you have access to the platform, if you wish to deploy SecureCN integrated with SMM, please follow the guide on the SecureCN folder