Code of Conduct

Contributor License Agreement

Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution,
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to https://cla.developers.google.com/ to see
your current agreements on file or to sign a new one.

You generally only need to submit a CLA once, so if you’ve already
submitted one (even if it was for a different project), you probably
don’t need to do it again. When you submit pull requests, a helpful
Google CLA bot will tell you if you need to sign the CLA.

Code changes

Before you make significant code changes, please open an issue to
discuss your plans. This will minimize the amount of review required
for pull requests.

All submissions require review. We use GitHub pull requests for this
purpose. Consult
GitHub Help
for more information on using pull requests.

Code organization

MetalLB’s code is divided between a number of binaries, and some
supporting libraries. The libraries live in the internal directory,
and each binary has its own top-level directory. Here’s what we
currently have, relative to the top-level directory:

controller is the cluster-wide MetalLB controller, in charge of
IP assignment.

speaker is the per-node daemon that advertises services with
assigned IPs using various advertising strategies.

test-bgp-router is a small wrapper around
the
BIRD,
Quagga
and GoBGP open-source BGP routers
that presents a read-only interface over HTTP. We use it in the
tutorial, and during development of MetalLB.

internal/k8s contains the bowels of the logic to talk to the
Kubernetes apiserver to get and modify service information. It
allows most of the rest of the MetalLB code to be ignorant of the
Kubernetes client library, other than the objects (Service,
ConfigMap…) that they manipulate.

internal/config parses and validates the MetalLB configmap.

internal/allocator is the IP address manager. Given pools from the
MetalLB configmap, it can allocate addresses on demand.

internal/bgp is a very stripped down implementation of BGP. It
speaks just enough of the protocol to keep peering sessions up, and
to push routes to the peer.

In addition to code, there’s deployment configuration and
documentation:

manifests contains a variety of Kubernetes manifests. The most
important one is manifests/metallb.yaml, which specifies how to
deploy MetalLB onto a cluster.

website contains the website for MetalLB. The website/content
subdirectory is where all the pages live, in Markdown format.

Optionally, if you want to update the vendored dependency, you’ll
need glide, the Go dependency
manager

Building the code

Start by fetching the MetalLB repository, with go get
go.universe.tf/metallb.

From there, you can use normal Go commands to build binaries and run
unit tests, e.g. go install go.universe.tf/metallb/bgp-speaker, go
test ./internal/allocator.

For development, fork
the github repository, and add
your fork as a remote in $GOPATH/src/go.universe.tf/metallb, with
git remote add fork git@github.com:<your-github-user>/metallb.git.

Note: the repository must be checked out at
$GOPATH/src/go.universe.tf/metallb. The source code uses canonical
import paths, so if you check it out at
$GOPATH/src/github.com/google/metallb or similar, it will fail to
compile.

Testing in Minikube

To really test MetalLB fully, you need to run it in a Kubernetes
cluster, to verify that all the pieces are working together. The
repository has a set of Fabric commands that makes this easy, by
setting up a Minikube sandbox and deploying a production MetalLB
setup, but running your locally built binaries.

Sandbox setup

Start by running make start-minikube. This will:

Create the Minikube sandbox in a local VM

Enable the registry addon, so that we can host container images in the sandbox

Deploy test-bgp-router, which sets up BIRD, Quagga routers as a
pod inside the cluster

Deploy MetalLB, which will install the controller and speaker

Push a MetalLB configuration that connects MetalLB to the test-bgp-router

At this point, your sandbox is running the precompiled version of
MetalLB, pulled from Docker Hub.

You can inspect the state of the test-bgp-router by running
minikube service test-bgp-router-ui -n metallb-system, which will open a browser tab
that shows you the current BGP connections and routing state, as seen
by the test routers.

Pushing test binaries

When you’re ready to test a local change you’ve made to MetalLB, you
can build and deploy MetalLB containers to your sandbox. First, if
you’re using minikube, leave make proxy-to-registry running in a
second terminal. This will make the cluster’s internal registry
available on localhost, so that we can push to it.

Update the MetalLB deployments and daemonsets to use the ephemeral containers

Wait for all the pieces of MetalLB to update

Once the push is done, MetalLB will still be running in your Minikube
sandbox, but using binaries built from your local source code instead
of the public images.

Note for MacOS users: Since Docker is run inside a virtual machine
in MacOS the local registry won’t work out of the box. To make it work
you have to add docker.for.mac.localhost:5000 under Insecure
registries in your Docker daemon preferences. Once you’ve done that,
make push should work.

If you need to get back to a working configuration, make
push-manifests will revert MetalLB to running from the public Docker
Hub images and the config from the repository.

Sandbox teardown

When you’re done with minikube, run minikube delete to destroy the
sandbox.

Existing users of Minikube

If you’re already using minikube, be warned: make start-minikube
will touch the default minikube sandbox, and so may interfere with
other experiments you have going on.

Testing outside of Minikube

You can also use make push on clusters other than minikube. make
push will deploy to whichever cluster your kubectl is currently
pointing to.

If your cluster has a local registry, usage instructions are exactly
the same as with minikube: leave make proxy-to-registry running in a
secondary terminal, and then make push each time you want to test
your changes.

If you want to use an external registry, you can specify it with the
REGISTRY make variable. For example, make push REGISTRY=danderson
will push the docker images
to
danderson’s account on docker hub,
and make the cluster pull from there as well.

Cross compiling

Released versions of MetalLB (0.3.0 and later) use multi-architecture
images, and so should work on all platforms supported by
kubernetes. However, the dev builds made by make push only build for
one architecture, to save time.

By default, make push builds binaries for amd64 (aka x86_64). If you
want to test on a different architecture (for example a raspberry pi
cluster), you can select the architecture of the dev builds by setting
the ARCH make variable to your desired architecture, one of amd64,
arm, arm64, ppc64le, s390x. For example, make push ARCH=arm will
build and deploy containers that work on ARM machines.

Build customizations

You can write custom make configuration options to
Makefile.defaults, and they will be included as defaults for all
builds. For example, if you normally build with go1.10beta1 and push
arm64 binaries to a custom registry, you can use the following
Makefile.defaults:

GOCMD=go1.10beta1
ARCH=arm64
REGISTRY=my-cool-images

To see a list of customizable options and what they do, look at the
top of Makefile.

Peering with real BGP routers

While testing, it might be useful to peer with “real” routers outside
of the cluster, rather than always use the in-cluster
test-bgp-router. If you do so, you need to reconfigure the address
pool from the default config! The default configuration uses the
TEST-NET-2 IP range
from RFC5735, which is reserved
for use in documentation and example code. It’s fine to use it with
our test-bgp-router, since they doesn’t propagate the addresses
beyond themselves, but if you try injecting those addresses into a
real network, you may run into trouble.

The website

The website at https://metallb.universe.tf is pinned to the latest
released version, so that users who don’t care about ongoing
development see documentation that is consistent with the released
code.

However, there is a version of the website synced to the latest master
branch
at
https://master–metallb.netlify.com. Similarly,
every branch has a published website at <branch
name>--metallb.netlify.com. So if you want to view the documentation
for the 0.2 version, regardless of what the currently released version
is, you can
visit
https://v0.2–metallb.netlify.com.

When editing the website, you can preview your changes locally by
installing Hugo and running hugo server from
the website directory.