ListenerClass

A ListenerClass defines a category of listeners. For example, this could be "VPC-internal service", "internet-accessible service", or "K8s-internal service". The ListenerClass then defines how this intent is realized in a given cluster.

For example, a Google Kubernetes Engine (GKE) cluster might want to expose all internet-facing services using a managed load balancer, since GKE nodes are relatively short-lived and don’t have stable addresses:

---
apiVersion: listeners.stackable.tech/v1alpha1
kind: ListenerClass
metadata:
  name: public
spec:
  serviceType: LoadBalancer

On the other hand, an on-premise cluster might not have dedicated load balancer infrastructure at all, but instead use "pet" Nodes which may be expected to live for years. This might lead administrators of such systems to prefer exposing node ports directly instead:

---
apiVersion: listeners.stackable.tech/v1alpha1
kind: ListenerClass
metadata:
  name: public
spec:
  serviceType: NodePort

Finally, it can be desirable to add additional annotations to a Service. For example, a user might want to only expose some services inside a given cloud vendor VPC. How exactly this is accomplished depends on the cloud provider in question, but for GKE this requires the annotation networking.gke.io/load-balancer-type:

---
apiVersion: listeners.stackable.tech/v1alpha1
kind: ListenerClass
metadata:
  name: internal
spec:
  serviceType: LoadBalancer
  serviceAnnotations:
    networking.gke.io/load-balancer-type: Internal

Service types

The service type is defined by ListenerClass.spec.serviceType. The following service types are currently supported by the Stackable Listener Operator:

ClusterIP

The Listener can be accessed from inside the Kubernetes cluster. The Listener addresses will direct clients to the cluster-internal address.

NodePort

The Listener can be accessed from outside the Kubernetes cluster. This may include the internet, if the Nodes have public IP addresses. The Listener address will direct clients to connect to a randomly assigned port on the Nodes running the Pods.

Additionally, Pods bound to NodePort listeners will be pinned to a specific Node. If this is undesirable, consider using LoadBalancer instead.

LoadBalancer

The Listener can be accessed from outside the Kubernetes cluster. This may include the internet, depending on the configuration of the Kubernetes cloud controller manager. A dedicated address will be allocated for the Listener.

Compared to NodePort, this service type allows Pods to be moved freely between Nodes. However, it requires a cloud controller manager that supports load balancers. Additionally, many cloud providers charge for load-balanced traffic.

Default ListenerClasses

The Stackable Data Platform assumes the existence of a few predefined ListenerClasses, and will use them by default as appropriate:

cluster-internal

Used for listeners that are only accessible internally from the cluster. For example: communication between ZooKeeper nodes.

external-unstable

Used for listeners that are accessible from outside the cluster, but which do not require a stable address. For example: individual Kafka brokers.

external-stable

Used for listeners that are accessible from outside the cluster, and do require a stable address. For example: Kafka bootstrap.

Presets

To help users get started, the Stackable Listener Operator ships different ListenerClass presets for different environments. These are configured using the preset Helm value.

stable-nodes

The stable-nodes preset installs ListenerClasses appropriate for Kubernetes clusters that use long-lived "pet nodes". This does not require any particular networking setup, but makes pods that require stable addresses "sticky" to the Kubernetes Node that they were scheduled to. In addition, downstream operators may generate configurations that refer to particular nodes by name.

The following ListenerClasses are installed:

cluster-internal

ClusterIP

external-unstable

NodePort

external-stable

NodePort

ephemeral-nodes

The ephemeral-nodes preset installs ListenerClasses appropriate for Kubernetes clusters that use short-lived "cattle nodes". This makes them appropriate for managed cloud environments, but requires that a LoadBalancer controller is present in the cluster.

Managed cloud environments should generally already provide an integrated LoadBalancer controller. For on-premise environments, an external implementation such as Calico or MetalLB can be used.

K3s' built-in ServiceLB (Klipper) is not recommended, because it doesn’t allow multiple Services to bind the same Port. If you use ServiceLB, use the stable-nodes preset instead.

The following ListenerClasses are installed:

cluster-internal

ClusterIP

external-unstable

NodePort

external-stable

LoadBalancer

none

The none (pseudo-)preset installs no ListenerClasses, leaving the administrator to define them for themself.