Consul’s service mesh capabilities on EKS are fundamentally about injecting sidecar proxies that intercept and manage all network traffic between your services, providing features like discovery, routing, and security without application code changes.

Let’s see it in action. Imagine you have two simple applications running on EKS: frontend and backend. Without Consul, frontend would need to know the exact IP and port of backend to make a request. With Consul, frontend just needs to know the logical service name backend, and the Consul sidecar proxy handles the rest.

Here’s a simplified view of how it works. You deploy Consul itself, typically as a stateful set in Kubernetes. Then, you enable the Consul Kubernetes integration. The key component here is the consul-k8s binary, which acts as a controller. It watches for Kubernetes service and pod annotations. When it sees a pod that should be part of the mesh (indicated by an annotation like consul.hashicorp.com/connect-inject: "true"), it injects a consul-proxy container into that pod’s definition. This consul-proxy is the sidecar.

When frontend tries to connect to backend, the request first hits the frontend’s sidecar proxy. This proxy, knowing about Consul’s service catalog, looks up backend. If backend is also running with a sidecar, the frontend sidecar establishes a secure, TLS-encrypted connection to the backend sidecar. The backend sidecar then forwards the request to the actual backend application container. This entire process is transparent to frontend and backend themselves.

The problem Consul solves here is the complexity of distributed systems networking. Manually managing service discovery, load balancing, TLS certificates, and network policies across dozens or hundreds of microservices is a nightmare. Consul centralizes these concerns.

The core components you interact with are:

  • Consul Servers: The control plane. They maintain the service catalog, manage configuration, and handle consensus.
  • Consul Clients: Often co-located with the servers or deployed separately. They register services and proxy local requests.
  • Consul Connect: The service mesh feature. It enables secure service-to-service communication.
  • Consul-Proxy (Sidecar): The Envoy proxy injected into your application pods. It handles traffic interception and routing.
  • Consul Kubernetes Integration: The component that bridges Consul and Kubernetes, enabling features like automatic sidecar injection and service catalog synchronization.

To set this up on EKS, you’ll typically start by installing Consul itself. A common way is using Helm.

helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm install consul hashicorp/consul --namespace consul --create-namespace \
  --set global.enabled=true \
  --set global.tls.enabled=true \
  --set server.bootstrapExpect=3 \
  --set controller.enabled=true \
  --set kube_config_path_override=/etc/rancher/k3s/k3s.yaml # Example for K3s, adjust for EKS

This command installs Consul with TLS enabled for secure communication within the Consul cluster and enables the Kubernetes controller. The server.bootstrapExpect=3 sets up a 3-node Consul server cluster for high availability.

Once Consul is running, you enable sidecar injection for your application deployments. You do this by adding an annotation to your deployment’s pod template:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      annotations:
        consul.hashicorp.com/connect-inject: "true"
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:latest
        ports:
        - containerPort: 8080

When Kubernetes applies this deployment, the Consul Kubernetes controller detects the connect-inject: "true" annotation. It then modifies the pod spec before it’s created, adding a new container: the Envoy sidecar proxy. This sidecar is configured by Consul to intercept traffic destined for or originating from my-app-container.

The most surprising thing about Consul Connect is that it doesn’t require any changes to your application code to achieve TLS encryption and mutual TLS authentication between services. The sidecar proxy handles the certificate generation, rotation, and TLS handshake entirely on behalf of your application. Your application just makes a plain HTTP or gRPC request to localhost:port, and the sidecar ensures that request is secured before it leaves the pod and is decrypted by the destination sidecar.

The next step after getting basic service mesh functionality working is often configuring L7 routing rules, such as traffic splitting for canary deployments or defining specific API path routing.

Want structured learning?

Take the full Consul course →