An Ingress resource is a popular way to expose Kubernetes services to the Internet. In order to use Ingress resources, you need to install an ingress controller. Emissary can function as a fully-fledged Ingress controller, making it easy to work with other Ingress-oriented tools within the Kubernetes ecosystem.
If you’re new to Emissary and to Kubernetes, we’d recommend you start with our quickstart instead of this Ingress guide. If you’re a power user and need to integrate with other software that leverages the Ingress resource, read on. The Ingress specification is very basic and does not support many of the features of Emissary, so you’ll be using both the Ingress resource and Emissary’s Mapping resource to manage your Kubernetes services.
Know what version of Kubernetes you are using.
In Kubernetes 1.13 and below, the Ingress was only included in the extensions
API.
Starting in Kubernetes 1.14, the Ingress was added to the new networking.k8s.io
API.
Kubernetes 1.18 introduced the IngressClass resource to the existing networking.k8s.io/v1beta1
API.
apiVersion: networking.k8s.io/v1beta1
when defining an Ingress. Since both are still supported in all 1.14+ versions of Kubernetes, this document will use extensions/v1beta1
for compatibility reasons.
If you are using 1.18 and above, sample usage of the IngressClass resource and pathType
field are available on our blog.
You will need RBAC permissions to create Ingress resources in either
the extensions
apiGroup
(present in all supported versions of
Kubernetes) or the networking.k8s.io
apiGroup
(introduced in
Kubernetes 1.14).
Emissary will need RBAC permissions to get, list, watch, and update Ingress resources.
You can see this in the aes-crds.yaml
file, but this is the critical rule to add to Emissary’s Role
or ClusterRole
:
- apiGroups: ['extensions', 'networking.k8s.io']
resources: ['ingresses', 'ingressclasses']
verbs: ['get', 'list', 'watch']
- apiGroups: ['extensions', 'networking.k8s.io']
resources: ['ingresses/status']
verbs: ['update']
You must create your Ingress resource with the correct ingress.class
.
Emissary will automatically read Ingress resources with the annotation
kubernetes.io/ingress.class: ambassador
.
You may need to set your Ingress resource’s ambassador-id
.
If you are using amabssador-id
on your Module, you’ll need to add the getambassador.io/ambassador-id
annotation to your Ingress. See the examples below.
You must create a Service resource with the correct app.kubernetes.io/component
label.
Emissary will automatically load balance Ingress resources using the endpoint exposed
from the Service with the annotation app.kubernetes.io/component: ambassador-service
.
---
kind: Service
apiVersion: v1
metadata:
name: ingress-ambassador
labels:
app.kubernetes.io/component: ambassador-service
spec:
externalTrafficPolicy: Local
type: LoadBalancer
selector:
service: ambassador
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
We recommend that Emissary be configured using CRDs. The Ingress resource is available to users who need it for integration with other ecosystem tools, or who feel that it more closely matches their workflows. However, it is important to recognize that the Ingress resource is rather more limited than the Emissary Mapping is (for example, the Ingress spec has no support for rewriting or for TLS origination). When in doubt, use CRDs.
Emissary supports basic core functionality of the Ingress resource, as defined by the Ingress resource itself:
route
specification and the default backend functionality. It’s particularly easy to use a minimal Ingress to the Emissary diagnostic UI.Emissary does not extend the basic Ingress specification with the following exceptions:
The getambassador.io/ambassador-id
annotation allows you to set the Ambassador ID for the Ingress itself.
The getambassador.io/config
annotation can be provided on the Ingress resource, just as on a Service.
Note that if you need to set getambassador.io/ambassador-id
on the Ingress, you will also need to set ambassador-id
on resources within the annotation.
Emissary actually creates Mapping objects from the Ingress route rules. These Mapping objects interact with Mappings defined in CRDs exactly as they would if the Ingress route rules had been specified with CRDs originally.
For example, this Ingress resource routes traffic to /foo/
to service1
:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: ambassador
name: test-ingress
spec:
rules:
- http:
paths:
- path: /foo/
backend:
serviceName: service1
servicePort: 80
This is the equivalent configuration using a Mapping instead:
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: test-ingress-0-0
spec:
hostname: '*'
prefix: /foo/
service: service1:80
This YAML will set up Emissary to do canary routing where 50% of the traffic will go to service1
and 50% will go to service2
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: ambassador
name: test-ingress
spec:
rules:
- http:
paths:
- path: /foo/
backend:
serviceName: service1
servicePort: 80
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: my-mapping
spec:
hostname: '*'
prefix: /foo/
service: service2
An Ingress resource must provide at least some routes or a default backend. The default backend provides for a simple way to direct all traffic to some upstream service:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: ambassador
name: test-ingress
spec:
backend:
serviceName: exampleservice
servicePort: 8080
This is the equivalent configuration using a Mapping instead:
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: test-ingress
spec:
hostname: '*'
prefix: /
service: exampleservice:8080
This Ingress resource will result in all requests to foo.bar.com
going to service1
, and requests to bar.foo.com
going to service2
:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: ambassador
getambassador.io/ambassador-id: externalid
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
This is the equivalent configuration using a Mapping instead:
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: host-foo-mapping
spec:
ambassador_id: ['externalid']
prefix: /
host: foo.bar.com
service: service1
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: host-bar-mapping
spec:
ambassador_id: ['externalid']
prefix: /
host: bar.foo.com
service: service2
Read more on the Kubernetes documentation on name based virtual routing.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: ambassador
name: tls-example-ingress
spec:
tls:
- hosts:
- sslexample.foo.com
secretName: testsecret-tls
rules:
- host: sslexample.foo.com
http:
paths:
- path: /
backend:
serviceName: service1
servicePort: 80
This is the equivalent configuration using a Mapping instead:
---
apiVersion: getambassador.io/v3alpha1
kind: TLSContext
metadata:
name: sslexample-termination-context
spec:
hosts:
- sslexample.foo.com
secret: testsecret-tls
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: sslexample-mapping
spec:
host: sslexample.foo.com
prefix: /
service: service1
Note that this shows TLS termination, not origination: the Ingress spec does not support origination. Read more on the Kubernetes docs on TLS termination.
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.