metallb: MetalLB cannot peer with BGP routers that Calico is already peering with
Is this a bug report or a feature request?:
Question actually.
What happened: Can’t get MetalLB to peer with my core router.
What you expected to happen: Peering is expected to happen and for me to see the routes for each node in the routing table.
How to reproduce it (as minimally and precisely as possible): Setup MetalLB and peer it with a Cisco L3 routing device.
Anything else we need to know?: I am not sure if this is something related to the Cisco side or the MetalLB side. I also have calico peering with the same Cisco device with the same IP address and that could be the problem, but I wanted to verify. I am not sure that it is a bug.
Getting this in the log: {“log”:“E1213 22:09:35.960710 1 bgp.go:48] read OPEN from "10.1.105.1:179": message type is not OPEN, got 3, want 1\n”,“stream”:“stderr”,“time”:“2017-12-13T22:09:35.961076973Z”}
Makes me think the connection to calico is hijacking the metallb connection.
Environment:
- MetalLB version: Not sure how to find this.
- Kubernetes version: Server Version: version.Info{Major:“1”, Minor:“8”, GitVersion:“v1.8.5”
- BGP router type/version: Cisco 4500 Version 03.09.00.E
- OS (e.g. from /etc/os-release): “16.04.3 LTS (Xenial Xerus)”
- Kernel (e.g.
uname -a
): Linux 4.4.0-103-generic
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 80 (24 by maintainers)
Commits related to this issue
- Allow specifying a custom router ID for BGP peering. #114 — committed to metallb/metallb by danderson 6 years ago
- Add some tests for router-id config parsing. #114 — committed to metallb/metallb by danderson 6 years ago
- Document the new router-id configuration knob. #114 — committed to metallb/metallb by danderson 6 years ago
- Document how to run MetalLB alongside Romana's route publisher addon. #114 — committed to metallb/metallb by danderson 6 years ago
- Document the new router-id configuration knob. #114 — committed to metallb/metallb by danderson 6 years ago
- Document how to run MetalLB alongside Romana's route publisher addon. #114 — committed to metallb/metallb by danderson 6 years ago
- Document the interop problem between Calico and MetalLB. #114 Given Calico's current support for BGP peering options, we can't solve the interop problem with an elegant technical solution. We're left... — committed to metallb/metallb by danderson 6 years ago
- Document the upstream Calico bugs we filed for #114. — committed to metallb/metallb by danderson 6 years ago
- Set passive mode on localhost peers This allows services like MetalLB to peer with calico https://github.com/metallb/metallb/issues/114 — committed to logan2211/calico-confd by logan2211 4 years ago
- Set passive mode on localhost peers This allows services like MetalLB to peer with calico https://github.com/metallb/metallb/issues/114 — committed to logan2211/calico-confd by logan2211 4 years ago
- Set passive mode on localhost peers This allows services like MetalLB to peer with calico https://github.com/metallb/metallb/issues/114 — committed to logan2211/calico-confd by logan2211 4 years ago
- Set passive mode on localhost peers This allows services like MetalLB to peer with calico https://github.com/metallb/metallb/issues/114 — committed to logan2211/calico-confd by logan2211 4 years ago
- Merge pull request #114 from openshift-bot/art-consistency-openshift-4.14-ose-metallb Updating ose-metallb images to be consistent with ART — committed to liornoy/metallb by openshift-merge-robot a year ago
Provide some setup guide for this please!
Sure! Check out https://gist.github.com/logan2211/bd0d8c3fd9091ddb207cde57e16d73a4
Another update here - in Calico v3.18, Calico will be capable of advertising LoadBalancer IPs allocated by the MetalLB controller without installing Speaker. https://github.com/projectcalico/confd/pull/422
Ok, I can confirm that the override above works without any issues.
All you need to do mount in that modified config, and then create a disabled IPPool in calico to get it to re-advertise the prefixes that metallb is pumping in.
Then configure your Calico Peering:
and Metallb (in this case, calico has an ASN of 65479)
Note: This needs to be an eBGP session, I got a load of errors if the ASNs are the same.
@danderson if you like I can write this up as a docs PR for you if you like?
For people wanting the exact code to mount the modified
bird.cfg.template
into calico (I haven’t tested this but it should work).Use this in your Calico manifest to inject the new bird template
And here’s an example of the v3.0.2 calico template with the patch
It’s working for me now, with Calico version 3.0.1.
I’ve hacked the
/etc/calico/confd/templates/bird.cfg.template
and altered the “Global peers” section, so BIRD is passive when the peer is 127.0.0.1. No ideal, but it’s working. I did this by just mounting my change into the Pod, I don’t want to rebuild Calico now.I added the MetalLB IP pool to calico (Create it with calicoctl). Then these IPs won’t get filtered out. I don’t yet know, what https://github.com/projectcalico/calico/issues/1604 would change here.
When I now create a local peer for Calico on each Node, MetalLB is happily connecting to it. It seems to work without a unique AS per Node or MetalLB instance.
On the Calico side:
and on the MetalLB side:
The setup is very similar to the Romana setup then.
@falfaro This isn’t something that I’ve been actively working on recently. I think Calico is missing the ability to set
passive on
in the BGP peer resource.This is the issue tracking that: https://github.com/projectcalico/calico/issues/1603 (there’s a comment explaining the work that needs to be done, and even a half-finished PR that has since been closed). It should be fairly straightforward to do, if anyone has the appetite.
Very happy to hear this @gautvenk. Thank you @caseydavenport for pushing this over the line.
@adamdunstan Sounds good, FWIW the original thought actually came from this comment here regarding kube-router and MetalLB https://github.com/metallb/metallb/issues/160#issuecomment-446708166.
@Elegant996 As I guessed. With the caveat that I havent looked at how calico is configuring bird,… I assume that its importing the interfaces from ipvs0, and advertising those routes. If I am correct you will be getting all the routes to all of the addresses that Ipvs has attached. This may be what you want, but this will include endpoints and kubeapi. You may want to modify the bird configuration (I think its in a configmap) to filter only the external addresses, and it would then advertise thoses. Make sure that ipvs is configured with the strict_arp flag. Bit of a confusing name, just means that the IPVS interface should not answer arp requests, otherwise every node will answer for those addresses locally, which doesnt really matter for routed destinations but could cause you some confusion later on… Hope I have been helpful…
Not quite, I found out that the LB should be used for service health checks as External IPs do not perform them. Instead it just throws you at one of the endpoints without checking.
That being said, when I read this over I realized something. The point of the MetalLB controller is to create the LoadBalancer IP. So if we can route to the service through an External IP, then the controller can route to it as well making it accessible through the LoadBalancer IP.
Give this a go, install MetalLB but completely remove the speaker daemonset. You should still be able to route your ingress controller on the LoadBalancer IP without issue.
Forget BGP and with MetalLB, let Calico handle it and just use MetalLB for your LoadBalancer IP 😃 This completely removes the need for peering and accomplishes the same goals. Perhaps this is sufficient to close the issue?
For now I built custom templates with a number of fixes that make calico-node operate more smoothly in a bare metal environment with MetalLB.
Patched calico-node images are available at https://github.com/logan2211/calico-node-baremetal/tree/v3.12.0
The kustomize present in the repo allows you to announce IPs from MetalLB using community string
<calico asn>:100
that will push routes through from MetalLB to your node/global calico peers without requiring creation of calico ippool resources. MetalLB community configuration is documented here.Interesting!
First off, I haven’t tried this configuration myself in about a year. I can’t think of anything that would change the behavior significantly, but that’s a point to consider.
The repro steps you described are pretty much exactly what I did. I will note that peering was intermittently successful when I tried: Calico was actively trying to connect to localhost (i.e. itself) and then disconnecting when it correctly detected the loop. If MetalLB slipped in at the right time between attempts and at the right spot in the backoff cycle, it was able to peer and break the cycle. However, it was a rare occurence on my 3-node cluster, meaning that at best 1 in 3 nodes successfully peered, and the others started spinning on hitting the backoff timers on the calico side.
One possible change to your repro to “help” with this: after Calico is configured with a localhost BGPPeer, let it sit like that for ~5min so that it can attempt+fail to connect a bunch of times. Then configure MetalLB and see if the peering works out.
If that doesn’t help, once MetalLB is Established, try removing the MetalLB speaker DaemonSet and recreating it after 5min. In both cases, the thing I’m trying to do is to give calico’s BGPd enough time to get into a backed-off state trying to reestablish the session, if that makes sense?
Your hypothesis on source IPs might be implicated… Specifically, you say you select the primary node IP as the BGP source address. Do you also configure Calico to only listen on specific addresses? Possibly the change could be that Calico is no longer listening on 127.0.0.1:179, so when MetalLB isn’t around the failure mode is nice and clean (connection refused, not “hey you have a BGP loop misconfiguration”).
Those are my thoughts so far. I’m travelling for work this week and next with minimal time to dig further, but when I get back I can try setting up a test case in virtuakube (metallb’s shiny new e2e testing setup) and see if I can give you a crisp reproduction recipe. I already have k8s+calico in the test matrix, it’s just a question of adding a test that exercises this peering config.
So, @danderson, I was working with @stevegaossou today trying to reproduce the original issues you hit while attempting this, and we didn’t see the same behaviors mentioned - Calico trying to peer with itself and hitting the backoff. In fact, we saw Calico peer with MetalLB seamlessly over 127.0.0.1 without needing passive set at all on the peering.
I’m a bit suspicious of the result, since clearly lots of folks have hit some variation of this, but wondering if there might be something we did differently that made it work… The main thought I had is that Calico is selecting its BGP source address as the primary IP of the node, which is different from the configured MetalLB peer on localhost.
The steps we took were dead simple, much like others have described above but without needing passive set. We started with the MetalLB minikube example and then:
Do you recall what differences might have existed in your test environment that might have caused this difference in result?
Thanks for thinking about more solutions! It’s definitely appreciated.
So far, I’m optimistic that the things we need will get implemented by the Calico folks, they seemed receptive to the bugs and I’ve heard that it’s on the plate for the next release.
I will investigate in more detail later today after work, but after a very quick reading of calico’s documentation, one potential hack suggests itself…
Calico supports per-node BGP peering configurations. Assuming we can get the configuration to be acceptable in terms of the BGP spec, we could make MetalLB listen for BGP on a static host port (not 179), and create per-node BGP peerings in Calico to peer with MetalLB. Basically, make calico’s bgpd on each node peer with localhost:1234, so that MetalLB can inject its routes into Calico that way.
Open questions: