Skip to content

Commit

Permalink
add loadbalancer address allocator
Browse files Browse the repository at this point in the history
This adds a simple controller that will watch for services of type LoadBalancer
and try to allocated addresses from the specified IPv4 and/or IPv6 ranges.
It's assumed that kube-router (or another network controller) will announce the addresses.

As the controller uses leases for leader election and updates the service status new
RBAC permissions are required.
  • Loading branch information
whooo authored and aauren committed Oct 7, 2023
1 parent 7699d16 commit afdf553
Show file tree
Hide file tree
Showing 17 changed files with 1,592 additions and 35 deletions.
18 changes: 18 additions & 0 deletions daemonset/generic-kuberouter-all-features-advertise-routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -206,6 +210,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update

---
kind: ClusterRoleBinding
Expand Down
18 changes: 18 additions & 0 deletions daemonset/generic-kuberouter-all-features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -202,6 +206,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
18 changes: 18 additions & 0 deletions daemonset/generic-kuberouter-only-advertise-routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
livenessProbe:
httpGet:
path: /healthz
Expand Down Expand Up @@ -114,6 +118,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update

---
kind: ClusterRoleBinding
Expand Down
18 changes: 18 additions & 0 deletions daemonset/generic-kuberouter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -169,6 +173,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update

---
kind: ClusterRoleBinding
Expand Down
18 changes: 18 additions & 0 deletions daemonset/kubeadm-kuberouter-all-features-dsr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -185,6 +189,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
18 changes: 18 additions & 0 deletions daemonset/kubeadm-kuberouter-all-features-hostport.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -184,6 +188,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
18 changes: 18 additions & 0 deletions daemonset/kubeadm-kuberouter-all-features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -177,6 +181,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
18 changes: 18 additions & 0 deletions daemonset/kubeadm-kuberouter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBE_ROUTER_CNI_CONF_FILE
value: /etc/cni/net.d/10-kuberouter.conflist
livenessProbe:
Expand Down Expand Up @@ -173,6 +177,20 @@ rules:
- get
- list
- watch
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
81 changes: 81 additions & 0 deletions docs/load-balancer-allocator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Load Balancer allocator

## What does it do

The load balancer allocator controller looks for services with the type LoadBalancer and tries to allocate addresses for it if needed.
The controller doesn't enable any announcement of the addresses by default, so `--advertise-loadbalancer-ip` should be set to true and BGP peers configured.

## Load balancer classes

By default the controller allocates addresses for all LoadBalancer services with the where `loadBalancerClass` is empty or set to one of "default" or "kube-router".
If `--loadbalancer-default-class` is set to false, the controller will only handle services with the class set to "kube-router".

## RBAC permissions

The controller needs some extra permissions to get, create and update leases for leader election and to update services with allocated addresses.

Example permissions:
```yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kube-router
namespace: kube-system
rules:
- apiGroups:
- "coordination.k8s.io"
resources:
- leases
verbs:
- get
- create
- update
- apiGroups:
- ""
resources:
- services/status
verbs:
- update
```

## Environment variables

The controller uses the environment variable `POD_NAME` as the identify for the lease used for leader election.
Using the kubernetes downward api to set `POD_NAME` to the pod name the lease identify will match the current leader.
```yaml
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: kube-router
tier: node
name: kube-router
namespace: kube-system
spec:
...
template:
metadata:
....
spec:
...
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
...
```

The environment variable `POD_NAMESPACE` can also be specified to set the namespace used for the lease.
By default the namespace is looked up from within the pod using `/var/run/secrets/kubernetes.io/serviceaccount/namespace`.

## Running outside kubernetes

When running the controller outside a pod, both `POD_NAME` and `POD_NAMESPACE` must set for the controller to work.
`POD_NAME` should be unique per instance, so using for example the hostname of the machine might be a good idea.
`POD_NAMESPACE` must be the same across all instances running in the same cluster.

## Notes

It's not possible to specify the addresses for the load balancer services. A externalIP service can be used instead.
4 changes: 4 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ Usage of kube-router:
--ipvs-permit-all Enables rule to accept all incoming traffic to service VIP's on the node. (default true)
--ipvs-sync-period duration The delay between ipvs config synchronizations (e.g. '5s', '1m', '2h22m'). Must be greater than 0. (default 5m0s)
--kubeconfig string Path to kubeconfig file with authorization information (the master location is set by the master flag).
--loadbalancer-default-class Handle loadbalancer services without a class (default true)
--loadbalancer-ip-range strings CIDR values from which loadbalancer services addresses are assigned (can be specified multiple times)
--loadbalancer-sync-period duration The delay between checking for missed services (e.g. '5s', '1m'). Must be greater than 0. (default 1m0s)
--masquerade-all SNAT all traffic to cluster IP/node port.
--master string The address of the Kubernetes API server (overrides any value in kubeconfig).
--metrics-path string Prometheus metrics path (default "/metrics")
Expand All @@ -113,6 +116,7 @@ Usage of kube-router:
--router-id string BGP router-id. Must be specified in a ipv6 only cluster, "generate" can be specified to generate the router id.
--routes-sync-period duration The delay between route updates and advertisements (e.g. '5s', '1m', '2h22m'). Must be greater than 0. (default 5m0s)
--run-firewall Enables Network Policy -- sets up iptables to provide ingress firewall for pods. (default true)
--run-loadbalancer Enable loadbalancer address allocator
--run-router Enables Pod Networking -- Advertises and learns the routes to Pods via iBGP. (default true)
--run-service-proxy Enables Service Proxy -- sets up IPVS for Kubernetes Services. (default true)
--runtime-endpoint string Path to CRI compatible container runtime socket (used for DSR mode). Currently known working with containerd.
Expand Down
14 changes: 14 additions & 0 deletions pkg/cmd/kube-router.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"syscall"
"time"

"github.com/cloudnativelabs/kube-router/v2/pkg/controllers/lballoc"
"github.com/cloudnativelabs/kube-router/v2/pkg/controllers/netpol"
"github.com/cloudnativelabs/kube-router/v2/pkg/controllers/proxy"
"github.com/cloudnativelabs/kube-router/v2/pkg/controllers/routing"
Expand Down Expand Up @@ -228,6 +229,19 @@ func (kr *KubeRouter) Run() error {
go npc.Run(healthChan, stopCh, &wg)
}

if kr.Config.RunLoadBalancer {
klog.V(0).Info("running load balancer allocator controller")
lbc, err := lballoc.NewLoadBalancerController(kr.Client, kr.Config, svcInformer)
if err != nil {
return errors.New("Failed to create load balancer allocator: " + err.Error())
}

svcInformer.AddEventHandler(lbc)

wg.Add(1)
go lbc.Run(healthChan, stopCh, &wg)
}

// Handle SIGINT and SIGTERM
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
Expand Down
Loading

0 comments on commit afdf553

Please sign in to comment.