Introduction
In modern micro-service architectures, service discovery and routing are pivotal to enabling dynamic communication between microservices, both inside and outside a service mesh. One of Consul’s most valuable components is its API Gateway (API GW), which allows developers to expose services to external consumers and manage API traffic between internal and external systems.
However, when integrating external non-mesh services – services that are not part of Consul’s service mesh – into this ecosystem, it can become complex to manage routing, traffic redirection, and secure communication. Service redirection from Consul’s API Gateway to these external services provides a solution, enabling the API Gateway to forward requests to external endpoints while preserving Consul’s capabilities for traffic management, observability, and security.
Expected Outcome
This guide explores how to configure service redirection from Consul’s API Gateway to external non-mesh services. By leveraging the flexible routing mechanisms in Consul, administrators can ensure that requests originating from within the mesh are securely redirected to external services without compromising performance, security, or reliability.
In this guide, we will be covering various configuration aspects to use like API GW related CRDs to implement this service redirection behaviour.
Prerequisites (if applicable)
The tutorial assumes that you are familiar with Consul and its core functionality.
You may follow the guide to configure Consul cluster on a K8s cluster on AWS EKS, also you could register API GW to configure routes for backend sample services.
Use Case
Service redirection from HashiCorp Consul's API Gateway to an external non-mesh service is a crucial capability for modern hybrid architectures. Below are several key use cases where this functionality proves to be highly beneficial:
-
Integration with Legacy Systems - Many organizations operate in hybrid environments where new microservices are built in a service mesh, while older legacy systems, often residing outside the mesh, need to continue functioning.
-
Connecting to External Third-Party APIs - Enterprises often need to integrate with external third-party services or APIs that are not part of their internal Consul service mesh. This can be particularly challenging when trying to centralize API management, security, and traffic observability.
-
API Gateway for Multi-Cloud or Hybrid Environments - Organizations operating in multi-cloud or hybrid cloud environments often have services spread across different platforms, including on-premises, public cloud, or third-party data centers.
-
Connecting to External Databases or Storage Services - Many external services such as databases, object storage (e.g., AWS S3, Google Cloud Storage), or other stateful resources may not be part of the service mesh but need to be accessed by services within the mesh.
-
External Authentication or Authorization Systems - Organizations may use external systems for user authentication (e.g., OAuth providers, SAML servers) or third-party authorization services (e.g., identity and access management systems) that are not part of the Consul mesh.
Procedure
To setup service redirection on API Gateway to pass re-route request to an external service/system/site (running in non-service mesh) could be implemented using following steps:-
-
Use this guide to take reference of the site https://jsonplaceholder.typicode.com/ as an external service.
-
Once the lab setup is configured using this guide, then the user may take a reference of an official doc to configure Terminating Gateway (which allows service inside mesh to connect to the non-mesh service).
-
Following the official doc, first register the external site as a service in the Consul catalog.
-
The user needs to
exec
into theconsul-server
pod, then move to the/tmp
folder and create following files over there.
external-service.json
{
"Node": "external-service",
"Address": "jsonplaceholder.typicode.com",
"NodeMeta": {
"external-node": "true",
"external-probe": "true"
},
"Service": {
"ID": "external-service-v1",
"Service": "external-service",
"Port": 443
},
"Partition": "default"
}
From the pod, run the following command to register the external service with Consul:
$ curl --request PUT --header "X-Consul-Token: $CONSUL_HTTP_TOKEN" --data @external.json --insecure $CONSUL_HTTP_ADDR/v1/catalog/register
true
-
To let API GW to redirect to
external-service
the user needs to create a CRD MeshService by passing reference of the external service.
mesh-service.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: MeshService
metadata:
name: external-service-virtual
namespace: default
spec:
name: external-service
% kubectl apply -f mesh-service.yaml
meshservice.consul.hashicorp.com/external-service-virtual configured
-
Then the user needs to create a config entry for Terminating Gateway to pass
external-service
name, its respectivecaFile
andsni
details.
tgw.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: TerminatingGateway
metadata:
name: terminating-gateway
spec:
services:
- name: external-service
namespace: default
caFile: /etc/ssl/certs/ca-certificates.crt
sni: typicode.com
% kubectl apply -f tgw.yaml
terminatinggateway.consul.hashicorp.com/terminating-gateway configured
-
Then configure
HTTPRoute
CRD for API Gateway by passing reference of MeshService asbackendRef
for the serviceexternal-service
. Ref. https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway/configuration/routes#rules-backendrefs
route-external.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: route-external
namespace: default
spec:
parentRefs:
- name: api-gateway
namespace: consul
#sectionName: http
rules:
- matches:
- path:
type: PathPrefix
value: /external
backendRefs:
- kind: MeshService
group: "consul.hashicorp.com"
name: external-service-virtual
namespace: default
% kubectl apply -f api-gw/route-external.yaml
httproute.gateway.networking.k8s.io/route-external configured
-
Lastly, if ACL is in place then the user needs to create
ServiceIntentions
to allow communication between API GW and external-service.
api-to-external-intention.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceIntentions
metadata:
name: api-to-external
spec:
destination:
name: external-service
namespace: default
sources:
- name: api-gateway
namespace: consul
action: allow
% kubectl apply -f api-gw/api-to-external-intention.yaml
serviceintentions.consul.hashicorp.com/api-to-external configured
Test the redirection flow from API GW
-
In order to validate the efficacy of the setup, exec to the API GW pod using the following command.
kubectl debug -it api-gateway-7fd85f66c5-whs8x -n consul --target api-gateway --image nicolaka/netshoot
Once, user is inside the ephemeral container of API GW, then run the following command to check connectivity from API GW pod to the external-service by passing Host
field in the header and also by directly hitting the POD IP of the Terminating-Gateway POD (192.168.87.117
in my case).
$ curl -H "Host: jsonplaceholder.typicode.com" 192.168.87.117
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<link rel="stylesheet" href="/style.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-lucario.min.css"
/>
...
-
Other method to check the connectivity is directly by hitting the API GW LB URL and append
/external
URI to it. Also, ensure to pass theHost
header.
$ curl -v -H "Host: jsonplaceholder.typicode.com" a8ee84967053c4e6b80e52ed20d69689-2083586290.eu-west-1.elb.amazonaws.com/external
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<link rel="stylesheet" href="/style.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/prism-themes/1.9.0/prism-lucario.min.css"
/>
...
Additional Information
https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway
https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway/configuration
https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway/configuration/gateway
https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway/configuration/routes