Create a Load Balancer Service
SUMMARY This topic describes how to create a Load Balancer service in Juniper Cloud-Native Contrail® Networking (CN2). Juniper Networks supports this feature using Contrail Networking Release 22.1 or later in a Kubernetes-orchestrated environment.
Load Balancer Service Overview
In Kubernetes, a service is an abstract way to expose an application running on a set of pods as a network service. Kubernetes supports three types of services: ClusterIP, NodePort and LoadBalancer. This topic describes how to create a load balancer service in CN2.
In CN2, a load balancer service is implemented with the InstanceIP
resource and FloatingIP
resource as described below:
-
The
FloatingIP
is used in the service implementation to expose an external IP to the load balancer service. TheFloatingIP
resource is also associated with the pod'sVirtualMachineInterfaces
. -
The
InstanceIP
resource is related to theVirtualNetwork
. TwoinstanceIPs
are created, one for the service network and one for the external network.
A controller service is implemented in Contrail's kube-manager. Kube-manager is the
interface between Kubernetes core resources and the extended Contrail resources, such as the
VirtualNetwork.
When you create a load balancer service, kube-manager
listens and allocates the IP from an external virtual network. This external virtual network
exposes the load balancer service on the external IPs. Any requests received through the
provisioned external IP is ECMP load-balanced across the pods associated with the load
balancer.
Create a Load Balancer Service
The following sections describe how to create a load balancer service in CN2.
- Prerequisites
- Define an External Virtual Network
- Specify the External Networks
- Define Service-Level Annotations
- Examples: External Network Selection
Prerequisites
Before you begin, make sure of the following:
-
You have set up a working cloud networking environment with Kubernetes.
-
CN2 is installed and is operational.
-
You have configured kube-manager to define the external networks to be used by the load balancer service.
Define an External Virtual Network
First, define an external virtual network. You can define the virtual network two ways: by creating a Network Attachment Definition (NAD) or by creating a virtual network.
A Multus deployment requires that you use a NAD to define an external network.
The following example shows how to define an external virtual network using a
NetworkAttachmentDefinition
. In this example, the external IP is allocated from
the subnet range 192.168.102.0/24
. When the
NetworkAttachmentDefinition
is applied, kube-manager creates a virtual
network with the name ecmp-default
in the namespace
ecmp-project
.
apiVersion: "k8s.cni.cncf.io/v1" kind: NetworkAttachmentDefinition metadata: name: ecmp-default namespace: ecmp-project annotations: juniper.net/networks: '{ "ipamV4Subnet": "192.168.102.0/24", "fabricSNAT": false "core.juniper.net/display-name: "External Virtual Network" }' core.juniper.net/display-name: "External Virtual Network" labels: service.contrail.juniper.net/externalNetworkSelector: default-external spec: config: '{ "cniVersion": "0.3.1", "name": "ecmp-default", "type": "contrail-k8s-cni" }'
Specify the External Networks
By default, kube-manager allocates the external IP for a load balancer service from the
default-external
network. If desired, you can allocate the external IP
from a different network by defining custom selectors, as shown in the following example:
apiVersion: configplane.juniper.net/v1alpha1 kind: Kubemanager metadata: generation: 148 name: contrail-k8s-kubemanager namespace: contrail spec: externalNetworkSelectors: default-external: networkSelector: matchLabels: service.contrail.juniper.net/externalNetwork: default-external custom-external: namespaceSelector: matchLabels: customNamespaceKey: custom-namespace-value networkSelector: matchLabels: customNetworkKey: custom-network-value custom-external-in-service-namespace: networkSelector: matchLabels: customExternalInServiceNetworkKey: custom-external-in-service-network-value
The VirtualNetworks
in this example match the labels shown in the
previous example (in relative order).
apiVersion: core.contrail.juniper.net/v3 kind: Subnet metadata: namespace: contrail name: external-subnet spec: cidr: "10.244.0.0/16" defaultGateway: 10.244.0.1 --- apiVersion: core.contrail.juniper.net/v3kind: VirtualNetwork # matches example 1 metadata: name: default-external-vn namespace: contrail labels: service.contrail.juniper.net/externalNetworkSelector: default-external spec: v4SubnetReference: apiVersion: core.contrail.juniper.net/v3 kind: Subnet namespace: contrail name: external-subnet --- # this is how you define namespace selector # Namespace must have appropriate label if required by namespaceSelector apiVersion: v1 kind: Namespace metadata: labels: customNamespaceKey: custom-namespace-value #user for your external ip name: custom-namespace --- apiVersion: core.contrail.juniper.net/v3kind: Subnet metadata: namespace: custom-namespace name: external-subnet-custom-namespace spec: cidr: "10.0.0.0/16" defaultGateway: 10.0.0.1 --- apiVersion: core.contrail.juniper.net/v3 kind: VirtualNetwork metadata: name: external-vn-1 # matches example 2 and example 3 namespace: custom-namespace labels: customNetworkKey: custom-network-value spec: v4SubnetReference: apiVersion: core.contrail.juniper.net/v3 kind: Subnet namespace: custom-namespace name: external-subnet-custom-namespace --- apiVersion: core.contrail.juniper.net/v3kind: Subnet metadata: namespace: custom-namespace name: external-subnet-in-service spec: cidr: "192.168.0.0/16" defaultGateway: 192.168.0.1 --- apiVersion: core.contrail.juniper.net/v3 kind: VirtualNetwork metadata: name: external-vn-2 # matches example 4 namespace: custom-namespace labels: customExternalInServiceNetworkKey: custom-external-in-service-network-value spec: v4SubnetReference: apiVersion: core.contrail.juniper.net/v3 kind: Subnet namespace: custom-namespace name: external-subnet-in-service
Define Service-Level Annotations
Additionally, you can define the following service-level annotations for external network discovery.
Annotation: externalNetwork.
In this example, the externalNetwork
annotation allocates an external IP
from the evn
virtual network in the namespace ns
.
apiVersion: v1 kind: Service metadata: name: my-service annotation: service.contrail.juniper.net/externalNetwork: ns/evn spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
Annotation: externalNetworkSelector
In this example, the externalNetworkSelector
matches the name of the
externalNetworkSelector
defined in kube-manager.
apiVersion: v1 kind: Service metadata: name: my-service annotation: service.contrail.juniper.net/externalNetworkSelector: custom-external spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
You can also define service-level annotations in the namespace of the Kubernetes cluster or in the namespace of the Contrail cluster. The service-level annotation take precedence.
Examples: External Network Selection
The external virtual network is selected from one of the following in priority order:
The virtual networks defined in Specify the External Networks are linked to the annotations in the following examples.
- Example 1: Default Selector
- Example 2: Custom Namespace
- Example 3: External Network Matches Preconfigured Selector in a Namespace
- Example 4: External Network Matches Preconfigured Selector in Service Namespace
Example 1: Default Selector
Kube-manager first searches for the default external network. This example uses the
default-external
selector because no annotation is specified.
This example matches the network contrail/default-external-vn
.
apiVersion: v1 kind: Service metadata: name: my-service spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
Example 2: Custom Namespace
This example matches the network custom-namespace/external-vn-1
.
apiVersion: v1 kind: Service metadata: name: my-service annotation: service.contrail.juniper.net/externalNetwork: custom-namespace/external-vn-1 spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
Example 3: External Network Matches Preconfigured Selector in a Namespace
This example matches the network custom-namespace/external-vn-1
.
apiVersion: v1 kind: Service metadata: name: my-service annotation: service.contrail.juniper.net/externalNetworkSelector: custom-external spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
Example 4: External Network Matches Preconfigured Selector in Service Namespace
This example matches the network custom-namespace/external-vn-2
.
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: custom-namespace
annotation:
customExternalInServiceNetworkKey: custom-external-in-service-network-value
spec:
type: LoadBalancer
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
Dual-Stack Networking Support
IPv4 or IPv6 dual-stack networking enables the allocation of both IPv4 and IPv6 addresses to pods and services. As an administrator, you might need to select the IP family (IPv4 or IPv6) to use when defining a service. If you do not define the IP family, the default IPv4 address is used.
apiVersion: v1 kind: Service metadata: name: MyService specs: ipFamilies: ["IPv4", "IPv6"]
For more information, see Overview: IPv4 and IPv6 Dual-Stack Networking.
Configure Load Balancer Services Without Selectors
In Kubernetes, you can expose an application running on a set of pods as a network service. Kubernetes uses selectors to automatically create a load balancer service, but only uses the default primary interface for load balancing.
Starting in CN2 Release 22.3, you can load balance a service across multiple secondary interfaces. You can create secondary interfaces in CN2 without using a selector. Because the load balancer service has no selector, you must create the endpoint manually.
To configure load balancer services without selectors:
In addition to creating a load balancer service on the secondary interface, you can use a selector to create a load balancer on the default primary interface. The default primary interface can work in tandem with the secondary interface. You can use either interface to load balance across your desired service.