2017-03-31 20:25:41 +00:00
---
2018-02-27 18:51:46 +00:00
reviewers:
2017-03-31 20:25:41 +00:00
- bprashanth
2017-10-25 18:21:46 +00:00
title: Ingress
2018-05-05 16:00:51 +00:00
content_template: templates/concept
2018-06-06 23:51:26 +00:00
weight: 40
2017-03-31 20:25:41 +00:00
---
2018-05-05 16:00:51 +00:00
{{% capture overview %}}
{{< glossary_definition term_id = "ingress" length = "all" > }}
{{% /capture %}}
2017-03-31 20:25:41 +00:00
2018-05-05 16:00:51 +00:00
{{% capture body %}}
2018-06-11 19:38:26 +00:00
## Terminology
2017-03-31 20:25:41 +00:00
2018-11-16 20:37:21 +00:00
For the sake of clarity, this guide defines the following terms:
2017-03-31 20:25:41 +00:00
* Node: A single virtual or physical machine in a Kubernetes cluster.
* Cluster: A group of nodes firewalled from the internet, that are the primary compute resources managed by Kubernetes.
2017-05-12 01:29:58 +00:00
* Edge router: A router that enforces the firewall policy for your cluster. This could be a gateway managed by a cloud provider or a physical piece of hardware.
2018-11-16 20:37:21 +00:00
* Cluster network: A set of links, logical or physical, that facilitate communication within a cluster according to the [Kubernetes networking model ](/docs/concepts/cluster-administration/networking/ ).
2017-04-19 17:56:47 +00:00
* Service: A Kubernetes [Service ](/docs/concepts/services-networking/service/ ) that identifies a set of pods using label selectors. Unless mentioned otherwise, Services are assumed to have virtual IPs only routable within the cluster network.
2017-03-31 20:25:41 +00:00
## What is Ingress?
2018-11-16 20:37:21 +00:00
Ingress, added in Kubernetes v1.1, exposes HTTP and HTTPS routes from outside the cluster to
{{< link text = "services" url = "/docs/concepts/services-networking/service/" > }} within the cluster.
Traffic routing is controlled by rules defined on the ingress resource.
2017-03-31 20:25:41 +00:00
2018-06-11 19:38:26 +00:00
```none
2017-03-31 20:25:41 +00:00
internet
|
[ Ingress ]
--|-----|--
[ Services ]
```
2018-11-16 20:37:21 +00:00
An ingress can be configured to give services externally-reachable URLs, load balance traffic, terminate SSL, and offer name based virtual hosting. An [ingress controller ](#ingress-controllers ) is responsible for fulfilling the ingress, usually with a loadbalancer, though it may also configure your edge router or additional frontends to help handle the traffic.
An ingress does not expose arbitrary ports or protocols. Exposing services other than HTTP and HTTPS to the internet typically
uses a service of type [Service.Type=NodePort ](/docs/concepts/services-networking/service/#nodeport ) or
[Service.Type=LoadBalancer ](/docs/concepts/services-networking/service/#loadbalancer ).
2017-03-31 20:25:41 +00:00
## Prerequisites
2018-11-16 20:37:21 +00:00
{{< feature-state for_k8s_version = "v1.1" state = "beta" > }}
Before you start using an ingress, there are a few things you should understand. The ingress is a beta resource. You will need an ingress controller to satisfy an ingress, simply creating the resource will have no effect.
GCE/Google Kubernetes Engine deploys an [ingress controller ](#ingress-controllers ) on the master. Review the
[beta limitations ](https://github.com/kubernetes/ingress-gce/blob/master/BETA_LIMITATIONS.md#glbc-beta-limitations )
of this controller if you are using GCE/GKE.
In environments other than GCE/Google Kubernetes Engine, you may need to
[deploy an ingress controller ](https://kubernetes.github.io/ingress-nginx/deploy/ ). There are a number of
[ingress controller ](#ingress-controllers ) you may choose from.
## Ingress controllers
In order for the ingress resource to work, the cluster must have an ingress controller running. This is unlike other types of controllers, which run as part of the `kube-controller-manager` binary, and are typically started automatically with a cluster. Choose the ingress controller implementation that best fits your cluster.
* Kubernetes as a project currently supports and maintains [GCE ](https://git.k8s.io/ingress-gce/README.md ) and
[nginx ](https://git.k8s.io/ingress-nginx/README.md ) controllers.
Additional controllers include:
* [Contour ](https://github.com/heptio/contour ) is an [Envoy ](https://www.envoyproxy.io ) based ingress controller
provided and supported by Heptio.
* F5 Networks provides [support and maintenance ](https://support.f5.com/csp/article/K86859508 )
for the [F5 BIG-IP Controller for Kubernetes ](http://clouddocs.f5.com/products/connectors/k8s-bigip-ctlr/latest ).
* [HAProxy ](http://www.haproxy.org/ ) based ingress controller
[jcmoraisjr/haproxy-ingress ](https://github.com/jcmoraisjr/haproxy-ingress ) which is mentioned on the blog post
[HAProxy Ingress Controller for Kubernetes ](https://www.haproxy.com/blog/haproxy_ingress_controller_for_kubernetes/ ).
[HAProxy Technologies ](https://www.haproxy.com/ ) offers support and maintenance for HAProxy Enterprise and
the ingress controller [jcmoraisjr/haproxy-ingress ](https://github.com/jcmoraisjr/haproxy-ingress ).
* [Istio ](https://istio.io/ ) based ingress controller
[Control Ingress Traffic ](https://istio.io/docs/tasks/traffic-management/ingress/ ).
* [Kong ](https://konghq.com/ ) offers [community ](https://discuss.konghq.com/c/kubernetes ) or
[commercial ](https://konghq.com/api-customer-success/ ) support and maintenance for the
[Kong Ingress Controllerfor Kubernetes ](https://konghq.com/blog/kubernetes-ingress-controller-for-kong/ ).
* [NGINX, Inc. ](https://www.nginx.com/ ) offers support and maintenance for the
[NGINX Ingress Controller for Kubernetes ](https://www.nginx.com/products/nginx/kubernetes-ingress-controller ).
* [Traefik ](https://github.com/containous/traefik ) is a fully featured ingress controller
([Let's Encrypt](https://letsencrypt.org), secrets, http2, websocket), and it also comes with commercial
support by [Containous ](https://containo.us/services ).
2017-03-31 20:25:41 +00:00
2018-11-16 20:37:21 +00:00
You may deploy [any number of ingress controllers ](https://git.k8s.io/ingress-nginx/docs/user-guide/multiple-ingress.md#multiple-ingress-controllers ) within a cluster.
When you create an ingress, you should annotate each ingress with the appropriate
[`ingress-class` ](https://git.k8s.io/ingress-gce/examples/PREREQUISITES.md#ingress-class ) to indicate which ingress
controller should be used if more than one exists within your cluster.
If you do not define a class, your cloud provider may use a default ingress provider.
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
### Before you begin
Ideally, all ingress controllers should fulfill this specification, but the various ingress
controllers operate slightly differently.
{{< note > }}
Make sure you review your ingress controller's documentation to understand the caveats of choosing it.
{{< / note > }}
2017-03-31 20:25:41 +00:00
## The Ingress Resource
2018-11-25 07:28:46 +00:00
A minimal ingress resource example:
2017-03-31 20:25:41 +00:00
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
2017-06-12 05:58:12 +00:00
annotations:
2018-03-12 23:04:10 +00:00
nginx.ingress.kubernetes.io/rewrite-target: /
2017-03-31 20:25:41 +00:00
spec:
rules:
- http:
paths:
- path: /testpath
backend:
serviceName: test
servicePort: 80
```
2018-11-25 07:28:46 +00:00
As with all other Kubernetes resources, an ingress needs `apiVersion` , `kind` , and `metadata` fields.
2018-11-16 20:37:21 +00:00
For general information about working with config files, see [deploying applications ](/docs/tasks/run-application/run-stateless-application-deployment/ ), [configuring containers ](/docs/tasks/configure-pod-container/configure-pod-configmap/ ), [managing resources ](/docs/concepts/cluster-administration/manage-deployment/ ).
Ingress frequently uses annotations to configure some options depending on the ingress controller, an example of which
is the [rewrite-target annotation ](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md ).
Different [ingress controller ](#ingress-controllers ) support different annotations. Review the documentation for
2018-11-25 07:28:46 +00:00
your choice of ingress controller to learn which annotations are supported.
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
The ingress [spec ](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status )
2018-11-16 20:37:21 +00:00
has all the information needed to configure a loadbalancer or proxy server. Most importantly, it
contains a list of rules matched against all incoming requests. Ingress resource only supports rules
2018-11-25 07:28:46 +00:00
for directing HTTP traffic.
### Ingress rules
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
Each http rule contains the following information:
2017-03-31 20:25:41 +00:00
2018-11-28 15:46:01 +00:00
* An optional host. In this example, no host is specified, so the rule applies to all inbound
HTTP traffic through the IP address is specified. If a host is provided (for example,
foo.bar.com), the rules apply to that host.
* a list of paths (for example, /testpath), each of which has an associated backend defined with a `serviceName`
2018-11-16 20:37:21 +00:00
and `servicePort` . Both the host and path must match the content of an incoming request before the
2018-11-25 07:28:46 +00:00
loadbalancer will direct traffic to the referenced service.
* A backend is a combination of service and port names as described in the
[services doc ](/docs/concepts/services-networking/service/ ). HTTP (and HTTPS) requests to the
ingress matching the host and path of the rule will be sent to the listed backend.
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
A default backend is often configured in an ingress controller that will service any requests that do not
match a path in the spec.
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
### Default Backend
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
An ingress with no rules sends all traffic to a single default backend. The default
backend is typically a configuration option of the [ingress controller ](#ingress-controllers )
and is not specified in your ingress resources.
2017-03-31 20:25:41 +00:00
2018-11-25 07:28:46 +00:00
If none of the hosts or paths match the HTTP request in the ingress objects, the traffic is
routed to your default backend.
2017-03-31 20:25:41 +00:00
## Types of Ingress
### Single Service Ingress
2018-07-10 15:56:25 +00:00
There are existing Kubernetes concepts that allow you to expose a single Service
2018-11-16 20:37:21 +00:00
(see [alternatives ](#alternatives )). You can also do this with an ingress by specifying a
*default backend* with no rules.
2017-03-31 20:25:41 +00:00
2018-07-10 15:56:25 +00:00
{{< codenew file = "service/networking/ingress.yaml" > }}
2017-03-31 20:25:41 +00:00
If you create it using `kubectl create -f` you should see:
```shell
2018-08-29 07:09:41 +00:00
kubectl get ingress test-ingress
```
```shell
NAME HOSTS ADDRESS PORTS AGE
test-ingress * 107.178.254.228 80 59s
2017-03-31 20:25:41 +00:00
```
2018-11-16 20:37:21 +00:00
Where `107.178.254.228` is the IP allocated by the ingress controller to satisfy
this ingress.
{{< note > }}
2018-11-25 07:28:46 +00:00
Ingress controllers and load balancers may take a minute or two to allocate an IP address.
Until that time you will often see the address listed as `<pending>` .
2018-11-16 20:37:21 +00:00
{{< / note > }}
2017-03-31 20:25:41 +00:00
### Simple fanout
2018-11-25 07:28:46 +00:00
A fanout configuration routes traffic from a single IP address to more than one service,
based on the HTTP URI being requested. An ingress allows you to keep the number of loadbalancers
down to a minimum. For example, a setup like:
2017-03-31 20:25:41 +00:00
```shell
2018-11-16 20:37:21 +00:00
foo.bar.com -> 178.91.123.132 -> / foo service1:4200
/ bar service2:8080
2017-03-31 20:25:41 +00:00
```
2018-11-16 20:37:21 +00:00
would require an ingress such as:
2017-03-31 20:25:41 +00:00
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
2018-11-16 20:37:21 +00:00
name: simple-fanout-example
2017-06-12 05:58:12 +00:00
annotations:
2018-04-12 22:11:59 +00:00
nginx.ingress.kubernetes.io/rewrite-target: /
2017-03-31 20:25:41 +00:00
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
2018-11-16 20:37:21 +00:00
serviceName: service1
servicePort: 4200
2017-03-31 20:25:41 +00:00
- path: /bar
backend:
2018-11-16 20:37:21 +00:00
serviceName: service2
servicePort: 8080
2017-03-31 20:25:41 +00:00
```
2018-11-16 20:37:21 +00:00
When you create the ingress with `kubectl create -f` :
2017-03-31 20:25:41 +00:00
```shell
2018-11-16 20:37:21 +00:00
kubectl describe ingress simple-fanout-example
2018-08-29 07:09:41 +00:00
```
```shell
2018-11-16 20:37:21 +00:00
Name: simple-fanout-example
2018-08-29 07:09:41 +00:00
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
2018-11-16 20:37:21 +00:00
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
2018-08-29 07:09:41 +00:00
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
2017-03-31 20:25:41 +00:00
```
2018-08-29 07:09:41 +00:00
2018-11-16 20:37:21 +00:00
The ingress controller will provision an implementation specific loadbalancer
that satisfies the ingress, as long as the services (`s1`, `s2` ) exist.
2018-08-29 07:09:41 +00:00
When it has done so, you will see the address of the loadbalancer at the
Address field.
{{< note > }}
2018-11-16 20:37:21 +00:00
Depending on the [ingress controller ](#ingress-controllers ) you are using, you may need to
create a default-http-backend [Service ](/docs/concepts/services-networking/service/ ).
2018-08-29 07:09:41 +00:00
{{< / note > }}
2017-03-31 20:25:41 +00:00
### Name based virtual hosting
2018-11-16 20:37:21 +00:00
Name-based virtual hosts support routing HTTP traffic to multiple host names at the same IP address.
2017-03-31 20:25:41 +00:00
2018-06-11 19:38:26 +00:00
```none
2017-03-31 20:25:41 +00:00
foo.bar.com --| |-> foo.bar.com s1:80
| 178.91.123.132 |
bar.foo.com --| |-> bar.foo.com s2:80
```
2018-11-16 20:37:21 +00:00
The following ingress tells the backing loadbalancer to route requests based on
2018-07-10 15:56:25 +00:00
the [Host header ](https://tools.ietf.org/html/rfc7230#section-5.4 ).
2017-03-31 20:25:41 +00:00
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
2018-11-16 20:37:21 +00:00
name: name-virtual-host-ingress
2017-03-31 20:25:41 +00:00
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
2018-11-16 20:37:21 +00:00
serviceName: service1
2017-03-31 20:25:41 +00:00
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
2018-11-16 20:37:21 +00:00
serviceName: service2
2017-03-31 20:25:41 +00:00
servicePort: 80
```
2018-11-25 07:28:46 +00:00
If you create an ingress resource without any hosts defined in the rules, then any
web traffic to the IP address of your ingress controller can be matched without a name based
virtual host being required. For example, the following ingress resource will route traffic
requested for `first.bar.com` to `service1` , `second.bar.com` to `service2` , and any traffic
to the IP address without a hostname defined in request (that is, without a request header being
presented) to `service3` .
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: first.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: second.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
- http:
paths:
- backend:
serviceName: service3
servicePort: 80
```
2017-03-31 20:25:41 +00:00
### TLS
2018-11-16 20:37:21 +00:00
You can secure an ingress by specifying a [secret ](/docs/concepts/configuration/secret )
that contains a TLS private key and certificate. Currently the ingress only
2018-07-10 15:56:25 +00:00
supports a single TLS port, 443, and assumes TLS termination. If the TLS
2018-11-16 20:37:21 +00:00
configuration section in an ingress specifies different hosts, they will be
2018-07-10 15:56:25 +00:00
multiplexed on the same port according to the hostname specified through the
2018-11-16 20:37:21 +00:00
SNI TLS extension (provided the ingress controller supports SNI). The TLS secret
2018-07-10 15:56:25 +00:00
must contain keys named `tls.crt` and `tls.key` that contain the certificate
and private key to use for TLS, e.g.:
2017-03-31 20:25:41 +00:00
```yaml
apiVersion: v1
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
kind: Secret
metadata:
2018-11-16 20:37:21 +00:00
name: testsecret-tls
2017-03-31 20:25:41 +00:00
namespace: default
type: Opaque
```
2018-11-16 20:37:21 +00:00
Referencing this secret in an ingress will tell the ingress controller to
secure the channel from the client to the loadbalancer using TLS. You need to make
sure the TLS secret you created came from a certificate that contains a CN
for `sslexample.foo.com` .
2017-03-31 20:25:41 +00:00
```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
2018-11-16 20:37:21 +00:00
name: tls-example-ingress
2017-03-31 20:25:41 +00:00
spec:
tls:
2018-11-19 18:23:49 +00:00
- hosts:
- sslexample.foo.com
2018-11-16 20:37:21 +00:00
secretName: testsecret-tls
rules:
- host: sslexample.foo.com
http:
paths:
- path: /
backend:
serviceName: service1
servicePort: 80
2017-03-31 20:25:41 +00:00
```
2018-11-16 20:37:21 +00:00
{{< note > }}
There is a gap between TLS features supported by various ingress
2018-07-10 15:56:25 +00:00
controllers. Please refer to documentation on
[nginx ](https://git.k8s.io/ingress-nginx/README.md#https ),
[GCE ](https://git.k8s.io/ingress-gce/README.md#frontend-https ), or any other
2018-11-16 20:37:21 +00:00
platform specific ingress controller to understand how TLS works in your environment.
{{< / note > }}
2017-03-31 20:25:41 +00:00
### Loadbalancing
2018-11-16 20:37:21 +00:00
An ingress controller is bootstrapped with some load balancing policy settings
that it applies to all ingress, such as the load balancing algorithm, backend
2018-07-10 15:56:25 +00:00
weight scheme, and others. More advanced load balancing concepts
(e.g. persistent sessions, dynamic weights) are not yet exposed through the
2018-11-16 20:37:21 +00:00
ingress. You can still get these features through the
2018-08-17 17:00:10 +00:00
[service loadbalancer ](https://github.com/kubernetes/ingress-nginx ).
2018-07-10 15:56:25 +00:00
It's also worth noting that even though health checks are not exposed directly
2018-11-16 20:37:21 +00:00
through the ingress, there exist parallel concepts in Kubernetes such as
2018-07-10 15:56:25 +00:00
[readiness probes ](/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ )
which allow you to achieve the same end result. Please review the controller
specific docs to see how they handle health checks (
[nginx ](https://git.k8s.io/ingress-nginx/README.md ),
[GCE ](https://git.k8s.io/ingress-gce/README.md#health-checks )).
2017-03-31 20:25:41 +00:00
## Updating an Ingress
2018-11-16 20:37:21 +00:00
To update an existing ingress to add a new Host, you can update it by editing the resource:
2017-03-31 20:25:41 +00:00
```shell
2018-08-29 07:09:41 +00:00
kubectl describe ingress test
```
```shell
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo s1:80 (10.8.0.90:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
```
```shell
kubectl edit ingress test
2017-03-31 20:25:41 +00:00
```
2017-09-21 14:00:02 +00:00
This should pop up an editor with the existing yaml, modify it to include the new Host:
2017-03-31 20:25:41 +00:00
```yaml
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: s1
servicePort: 80
path: /foo
- host: bar.baz.com
http:
paths:
- backend:
serviceName: s2
servicePort: 80
path: /foo
..
```
2018-11-16 20:37:21 +00:00
Saving the yaml will update the resource in the API server, which should tell the
ingress controller to reconfigure the loadbalancer.
2017-03-31 20:25:41 +00:00
```shell
2018-08-29 07:09:41 +00:00
kubectl describe ingress test
```
```shell
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo s1:80 (10.8.0.90:80)
bar.baz.com
/foo s2:80 (10.8.0.91:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
2017-03-31 20:25:41 +00:00
```
2018-11-16 20:37:21 +00:00
You can achieve the same by invoking `kubectl replace -f` on a modified ingress yaml file.
2017-03-31 20:25:41 +00:00
## Failing across availability zones
2018-11-16 20:37:21 +00:00
Techniques for spreading traffic across failure domains differs between cloud providers.
Please check the documentation of the relevant [ingress controller ](#ingress-controllers ) for
details. You can also refer to the [federation documentation ](/docs/concepts/cluster-administration/federation/ )
for details on deploying ingress in a federated cluster.
2017-03-31 20:25:41 +00:00
## Future Work
2018-11-16 20:37:21 +00:00
Track [SIG Network ](https://github.com/kubernetes/community/tree/master/sig-network )
for more details on the evolution of the ingress and related resources. You may also track the
[ingress repository ](https://github.com/kubernetes/ingress/tree/master ) for more details on the
evolution of various ingress controllers.
2017-03-31 20:25:41 +00:00
## Alternatives
2018-11-16 20:37:21 +00:00
You can expose a Service in multiple ways that don't directly involve the ingress resource:
2017-03-31 20:25:41 +00:00
2018-08-17 17:00:10 +00:00
* Use [Service.Type=LoadBalancer ](/docs/concepts/services-networking/service/#loadbalancer )
* Use [Service.Type=NodePort ](/docs/concepts/services-networking/service/#nodeport )
2017-06-26 22:40:13 +00:00
* Use a [Port Proxy ](https://git.k8s.io/contrib/for-demos/proxy-to-service )
2018-11-16 20:37:21 +00:00
2018-05-05 16:00:51 +00:00
{{% /capture %}}
2018-06-11 19:38:26 +00:00
{{% capture whatsnext %}}
{{% /capture %}}
2017-10-25 18:18:44 +00:00