Skip to content

david-alexander/nodejs-ingress-controller

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Node.js Ingress Controller

Node.js-based ingress controller for Kubernetes

What is this?

This is an ingress controller for Kubernetes.

Ingress controllers provide access to services running within a Kubernetes cluster, to clients outside the cluster. They can provide features such as SSL termination, authentication, and more. You can think of an ingress controller as the "front door" to your cluster.

This ingress controller is implemented in Node.js. This doesn't mean you can only use it with Node.js applications. However, if you need to add custom functionality to the ingress controller, you will find it easier if you're familiar with Node.js.

Why another ingress controller?

Currently, the most commonly used ingress controller is NGINX Ingress Controller. This works well for many people, and Node.js Ingress Controller does not seek to replace it. Instead, our goals are as follows:

  • Small, auditable codebase: An ingress controller is an important part of the security of your Kubernetes cluster. We think it's important that you can read the entire core codebase of your ingress controller and understand how it works. We keep the core codebase as small as possible, with as few dependencies as possible. (See Trusted Computing Base below.) Modern TypeScript features help us make the code readable and robust.
  • Access to the Node.js ecosystem: Extensions for NGINX are typically written in Lua. While Lua is an excellent language, and has a great ecosystem of its own, many web application developers are more comfortable with Node.js. With Node.js Ingress Controller, if you need to write an extension to add custom functionality, there's a good chance you'll find a library on NPM to do most of the work for you. Over time, we hope to build up a library of useful and high-quality extensions that you can enable with the flip of a switch.
  • Best practices by default: There are some things you'd rather not have to think about. Node.js Ingress Controller aims to handle these things for you, out-of-the-box or with minimal setup required.

Quick start

In most cases, the setup process should be very similar to that of other ingress controllers such as NGINX Ingress Controller. You can even use the two ingress controllers side-by-side if you want (just remember to put the appropriate kubernetes.io/ingress.class annotation on each Ingress to indicate which one you want to use).

The following guide is intended for people who have never set up an ingress controller before. If you already know what you're doing, feel free to do it a different way.

Prerequisites

The only strict prerequisite is that you have a Kubernetes cluster of some sort. However, there are a few other things that you'll probably want to set up, assuming you want your Ingresses to be accessible from the public internet.

  • Your Kubernetes cluster needs to be able to allocate a public IP address to the ingress controller's LoadBalancer Service. Most managed cloud Kubernetes providers will do this for you automatically when you deploy Node.js Ingress Controller to your cluster.
  • You'll want one or more domain names to point at your ingresses. You can either set these up manually (once you have your public IP address) or use something like external-dns to do it automatically. If you're planning on having just one (or a few) registered domains, and a lot of subdomains under them for your various services, you may find it helpful to set up a DNS zone with your cloud provider and then configure external-dns to manage that zone automatically for you.
  • Assuming you're using HTTPS (which you almost always should), you'll need certificates for your hostnames. We recommend installing cert-manager on your cluster, and configuring it to use Let's Encrypt.

Configuring your ingresses

Each Ingress that you want to expose via Node.js Ingress Controller must have the following annotation:

kubernetes.io/ingress.class: nodejs

If you're using cert-manager and Let's Encrypt, you'll also want the following annotations. (Assuming your Issuer is called letsencrypt as per the guide.)

cert-manager.io/cluster-issuer: letsencrypt
cert-manager.io/acme-challenge-type: http01

You should also have the following section in the spec of your Ingress (replace HOSTNAME_GOES_HERE with the hostname, and SECRET_NAME_FOR_TLS_CERT with a unique name for the Secret that the TLS certificate will be stored in).

tls:
  - hosts:
      - HOSTNAME_GOES_HERE
    secretName: SECRET_NAME_FOR_TLS_CERT

Deploying the ingress controller

Node.js Ingress Controller is provided as a Helm chart. You can install it as follows:

  • Build the container image and push it to your container registry:

    cd fs
    docker build . -t YOUR_REGISTRY_HERE/ingress-nodejs-controller
    docker push YOUR_REGISTRY_HERE/ingress-nodejs-controller
    
  • Configure the settings in chart/values.yaml.

  • Deploy the Helm chart to your Kubernetes cluster (here we use the example instance name my-ingress-controller, but you can use whatever name you want here):

    cd chart
    helm install my-ingress-controller .
    

If all goes well, the following steps should happen automatically over the next few minutes. You shouldn't need to do anything while this happens, but it may help to understand the process in case you need to troubleshoot.

  1. The Service called my-ingress-controller-nodejs-ingress-controller will be allocated a public IP address.
  2. The Node.js Ingress Controller will start running, find all Ingresses with the appropriate annotation, and put its public IP address into the .status.loadBalancer.ingress field of each one. This tells Kubernetes that the Ingresses can be reached via this IP address.
  3. Your external-dns instance (if applicable) will see this, and start pointing DNS records at this IP address. (If you're not using external-dns, you'll have to do this step manually.) Now people on the public internet will be able to reach the ingress controller via the relevant hostnames — but your sites are not quite ready yet.
  4. Your HTTPS Ingresses (i.e. those that have a tls section) need to have certificates provisioned. Assuming you're using cert-manager, it will do this for you as follows:
    1. cert-manager sees that an Ingress is configured for HTTPS but does not yet have a certificate.
    2. cert-manager contacts Let's Encrypt to get a "challenge". This is a string that it will use to prove to Let's Encrypt that you control the hostname in question.
    3. cert-manager sets up a special temporary Ingress to serve this challenge at a specific path under your hostname. This is served over HTTP (not HTTPS).
    4. cert-manager does a "self-check" to ensure that the challenge is reachable at the appropriate URL. (This step may fail a few times while the DNS is propagating, but cert-manager will keep retrying until it succeeds.)
    5. cert-manager tells Let's Encrypt that the challenge is reachable. Let's Encrypt checks for the presence of the challenge at the appropriate URL. Upon successful validation of the challenge, Let's Encrypt issues a certificate for the hostname.
    6. cert-manager stores the new certificate in the Secret whose name you specified in the tls section of the Ingress.
  5. When Node.js Ingress Controller sees a valid certificate in a Secret pointed to by an Ingress, it will start using that certificate to serve HTTPS for the Ingress. Your service is now live!

Trusted Computing Base

When thinking about the security (and general code quality) of a system, it is useful to consider the Trusted Computing Base (TCB) of that system. This is the full set of software and hardware that the system relies on.

We think it's important to keep tabs on the TCB of Node.js Ingress Controller to make sure it remains small and auditable as the project evolves. To that end, we document the TCB below. For simplicity, we only cover the software that runs inside the Node.js Ingress Controller container — but you can find discussions of the wider Kubernetes TCB elsewhere. We also do not include indirect NPM dependencies.

Item Purpose Used by component Notes
Alpine Linux v3.11 Operating system All Lightweight base image. Latest major release.
Node.js v14 JS runtime All Current long-term support (LTS) release. Only the core modules listed below are referenced directly.
(http core module) Handles HTTP requests. All
(https core module) Handles HTTPS requests. All
(tls core module) Reads and validates TLS certificates for use by HTTPS server. All
NPM CLI v7 Package manager All Build-time dependency.
TypeScript v4 JS preprocessor / static checker All TODO: Run this at build time.
ts-node Transpiles TS to JS at runtime. All TODO: Remove this and run TS transpiler at build time.
@kubernetes/client-node Kubernetes client library Core, K8sCRDSessionStore
http-proxy Facilitates proxying of HTTP connections to backend servers Core
cookie Parses and generates Cookie/Set-Cookie headers. Used for session management. Core
uuid Generates UUIDs. Used for session management. Core
openid-client Performs OAuth / OIDC flows. OpenIDConnectPlugin

About

Node.js-based ingress controller for Kubernetes

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages