Creating LoadBalancers
ServiceGroup configuration, annotations, and Service configuration determine how a LoadBalancer is created. Here’s an example Service using the localaddr ServiceGroup.
apiVersion: v1
kind: Service
metadata:
annotations:
purelb.io/service-group: localaddr
labels:
app: echoserver
name: servicetest
namespace: servicetest
spec:
externalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: echoserver
sessionAffinity: None
type: LoadBalancer
PureLB will allocate an address from localaddr, and assuming that localaddr has been configured with the local subnet, the following Service will be created:
$ kubectl describe service echoserver
Name: servicetest
Namespace: servicetest
Labels: app=echoserver
Annotations: purelb.io/service-group: localaddr
purelb.io/allocated-by: PureLB
purelb.io/allocated-from: localaddr
purelb.io/announcing-IPv4: pubelb2-1, enp1s0
Selector: app=echoserver
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.110.8.48
LoadBalancer Ingress: 172.30.250.53
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32380/TCP
Endpoints: 10.1.217.204:8080,10.1.217.205:8080,10.1.238.137:8080
Session Affinity: None
External Traffic Policy: Cluster
Events:Type Reason Age From Message
---- ------ ---- ---- -------
Normal IPAllocated 92m (x2 over 92m) purelb-allocator Assigned IP 172.30.250.53 from pool localaddr
Normal AnnouncingLocal 92m (x2 over 92m) purelb-lbnodeagent Node node3 announcing 172.30.250.53 on interface enp1s0
Describing the service displays the address provided by PureLB, in addition PureLB annotates the service to provide status information. The annotations show that PureLB allocated the address from the localaddr ServiceGroup. Further, the annotations show that the address was added to a local interface, enp1s0 on k8s node purelb2-1.
apiVersion: v1
kind: Service
metadata:
annotations:
purelb.io/service-group: virtualsub
labels:
app: echoserver
name: specificaddress
namespace: servicetest
spec:
externalTrafficPolicy: Cluster
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: echoserver
sessionAffinity: None
type: LoadBalancer
loadBalancerIP: 172.31.1.225
This example shows the use of an address allocated in the service.
$ kubectl describe service -n adamd specificaddress2
Name: specificaddress
Namespace: adamd
Labels: app=echoserver
Annotations: purelb.io/service-group: virtualsub
purelb.io/allocated-by: PureLB
purelb.io/allocated-from: virtualsub
Selector: app=echoserver3
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.104.193.121
IP: 172.31.1.225
LoadBalancer Ingress: 172.31.1.225
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31377/TCP
Endpoints: 10.129.3.151:8080,10.129.4.33:8080
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal IPAllocated 47m (x2 over 47m) purelb-allocator Assigned IP 172.31.1.225 from pool virtualsub
Normal AnnouncingNonLocal 47m purelb-lbnodeagent Announcing 172.31.1.225 from node node3 interface kube-lb0
Normal AnnouncingNonLocal 25m purelb-lbnodeagent Announcing 172.31.1.225 from node node1 interface kube-lb0
Normal AnnouncingNonLocal 25m purelb-lbnodeagent Announcing 172.31.1.225 from node node2 interface kube-lb0
Normal AnnouncingNonLocal 25m purelb-lbnodeagent Announcing 172.31.1.225 from node node5 interface kube-lb0
Normal AnnouncingNonLocal 25m purelb-lbnodeagent Announcing 172.31.1.225 from node node4 interface kube-lb0
Describing the service shows that the requested address has been allocated by PureLB from the virtualsub ServiceGroup. PureLB scanned the configured ServiceGroups to confirm the address is in a ServiceGroup and not in use prior to allocation.
apiVersion: v1
kind: Service
metadata:
annotations:
purelb.io/service-group: virtualsub
labels:
app: echoserver
name: endpoints
namespace: servicetest
spec:
externalTrafficPolicy: Local
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: echoserver
sessionAffinity: None
type: LoadBalancer
---
apiVersion: purelb.io/v1
kind: ServiceGroup
metadata:
name: virtualsub
spec:
local:
v4pools:
- subnet: '172.31.1.0/24'
pool: '172.31.1.0/24'
aggregation: '/32'
This sets externalTrafficPolicy: Local, changing the behavior of both PureLB and kube-proxy. PureLB will only advertise the allocated address on nodes that host pods with the app label echoserver. kube-proxy will not configure forwarding to send traffic over the CNI to pods.
$ kubectl describe service endpoints
Name: endpoints
Namespace: servicetest
Labels: app=echoserver
Annotations: purelb.io/service-group: virtualsub
purelb.io/allocated-by: PureLB
purelb.io/allocated-from: virtualsub
Selector: app=echoserver
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.108.97.71
LoadBalancer Ingress: 172.31.1.0
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31391/TCP
Endpoints: 10.129.1.70:8080,10.129.3.146:8080,10.129.4.30:8080
Session Affinity: None
External Traffic Policy: Local
HealthCheck NodePort: 31400
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal IPAllocated 47m (x2 over 47m) purelb-allocator Assigned IP 172.31.1.0 from pool virtualsub
Normal AnnouncingNonLocal 47m purelb-lbnodeagent Announcing 172.31.1.0 from node node3 interface kube-lb0
Normal AnnouncingNonLocal 25m purelb-lbnodeagent Announcing 172.31.1.0 from node node1 interface kube-lb0
Normal AnnouncingNonLocal 25m purelb-lbnodeagent Announcing 172.31.1.0 from node node2 interface kube-lb0
Describing the service shows that the address was requested and allocated from the virtualsub pool, which sets the resulting address to 172.31.1.0/32. This is the recommended configuration for externalTrafficPolicy: Local as the address is only added to a node’s kube-lb0 when a pod is running on that node, and therefore advertised via routing when the pod is present. If the scale of the application changes, the number of nodes advertised will change.
Aggregation. Setting ServiceGroup aggregation to a mask other than /32 (or /128) can result in traffic being sent to nodes that do not have pods. kube-proxy will not forward so the traffic will be lost. There are valid use cases but be careful!
Local Addresses. Local addresses can only be added to a single node, therefore externalTrafficPolicy: Local not applicable. PureLB supports only externalTrafficPolicy: Cluster for local addresses and will reset External Traffic Policy to Cluster.
Address Sharing. externalTrafficPolicy: Local does not support Address Sharing. Address sharing can result in nodes that do not have pods (endpoints) being advertised. kube-proxy will not forward, so traffic would be lost, so PureLB does not allow this configuration.
Kubernetes Configuration Options
The service API has options that impact how LoadBalancer Services behave.
| Parameter | example | description |
|---|---|---|
| ExternalTrafficPolicy | externalTrafficPolicy: Cluster |
Sets how PureLB should add the service and kube-proxy forward traffic for the service |
| allocateLoadBalancerNodePorts | allocateLoadBalancerNodePorts: false |
By default nodeports are added for loadbalancers but are seldom required |
| loadBalancerClass | loadBalancerClass: purelb.io/purelb |
When multiple loadbalancer controllers are present, select the specified controller |
| ipFamilyPolicy | ipFamilyPolicy: PreferDualStack |
Selects which address families should be added to the services, SingleStack, PreferDualStack, RequireDualStack |
| ipFamilies | ipFamilies: IPv6 |
Selects IPv4 and/or IPv6 |
PureLB Annotations
PureLB uses annotations to configure functionality not native in the k8s API.
| Annotation | example | Description |
|---|---|---|
| purelb.io/service-group | purelb.io/service-group: virtualsg |
Sets the ServiceGroup that will be used to allocate the address |
| purelb.io/allow-shared-ip | purelb.io/allow-shared-ip: sharingkey |
Allows the allocated address to be shared between multiple services as long as they expose different ports |
| purelb.io/addresses | purelb.io/addresses: 172.30.250.80,ffff::27 |
Assigns the provided addresses instead of allocating addresses from the ServiceGroup address pool |