Create a LoadBalancer Service
SUMMARY This topic describes how to create a Load Balancer service in Cloud-Native Contrail® Networking™.
LoadBalancer Service Overview
Juniper Networks supports LoadBalancer services using Cloud-Native Contrail Networking Release 22.1 or later in a Kubernetes-orchestrated environment.
In Kubernetes, a service is an abstract way to expose an application running on a set of pods as a network service. See Kubernetes Services.
In Contrail Networking, the Kubernetes LoadBalancer service is implemented using the
InstanceIP
resource and FloatingIP
resource, both of
which are similar to the ClusterIP
service.
- The
FloatingIP
is used in the service implementation to expose an external IP to the LoadBalancer 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 Kubemanger. Kubemanager is the interface
between Kubernetes core resources, and the extended Contrail resources, such as the
VirtualNetwork
. When you create a LoadBalancer service, Kubemanager
listens and allocates the IP from an external virtual network. This external virtual network
exposes the LoadBalancer service on the external IPs. Any requests received through the
provisioned external IP is ECMP load-balanced across the pods associated with the
LoadBalancer.
Create a LoadBalancer Service
The following sections describe how to create a LoadBalancer service in Cloud-Native Contrail Networking.
- Prerequisites
- Define an External Virtual Network
- Specify the External Networks
- Define Service Level Annotations
- Examples: External Network Selection
Prerequisites
Before you create a LoadBalancer service, make sure of the following:
-
You have set up a working cloud networking environment using Kubernetes orchestration, and Cloud-Native Contrail Networking is operational.
-
You configured Kubemanager to define the external networks to be used by the LoadBalancer service.
Define an External Virtual Network
Before you create a LoadBalancer service, you must define an external virtual network. You can define the virtual network two ways, by creating a NetworkAttachmentDefinition or by creating a virtual network.
A Multus deployment requires that you only use a NetworkAttachmentDefinition to define an external network.
The following example illustrates 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
.
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" }'
When you apply the NetworkAttachmentDefinition
, Kubemanger creates a
virtual network with the name ecmp-default
in the namespace
ecmp-project
.
Specify the External Networks
By default, Kubemanager allocates the external IP for a LoadBalancer service from the
default-external
network. To allocate the external IP from a different
network, you must define the external network using selectors.
The following is an example of the Kubemanager YAML file specifying the
default-external
network selector and user-defined network selectors.
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
listed below match the labels defined in Kubemanager
above (in relative order).
apiVersion: core.contrail.juniper.net/v1alpha1 kind: 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/v1alpha1 attributes: ipamSubnets: - defaultGateway: 10.244.0.1 enableDHCP: true subnet: ipPrefix: 10.244.0.0 ipPrefixLen: "16" ---#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: contrail namespace: custom-namespace --- apiVersion: core.contrail.juniper.net/v1alpha1 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/v1alpha1 attributes: ipamSubnets: - defaultGateway: 10.0.0.1 enableDHCP: true subnet: ipPrefix: 10.0.0.0 ipPrefixLen: "16" --- apiVersion: core.contrail.juniper.net/v1alpha1 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/v1alpha1 attributes: ipamSubnets: - defaultGateway: 192.168.0.1 enableDHCP: true subnet: ipPrefix: 192.168.0.0 ipPrefixLen: "16"
Define Service Level Annotations
Additionally, you can define the following service level annotations to control how an external network is discovered.
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 Kubemanager.
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 annotations takes precedence.
Examples: External Network Selection
The virtual networks defined in Specify the External Networks are linked to the annotations in the following examples.
The external virtual network is selected from one of the following in priority order:
Example 1: Default Selector
Kubemanager first looks for the default external network. In this example no annotation
is specified, so the default-external
selector is used.
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
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 matching preconfigured selector in a namespace
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 matching preconfigured selector in service namespace
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
Configure LoadBalancer Services without Selectors
In Kubernetes, you can expose an application running on a set of pods as a network service. The set of pods targeted by a service is usually determined by a selector. Kubernetes uses selectors to automatically create a LoadBalancer service, but only uses the default primary interface for load balancing.
Starting in Cloud-Native Contrail Networking Release 22.3, you can load balance a service across multiple secondary interfaces. You create secondary interfaces in CN2 without using a selector. Because the LoadBalancer service has no selector, you must create the endpoint manually.
To create a secondary interface for a LoadBalancer service:
In addition to creating a LoadBalancer service on the secondary interface, you can use a selector to create a LoadBalancer service on the default primary interface. The primary interface can work in tandem with the secondary interface. You can use either interface to load balance across your desired service.
Dual-Stack Networking Support
Cloud-Native Contrail Networking supports dual-stack networking. When you start a Kubernetes cluster, dual stack is enabled by default. The Cloud-Native Contrail Networking deployer then creates dual-stack (IPv4, IPv6) pod networks and service networks. If no IP family is defined, IPv4 is automatically used.
apiVersion: v1 kind: Service metadata: name: MyService specs: ipFamilies: ["IPv4", "IPv6"]