Cloud Provider
kube-vip On-Prem
We've designed kube-vip to be as decoupled or agnostic from other components that may exist within a Kubernetes cluster as possible. This has lead to kube-vip having a very simplistic but robust approach to advertising Kubernetes Services to the outside world and marking these Services as ready to use.
Cloud Controller Manager
kube-vip isn't coupled to anything other than the Kubernetes API and will only act upon an existing Kubernetes primitive (in this case the object of type Service
). This makes it easy for existing cloud controller managers (CCMs) to simply apply their logic to services of type LoadBalancer and leave kube-vip to take the next steps to advertise these load balancers to the outside world.
Using the kube-vip Cloud Provider
The kube-vip cloud provider can be used to populate an IP address for Services of type LoadBalancer
similar to what public cloud providers allow through a Kubernetes CCM. The below instructions should just work on Kubernetes regardless of the architecture (a Linux OS being the only requirement) and will install the latest components.
Install the kube-vip Cloud Provider
The kube-vip cloud provider can be installed from the latest release in the main
branch by using the following command:
1kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml
Create a global CIDR or IP Range
In order for kube-vip to set an IP address for a Service of type LoadBalancer
, it needs to have an availability of IP address to assign. This information is stored in a Kubernetes ConfigMap to which kube-vip has access. You control the scope of the IP allocations with the key
within the ConfigMap. Either CIDR blocks or IP ranges may be specified and scoped either globally (cluster-side) or per-Namespace.
To allow a global (cluster-wide) CIDR block which kube-vip can use to allocate an IP to Services of type LoadBalancer
in any Namespace, create a ConfigMap named kubevip
with the key cidr-global
and value equal to a CIDR block available in your environment. For example, the below command creates a global CIDR with value 192.168.0.220/29
from which kube-vip will allocate IP addresses.
1kubectl create configmap -n kube-system kubevip --from-literal cidr-global=192.168.0.220/29
To use a global range instead, create the key range-global
with the value set to a valid range of IP addresses. For example, the below command creates a global range using the pool 192.168.1.220-192.168.1.230
.
1kubectl create configmap -n kube-system kubevip --from-literal range-global=192.168.1.220-192.168.1.230
Creating services of type LoadBalancer
in any Namespace will now take addresses from one of the global pools defined in the ConfigMap unless a Namespace-specific pool is created.
The kube-vip Cloud Provider ConfigMap
To manage the IP address ranges for Services of type LoadBalancer
, the kube-vip-cloud-provider
uses a ConfigMap held in the kube-system
Namespace. IP addresses can be configured using one or multiple formats:
- CIDR blocks
- IP ranges [start address - end address]
- Multiple pools by CIDR per Namespace
- Multiple IP ranges per Namespace (handles overlapping ranges)
- Setting of static addresses through --load-balancer-ip=x.x.x.x (
kubectl expose
command)
To control which IP address range is used for which Service, the following rules are applied:
- Global address pools (
cidr-global
orrange-global
) are available for use by any Service in any Namespace - Namespace specific address pools (
cidr-<namespace>
orrange-<namespace>
) are only available for use by a Service in the specific Namespace - Static IP addresses can be applied to a Service of type
LoadBalancer
using thespec.loadBalancerIP
field, even outside of the assigned ranges
Example Configmap:
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: kubevip
5 namespace: kube-system
6data:
7 cidr-default: 192.168.0.200/29 # CIDR-based IP range for use in the default Namespace
8 range-development: 192.168.0.210-192.168.0.219 # Range-based IP range for use in the development Namespace
9 cidr-finance: 192.168.0.220/29,192.168.0.230/29 # Multiple CIDR-based ranges for use in the finance Namespace
10 cidr-global: 192.168.0.240/29 # CIDR-based range which can be used in any Namespace
Expose a Service
We can now expose a Service and once the cloud provider has provided an address, kube-vip will start to advertise that address to the outside world as shown below:
1kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx
or via a Service YAML definition:
1apiVersion: v1
2kind: Service
3metadata:
4 name: nginx
5spec:
6 ports:
7 - name: http
8 port: 80
9 protocol: TCP
10 selector:
11 app: nginx
12 type: LoadBalancer
We can also expose a specific address by specifying it imperatively on the command line:
1kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=1.1.1.1
or including it in the Service definition:
1apiVersion: v1
2kind: Service
3metadata:
4 name: nginx
5spec:
6 ports:
7 - name: http
8 port: 80
9 protocol: TCP
10 selector:
11 app: nginx
12 type: LoadBalancer
13 loadBalancerIP: "1.1.1.1"
Using DHCP for Load Balancers (experimental)
With kube-vip > 0.2.1, it is possible to use the local network DHCP server to provide kube-vip with a load balancer address that can be used to access a Kubernetes service on the network.
In order to do this, we need to signify to kube-vip and the cloud provider that we don't need one of their managed addresses. We do this by explicitly exposing a Service on the address 0.0.0.0
. When kube-vip sees a Service on this address, it will create a macvlan
interface on the host and request a DHCP address. Once this address is provided, it will assign it as the LoadBalancer
IP and update the Kubernetes Service.
1$ kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx-dhcp --load-balancer-ip=0.0.0.0; kubectl get svc
2service/nginx-dhcp exposed
3NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
4kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
5nginx-dhcp LoadBalancer 10.97.150.208 0.0.0.0 80:31184/TCP 0s
6
7{ ... a second or so later ... }
8
9$ kubectl get svc
10NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
11kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
12nginx-dhcp LoadBalancer 10.97.150.208 192.168.0.155 80:31184/TCP 3s
Using UPnP to expose a Service to the outside world
With kube-vip > 0.2.1, it is possible to expose a Service of type LoadBalancer
on a specific port to the Internet by using UPnP (on a supported gateway).
Most simple networks look something like the following:
<----- <internal network 192.168.0.0/24> <Gateway / router> <external network address> ----> Internet
Using UPnP we can create a matching port on the <external network address>
allowing your Service to be exposed to the Internet.
Enable UPnP
Add the following to the kube-vip env:
section of either the static Pod or DaemonSet for kube-vip, and the rest should be completely automated.
Note some environments may require (Unifi) Secure mode
being disabled
(this allows a host with a different address to register a port).
1- name: enableUPNP
2 value: "true"
Exposing a Service
To expose a port successfully, we'll need to change the command slightly:
--target-port=80
the port of the application in the pods (HTT/NGINX)
--port=32380
the port the Service will be exposed on (and what you should connect to in order to receive traffic from the Service)
kubectl expose deployment plunder-nginx --port=32380 --target-port=80 --type=LoadBalancer --namespace plunder
The above example should expose a port on your external (Internet facing) address that can be tested externally with:
1$ curl externalIP:32380
2<!DOCTYPE html>
3<html>
4...