Emissary-ingress and Istio: Edge Proxy and Service Mesh together in one. Emissary-ingress is deployed at the edge of your network and routes incoming traffic to your internal services (aka "north-south" traffic). Istio is a service mesh for microservices, and is designed to add application-level Layer (L7) observability, routing, and resilience to service-to-service traffic (aka "east-west" traffic). Both Istio and Emissary-ingress are built using Envoy.
Emissary-ingress and Istio can be deployed together on Kubernetes. In this configuration, Emissary-ingress manages traditional edge functions such as authentication, TLS termination, and edge routing. Istio mediates communication from Emissary-ingress to services, and communication between services.
This allows the operator to have the best of both worlds: a high performance, modern edge service (Emissary-ingress) combined with a state-of-the-art service mesh (Istio). While Istio has introduced a Gateway abstraction, Emissary-ingress still has a much broader feature set for edge routing than Istio. For more on this topic, see our blog post on API Gateway vs Service Mesh.
This guide explains how to take advantage of both Emissary-ingress and Istio to have complete control and observability over how requests are made in your cluster:
- Install Istio and configure auto-injection
- Install Emissary-ingress with Istio integration
- Configure an mTLS
- Route to services using mTLS
If desired, you may also
To follow this guide, you need:
- A Kubernetes cluster version 1.15 and above
- Istio version 1.10 or higher
Start by installing Istio. Any supported installation method for Istio will work for use with Emissary-ingress.
Istio functions by supplying a sidecar container running Envoy with every service in the mesh (including Emissary-ingress). The sidecar is what enforces Istio policies for traffic to and from the service, notably including mTLS encryption and certificate handling. As such, it is very important that the sidecar be correctly supplied for every service in the mesh!
While it is possible to manage sidecars by hand, it is far easier to allow Istio to automatically inject
the sidecar as necessary. To do this, set the
istio-injection label on each Kubernetes Namespace for
which you want auto-injection:
Properly integrating Emissary-ingress with Istio provides support for:
- Mutual TLS (mTLS), with certificates managed by Istio, to allow end-to-end encryption for east-west traffic;
- Automatic generation of Prometheus metrics for services; and
- Istio distributed tracing for end-to-end observability.
The simplest way to enable everything is to install Emissary-ingress using Helm, though you can use manual installation with YAML if you wish.
To install with Helm, write the following YAML to a file called
To install Emissary-ingress with Helm, use these values to configure Istio integration:
Enable Istio auto-injection for it:
Make sure the Helm repo is configured:
Use Helm to install Emissary-ingress in emissary:
To install using YAML files, you need to manually incorporate the contents of the
file shown above into your deployment YAML:
pod-annotationsshould be configured as Kubernetes
annotationson the Emissary-ingress Pods;
envcontents should be included in the emissary-ingress Deployment; and
- you must also label the emissary Namespace for auto-injection as described above.
If you have already installed Emissary-ingress and want to enable Istio:
- Install Istio.
- Label the emissary namespace for Istio auto-injection, as above.
- Edit the Emissary-ingress Deployments to contain the
envelements shown above.
- If you installed with Helm, you can use
-f istio-integration.yamlto modify the installation for you.
- If you installed with Helm, you can use
- Restart the Emissary-ingress pods.
After configuring Emissary-ingress for Istio integration, the Istio mTLS certificates are available within Emissary-ingress:
istio-proxysidecar and Emissary-ingress mount the
istio-proxysidecar saves the mTLS certificates into
Emissary-ingress reads the mTLS certificates from
AMBASSADOR_ISTIO_SECRET_DIRenvironment variable) and creates a Secret named
To make use of the
istio-certs Secret, create a
TLSContext referencing it:
TLSContext is created, a
Mapping can use it for TLS origination. An example might be:
Mapping will use mTLS when communicating with its upstream service.
After integrating Emissary-ingress with Istio, Emissary-ingress's feature-rich routing capabilities and Istio's mTLS and observability are all available for all incoming traffic. To take full advantage of both, you need to:
- configure upstream services with the Istio sidecar;
Mappings to use mTLS; and
- verify your service port configuration.
Upstream services must have the Istio sidecar configured. The easiest way to arrange for this is to use Istio automatic sidecar injection as discussed above.
This will tell Istio to automatically inject the
istio-proxy sidecar container into pods in this namespace.
Traffic routing in Emissary-ingress is configured with the
This is a powerful configuration object that lets you configure different routing rules for different services.
To configure a
Mapping to use mTLS, you need to use the
tls element of the
Mapping to tell it to originate
TLS using the
For example, if you have installed the Quote service as described on the
Getting Started page, you will have a
Mapping as follows:
To take advantage of Istio mTLS, update the above
Mapping to originate TLS using the Istio mTLS
certificates and to force access on port 80:
The behavior of your service will not seem to change, even though mTLS is active:
This request first went to Emissary-ingress, which routed it over an mTLS connection to the quote service in the
default namespace. That connection was intercepted by the
istio-proxy which authenticated the request as
being from Emissary-ingress, exported various metrics, and finally forwarded it on to the actual quote service.
When mTLS is active, Istio makes TLS connections to your services. Since Istio handles the TLS protocol for
you, you don't need to modify your services — however, the TLS connection will still use port 443
if you don't configure your
Mappings to explicitly use port 80.
If your upstream service was not written to use TLS, its
Service resource may only map port 80. If Istio
attempts a TLS connection on port 443 when port 443 is not defined by the
Service resource, the connection
will hang even though the Istio sidecar is active, because Kubernetes itself doesn't know how to handle
the connection to port 443.
As shown above, one simple way to deal with this situation is to explicitly specify port 80 in the
Another way is to set up your Kubernetes
Service to map both port 80 and port 443. For example, the
Quote (which listens on port 8080 in its pod) might use a
Service like this:
Note that ports 80 and 443 are both mapped to
targetPort 8080, where the service is actually listening.
This permits Istio routing to work whether mTLS is active or not.
Istio defaults to permissive mTLS, where mTLS is allowed between services, but not required. Configuring
strict mTLS requires all connections within the cluster be encrypted. To switch Istio to use strict mTLS,
PeerAuthentication resource in each namespace that should operate in strict mode:
To test strict mTLS, remove the
tls configuration from the quote-backend
Mapping and send a request:
Make sure to restore the
tls configuration when testing is complete!
By default, the Istio sidecar provides Prometheus metrics using
prometheus.io annotations. To take
advantage of these metrics, you must install Prometheus.
The Istio sidecar also supports distributed tracing by default. To take advantage of this support, you need to:
Install a tracing provider, for example Zipkin into your cluster.
TracingServiceto tell Emissary-ingress to send tracing to your tracing provider, for example:
After adding a
TracingService, restart Emissary-ingress for the configuration to take effect. Istio propagates
the tracing headers automatically, allowing for end-to-end observability within the cluster.
By default, Istio mTLS certificates are valid for 90 days, but get rotated every day.
Emissary-ingress updates the mTLS certificates as they are rotated, so you don't need to worry about certificate expiration.
To test that Emissary-ingress is properly rotating certificates, shorten the TTL of the Istio certificates by
setting the following environment variables in the
istiod container in the
This makes the certificates Istio issues expire in one hour so testing certificate rotation is much easier.