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
FloatingIPis used in the service implementation to expose an external IP to the load balancer service. TheFloatingIPresource is also associated with the pod'sVirtualMachineInterfaces. -
The
InstanceIPresource is related to theVirtualNetwork. TwoinstanceIPsare 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-valueThe 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-serviceDefine 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.