Kubernetes NGINX Ingress: 10 Useful Configuration Options

Sanni Michael
Nov 8, 2021
8 Minute Read

An ingress is a Kubernetes object that provides routing rules that are used for managing external access to the services in a cluster. Ingress makes it easy to define routing rules, paths, name-based virtual hosting, domains or subdomains, and tons of other functionalities for dynamically accessing your applications. But how do you keep track of all these rules, and what happens when you modify an ingress resource or add a new rule? That’s where an ingress controller comes in.

An ingress controller is an implementation of ingress that is tasked with constantly evaluating all the rules defined in your cluster, managing all redirections, and determining where to direct traffic based on the rules defined in the ingress resource. Ingress controllers do not come installed in a Kubernetes cluster by default, so you have to set one up yourself. There are several implementations of ingress controllers available today; you can check them out here.

In this article, you will learn about NGINX ingress controllers and ten useful configuration options you can add to make your application more dynamic.

#Evaluating Configuration Options

There are several types of configuration options that can be applied on Kubernetes’s ingress resources via annotations or ConfigMaps. This list was compiled by researching frequently used options in production systems, gathering detailed online information on ingress controllers, and considering several issues users face on Stack Overflow when setting up and configuring ingress resources and controllers. While this article focuses on only ten configuration options, you can review the other options here.

#Ingress Controller Configuration Categories

The NGINX ingress controller has additional configuration options that can be customized and configured to create a more dynamic application. Basically, this can be done in two ways:

  • Annotations: this option can be used if you want a specific configuration for a particular ingress rule.
  • ConfigMap: this option can be used when you need to set global configurations for the NGINX ingress controller.

Note: annotations take precedence over a ConfigMap.

#Useful Configurations

Now, consider the following configuration options for use in your application.

#WWW Redirects

There are a variety of scenarios where you may want to redirect from www.domain.com to domain.com or vice versa. To enable this feature, add the following annotation:

nginx.ingress.kubernetes.io/from-to-www-redirect: "true"

The resource would look like this:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
  rules:
  - host: domain.com
    http:
      paths:
      - backend:
          serviceName: service-www-redirect
          servicePort: 4000

When using a www-redirect, note the following:

  • If a new ingress is created at some point with the host equal to the one above, the annotation will be omitted.
  • For HTTPS to HTTPS redirects, it’s mandatory to define the SSL Certificate in the Secret and add the TLS section of the ingress.

Read more about www-redirects here.

#SSL Redirects

SSL redirects are useful for redirecting traffic from HTTP to HTTPS. If this rule is added in the TLS section of the ingress definition, the NGINX controller will redirect (301) to HTTPS. You can disable this rule by adding the following:

nginx.ingress.kubernetes.io/ssl-redirect: "false"

On the other hand, you can enforce a redirect to HTTPS even when no TLS certificate is available in the case of SSL off-loading. This can be done by using the following:

nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

You can also preserve the trailing slash in the URI with ssl-redirect. Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/preserve-trailing-slash: "true"
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

#Timeout Settings

There are also several timeout settings you can configure in the ingress resource using annotations:

  • proxy-connect-timeout: this defines the timeout for establishing a connection with a proxied server. The default value is 60 seconds, and the timeout typically cannot exceed 75 seconds. Check here for more information.
  • proxy-send-timeout: this will set a timeout for transmitting a request to the proxied server. The timeout is set only between two successive write operations, not for the transmission of the whole request. According to NGINX ingress documentation, if the proxied server does not receive anything within this time, the connection is closed.

For example, you can add timeout settings to your ingress resource, like the following:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress-with-annotations
  annotations:
    nginx.org/proxy-connect-timeout: "30s"
    nginx.org/proxy-read-timeout: "20s"
spec:
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        backend:
          serviceName: tea-svc
          servicePort: 80
      - path: /coffee
        backend:
          serviceName: coffee-svc
          servicePort: 80

Read more about the various timeout settings available here.

#CORS

You can also enable cross-origin resource sharing (CORS) in an ingress rule. This allows you to control the methods, headers, origins of requests, and other elements that are allowed to make requests to your cluster. There are several options that can also be activated when CORS is enabled on the ingress resource; for example, the origin of request, the exposed headers, and so forth. To activate CORS on ingress, add the enable-cors annotation on the ingress. Here’s an example:

nginx.ingress.kubernetes.io/enable-cors: "true"

There are other annotations you can use to control the CORS behavior:

nginx.ingress.kubernetes.io/cors-allow-methods # controls method accepted
nginx.ingress.kubernetes.io/cors-allow-headers # controls allowed headers

Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-headers: "X-Forwarded-For, X-app123-XPTO"
    nginx.ingress.kubernetes.io/cors-expose-headers: "*, X-CustomResponseHeader"
    nginx.ingress.kubernetes.io/cors-max-age: 600
    nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

You can read more about how to control the CORS functionality here.

#Rate Limiting

Rate-limiting annotations are useful for defining limits on connections and transmission rates. They can be very helpful for mitigating DDoS attacks.

  • nginx.ingress.kubernetes.io/limit-connections: this defines the number of concurrent connections allowed from an IP address.
  • nginx.ingress.kubernetes.io/limit-rps: rps stands for “request per second”, and it is used to define the number of connections that may be accepted from an IP per second.

Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "5"
    nginx.ingress.kubernetes.io/limit-rpm: "300"
    nginx.ingress.kubernetes.io/limit-connections: "10"
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

Note: when you specify both annotations in a single ingress resource, limit-rps takes precedence. Read more about rate-limiting ingress resources here.

#Custom Max Body Size

This rule can be used to set the maximum size of the body in a request. If the body exceeds the maximum size set, NGINX will return a 413 error to the client.

The body size can be configured by using the following:

nginx.ingress.kubernetes.io/proxy-body-size: 8m

Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 8m
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test

#Whitelist Source Range

It is also possible to whitelist the allowed IPs from the client. This means you can configure an ingress resource to only allow requests from a particular IP address. This feature can prevent unknown or unauthorized requests from reaching your cluster.

To specify whitelist source range, use the annotation below:

nginx.ingress.kubernetes.io/whitelist-source-range

Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
     ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/24,172.10.0.1"
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test

Note: you can run into an issue where the whitelisted IP can’t access the resource. In this case, you may need to enable externalTrafficPolicy in your service definition. Review this answer on Stack Overflow for more information.

#Default Backend

The default backend is used for handling an unknown request or a request that is not mapped to any path or host in the ingress resource. If you don’t define this service and enter a path not mapped, it returns an HTTP 404 (page not found) error. To fix this issue, create a service and map it to the default backend. This can be used to show custom 404 pages and error messages.

To configure this rule, add an annotation:

nginx.ingress.kubernetes.io/default-backend: <svc name>

Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
     nginx.ingress.kubernetes.io/default-backend: <svc name>
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test

#Enable Access Log

Access logs allow you to view information about client requests. NGINX writes the logs in a file once the request has been processed. They are enabled by default in NGINX, but they may need to be disabled for a given ingress. To do this, use this annotation:

nginx.ingress.kubernetes.io/enable-access-log: "false"

Here’s an example:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
     nginx.ingress.kubernetes.io/enable-access-log: "false"
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test

#Backend Protocol

You can use the backend protocol to specify how NGINX should communicate with the backend service. Valid values include HTTP, HTTPS, GRPC, GRPCS, AJP, and FCGI. By default, NGINX uses HTTP.

Here’s an example:

nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

#Conclusion

The NGINX ingress controller makes it easy to configure the rules and set up a more dynamic application for handling requests and responses from the client. This makes NGINX a great choice for ingress controllers with the available number of configurations and settings that can be applied to your ingress resource. In this article, you have learned what an ingress is, what the role of an ingress controller is, and how you can configure your ingress rules to be more dynamic. Learn more about configuring ingress resources here.

Photo by Denys Nevozhai on Unsplash

Guides
Kubernetes Insights
Tools
Tutorials

Do you want early access to great articles like this one?

Thank you for subscribing!
Oops! Something went wrong while submitting the form.

Explore Other Articles