K8s Ingress with NSX Advanced Load Balancer

Overview

Abbreviations used in this article:

  • NSX Advanced Load Balancer = NSX-ALB
  • K8s = Kubernetes (8 letters between the K and s in Kubernetes)
  • SSL = Secure Sockets Layer
  • AKO = Avi Kubernetes Operator (AVI now a VMware product called NSX Advanced Load Balancer)

In one of my previous posts I wrote about how to install and configure AKO (Avi Kubernetes Operator) to use as Service type LoadBalancer.

This post will try to cover the basics of how to use NSX Advanced LoadBalancer by using AKO to handle our Ingress requests (ingress-controller).
For more information on Ingress in Kubernetes

An API object that manages external access to the services in a cluster, typically HTTP.
Ingress may provide load balancing, SSL termination and name-based virtual hosting.

Ingress Load Balancer Kubernetes Definition

Within Kubernetes or K8s, a collection of routing rules that control how Kubernetes cluster services are accessed by external users is called ingress. Managing ingress in Kubernetes can take one of several approaches.

An application can be exposed to external users via a Kubernetes ingress resource; a Kubernetes NodePort service which exposes the application on a port across each node; or using an ingress load balancer for Kubernetes that points to a service in your cluster.

An external load balancer routes external traffic to a Kubernetes service in your cluster and is associated with a specific IP address. Its precise implementation is controlled by which service types the cloud provider supports. Kubernetes deployments on bare metal may require custom load balancer implementations.

However, properly supported ingress load balancing for Kubernetes is the simplest, more secure way to route traffic. link

Diagram depicts SSL Termination being performed at the secure socket layer (ssl) via a load blancer between application users and application web servers.

Getting AKO ready

While this post assumes AKO is already in place and working in your k8s clusters I will get straight to the parts that involve Ingress. If not head over here to read the official docs how to install Avi Kubernetes Operator (AKO). To verify that you AKO is ready to handle Ingress request, type in this and notice the output:

1$ kubectl get ingressclasses.networking.k8s.io 
2NAME     CONTROLLER              PARAMETERS   AGE
3avi-lb   ako.vmware.com/avi-lb   <none>       50d

Default secret for TLS Ingress

As AKO expects all ingresses with TLS termination to have a key and certificate specified, there is a couple of ways this can be done. We can go with a "pr service", meaning a dedicated set of keys and certs pr service or a default/common set of keys and certificates that AKO can use if nothing else is specified. To apply the common approach, one common key and certificate for one or more applications we need to add a secret for the AKO. Prepare your router-default.yaml definition file like this (the official docs wants you to put in your cert as is, that does not work so you need to base64 encode both keys and certs and paste in below):

 1apiVersion: v1
 2kind: Secret
 3metadata:
 4  name: router-certs-default
 5  namespace: avi-system
 6type: kubernetes.io/tls
 7data:
 8  tls.key: "base64 encoded"
 9  tls.crt: "base64 encoded"
10  alt.key: "base64 encoded"
11  alt.crt: "base64 encoded"
12  

To base64 encode your keys and certs this can be done like this:

If you have the keys and certs in a file, from whatever linux terminal type in:

1cat cert.pem | base64 -w 0 
2cat key.pem | base64 -w 0

Then paste into the above yaml accordingly (tls.key:key, tls.crt:crt) If you have both ECDSA and RSA certs use the alt.key and alt.crt to apply both. As soon as everything is pasted, apply the yaml file kubectl apply -f router-defaults.yaml

Apply your ingress service

To create an ingress service you need to define this in yaml. An example below:

 1apiVersion: networking.k8s.io/v1
 2kind: Ingress
 3metadata:
 4  name: "NameOfIngress-Service"
 5  namespace: "Namespaceofwhereyour-service-resides"
 6  labels:
 7    app: "ifyouwant"
 8  annotations:
 9    ako.vmware.com/enable-tls: "true" #"Indicates to Avi that you want to use TLS"
10spec:
11  ingressClassName: avi-lb #"The default class name for AVI"
12  rules:
13    - host: "FQDN"
14      http:
15        paths:
16        - pathType: Prefix
17          path: /
18          backend:
19            service:
20              name: "which-service-to-point-to"
21              port:
22                number: 80

Hostrules and HTTPrules

As I mentioned earlier, you can also define specific rules pr server such as certificates. Here we can use Hostrules and HTTPrules to further adjust granular settings pr service. One Hostrule example below:

 1apiVersion: ako.vmware.com/v1alpha1
 2kind: HostRule
 3metadata:
 4  name: name-of-your-rule
 5  namespace: namespace-of-your-service
 6spec:
 7  virtualhost:
 8    fqdn: must-match-hostname-above # mandatory
 9    fqdnType: Exact
10    enableVirtualHost: true
11    tls: # optional
12      sslKeyCertificate:
13        name: "name-of-certificate" # This must be already defined in your AVI controller
14        type: ref
15        alternateCertificate:
16          name: "name-of-alternate-cert" # This must be already defined in your AVI controller
17          type: ref
18      sslProfile: System-Standard-PFS
19      termination: edge

To get all features available head over to the official docs site here

Hostrule example from the official docs:

 1apiVersion: ako.vmware.com/v1alpha1
 2kind: HostRule
 3metadata:
 4  name: my-host-rule
 5  namespace: red
 6spec:
 7  virtualhost:
 8    fqdn: foo.region1.com # mandatory
 9    fqdnType: Exact
10    enableVirtualHost: true
11    tls: # optional
12      sslKeyCertificate:
13        name: avi-ssl-key-cert
14        type: ref
15        alternateCertificate:
16          name: avi-ssl-key-cert2
17          type: ref
18      sslProfile: avi-ssl-profile
19      termination: edge
20    gslb:
21      fqdn: foo.com
22      includeAliases: false
23    httpPolicy: 
24      policySets:
25      - avi-secure-policy-ref
26      overwrite: false
27    datascripts:
28    - avi-datascript-redirect-app1
29    wafPolicy: avi-waf-policy
30    applicationProfile: avi-app-ref
31    analyticsProfile: avi-analytics-ref
32    errorPageProfile: avi-errorpage-ref
33    analyticsPolicy: # optional
34      fullClientLogs:
35        enabled: true
36        throttle: HIGH
37      logAllHeaders: true
38    tcpSettings:
39      listeners:
40      - port: 8081
41      - port: 6443
42        enableSSL: true
43      loadBalancerIP: 10.10.10.1
44    aliases: # optional
45    -  bar.com
46    -  baz.com

Httprule example from the official docs:

 1apiVersion: ako.vmware.com/v1alpha1
 2kind: HTTPRule
 3metadata:
 4   name: my-http-rule
 5   namespace: purple-l7
 6spec:
 7  fqdn: foo.avi.internal
 8  paths:
 9  - target: /foo
10    healthMonitors:
11    - my-health-monitor-1
12    - my-health-monitor-2
13    loadBalancerPolicy:
14      algorithm: LB_ALGORITHM_CONSISTENT_HASH
15      hash: LB_ALGORITHM_CONSISTENT_HASH_SOURCE_IP_ADDRESS
16    tls: ## This is a re-encrypt to pool
17      type: reencrypt # Mandatory [re-encrypt]
18      sslProfile: avi-ssl-profile
19      destinationCA:  |-
20        -----BEGIN CERTIFICATE-----
21        [...]
22        -----END CERTIFICATE-----