Configuring Emissary Communications
For Emissary to do its job of managing network communications for your services, it first needs to know how its own communications should be set up. This is handled by a combination of resources: the Listener
, the Host
, and the TLSContext
.
Listener
: defines where, and how, Emissary should listen for requests from the network.Host
: defines which hostnames Emissary should care about, and how to handle different kinds of requests for those hosts.Host
s can be associated with one or moreListener
s.TLSContext
: defines whether, and how, Emissary will manage TLS certificates and options.TLSContext
s can be associated with one or moreHost
s.
Once the basic communications setup is in place, Emissary Mapping
s and TCPMapping
s can be associated with Host
s to actually do routing.
Listener
and Host
resources are
required for a functioning Emissary installation that can route traffic!Learn more about
Listener
.Learn more about
Host
.
Host
exists! If the
wildcard behavior is needed, a Host
with a hostname
of "*"
must be defined by the user.
Learn more about
Listener
.Learn more about
Host
.Learn more about
Mapping
.Learn more about
TCPMapping
.Learn more about
TLSContext
.
A Note on TLS
TLS can appear intractable if you haven’t set up certificates correctly. If you’re having trouble with TLS, always check the logs of your Emissary Pods and look for certificate errors.
Examples / Cookbook
Basic HTTP and HTTPS
A useful configuration is to support either HTTP or HTTPS, in this case on either port 8080 or port 8443. This
tends to make it as easy as possible to communicate with the services behind the Emissary instance. It uses
two Listener
s and at least one Host
.
Listener
s:
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: http-listener
spec:
port: 8080
protocol: HTTPS # NOT A TYPO, see below
securityModel: XFP
hostBinding:
namespace:
from: SELF # See below
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: https-listener
spec:
port: 8443
protocol: HTTPS
securityModel: XFP
hostBinding:
namespace:
from: SELF # See below
-
Both
Listener
s useprotocol: HTTPS
to allow Envoy to inspect incoming connections, determine whether or not TLS is in play, and setX-Forwarded-Proto
appropriately. ThesecurityModel
then specifies thatX-Forwarded-Proto
will determine whether requests will be considered secure or insecure. -
The
hostBinding
shown here will allow anyHost
in the same namespace as theListener
s to be associated with bothListener
s; in turn, that will allow access to thatHost
’sMapping
s from either port. For greater control, use aselector
instead. -
Note that the
Listener
s do not specify anything about TLS certificates. TheHost
handles that; see below.
Listener
Host
This example will assume that we expect to be reachable as foo.example.com
, and that the foo.example.com
certificate is stored in the Kubernetes Secret
named foo-secret
:
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: "foo.example.com"
tlsSecret:
name: foo-secret
requestPolicy:
insecure:
action: Redirect
- The
tlsSecret
specifies the certificate in use for TLS termination. - The
requestPolicy
specifies routing HTTPS and redirecting HTTP to HTTPS. - Since the
Host
does not specify aselector
, onlyMapping
s with ahostname
that matchesfoo.example.com
will be associated with thisHost
. - Note well that simply defining a
TLSContext
is not sufficient to terminate TLS: you must define either aHost
or anIngress
. - Note that if no
Host
is present, but a TLS secret namedfallback-secret
is available, the system will currently define aHost
usingfallback-secret
. This behavior is subject to change.
Host
HTTP-Only
Another straightforward configuration is to support only HTTP, in this case on port 8080. This uses a single
Listener
and a single Host
:
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: http-listener
spec:
port: 8080
protocol: HTTP
securityModel: INSECURE
hostBinding:
namespace:
from: SELF # See below
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: "foo.example.com"
requestPolicy:
insecure:
action: Route
- Here, we listen only on port 8080, and only for HTTP. HTTPS will be rejected.
- Since requests are only allowed using HTTP, we declare all requests
INSECURE
by definition. - The
Host
specifies routing HTTP, rather than redirecting it.
Listener
Learn more about
Host
TLS using ACME (Ambassador Edge Stack only)
This scenario uses ACME to get certificates for foo.example.com
and bar.example.com
. HTTPS traffic to either
host is routed; HTTP traffic to foo.example.com
will be redirected to HTTPS, but HTTP traffic to bar.example.com
will be rejected outright.
Since this example uses ACME, it is only supported in Ambassador Edge Stack.
For demonstration purposes, we show this example listening for HTTPS on port 9999, using X-Forwarded-Proto
.
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: https-listener-9999
spec:
port: 9999
protocol: HTTPS
securityModel: XFP
hostBinding: # Edit as needed
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: foo.example.com
acmeProvider:
email: julian@example.com
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: bar-host
spec:
hostname: bar.example.com
acmeProvider:
email: julian@example.com
requestPolicy:
insecure:
action: Reject
(Mapping
s are not shown.)
- Our
Listener
s will accept HTTPS and HTTP on port 9999, and the protocol used will dictate whether the requests are secure (HTTPS) or insecure (HTTP). foo-host
defaults to ACME with Let’s Encrypt, sinceacmeProvider.authority
is not provided.foo-host
defaults to redirecting insecure requests, since the default forrequestPolicy.insecure.action
isRedirect
.bar-host
uses Let’s Encrypt as well, but it will reject insecure requests.
If you use ACME for multiple Hosts, add a wildcard Host too. This is required to manage a known issue. This issue will be resolved in a future Ambassador Edge Stack release.
Listener
Learn more about
Host
Multiple TLS Certificates
This scenario uses TLS without ACME. Each of our two Host
s uses a distinct TLS certificate. HTTPS
traffic to eitherfoo.example.com
or bar.example.com
is routed, but this time foo.example.com
will redirect
HTTP requests, while bar.example.com
will route them.
Since this example does not use ACME, it is supported in Emissary as well as Ambassador Edge Stack.
For demonstration purposes, we show this example listening for HTTPS on port 4848, using X-Forwarded-Proto
.
---
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: foo-example-secret
data:
tls.crt: -certificate PEM-
tls.key: -secret key PEM-
---
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: bar-example-secret
data:
tls.crt: -certificate PEM-
tls.key: -secret key PEM-
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: https-listener-4848
spec:
port: 4848
protocol: HTTPS
securityModel: XFP
hostBinding: # Edit as needed
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: foo.example.com
tlsSecret:
name: foo-example-secret
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: bar-host
spec:
hostname: bar.example.com
tlsSecret:
name: bar-example-secret
requestPolicy:
insecure:
action: Route
foo-host
andbar-host
simply reference thetlsSecret
to use for termination.- If the secret involved contains a wildcard cert, or a cert with multiple SAN, both
Host
s could reference the sametlsSecret
.
- If the secret involved contains a wildcard cert, or a cert with multiple SAN, both
foo-host
relies on the default insecure routing action ofRedirect
.bar-host
must explicitly specify routing HTTP.
Listener
Learn more about
Host
Using a TLSContext
If you need to share other TLS settings between two Host
s, you can reference a TLSContext
as well as
the tlsSecret
. This is the same as the previous example, but we use a TLSContext
to set ALPN
information,
and we assume that the Secret
contains a wildcard cert.
---
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: wildcard-example-secret
data:
tls.crt: -wildcard here-
tls.key: -wildcard here-
---
apiVersion: getambassador.io/v3alpha1
kind: TLSContext
metadata:
name: example-context
spec:
secret: wildcard-example-secret
alpn_protocols: [h2, istio]
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: https-listener-4848
spec:
port: 4848
protocol: HTTPS
securityModel: XFP
hostBinding: # Edit as needed
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: foo.example.com
tlsContext:
name: example-context
tlsSecret:
name: wildcard-example-secret
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: bar-host
spec:
hostname: bar.example.com
tlsContext:
name: example-context
tlsSecret:
name: wildcard-example-secret
requestPolicy:
insecure:
action: Route
- Note that specifying the
tlsSecret
is still necessary, even whentlsContext
is specified.
Listener
Learn more about
Host
ACME With a TLSContext (Ambassador Edge Stack Only)
In Ambassador Edge Stack, you can use a TLSContext
with ACME as well. This example is the same as “TLS using ACME”,
but we use a TLSContext
to set ALPN
information. Again, ACME is only supported in Ambassador Edge Stack.
---
apiVersion: getambassador.io/v3alpha1
kind: TLSContext
metadata:
name: example-context
spec:
secret: example-acme-secret
alpn_protocols: [h2, istio]
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: foo.example.com
acmeProvider:
email: julian@example.com
tlsContext:
name: example-context
tlsSecret:
name: example-acme-secret
- Note that we don’t provide the
Secret
: the ACME client will create it for us.
Listener
Learn more about
Host
Using an L7 Load Balancer to Terminate TLS
In this scenario, a layer 7 load balancer ahead of Emissary will terminate TLS, so Emissary will always see HTTP with a known good X-Forwarded-Protocol
. We’ll use that to route HTTPS and redirect HTTP.
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: lb-listener
spec:
port: 8443
protocol: HTTP
securityModel: XFP
l7Depth: 1
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: "foo.example.com"
requestPolicy:
insecure:
action: Redirect
- We set
l7Depth
to 1 to indicate that there’s a single trusted L7 load balancer ahead of us. - We specifically set this Listener to HTTP-only, but we stick with port 8443 just because we expect people setting up TLS at all to expect to use port 8443. (There’s nothing special about the port number, pick whatever you like.)
- Our
Host
does not specify atlsSecret
, so Emissary will not try to terminate TLS. - Since the
Listener
still pays attention toX-Forwarded-Proto
, both secure and insecure requests are possible, and we use theHost
to route HTTPS and redirect HTTP.
Listener
Learn more about
Host
Using a Split L4 Load Balancer to Terminate TLS
Here, we assume that Emissary is behind a load balancer setup that handles TLS at layer 4:
- Incoming cleartext traffic is forwarded to Emissary on port 8080.
- Incoming TLS traffic is terminated at the load balancer, then forwarded to Emissary as cleartext on port 8443.
- This might involve multiple L4 load balancers, but the actual number doesn’t matter.
- The actual port numbers we use don’t matter either, as long as Emissary and the load balancer(s) agree on which port is for which traffic.
We’re going to route HTTPS for both foo.example.com
and bar.example.com
, redirect HTTP for foo.example.com
, and reject HTTP for bar.example.com
.
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: split-lb-one-listener
spec:
protocol: HTTP
port: 8080
securityModel: INSECURE
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: split-lb-two-listener
spec:
protocol: HTTP
port: 8443
securityModel: SECURE
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
spec:
hostname: foo.example.com
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: bar-host
spec:
hostname: bar.example.com
requestPolicy:
insecure:
action: Reject
- Since L4 load balancers cannot set
X-Forwarded-Protocol
, we don’t use it at all here: instead, we dictate that 8080 and 8443 both speak cleartext HTTP, but everything arriving at port 8080 is insecure and everything at port 8443 is secure.
Listener
Learn more about
Host
Listening on Multiple Ports
There’s no reason you need to use ports 8080 and 8443, or that you’re limited to two ports. Here we’ll use ports 9001 and 9002 for HTTP, and port 4001 for HTTPS. We’ll route traffic irrespective of protocol.
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: listener-9001
spec:
protocol: HTTP
port: 9001
securityModel: XFP
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: listener-9002
spec:
protocol: HTTP
port: 9002
securityModel: XFP
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: listener-4001
spec:
protocol: HTTPS
port: 4001
securityModel: XFP
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: route-host
spec:
requestPolicy:
insecure:
action: Route
- We can use
X-Forwarded-Proto
for all ourListener
s: the HTTP-onlyListener
s will set it correctly. - Each
Listener
can specify only one port, but there’s no hardcoded limit on the number ofListener
s you can have.
Listener
Learn more about
Host
Using Labels to Associate Host
s and Listener
s
In the examples above, the Listener
s all associate with any Host
in their namespace. In this
example, we will use Kubernetes labels to control the association instead.
Here, we’ll listen for HTTP to foo.example.com
on port 8888, and for either HTTP or HTTPS to bar.example.com
on
port 9999 (where we’ll redirect HTTP to HTTPS). Traffic to baz.example.com
will work on both ports, and we’ll route
HTTP for it rather than redirecting.
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: listener-8888
spec:
protocol: HTTP
port: 8888
securityModel: XFP
hostBinding:
selector:
matchLabels:
tenant: foo
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: listener-9999
spec:
protocol: HTTPS
port: 9999
securityModel: XFP
hostBinding:
selector:
matchLabels:
tenant: bar
---
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: bar-secret
data:
tls.crt: -wildcard here-
tls.key: -wildcard here-
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: foo-host
labels:
tenant: foo
spec:
hostname: foo.example.com
requestPolicy:
insecure:
action: Route
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: bar-host
labels:
tenant: bar
spec:
hostname: bar.example.com
tlsSecret:
name: bar-secret
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: baz-host
labels:
tenant: foo
tenant: bar
spec:
hostname: baz.example.com
tlsSecret:
name: bar-secret
requestPolicy:
insecure:
action: Route
- Note the
labels
on eachHost
, which thehostBinding
on theListener
can reference.- Note also that only label selectors are supported at the moment.
Listener
Learn more about
Host
Wildcard Host
s and Mapping
s
In a Mapping
, the host
is now treated as a glob rather than an exact match, with the goal of vastly reducing the need for host_regex
. (The hostname
in a Host
has always been treated as a glob).
- Note that only prefix and suffix matches are supported, so
*.example.com
andfoo.*
are both fine, butfoo.*.com
will not work – you’ll need to usehost_regex
if you really need that. (This is an Envoy limitation.)
In this example, we’ll accept both HTTP and HTTPS, but:
- Cleartext traffic to any host in
lowsec.example.com
will be routed. - Cleartext traffic to any host in
normal.example.com
will be redirected. - Any other cleartext traffic will be rejected.
---
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: example-secret
data:
tls.crt: -wildcard for *.example.com here-
tls.key: -wildcard for *.example.com here-
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: listener-8443
spec:
port: 8443
protocol: HTTPS
securityModel: XFP
hostBinding: # This may well need editing for your case!
namespace:
from: SELF
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: lowsec-host
spec:
hostname: "*.lowsec.example.com"
tlsSecret:
name: example-secret
requestPolicy:
insecure:
action: Route
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: normal-host
spec:
hostname: "*.normal.example.com"
tlsSecret:
name: example-secret
requestPolicy: # We could leave this out since
insecure: # redirecting is the default, but
action: Redirect # it's spelled out for clarity.
---
apiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: catchall-host
spec:
hostname: "*.example.com"
tlsSecret:
name: example-secret
requestPolicy:
insecure:
action: Reject
- We’ll listen for HTTP or HTTPS on port 8443.
- The three
Host
s apply different insecure routing actions depending on the hostname. - You could also do this with
host_regex
, but usinghost
with globs will give better performance.- Being able to not associate a given
Mapping
with a givenHost
when theMapping
’shost
doesn’t match helps a lot when you have manyHost
s. - Reliably determining if a regex (for the
Mapping
) matches a glob (for theHost
) isn’t really possible, so we can’t prunehost_regex
Mapping
s at all.
- Being able to not associate a given
Listener
Learn more about
Host
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.