Connect services between Consul datacenters with cluster peering
Service meshes provide secure communication across your services within and across your infrastructure, including on-premises and cloud environments. As your organization scales, it may need to deploy services in multiple cloud providers in different regions. Cluster peering enables you to connect multiple Consul clusters, letting services in one cluster securely communicate with services in the other.
Cluster peering removes some of the administrative burdens associated with WAN federation. Because there is no primary cluster, administrative boundaries are clearly separated per cluster since changes in one Consul cluster does not affect peered clusters. For more information on differences between WAN federation and cluster peering, refer to the cluster peering documentation.
In this tutorial you will:
- Deploy two managed Kubernetes environments with Terraform
- Deploy Consul in each Kubernetes cluster
- Deploy the microservices from HashiCups, a demo application, in both Kubernetes cluster
- Peer the two Consul clusters
- Connect the services across the peered service mesh
Scenario overview
HashiCups is a coffee-shop demo application. It has a microservices architecture and uses Consul service mesh to securely connect the services. In this tutorial, you will deploy HashiCups services on Kubernetes clusters in two different regions. By peering the Consul clusters, the frontend services in one region will be able to communicate with the API services in the other.
HashiCups uses the following microservices:
- The
nginx
service is an NGINX instance that routes requests to thefrontend
microservice and serves as a reverse proxy to thepublic-api
service. - The
frontend
service provides a React-based UI. - The
public-api
service is a GraphQL public API that communicates with theproducts-api
and thepayments
services. - The
products-api
service stores the core HashiCups application logic, including authentication, coffee (product) information, and orders. - The
postgres
service is a Postgres database instance that stores user, product, and order information. - The
payments
service is a gRCP-based Java application service that handles customer payments.
Prerequisites
If you are not familiar with Consul's core functionality, refer to the Consul Getting Started tutorials collection first.
For this tutorial, you will need:
- A Google Cloud account configured for use with Terraform
- gcloud CLI with the
gke-cloud-auth-plugin
plugin installed
This tutorial uses Terraform automation to deploy the demo environment. You do not need to know Terraform to successfully complete this tutorial.
Clone example repository
Clone the GitHub repository containing the configuration files and resources.
Change into the directory with the newly cloned repository.
This repository has the following:
- The
dc1
directory contains Terraform configuration to deploy an GKE cluster inus-central1-a
. - The
dc2
directory contains Terraform configuration to deploy an GKE cluster inus-west1-a
. - The
k8s-yamls
directory contains YAML configuration files that support this tutorial. - The
hashicups-v1.0.2
directory contains YAML configuration files for deploying HashiCups.
Deploy Kubernetes clusters and Consul
In this section, you will create a Kubernetes cluster on each datacenter, and install Consul to provide service mesh functionality.
Initialize the Terraform configuration for dc1
to download the necessary providers and modules.
Use the terraform.tfvars.example
template file to create a terraform.tfvars
file in the dc1 folder.
Edit this file to specify your project ID and zones. By default, dc1
deploys to us-central1-a
.
Open a new terminal window and initialize the Terraform configuration for dc2
.
Next, use the terraform.tfvars.example
template file to create a terraform.tfvars
file in the dc2 folder.
Edit this file to specify your project ID and zones. By default, dc2
deploys to us-west1-b
.
Then, deploy the resources for dc1
. Confirm the run by entering yes
. This will take about 15 minutes to deploy your infrastructure.
Deploy the resources for dc2
. Confirm the run by entering yes
.
Review Consul deployment
Terraform automatically deploys Consul into each datacenter using the Helm charts consul-helm-dc1.yaml
and consul-helm-dc2.yaml
located in the ./k8s-yamls/
folder. The following configuration shows the mandatory features for cluster peering enabled in dc1
. Features enabled in dc2
are equivalent.
Configure kubectl
Now that you have deployed the two datacenters, configure the kubectl
tool to interact with the Kubernetes cluster in the first datacenter.
Notice that this command stores the cluster connection information for dc1
.
Set the current Google Cloud project, and then fetch the related credentials.
Then, rename the first cluster context to dc1. This lets you target this specific Kubernetes cluster in later commands.
Configure the kubectl
tool to interact with the Kubernetes cluster in the second datacenter.
Notice that this command stores the cluster connection information for dc2
.
Then, rename the second cluster context to dc2.
Verify that Consul was successfully deployed by Terraform in dc1
by inspecting the Kubernetes pods in the dc1 consul
namespace.
Then, verify that Consul was successfully deploeyd by Terraform in dc2
by inspecting the Kubernetes pods in the dc2 consul
namespace.
Verify HashiCups deployment
The Terraform deployments for both dc1
and dc2
include a subset of the HashiCups microservices. The dc1
Kubernetes cluster hosts the frontend services, while the dc2
Kubernetes cluster hosts the API and database services. Later in this tutorial, you will connect the Consul datacenters to form the complete HashiCups deployment. The following diagram illustrates how HashiCups is deployed across the two clusters.
Verify HashiCups on first cluster
In dc1
, you can view the HashiCups frontend, but the demo application will not display any products because products-api
is not deployed.
Terraform deploys in dc1
the K8s YAML files present in hashicups-v1.0.2/dc1
. Verify that Terraform has successfully deployed these services by listing the Kubernetes services.
List the services registered with Consul in dc1
. This command runs consul catalog services
in one of the Consul server agents.
Verify HashiCups on second cluster
Terraform deploys the remaining two HashiCups services in dc2
from the K8s YAML files present in hashicups-v1.0.2/dc2
. Verify that Terraform has successfully deployed products-api
and postgres
by listing the Kubernetes services in dc2
.
List the services registered with Consul in dc2
.
Explore the Consul UI (optional)
Retrieve the Consul UI address for dc1
and open it in your browser.
Retrieve the Consul UI address for dc2
and open it in your browser.
Explore HashiCups in browser
Open the HashiCups application in your browser and notice that it displays no products.
At this point, the public-api
service in dc1
is configured to connect to its local instance of the products-api
service, however there is currently no instance of products-api
on dc1
. To use the instance of products-api
hosted in another datacenter, you will first configure Consul cluster peering, and then point the upstream to the products-api
service in dc2
.
Configure Consul cluster peering
Tip
Consul cluster peering works on both Enterprise and OSS versions of Consul. On Consul OSS, you can only peer clusters between the default
partitions. On Consul Enterprise, you can peer clusters between any partition.
You will now peer the two data centers to enable services in dc1
to communicate to products-api
in dc2
.
Consul cluster peering works by defining two cluster roles:
- A peering acceptor is the cluster that generates a peering token and accepts an incoming peering connection.
- A peering dialer is the cluster that uses a peering token to make an outbound peering connection with the cluster that generated the token.
Configure cluster peering traffic routing
You can peer Consul clusters by either directly connecting Consul server nodes or connecting the Consul mesh gateways.
Most Kubernetes deployments will not let services connect outside the cluster. This prevents the Consul server pods from communicating to other Kubernetes clusters. Therefore, we recommend configuring the clusters to use mesh gateways for peering. The following file configures the Consul clusters to use mesh gateways for cluster peering:
Configure cluster peering traffic for both dc1
and dc2
to be routed via the mesh gateways.
There are two modes for routing traffic from local services to remote services when cluster peering connections are routed through mesh gateways. In remote
mode, your local services contact the remote mesh gateway in order to reach remote services. In local
mode, your local services contact their local gateway in order to reach remote services. Refer to the modes documentation and well as the Mesh architecture diagram for more information.
We recommend you use local
mode because most Kubernetes deployments do not allow local services to connect outside the cluster. The following configuration specifies local
mode for traffic routed over the mesh gateways:
Configure local
mode for traffic routed over the mesh gateways for both dc1
and dc2
.
Create a peering token
Configuring the peering acceptor role for a cluster generates a peering token and waits to accept an incoming peering connection. The following configuration sets dc1
as the peering acceptor:
Configure a PeeringAcceptor
role for dc1
.
Confirm you successfully created the peering acceptor custom resource definition (CRD).
Confirm that the PeeringAcceptor CRD generated a peering token secret.
Import the peering token generated in dc1
into dc2
.
Establish a connection between clusters
Configuring a peering dialer role for a cluster makes an outbound peering connection towards a peering acceptor cluster using the specified peering token. The following configuration sets dc2
as the peering dialer and peering-token-dc2
as its token.
Configure a PeeringDialer
role for dc2
. This will create a peering connection from the second datacenter towards the first one.
Verify that the two Consul clusters are peered. This command queries the peering
API endpoint on the Consul server agent in dc1
.
Notice the state is Active
, which means that the two clusters are peered successfully.
Export the products-api service
After you peer the Consul clusters, you need to create a configuration entry that defines the services you want to export to other clusters. Consul uses this configuration entry to advertise those services' information and connect those services across Consul clusters. The following configuration exports the products-api
service into the dc1
peer.
In dc2
, apply the ExportedServices
custom resource file that exports the products-api
service to dc1
.
Confirm that the Consul cluster in dc1
can access the products-api
in dc2
. This command queries the services
API endpoint on the Consul server agent in dc1
about the products-api
service from dc2
for its sidecar service ID and the related peer name.
Notice the output contains the products-api
sidecar service ID and the name of the related cluster peering.
Create a cross-cluster service intention
In order for communication from products-api
service in dc1
to reach public-api
in dc2
, you must define a ServiceIntentions
custom resource definition that enables communication from products-api
service in dc1
.
Create a service intention in dc2
that that allows communication from the public-api
service in dc1
to the products-api
service in dc2
.
Modify upstream for the public-api service
Next, modify the public-api
service definition in dc1
with the updated configuration pointing to upstream in dc2
. In this scenario, the correct destination is products-api.virtual.dc2.consul
.
Consul uses the DNS syntax for service virtual IP lookups to contact services across peered datacenters. The upstream address is formatted as <service>.virtual[.<namespace>].<peer>.<domain>
. The namespace
segment is only available in Consul Enterprise.
Apply the updated public-api
service definition in dc1
with the upstream targeted at dc2
.
Verify peered Consul services
Verify the cluster peering is operational by opening the HashiCups application in your browser. Notice that it now displays a curated selection of coffee drinks.
Destroy environment
Now that you have peered two Consul clusters, you will now remove the exported service and cluster peering, before destroying the environment.
Remove exported service (optional)
Stop the products-api
service from being exported.
Remove cluster peering (optional)
To remove a peering connection, delete both the PeeringAcceptor
and PeeringDialer
resources.
First, delete the PeeringDialer
from dc2
.
Then, delete the PeeringAcceptor
from dc1
.
Verify the two clusters are no longer peered by querying the /health
HTTP endpoint in dc1
.
Delete supporting infrastructure
Destroy the supporting infrastructure in your first datacenter.
Next, destroy the supporting infrastructure in your second datacenter.
Next steps
In this tutorial, you used the Consul cluster peering to route traffic across service meshes in two Consul clusters. In the process, you learned the benefits of using cluster peering for cluster interconnections with minimal shared administrative overhead.
For a much easier experience in configuring cluster peering, consider using Consul on the HashiCorp Cloud Platform (HCP). In HCP, you can easily launch and operate a fully-managed Consul platform in the cloud.
Feel free to explore these tutorials and collections to learn more about Consul service mesh, microservices, and Kubernetes security.