Virtual Day
Building the ecosystem for the Cloud Operating Model with Azure, Cisco, F5 and GitLab Register

Service Mesh and Consul Connect

Allow External Traffic Inside Your Service Mesh With Ingress Gateways

Ingress gateways enable ingress traffic from services outside the Consul service mesh to access services inside the Consul service mesh. An ingress gateway is a type of proxy and must be registered as a service in Consul. They are an entrypoint for outside traffic and allow you to define what services are exposed and on which port.

Ingress Gateway single datacenter with external


In order to deploy and test Consul ingress gateways, you will need the following resources deployed in a non-production environment:

  • A node hosting an external service that needs to communicate with a service inside the mesh. You do not have Consul installed on this node.

  • A Consul datacenter with Consul service mesh functionality enabled. Check Secure Service-to-Service Communication for configuration help. To test the functionality of the ingress gateway, you will need at least two client nodes inside the service mesh:

    • A node hosting a backend service.
    • An ingress gateway node. This node requires unrestricted, verified network connectivity between its host and other nodes in the service mesh.

The following tools are required on the different nodes:

Binary/NodeConsul serverCounting serviceDashboard serviceIngress gateway
Consul v1.8.0+🚫
Counting Service🚫🚫🚫
Dashboard Service🚫🚫🚫

»Configure an ingress gateway for your service mesh

In this tutorial you will make a service running inside the service mesh available to clients outside the service mesh by performing the following steps:

  1. Register a counting service inside the service mesh and start an Envoy proxy as a sidecar.
  2. Enable zero-trust networking with intentions. This is not strictly required for the functionality to work but is a recommended best practice.
  3. Configure and start the ingress gateway.
  4. Use the DNS interface to discover the ingress gateway.
  5. Configure intentions to allow external connectivity.

»Deploy the counting service into the mesh

On the host running within the service mesh, register the counting service by creating a file called counting.hcl with the following content.

service {
 name = "counting"
 id = "counting-1"
 port = 9003

 connect {
   sidecar_service {}

 check {
   id       = "counting-check"
   http     = "http://localhost:9003/health"
   method   = "GET"
   interval = "10s"
   timeout  = "1s"

This configuration defines a service named counting running on port 9003. The counting service is enabled for Consul service mesh with the connect configuration.

Register the service with the local Consul agent.

$ consul services register counting.hcl
Registered service: counting

Start the sidecar proxy for the service.

$ consul connect envoy -sidecar-for counting-1 > dashboard-proxy.log &

Finally, in case you did not start the service yet, start it now.

PORT=9003 ./counting-service &

»Configure zero-trust networking

The first intention you will create changes from the default-allow approach where all traffic is allowed unless specifically denied to a default-deny approach where all traffic is denied, and only specific connections are allowed.

Use the consul intention create command to create the intention.

$ consul intention create -deny "*" "*"
Created: * => * (deny)

This intention will prevent all service-to-service communication. Traffic between the previously deployed services will also be prevented.

»Deploy the ingress gateway

On the host where you will deploy the ingress gateway, create a file named ingress-gateway.hcl with the following contents.

Kind = "ingress-gateway"
Name = "ingress-service"

Listeners = [
   Port = 8080
   Protocol = "tcp"
   Services = [
       Name = "counting"

This file defines configuration for an ingress gateway named ingress-service which acts as an ingress proxy for traffic destined to the service named counting.

Register the ingress gateway configuration with Consul.

$ consul config write ingress-gateway.hcl

»Start the ingress gateway

After the configuration is written in your datacenter, you can start the ingress gateway using the following command:

$ consul connect envoy -gateway=ingress -register -service ingress-service \
   -address '{{ GetInterfaceIP "eth0" }}:8888'

After the gateway is started the UI should show a new service registered:

Consul UI services with ingress gateway

»Discover the external service

Once started, the ingress gateway services can be discovered via the Consul DNS interface using the pattern <service>.ingress.<datacenter>.<domain>.

$ dig @ -p 8600 dashboard.ingress.dc1.consul. ANY
; <<>> DiG 9.10.6 <<>> @ -p 8600 counting.ingress.dc1.consul. ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20095
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

; EDNS: version: 0, flags:; udp: 4096
;counting.ingress.dc1.consul.   IN  ANY

counting.ingress.dc1.consul. 0  IN  A

;; Query time: 4 msec
;; WHEN: Thu Jun 25 09:17:37 EDT 2020
;; MSG SIZE  rcvd: 72

In this example your gateway will be reachable at counting.ingress.dc1.consul.

You can use the IP resolved by Consul to configure the dashboard service:

PORT=9002 COUNTING_SERVICE_URL="" ./dashboard-service_linux_amd64 &

»Allow access between the services

By default, if you configured zero-trust networking as a recommended best practice, you will not be able to use the ingress gateway until you explicitly enable connectivity from the ingress to the services represented by it. This is one extra layer of security to prevent your services being exposed externally until ready.

Open a browser and navigate to the dashboard web interface at http://localhost:9002.

The connection indicator in the dashboard UI will show the word "Disconnected" because of the zero-trust networking approach. This means you need to explicitly enable the connection across the two services.

Image of Dashboard UI. There is white text on a magenta background, with the
page title "Dashboard" at the top left. There is a red indicator in the top
right with the words "Counting Service is Unreachable" in white.  There is a
large number -1 to show sample counting output. The word "Unreachable"
surrounded by square brackets is in monospaced type underneath the large

To enable communication between two services, in Consul service mesh, you need to create an intention that explicitly allows traffic between a source service (downstream) and a destination service (upstream).

In this scenario, or generally when you want to use ingress gateways to enable external services to access services inside the service mesh, the source service is not present in the catalog. Furthermore, there's no guarantee that the service could be configured to respect mTLS and ACLs requirements.

Ingress gateways help you configure these communications by representing the external services inside your service mesh. In this way you can permit north-south traffic by creating intentions that allow communications between the ingress gateway (since it represents the external service) and the service registered in Consul.

Create the intention to allow communication to the counting service.

$ consul intention create -allow ingress-service counting
Created: ingress-service => counting (allow)

Refresh your browser. The indicator in the top right that should turn green and show the word "Connected" when the dashboard service is able to connect to the counting service.

Image of Dashboard UI. There is white text on a magenta background, with the
page title "Dashboard" at the top left. There is a green indicator in the top
right with the word connected in white.  There is a large number 10 to show
sample counting output. The node name that the counting service is running on,
host01, is in very small monospaced type underneath the large

»Next steps

In this tutorial you configured an ingress gateway to enable external services to reach a service running in the service mesh. You used global configuration to add a ingress-gateway configuration entry, and started the ingress gateway sidecar proxy. Finally you enabled connectivity from outside the service mesh using intentions.

Check the Consul documentation for more info on Ingress Gateways.