Fortinet black logo
7.4.0

Kubernetes Ingress

Kubernetes Ingress

Kubernetes Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

An Ingress can be configured to give Kubernetes services externally reachable URLs, load balance traffic, terminate SSL/TLS, and offer name-based virtual hosting.

It is important to note that to satisfy an Ingress, you must have an Ingress controller (in the example above, FortiWeb Ingress Controller is used). Only creating an Ingress resource would have no effect.

FortiWeb Ingress Controller version 1.0.0 only supports services of type NodePort.

Ingress class

Ingresses can be implemented by different controllers, often with different configurations. Each Ingress should specify an IngressClass name, which is a reference to an IngressClass resource that contains additional configuration including the name of the controller that should implement the class.

For an Ingress that would be implemented by FortiWeb Ingress Controller, please specify the ingressClassName to fwb-ingress-controller in the ingress specification. Upon installation, FortiWeb Ingress Controller is set as the default Ingress controller in the Helm chart value.yaml.

controller:
  ingressClassResource:
    name: "fwb-ingress-controller"
    enabled: true
    default: true
    controllerValue: "fortinet.com/fwb-ingress-controller"

Mapping of the Ingress related resources with the FortiWeb objects

Kubernetes Objects

FortiWeb Objects

Ingress

Virtual server

Content Routing

Scripting

Service

Real Server Pool

Real Server

Node Real Server
Secret

Local Certificate

Local Certificate Group

Client-SSL

Naming rule

For FortiWeb objects created by FortiWeb Ingress Controller, the name of the object is composed of the namespace and the name of the Kubernetes objects. The naming rule is shown below:

FortiWeb Objects

Naming Rule

Virtual server

Real Server Pool

Scripting

Local Certificate

Local Certificate Group

Client-SSL

[namespace of Kubernetes objects]_[name of Kubernetes objects]
Content Routing [namespace of Kubernetes objects]_[name of Kubernetes ingress]_[name of Kubernetes service]
Real Server Name of the Kubernetes node

Ingress types

FortiWeb supports all 5 types of Ingress:

  1. Default backend
  2. Minimal-Ingress
  3. Name-based virtual hosting
  4. Hostname wildcards
  5. TLS

For details on each Ingress type, see https://kubernetes.io/docs/concepts/services-networking/ingress/.

For an example Ingress file, see https://github.com/fortinet/fortiweb-ingress/tree/main/service_examples/.

Ensure the service used in the Ingress is already deployed with NodePort type. Kubernetes does not verify whether the service defined in the Ingress exists or not when deploying an Ingress. So, if you remove the service used in the deployed Ingress, you will not be warned or blocked from this action.

Default backend

An Ingress with no rules sends all traffic to a single default backend. If none of the hosts or paths match the HTTP request in the Ingress objects, the traffic is routed to your default backend. Therefore, if Rules are not specified, defaultBackend must be specified in the Ingress.

Note: FortiWeb Ingress Controller only supports Service backend. A Resource backend is not supported.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-with-default-backend
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-port": "443",
    "fortiweb-ctrl-log" : "enable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }

spec:
  ingressClassName: fwb-ingress-controller
  defaultBackend:
    service:
      name: service1
      port:
        number: 1241

You can add defaultBackend in any particular Ingress. You can check the example here:

https://github.com/fortinet/fortiweb-ingress/blob/main/service_examples/default-http-backend.yaml

Minimal-Ingress

A minimal-Ingress has at least one rule defined in the Ingress with no specified default backend. The following is an example of a minimal-Ingress.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }
spec:
  ingressClassName: fwb-ingress-controller
  rules:
  - host: test.com
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241

Name-based virtual hosting

Name-based virtual hosts support the routing of HTTP/HTTPS traffic to multiple host names at the same IP address.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }
spec:
  ingressClassName: fwb-ingress-controller
  rules:
  - host: test.com
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241
      - path: /hello
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 1242

Hostname wildcards

The hostname can be a precise match or a wildcard. Precise matches require the HTTP host header to match the host field (e.g., foo.bar.com). Wildcard matches require the HTTP host header to be equal to the suffix of the wildcard rule (e.g., *.foo.com).

Refer to the examples below to determine whether an HTTP host header is a wildcard match or not.

Host

Host header

Does it match?

*.foo.com bar.foo.com Yes, it matches based on shared suffix.
*.foo.com baz.bar.foo.com No, it does not match. Wildcard only covers a single DNS label.
*.foo.com foo.com No, it does not match. Wildcard only covers a single DNS label.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wildcard-host
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }

spec:
  ingressClassName: fwb-ingress-controller
  rules:
  - host: "test.com"
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241
  - host: "*.test1.com"
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 1242

TLS

You can secure an Ingress by specifying a Secret that contains a TLS private key and certificate. The Ingress resource only supports a single TLS port, 443, and assumes TLS termination at the Ingress point (traffic to the Service and its Pods is in plain text). If the TLS configuration section in an Ingress specifies different hosts, they are multiplexed on the same port according to the hostname specified through the SNI TLS extension (provided the Ingress controller supports SNI). The TLS secret must contain keys named tls.crt and tls.key that contain the certificate and private key to use for TLS.

For example:

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
type: kubernetes.io/tls

You can create the TLS secret by using the kubectl command, for example:

kubectl create secret tls  tls-example --cert=/etc/ssl/tls.crt --key=/etc/ssl/tls.key

Referencing this secret in an Ingress tells the Ingress controller to secure the channel from the client to the load balancer using TLS. You need to ensure the TLS secret you created came from a certificate that contains a Common Name (CN), also known as a Fully Qualified Domain Name (FQDN) for https-example.foo.com.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-example-ingress
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }

spec:
  ingressClassName: fwb-ingress-controller
  tls:
  - hosts:
    - test.com
    secretName: tls-example
  rules:
  - host: test.com
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241
      - path: /hello
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 1242

Kubernetes Ingress

Kubernetes Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

An Ingress can be configured to give Kubernetes services externally reachable URLs, load balance traffic, terminate SSL/TLS, and offer name-based virtual hosting.

It is important to note that to satisfy an Ingress, you must have an Ingress controller (in the example above, FortiWeb Ingress Controller is used). Only creating an Ingress resource would have no effect.

FortiWeb Ingress Controller version 1.0.0 only supports services of type NodePort.

Ingress class

Ingresses can be implemented by different controllers, often with different configurations. Each Ingress should specify an IngressClass name, which is a reference to an IngressClass resource that contains additional configuration including the name of the controller that should implement the class.

For an Ingress that would be implemented by FortiWeb Ingress Controller, please specify the ingressClassName to fwb-ingress-controller in the ingress specification. Upon installation, FortiWeb Ingress Controller is set as the default Ingress controller in the Helm chart value.yaml.

controller:
  ingressClassResource:
    name: "fwb-ingress-controller"
    enabled: true
    default: true
    controllerValue: "fortinet.com/fwb-ingress-controller"

Mapping of the Ingress related resources with the FortiWeb objects

Kubernetes Objects

FortiWeb Objects

Ingress

Virtual server

Content Routing

Scripting

Service

Real Server Pool

Real Server

Node Real Server
Secret

Local Certificate

Local Certificate Group

Client-SSL

Naming rule

For FortiWeb objects created by FortiWeb Ingress Controller, the name of the object is composed of the namespace and the name of the Kubernetes objects. The naming rule is shown below:

FortiWeb Objects

Naming Rule

Virtual server

Real Server Pool

Scripting

Local Certificate

Local Certificate Group

Client-SSL

[namespace of Kubernetes objects]_[name of Kubernetes objects]
Content Routing [namespace of Kubernetes objects]_[name of Kubernetes ingress]_[name of Kubernetes service]
Real Server Name of the Kubernetes node

Ingress types

FortiWeb supports all 5 types of Ingress:

  1. Default backend
  2. Minimal-Ingress
  3. Name-based virtual hosting
  4. Hostname wildcards
  5. TLS

For details on each Ingress type, see https://kubernetes.io/docs/concepts/services-networking/ingress/.

For an example Ingress file, see https://github.com/fortinet/fortiweb-ingress/tree/main/service_examples/.

Ensure the service used in the Ingress is already deployed with NodePort type. Kubernetes does not verify whether the service defined in the Ingress exists or not when deploying an Ingress. So, if you remove the service used in the deployed Ingress, you will not be warned or blocked from this action.

Default backend

An Ingress with no rules sends all traffic to a single default backend. If none of the hosts or paths match the HTTP request in the Ingress objects, the traffic is routed to your default backend. Therefore, if Rules are not specified, defaultBackend must be specified in the Ingress.

Note: FortiWeb Ingress Controller only supports Service backend. A Resource backend is not supported.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-with-default-backend
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-port": "443",
    "fortiweb-ctrl-log" : "enable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }

spec:
  ingressClassName: fwb-ingress-controller
  defaultBackend:
    service:
      name: service1
      port:
        number: 1241

You can add defaultBackend in any particular Ingress. You can check the example here:

https://github.com/fortinet/fortiweb-ingress/blob/main/service_examples/default-http-backend.yaml

Minimal-Ingress

A minimal-Ingress has at least one rule defined in the Ingress with no specified default backend. The following is an example of a minimal-Ingress.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }
spec:
  ingressClassName: fwb-ingress-controller
  rules:
  - host: test.com
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241

Name-based virtual hosting

Name-based virtual hosts support the routing of HTTP/HTTPS traffic to multiple host names at the same IP address.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }
spec:
  ingressClassName: fwb-ingress-controller
  rules:
  - host: test.com
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241
      - path: /hello
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 1242

Hostname wildcards

The hostname can be a precise match or a wildcard. Precise matches require the HTTP host header to match the host field (e.g., foo.bar.com). Wildcard matches require the HTTP host header to be equal to the suffix of the wildcard rule (e.g., *.foo.com).

Refer to the examples below to determine whether an HTTP host header is a wildcard match or not.

Host

Host header

Does it match?

*.foo.com bar.foo.com Yes, it matches based on shared suffix.
*.foo.com baz.bar.foo.com No, it does not match. Wildcard only covers a single DNS label.
*.foo.com foo.com No, it does not match. Wildcard only covers a single DNS label.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wildcard-host
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }

spec:
  ingressClassName: fwb-ingress-controller
  rules:
  - host: "test.com"
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241
  - host: "*.test1.com"
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 1242

TLS

You can secure an Ingress by specifying a Secret that contains a TLS private key and certificate. The Ingress resource only supports a single TLS port, 443, and assumes TLS termination at the Ingress point (traffic to the Service and its Pods is in plain text). If the TLS configuration section in an Ingress specifies different hosts, they are multiplexed on the same port according to the hostname specified through the SNI TLS extension (provided the Ingress controller supports SNI). The TLS secret must contain keys named tls.crt and tls.key that contain the certificate and private key to use for TLS.

For example:

apiVersion: v1
kind: Secret
metadata:
  name: testsecret-tls
  namespace: default
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
type: kubernetes.io/tls

You can create the TLS secret by using the kubectl command, for example:

kubectl create secret tls  tls-example --cert=/etc/ssl/tls.crt --key=/etc/ssl/tls.key

Referencing this secret in an Ingress tells the Ingress controller to secure the channel from the client to the load balancer using TLS. You need to ensure the TLS secret you created came from a certificate that contains a Common Name (CN), also known as a Fully Qualified Domain Name (FQDN) for https-example.foo.com.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-example-ingress
  annotations: {
    "fortiweb-ip" : "172.23.133.148",
    "fortiweb-login" : "fwb-login1",
    "fortiweb-ctrl-log" : "disable",
    "virtual-server-ip" : "192.23.133.6",
    "virtual-server-addr-type" : "ipv4",
    "virtual-server-interface" : "port2",
    "server-policy-web-protection-profile" : "Inline Standard Protection",
    "server-policy-https-service" : "HTTPS",
    "server-policy-http-service" : "HTTP",
    "server-policy-syn-cookie" : "enable",
    "server-policy-http-to-https" : "disable"
  }

spec:
  ingressClassName: fwb-ingress-controller
  tls:
  - hosts:
    - test.com
    secretName: tls-example
  rules:
  - host: test.com
    http:
      paths:
      - path: /info
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 1241
      - path: /hello
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 1242