Kubernetes Ingress Virtual Service Configuration

In an Kubernetes cloud, Kubernetes ingress creation triggers creation of north-south or ingress Avi Vantage VirtualService and Pool objects. OpenShift/Kubernetes Service Configuration in Avi Vantage explains how Kubernetes services map to Avi Vantage’s VirtualService and Pool objects. This article explains how Kubernetes ingresses trigger VirtualService and Pool object creation in Avi Vantage.

Note: Support for Ingresses is available beginning 17.2.3 in the 17.2 release series.

Kubernetes Ingresses to Avi Vantage Object Mapping

Kubernetes ingresses can be configured in one of two ways as far as virtual IPs are concerned.

  • Dedicated virtual IP per ingress: Each Kubernetes ingress is allocated its own VirtualService/Pool objects and a virtual IP (VIP). This provides the best performance, availability and isolation, but consumes an IP address per route.
  • Shared virtual service across multiple ingresses: Each Kubernetes ingress is tied to a pre-created parent shared virtual service and will use the shared virtual service’s virtual IP. This conserves IP addresses, but provides variable performance, no isolation, and shares fate with all sibling routes. A parent shared virtual service is pre-created with HTTP/HTTPS application profiles with listeners on ports 80 and 443 for every Service Engine group configured in the cloud. The parent virtual service’s name is of the form parent-vs-SEGroupname-Cloudname.

NB: Support for shared virtual services is available beginning 17.2.3 in the 17.2 release series.

The following table maps each type of Kubernetes ingress to Avi Vantage objects.

Kubernetes ingress Avi Vantage Object Comment
Dedicated virtual service per ingress VirtualService, Pool Every ingress creates a VirtualService, Pool object. Ingress annotation avi_proxy: '{"dedicated_route": true}' creates a dedicated virtual service (that uses a VIP) per ingress in shared VirtualService Projects/Namespaces. Layer4 (TCP, UDP) ingresses require a dedicated VIP per ingress
Shared virtual service: HTTP Virtual Hosting ingresses Pool HTTP policy is used in parent virtual service to switch host/path to the appropriate pool.
Shared virtual service: HTTPS ingresses Child virtual hosted/SNI VirtualService, Pool SNI is used to route traffic to the appropriate child VirtualService/Pool.

Shared Virtual Service Mode Configuration

shared namespace configuration

  • Field shared_virtualservice_namespace configures the cloud to operate in either dedicated or shared VS mode. Check or uncheck Use Shared Virtual Service in the UI above during cloud configuration. Enabling shared_virtualservice_namespace uses the shared parent virtual service for all ingresses in all namespaces by default. Disabling shared_virtualservice_namespace creates a dedicated virtual service per ingress in all namespaces by default.
  • Changing this mode is disruptive and can be time consuming with a large number of ingresses; hence, it is recommended that this be configured once at initial cloud configuration time.
  • Individual namespaces can be overriden to operate in either shared or dedicated modes using the avi_virtualservice: shared|dedicated namespace annotation.
    • If shared_virtualservice_namespace is enabled for the cloud, namespace annotation avi_virtualservice: dedicated creates dedicated virtual services for all ingresses in the namespace.
    • On the contrary, if shared_virtualservice_namespace is disabled for the cloud, namespace annotation avi_virtualservice: shared uses the shared virtual service for all ingresses in the namespace.
  • Every ingress can be overriden to create a dedicated virtual service for itself, even if the cloud or the namespace is operating in the shared mode. Ingress annotation avi_proxy: '{"dedicated_route": true}' creates a dedicated virtual service for that ingress. The most common use case for dedicated virtual service is for non-HTTP(S) layer 4 (TCP, UDP) ingresses.

Ingress Configuration Examples

NB: The following examples assume the following cloud configuration.

  • http_container_ports is configured with 80, 8080.
  • A Network object is created with an IP address pool for north-south VIPs; a north-south IPAM profile is created and linked to the Network object and the cloud is linked to the north-south IPAM profile.
  • A Network object is created with a IP address pool for east-west VIPs; an east-west IPAM profile is created and linked to the Network object and the cloud is linked to the east-west IPAM profile.

Sample Deployment and Service

The following deployment and service are examples for deploying HTTP pods.

Sample deployment configuration in YAML format.


kind: Deployment
apiVersion: apps/v1beta2
metadata:
  name: avitest-deployment
  labels:
    app: avitest
spec:
  replicas: 2
  selector:
    matchLabels:
      app: avitest
  template:
    metadata:
      labels:
        app: avitest
    spec:
      containers:
      - name: avitest
        image: avinetworks/server-os
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP

Sample service file to create an east-west service in YAML format.


kind: Service
apiVersion: v1
metadata:
  name: avisvc
  labels:
    svc: avisvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: avitest

Since default_service_as_east_west_service is enabled in the cloud configuration, this service creates an east-west virtual service.

If HTTPS pods are deployed, containerPort is usually 443 or 8443 and service port is 443 or 8443.

Sample Ingresses

Dedicated VIP for HTTP Ingress

In this case shared_virtualservice_namespace is disabled in the cloud and namespace does not have the avi_virtualservice: shared annotation.

The following sample ingress file creates a http ingress with a dedicated VIP for service avisvc.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: aviingress
spec:
  rules:
  - host: aviingress1.default.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc1
          servicePort: 80
        path: /foo
      - backend:
          serviceName: avisvc2
          servicePort: 80
        path: /bar
  - host: aviingress2.default.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc3
          servicePort: 80

This dedicated virtual service ingress will create its own virtual service and pool with its dedicated VIP. VirtualService name is of the form ingressname.dns_sub_domain. In the example above, a VirtualService called aviingress.default.acme.local will be created.

Shared VIP for HTTP Ingress

In this case either shared_virtualservice_namespace is enabled in the cloud or namespace has the avi_virtualservice: shared annotation.

The following sample ingress file creates a HTTP route associated with parent virtual service parent-vs-Default-Group-Default-Cloud for service avisvc.


apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: aviingress
spec:
  rules:
  - host: aviingress1.default.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc1
          servicePort: 80
        path: /foo
      - backend:
          serviceName: avisvc2
          servicePort: 80
        path: /bar
  - host: aviingress2.default.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc3
          servicePort: 80

The HTTP application will be created as a poolgroup and pool for the parent virtual service. Pool name will be of the form namespace-host--path-aviroute-pool-port-protocol. For example, ingress with host aviingress1.default.acme.local and path /foo in namespace default will have a pool name default-aviingress1.default.acme.local--foo-aviroute-pool-http-tcp. For the HTTP Ingress object above, 3 Pools will be created for the 3 Services. An HTTP policy will provide host/path switching for the pool.

Dedicated VIP for HTTPS with Edge Termination

In this case shared_virtualservice_namespace is enabled in the cloud but namespace has the avi_virtualservice: dedicated annotation.

The avi_virtualservice: dedicated namespace annotation overrides the shared_virtualservice_namespace cloud configuration and creates dedicated virtual services for all routes in the namespace.

Namespace looks as follows.

apiVersion: v1
kind: Namespace
metadata:
  annotations:
    avi_virtualservice: dedicated
  name: ns1
spec:
  finalizers:
  - kubernetes
status:
  phase: Active

The following sample ingress file creates a HTTPS ingress with edge termination with a dedicated VIP.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: aviingress
spec:
  rules:
  - host: aviingress1.ns1.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc1
          servicePort: 80
        path: /foo
  - host: aviingress2.ns1.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc2
          servicePort: 80
  tls:
    - secretName: aviingress1cert
      hosts:
      - aviingress1.ns1.acme.local
    - secretName: aviingress2cert
      hosts:
      - aviingress2.ns1.acme.local
  backend:
    serviceName: avisvc3
    servicePort: 80

This dedicated virtual service ingress will create its own virtual service with its dedicated VIP. VirtualService name is of the form ingressname.dns_sub_domain. In the example above, a VirtualService called aviingress.ns1.acme.local will be created. 2 child SNI VirtualServices called ns1-aviingress-aviingress1cert will also be created. SNI child VirtualServices will be of the form namespace-ingressname-certificatename.

Shared VIP for HTTPS with Edge Termination

In this case shared_virtualservice_namespace is enabled in the cloud.

The following sample ingress file creates a HTTPS ingress with edge termination with a dedicated VIP.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: aviingress
spec:
  rules:
  - host: aviingress1.ns1.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc1
          servicePort: 80
        path: /foo
  - host: aviingress2.ns1.acme.local
    http:
      paths:
      - backend:
          serviceName: avisvc2
          servicePort: 80
  tls:
    - secretName: aviingress1cert
      hosts:
      - aviingress1.ns1.acme.local
    - secretName: aviingress2cert
      hosts:
      - aviingress2.ns1.acme.local
  backend:
    serviceName: avisvc3
    servicePort: 80

The above ingress will create 2 child SNI VirtualServices for the parent VirtualService called ns1-aviingress-aviingress1cert. SNI child VirtualServices will be of the form namespace-ingressname-certificatename.

Automatic Configuration

The following fields in the VirtualServices and Pools objects are automatically derived from Kubernetes Ingress by the cloud connector.


VirtualService Field Kubernetes Field Comments
tenant Namespace
name Derived from ingress name and optionally certificate name for HTTPS
fqdn Host
ip_address Dedicated VIP: Can be explicitly specified via annotations or will be auto-allocated from the north-south IPAM object

Shared VIP: Uses parent VritualServices VIP.

services Port field in the corresponding service
application_profile Layer4 if overridden via annotations or container ports don't match http_container_ports in Cloud Configuration, else Layer7
network_profile Default to System-TCP-Proxy unless overridden by annotations
pool_group One for every Service in Ingress
pool One for every Service in Ingress
network_security_policy A default network security policy is created for every new or child SNI virtual service
http_policies Layer7 policy for URL (host, path, port) switching amongst routes sharing the virtual service
microservice A microservice is automatically created for every Service
east_west_placement Always north-south

Annotations

Additional configuration for Avi VirtualServices can be provided via annotations.

Automatic WAF policy

Starting release 17.2.4, the following annotation automatically creates and attaches a WAF policy to the VirtualService. After initial creation, the WAF policy can be modified independently of the VirtualService. Note that the version field is necessary, since a waf profile was introduced in the VirtualService starting this release.

metadata:
  annotations:
    avi_proxy: '{"waf_policy": true, "version": "17.2.4"}'

If the cloud uses the shared VirtualService model and just a few Ingresses require WAF service, dedicated VirtualServices can be created just for these Ingresses using the dedicated_route flag. The annotation would be as follows in this case.

metadata:
  annotations:
    avi_proxy: '{"waf_policy": true, "dedicated_route": true, "version": "17.2.4"}'