Ingress
Ingress (nginx-ingress) routes outside traffic to your apps. It runs the NGINX ingress controller behind one load balancer: an app is reached through it by an Ingress with ingressClassName: nginx, and custom domains route through it. It runs on any cluster and needs no cloud credential; your cloud creates the load balancer in front of it.
When to use it
- You want an image app on a hostname, over HTTPS. Without Ingress, the dry run and the deploy warn Nothing may serve this hostname: "The nginx-ingress add-on isn't installed on this cluster, so unless the cluster runs its own Ingress controller, nothing will serve this application's hostname. Install the nginx-ingress add-on." With it and Certificates, setting the app's domain is enough: AstroPulse writes its Ingress and asks for its certificate. See Put an application on your domain.
- You run several apps and want them behind one load balancer. Without it, each app exposed with
accessType: LoadBalancergets a cloud load balancer of its own. With it, they share one, and NGINX picks each app's certificate by hostname. - You add apps under one domain often. With the wildcard certificate on, a new app one level below the domain needs no certificate of its own. See TLS modes.
- An app must end TLS itself. The
PassthroughTLS mode hands it the encrypted connection on the shared load balancer. - You expose a model on a cluster without the Gateway add-on. Without Ingress, the deploy is refused with Ingress exposure needs the nginx-ingress add-on.
You don't need it when your apps are reached only from inside the cluster, when an app speaks plain TCP (use accessType: LoadBalancer), or when every app you expose is a model behind an access policy, which only the Gateway serves.
Before you start
- A cluster. On a cluster with no cloud load balancer, such as a local or bare-metal one, turn on Enable node port.
- For the wildcard certificate: Certificates with an issuer, and a domain under one of your organization's verified domains.
In the console
After Version, its steps are Settings, Auto scaling and Wildcard certificate, then Advanced and Resources. Review runs the dry run, and Ask Nova at the top of the steps answers about the open step.
-
Open the cluster from the cluster list, select the Add-ons tab, then Install Add-on, and pick Ingress.
-
Keep the defaults for one controller behind a cloud load balancer, or set the settings below. SSL passthrough and Wildcard certificate turn on the TLS modes; its steps also hold Default TLS mode, Exposure, Ingress class name, Enable node port, Replicas, Auto scaling, Node selector and Annotations.
Open zoom view -
On Review, the dry run runs by itself; select Continue to deploy once it passes, then Deploy nginx-ingress.
You should see
The add-on reads Deployed, and its Overview shows the load balancer's address under Access, or the node ports and node addresses with Enable node port on. astroctl infra k8s addons get <cluster> nginx-ingress reports the same. While the load balancer is still being created, Events shows why.
TLS modes
An image application served through Ingress is always HTTPS. Its externalAccess.tls.mode says who presents the certificate:
| Mode | The client sees | Needs on the add-on | Use it for |
|---|---|---|---|
Certificate | A certificate issued for the application's hostname | Nothing (Certificates issues it) | Any application, any hostname |
Wildcard | The add-on's certificate for *.<domain> | Wildcard certificate | Many applications under one domain: nothing is issued per application, so a new one never waits for a certificate |
Passthrough | The application's own certificate | SSL passthrough | An application that must end TLS itself, such as gRPC or MQTT with client certificates |
An application that names no mode gets the add-on's Default TLS mode when that mode covers its hostname, otherwise Certificate. Model applications always use Certificate. Helm, Git repository and YAML applications serve their own Ingress and take no tls field: Expose each source type.
Passthrough needs TLS that carries a server name (SNI). Plain TCP has none: serve it with accessType: LoadBalancer instead. While SSL passthrough is on, NGINX reads the server name of every new connection on port 443, which adds a little latency, so leave it off if no app needs it.
Turn on the wildcard and passthrough
- Open the cluster's Add-ons tab, select Ingress, open Update, then select Change configuration.
- Turn on SSL passthrough if an application will use
Passthrough. - Under Wildcard certificate, turn on Enabled and enter the Domain, such as
apps.example.com, without*.. - Optional: set Default TLS mode. Not set follows the rule above.
- Go to Review: it lists what changes and runs the dry run. Select Continue to apply once it passes, type
nginx-ingress, then select Update nginx-ingress.
The wildcard certificate is astro-wildcard in the ingress-nginx namespace. Security: its private key stays in that namespace and is never copied to the applications it serves; an application can only use a hostname under your verified domains. Let's Encrypt issues a wildcard only through a DNS check, so Certificates needs a DNS solver; an EKS cluster AstroPulse created has one, and anywhere else add identity and dnsSolver to Certificates first. A self-signed issuer issues it at once, and clients must trust it themselves.
The add-on's ingressTls block, in astroctl infra k8s addons get <cluster> nginx-ingress -o yaml, lists the TLS modes the cluster offers, the default mode, the wildcard domain and the app URL shape, and for each mode it does not offer, what turns it on. wildcardWait says why the wildcard certificate is not issued yet, and wildcardStale says Certificates changed its issuer since this add-on was applied: apply Ingress again.
One application per mode
In the console, an image app's Access step in the deploy wizard sets its domain under External access, then its TLS mode: Add-on default, Certificate, Wildcard or Passthrough. A mode the cluster does not offer is turned off, with what turns it on. On a running app, its Update tab changes TLS mode and keeps the domain.
- certificate
- wildcard
- passthrough
apiVersion: platform.astropulse.io/v1
kind: Application
metadata:
name: shop
spec:
profileName: production
source:
type: Image
image:
repository: nginxinc/nginx-unprivileged
tag: 1.27-alpine
port: 8080
externalAccess:
hostname: shop.example.com
tls:
mode: Certificate
Serves https://shop.example.com with a certificate issued for shop.example.com.
apiVersion: platform.astropulse.io/v1
kind: Application
metadata:
name: docs
spec:
profileName: production
source:
type: Image
image:
repository: nginxinc/nginx-unprivileged
tag: 1.27-alpine
port: 8080
externalAccess:
hostname: docs.apps.example.com
tls:
mode: Wildcard
Serves https://docs.apps.example.com with the certificate for *.apps.example.com. The hostname must be one level below the wildcard domain.
apiVersion: platform.astropulse.io/v1
kind: Application
metadata:
name: tls-echo
spec:
profileName: production
source:
type: Image
image:
repository: mendhak/http-https-echo
tag: "43"
port: 8443
externalAccess:
hostname: tls-echo.example.com
tls:
mode: Passthrough
tls-echo.example.com:443 is forwarded unopened to the container's port 8443, which must serve TLS, so the client sees the application's own certificate. The profile's request limits do not apply, because NGINX does not read the traffic.
The dry run says where each application will be served and which certificate it presents, for example "Your app will be at https://shop.example.com, presenting a certificate issued for shop.example.com."
Three applications on one load balancer
With both the wildcard and passthrough on, the three applications above share one load balancer, and NGINX picks the certificate by hostname. Check what each one presents (-ext needs OpenSSL 1.1.1 or later):
for host in shop.example.com docs.apps.example.com tls-echo.example.com; do
echo | openssl s_client -connect "$host:443" -servername "$host" 2>/dev/null \
| openssl x509 -noout -issuer -ext subjectAltName
done
Change an application's mode
Change externalAccess.tls.mode and apply again. Each change is a new version, so a rollback returns to the earlier mode. Moving off Certificate removes the application's own certificate; moving back issues it again.
Turning the wildcard on moves every application that names no mode, and whose hostname it covers, onto the wildcard at that application's next deploy that changes something. To keep an application on its own certificate, set tls.mode: Certificate on it, or set Default TLS mode to Certificate on the add-on.
Behavior and limits
- An Ingress of your own with a
tlsblock gets HTTPS from NGINX; pair it with Certificates to issue and renew the certificate (Automatic HTTPS). With the wildcard on, an Ingress that lists a host one level below the wildcard domain underspec.tls, with nosecretName, is served the wildcard certificate. - Enable node port is for clusters without a cloud load balancer, such as kind and bare metal.
exposuredecides who can reach the load balancer, and so every Ingress it serves:Public, the internet (the default), orPrivate, only the cluster's network. In the console, Exposure. Security: setPrivatewhen no app on the cluster should be reachable from the internet.
Run it in production
Every request into the cluster's Ingresses passes through it, so treat it as critical.
- Two copies. The controller runs 2 copies on a cluster AstroPulse created with 2 or more fixed nodes, and 1 otherwise. With Enabled on under Auto scaling, set Min replicas to 2 or more, or it can scale down to one pod.
- While it is down, traffic through it stops, and new or changed Ingresses are refused.
- Changing Exposure replaces the load balancer. Moving between public and private creates a new load balancer with a new address. Plan the DNS change first.
- The load balancer is billed by your cloud (a Network Load Balancer on AWS) for as long as the add-on is installed.
- It grows with traffic. The controller reserves 100m CPU and 384Mi memory, with no memory limit. Raise Resources as traffic grows: Availability and resources.
Other ways in
- Nova: ask it, for example "install Ingress on eks-prod with the wildcard certificate for apps.example.com".
- SDK and API: the same operations, in the API reference.
With astroctl
apiVersion: platform.astropulse.io/v1
kind: K8sClusterAddon
metadata:
name: nginx-ingress
spec:
clusterName: eks-prod
configuration:
nginx:
sslPassthrough: true
wildcardCertificate:
enabled: true
domain: apps.example.com
astroctl infra k8s addons apply -f nginx-ingress.yaml --dry-run
astroctl infra k8s addons apply -f nginx-ingress.yaml
astroctl infra k8s addons template <cluster> nginx-ingress writes every setting with what it does.
Settings
Its own settings, under nginx, plus availability and resources. Every one is optional.
nginx.sslPassthroughLets applications that serve their own TLS receive it still encrypted: an image application using TLS mode Passthrough, or an Ingress of your own annotated nginx.ingress.kubernetes.io/ssl-passthrough. Every other application's TLS ends at the controller.
nginx.wildcardCertificate.enabledIssues one certificate for a domain and every name one level below it, and serves it to applications using TLS mode Wildcard. Needs Certificates.
nginx.wildcardCertificate.domainThe domain the certificate covers, without *.: apps.example.com covers apps.example.com and every name one level below it. Required with the wildcard on.
nginx.defaultTlsModeThe TLS mode an application gets when it names none.
Certificate, Wildcard or Passthrough.Wildcard while the wildcard certificate is on, otherwise Certificate.nginx.exposureWho can reach the controller's load balancer, and so every Ingress it serves.
PublicPublic Reachable from the internet.PrivatePrivate Reachable only from inside the cluster's network.
Public
nginx.enableNodePortPublishes the controller on a NodePort instead of a cloud load balancer, for clusters that have none.
nginx.ingressClassNameThe class this controller answers to.
nginx.nginx.replicasHow many controller pods to run.
nginx.autoScalingScales the controller itself with load: enabled, minReplicas, maxReplicas and targetCPUPercent, the CPU use replicas are scaled to hold.
nginx.nodeSelectorConfines the controller to matching nodes.
key=value, for example disktype=ssd.nginx.annotationsAdded to the controller's Service, for the load balancer settings your cloud reads from there.
If it's refused
apps.example.com.Wildcard with the wildcard off.Certificate.These come on an application's dry run and apply, on externalAccess.tls:
Wildcard, and the add-on's wildcard is off.Certificate.Certificate.Certificate.Certificate.tls from the model, or set Certificate.Passthrough.Certificate, or remove tls.externalAccess.tls.tls: these applications serve their own Ingress.