Dynamic IPv6 Prefix support for MetalLB.
This utility enables MetalLB to manage an IPv6 address pool with a dynamically changing prefix. It synchronizes the network part of an Ipv6 Address Range in a MetalLB IPAddressPool with a dynamically retrieved Ipv6 network. It ensures that the address range in the pool always corresponds to the currently assigned network and automatically reloads MetaLLB when required.
The main use case for this tool is running an Ipv6-enabled k8s cluster from a residential ISP connection with no static Ipv6 Prefix.
Consider the following situation:
You want to host an IPv6-enabled k8s cluster and have gotten an Ipv6 prefix from your ISP, say 2001:db8:aaaa::/48
.
To make your cluster-hosted services accessible from the internet, you'd assign them addresses from within that prefix (and setup your router, but that's outside the scope of this README).
For example, your IPAddressPool
could look like this:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
namespace: metallb-system
spec:
addresses:
# Some private IPv4 addresses
- 10.10.1.10-10.10.1.99
# A range from within your ISP-assigned Prefix
- 2001:db8:aaaa::1000-2001:db8:aaaa::1999
This works great, as long as the prefix assigned to you is static - that is, it does not change.
However, many consumer ISPs regularly change the assigned prefix (for example when the connection gets interrupted).
This means that after a power outage, your assigned prefix might suddenly be 2001:db8:ffff::/48
, resulting in an incorrect MetalLB configuration and thus no internet access.
Unfortunately, as IPAddressPool
resources are static, MetalLB has no native way to address this.
This is where metallb-dyn6
comes in.
metallb-dyn6
addresses this issue by listening to changes in the prefix, replacing the range in the IPAddressPool
with one based on the new prefix whenever a change occurs.
It does this by performing the following actions:
- First, it queries a source for the IPv6 prefix, which simply tells
metallb-dyn6
what prefix to use. Right now, the only available source ismy-ip
, which queries the MyIP API for your current public IPV6 address.metallb-dyn6
s design is modular, so more sources can easily be added in the future.
- It then compares the Prefix stored in the
IPAddresspool
with the one retrieved from the source. If there is a mismatch, it updates theIPAddressPool
to match the prefix retrieved from the source. - Finally, it forces MetalLB to accept this new configuration by deleting all of its pods and waiting for them to be recreated (this is the officially recommended way to do this).
The officially recommanded way to install metallb-dyn6
is through Helm.
First, install the repository like so:
helm repo add spacebird https://charts.spacebird.dev
Then, install the chart:
helm install metallb-dyn6 spacebird/metallb-dyn6 \
--namespace metallb-system
--set "metallb.hostRange=::1000-::1999"
--set "metallb.pool=my-ipaddress-pool-name"
- You must install
metallb-dyn6
into the same namespace as yourmetallb
installation. - The parameters
metallb.hostRange
andmetallb.pool
are required. metallb.hostRange
must be a dash-separated range - it cannot be a/xx
CIDR-style range.
For a full list of possible values, please see the Helm chart docs
Sometimes, the IPv6 network returned from the source may not have the correct subnet applied. For example, you may have a separate subnet configured for just your k8s cluster services traffic that you'd like MetalLB to use.
In those cases, you can override parts of the returned network with the subnetOverride
values.
For example, to always override the last 8 bits of the network with cd:
, you would supply the following values:
dyn6:
subnetOverride:
enabled: true
prefixLen: 56 # how many of the original network bits to keep
override: "0:0:0:00cd::" # note the leading zeros - they are required
To begin development on this project, follow the steps below:
- Clone this repository
- Install cargo-make:
cargo install cargo-make --locked
- (Optional but recommended) Install pre-commit
- (Optional, for Docker builds and cross-compiling) Ensure docker is installed
- Happy hacking!
This project uses an up-to-date version of Rust and cargo-make
for builds.
Most common actions can be performed by running cargo make <command>
.
See cargo make --list-all-steps
for a list of available actions.
cargo make lint
- Local Build:
cargo make build
- For a release binary:
cargo make -p release build
This project uses cross
to cross-compile binaries for different target platforms.
You can create a binary for a different target like so:
- Debug:
cargo make build-aarch64-unknown-linux-gnu
- Release:
cargo make -p release build-aarch64-unknown-linux-gnu
To see which targets are available, run cargo make --list-category-steps build
- Default (host) target:
cargo make test
- Custom target:
cargo make test-aarch64-unknown-linux-gnu
- Get a coverage report:
cargo make coverage
cargo make docs
- To build a image for your local platform:
cargo make docker
- Custom target:
cargo make docker-arm64
- Make sure your system can build multi-platform images using QEMU
cargo-make
will automatically generate an appropriate builder.
- To build the image with a custom tag:
cargo make -e DOCKER_TAG=registry.invalid/user/project:0.1.2 docker
Draft Releases are automatically managed through the version-maintenance
workflow.
Follow the instructions in those drafts to publish a new release.