Contrail Service Load Balancer
Let’s take a look at service load balancer and related objects.
The highlights in Figure 1 are:
Each service is represented by a loadbalancer object.
The load balancer object comes with a loadbalancer_provider property. For service implementation, a new loadbalancer_provider type called native is implemented.
For each service port a listener object is created for the same service loadbalancer.
For each listener there will be a pool object.
The pool contains members, depending on the number of back-end pods, one pool may have multiple members.
Each member object in the pool will map to one of the back-end pods.
Contrail-kube-manager listens kube-apiserver for k8s service and when a custerIP or loadbalancer type of service is created, a loadbalancer object with loadbalancer_provider property native is created.
Loadbalancer will have a virtual IP VIP, which is the same as the serviceIP.
The service-ip/VIP will be linked to the interface of each back-end pod. This is done with an ECMP load balancer driver.
The linkage from service-ip to the interfaces of multiple back-end pods creates an ECMP next-hop in Contrail, and traffic will be load balanced from the source pod towards one of the back-end pods directly. Later we’ll show the ECMP prefix in the pod’s VRF table.
The contrail-kube-manager continues to listen to kube-apiserver for any changes, based on the pod list in Endpoints, it will know the most current back-end pods, and update members in the pool.
The most important thing to understand in Figure 1, as mentioned before, is that in contrast to the legacy neutron load balancer (and the ingress load balancer which we’ll discuss later), there is no application layer proxy in this process. Contrail service implementation is based on Layer 4 (transport layer) ECMP-based load balancing.
Contrail Load Balancer Objects
We’ve talked a lot about the Contrail load balancer object and you may wonder what exactly it looks like. Well it’s time to dig a little bit deeper to look at the load balancers and the supporting objects: listener, pool, and members.
In a Contrail setup you can pull the object data either from Contrail UI, CLI (curl), or third-party UI tools based on REST API. In production, depending on which one is available and handy, you can select your favorite.
Let’s explore load balancer object with curl. With the curl tool you just need a FQDN of the URL pointing to the object.
For example, to find the load balancer object URL for the service service-web-clusterip from load balancers list:
$ curl http://10.85.188.19:8082/loadbalancers | \ python -mjson.tool | grep -C4 `service-web-clusterip` { "fq_name": [ "default-domain", "k8s-ns-user-1", "service-web-clusterip 99fe8ce7-9e75-11e9-b485-0050569e6cfc" ], "href": "http://10.85.188.19:8082/loadbalancer/99fe8ce7-9e75-11e9-b485-0050569e6cfc", "uuid": "99fe8ce7-9e75-11e9-b485-0050569e6cfc" },
Now with one specific load balancer URL, you can pull the specific LB object details:
$ curl \ http://10.85.188.19:8082/loadbalancer/99fe8ce7-9e75-11e9-b485-0050569e6cfc \ | python -mjson.tool { "loadbalancer": { "annotations": { "key_value_pair": [ { "key": "namespace", "value": "ns-user-1" }, { "key": "cluster", "value": "k8s" }, { "key": "kind", "value": "Service" }, { "key": "project", "value": "k8s-ns-user-1" }, { "key": "name", "value": "service-web-clusterip" }, { "key": "owner", "value": "k8s" } ] }, "display_name": "ns-user-1 service-web-clusterip", "fq_name": [ "default-domain", "k8s-ns-user-1", "service-web-clusterip 99fe8ce7-9e75-11e9-b485-0050569e6cfc" ], "href": "http://10.85.188.19:8082/loadbalancer/99fe8ce7-9e75-11e9-b485-0050569e6cfc", "id_perms": { ...<snipped>... }, "loadbalancer_listener_back_refs": [ #<--- { "attr": null, "href": "http://10.85.188.19:8082/loadbalancer-listener/3702fa49-f1ca-4bbb-87d4-22e1a0dc7e67", "to": [ "default-domain", "k8s-ns-user-1", "service-web-clusterip 99fe8ce7-9e75-11e9-b485-0050569e6cfc-TCP-8888- 3702fa49-f1ca-4bbb-87d4-22e1a0dc7e67" ], "uuid": "3702fa49-f1ca-4bbb-87d4-22e1a0dc7e67" } ], "loadbalancer_properties": { "admin_state": true, "operating_status": "ONLINE", "provisioning_status": "ACTIVE", "status": null, "vip_address": "10.105.139.153", #<--- "vip_subnet_id": null }, "loadbalancer_provider": "native", #<--- "name": "service-web-clusterip 99fe8ce7-9e75-11e9-b485-0050569e6cfc", "parent_href": "http://10.85.188.19:8082/project/86bf8810-ad4d-45d1-aa6b-15c74d5f7809", "parent_type": "project", "parent_uuid": "86bf8810-ad4d-45d1-aa6b-15c74d5f7809", "perms2": { ...<snipped>... }, "service_appliance_set_refs": [ ...<snipped>... ], "uuid": "99fe8ce7-9e75-11e9-b485-0050569e6cfc", "virtual_machine_interface_refs": [ { "attr": null, "href": "http://10.85.188.19:8082/virtual-machine- interface/8d64176c-9fc7-491a-a44d-430e187d6b52", "to": [ "default-domain", "k8s-ns-user-1", "k8s Service service-web-clusterip 99fe8ce7-9e75-11e9-b485-0050569e6cfc" ], "uuid": "8d64176c-9fc7-491a-a44d-430e187d6b52" } ] } }
The output is very extensive and includes many details that are not of interest to us at the moment, except for a few details worth mentioning:
In loadbalancer_properties, the LB use service IP as its VIP.
The LB is connected to a listener by a reference.
The loadbalancer_provider attribute is native, a new extension to implement Layer 4 (transport layer) ECMP for Kubernetes service.
In the rest of the exploration of LB and its related objects, let’s use the legacy Contrail UI.
You can also easily use the new Contrail Command UI to do the same.
For each service there is an LB object, in Figure 2 the screen capture shows two LB objects:
ns-user-1-service-web-clusterip
ns-user-1-service-web-clusterip-mp
This indicates two services were created. The service load balancer object’s name is composed by connecting the NS name with the service name, hence you can tell the names of the two services:
service-web-clusterip
service-web-clusterip-mp
Click on the small triangle icon in the left of the first load balancer object ns-user-1-service-web-clusterip to expand it, then click on advanced json view icon on the right, and you will see detailed information similar to what you’ve seen in curl capture. For example, the VIP, load balancer_provider, load balancer_listener object that refers it, etc.
From here you can keep expanding the loadbalancer_listener object by clicking the + character to see the detail as shown in Figure 3. You’ll then see a loadbalancer_pool; expand it again and you will see member. You can repeat this process to explore the object data.
Listener
Click on the LB name and select listener, then expand it and display the details with JSON format and you will get the listener details. The listener is listening on service port 8888, and it is referenced by a pool in Figure 4.
In order to see the detailed parameters of an object in JSON format, click the triangle in the left of the load balancer name to expand it, then click on the Advanced JSON view icon on the upper right corner in the expanded view. The JSON view is used a lot in this book to explore different Contrail objects.
Pool and Member
Just repeating this explorative process will get you down to the pool and the two members in it. The member is with a port of 80, which maps to the container targetPort in pod as shown in Figure 5 and Figure 6.
Next we’ll examine the vRouter VRF table for the pod to show Contrail service load balancer ECMP operation details. To better understand the 1-to-N mapping between load balancer and listener shown in the load balancer object figure, we’ll also give an example of a multiple port service in our setup. We’ll conclude the clusterIP service section by inspecting the vRouter flow table to illustrate the service packet workflow.