Page MenuHomePhabricator

Problem re-imaging hosts on row-wide vlan on EVPN switches
Closed, ResolvedPublic

Assigned To
Authored By
cmooney
May 16 2024, 9:23 PM
Referenced Files
F54144645: install2004_fwd_only.pcap
May 22 2024, 6:03 PM
F54144410: install2004_stateful_relay.pcap
May 22 2024, 6:03 PM
F53586857: contint2002.pcap
May 17 2024, 10:31 AM
F53526853: image.png
May 16 2024, 9:23 PM
F53525946: image.png
May 16 2024, 9:23 PM

Description

We had a strange issue this evening when Daniel tried to re-image contint2002 on the public1-b-codfw vlan.

Symptoms

PXEboot worked, so it seemed DHCP was ok. But during the Debian installer the system was not able to get an IP address. What was strange is that when I ran a "monitor traffic" command on lsw1-b5-codfw, where the host was connected, I could see the normal DHCP message flow working. Or at least it seemed to, we had the normal DISCOVER / OFFER / REQUEST / ACK series of messages, however the host just sent another DISCOVER every time after the ACK, instead of completing the interface configuration and moving on.

I was surprised at this as we had some issues with the DHCP config for the public vlans in testing before migrating hosts to the new switches. Those issues were resolved in T358488, and I did multiple reimage tests on the very same vlan that was having problems today.

Troubleshooting

It took us a while to spot what was going on. Daniel via the serial console dropped to a BusyBox shell and was able to execute udhcpd manually, which showed this:

udhcpc: received DHCP NAK

That seemed quite strange, as at the same time I was running a "monitor" on the switch port and no NAK could be observed, instead we seen the normal message exchange with a final ACK. To troubleshoot further I booted the system from a debian live cd image, so we could run the ISC dhclient and observe the output:

image.png (645×388 px, 75 KB)

The DHCP process worked, but you can see there are several 'NAKs' prior to the actual ACK that completes the exchange. The multiple packets immediately gave me a clue as to what might be going on.

Problem

When we originally tested this we observed that as well as the connected switch relaying the DHCP packets, every other switch participating in the vlan did also. This duplication of packets was far from ideal, but as the other switches inserted different option-82 strings (with their own hostname, and VXLAN vtep interface listed), the requests were ignored by the install server. So the only DISCOVER that got an answer was the one from the actual top-of-rack, and the DHCP exchange worked successfully.

The multiple NAKs seen today made me think it could be related to the duplicate relay packets, even though we'd tested reimage on this very vlan prior to migration. As a test I disabled the DHCP relay function for private1-b-codfw on all switches apart from the one contint2002 was connected to and ran dhclient again:

image.png (650×273 px, 55 KB)

No NAKs at all this time. So the fact that multiple switches were relaying packets was causing the problem. The multiple NAKs weren't visible when I was running "monitor" on the switch side, as they were being bridged in the vlan from the other switches on receipt from the install server ('monitor' on a Juniper only catches packets from the actual system's control plane).

Daniel tried the reimage again - with relay still disabled on the other switches - and both PXE and DHCP within the Debian installer worked.

What we know

  • The DHCP relay config on all switches participating in the stretched vlan is the cause of the NAK messages
  • The NAKs are ignored by ISC's dhclient, and the PXEboot DHCP, but they cause DHCP in the Debian installer to fail
  • This didn't happen on the exact same vlan in multiple reimage tests prior to the switch migration
    • Reason is probably that at that point the only port in the vlan across all switches was the test host
    • No other ports in an 'up' state meant the vlan and irb interface were DOWN on all other devices
    • That probably stopped them relaying dhcp packets during our tests
    • Now we have several devices in the vlan connected to different switches, so the irb int is UP on multiple switches
  • It is unclear if this only affects the public vlans, which use an 'anycast gw' with only the GW VIP on it, or if it also affects the row-wide private vlans, which have a unique per-switch IP on the irb int in addition to the GW address.
    • The significant different for the irb ints with a unicast and anycast IP is they use their individual unicast IP to send responses from the install server back to hosts.
    • On the public vlans, where the irb only has the anycast GW IP on it, all switches use that same IP to source the responses from.
    • That means the NAKs arrive on the host from the same IP as the DHCP OFFER, unlike on the stretched private vlans.

Next steps

It's unclear exactly how to tackle this one. Off the top of my head I suspect we may need to create some kind of firewall filter on the switches to block relay of DHCP packets that have been bridged from remote devices. But not sure exactly where we could place that. We might be able to contact Juniper to ask, but they mostly refuse to assist with configuration issues these days.

What we will definitely need is to get a test server set up in codfw row A or B so we can try to get to the bottom of it. @Papaul do you think that might be possible? Is there any hardware we could use?

Workaround

Until we have it fixed, if anyone needs to reimage a host on one of these vlans, we'll need to manually configure the relay function on just the switch their host is connected to.

Event Timeline

cmooney triaged this task as High priority.
cmooney updated the task description. (Show Details)

Pcap of DHCP request from contint2002 here:

One observation is that the NAK's are unique in so far as they are sent from 208.80.153.33 (Switch IRB int IP) to 255.255.255.255 (and matching L2 MACs).

The legitimate OFFER and ACK is sent from 208.80.153.33 to 208.80.153.39 (contint assigned IP), and matching MACs.

Potentially a firewall rule to "deny UDP dst-port 68, src <gw_ip>, dst 255.255.255.255" outbound on the IRB ints would block them.

Also I didn't see in the dhcpd docs and way to constrain the generation of NAKs in response to invalid REQUEST messages.

RFC2131 suggests this behaviour is ok:

3.1.4:  If the selected server is unable to satisfy the DHCPREQUEST message (e.g., the requested network address has been allocated), the server SHOULD respond with a DHCPNAK message.

The fact that udhcpc restarts the process after receiving a NAK also looks to be compliant:

3.1.5:  If the client receives a DHCPNAK message, the client restarts the configuration process.

Change #1032791 had a related patch set uploaded (by Cathal Mooney; author: Cathal Mooney):

[operations/homer/public@master] Drop NAK outbound from IRB interface with EVPN Anycast IRB

https://gerrit.wikimedia.org/r/1032791

Re-reading the man page for dhcpd.conf it seems that pontentially changing the 'authoritative' statement at the top of our config to 'not authoritative' would prevent it sending the NAKs. Might be worth a shot? Better to not create them than to filter them elsewhere. I don't believe in our environment there is any use-case where we need NAKs.

The authoritative statement

  authoritative;

  not authoritative;

  The DHCP server will normally assume that the configuration information about a given network segment is not known to be correct and is not authoritative.  This is so that if a naive user installs a DHCP server not fully understanding how to configure it, it does not send spurious DHCPNAK messages to clients that have obtained addresses from a legiti‐mate DHCP server on the network.

  Network  administrators  setting up authoritative DHCP servers for their networks should always write authoritative; at the top of their configuration file to indicate that the DHCP server should send DHCPNAK messages to misconfigured clients.  If this is not done, clients will be unable to get a correct IP address after changing subnets  until  their old lease has expired, which could take quite a long time.

  Usually,  writing authoritative; at the top level of the file should be sufficient.  However, if a DHCP server is to be set up so that it is aware of some networks for which it is authoritative and some networks for which it is not, it may be more appropriate to declare authority on a per-network-segment basis.

  Note that the most specific scope for which the concept of authority makes any sense is the physical network segment - either a shared-network statement or a  subnet  statement that is not contained within a shared-network statement.  It is not meaningful to specify that the server is authoritative for some subnets within a shared network, but not authoritative for others, nor is it meaningful to specify that the server is authoritative for some host declarations and not others.

  In order for DHCPINFORMs to be responded to by the server, they must match to subnets over which the server has authority; otherwise they will be ignored and logged.  To  minimize the impact on logging volume, only the first and every subsequent 100th occurrence of an ignored DHCPINFORM is logged.

From what I can tell the 'authoritative' statement only controls NAK generation. I think we're hitting this part of the code, and the different source address (of another switch) on the duplicate REQUESTS is why it is sending the NAKs:

https://github.com/isc-projects/dhcp/blob/572032cb0e514606559de3784e3f7ca8e1539d17/server/dhcp.c#L718

Seems the most promising option to me right now, will discuss and try to test if we can get a test host connected.

Cookbook cookbooks.sre.hosts.reimage was started by cmooney@cumin1002 for host sretest2002.wikimedia.org with OS bookworm

Mentioned in SAL (#wikimedia-operations) [2024-05-20T13:19:30Z] <topranks> adding outbound ACL on irb.2002 on lsw1 switches in codfw to test DHCP function T365204

So some interesting findings when testing today.

I was able to reproduce the issue with sretest2002, and took a PCAP of the traffic on install2004. This revealed that the install server was not generating the NAKs at all. The only DHCP REQUEST that hits the install server is the one from the switch the host is connected to, and the install server sends an ACK in response.

Looking at the pcaps closer I see the REQUEST message from the host is a broadcast, meaning it is relayed by the top of rack and also broadcast to all other ports in the vlan, reaching all other participating switches. There is a "forward-only" option to make the Juniper DHCP relay stateless, in which case I think all of them would also relay the REQUEST message from the host, but right now they are configured to operate in stateful mode.

The result is that a switch creates a DHCP binding when it sees a DHCP OFFER message being returned from our install server, for instance in this case on lsw1-b7-codfw:

cmooney@lsw1-b7-codfw> show dhcp relay binding routing-instance PRODUCTION detail 

Client IP Address:  208.80.153.42
     Hardware Address:             b0:26:28:32:a6:a0
     State:                        BOUND(RELAY_STATE_BOUND)
     Lease Expires:                2024-05-21 01:18:40 UTC
     Lease Expires in:             43200 seconds
     Lease Start:                  2024-05-20 13:18:40 UTC
     Last Packet Received:         2024-05-20 13:18:40 UTC
     Incoming Client Interface:    irb.2002:xe-0/0/9.0
     Server Ip Address:            208.80.153.105
     Server Interface:             none
     Bootp Relay Address:          208.80.153.33
     Session Id:                   271
     Generated Circuit ID:         lsw1-b7-codfw:xe-0/0/9.0:public1-b-codfw
     Relay Id Length:              31
     Relay Id:                     /0x00020000/0x00000583/0x01000000/0x62303a65
     Relay Id:                     /0x623a3766/0x3a33373a/0x39303a32/0x300000

The other switches, we never see the unicast DHCP OFFER message that gets sent to the right switch, have no such entry. When they see the DHCP REQUEST broadcast they look for such a binding, and when none is found generate a NAK themselves. You can see how this may be beneficial and reduce load on DHCP servers in some circumstances, but its not of much use to us. I had a quick look at the options for Juniper DHCP relay in this mode but couldn't find a toggle to disable this NAK generation.

So it looks like changing the install server to be not authoritative in dhcpd.conf to disable NAKs won't work for us. The install server is not generating the NAKs.

Filter on IRB int out

I also, as a test, applied the config from this change to the switches in codfw row B and tested. For whatever reason that does not seem to be having the desired affect, the host still got the NAKs:

~ # udhcpc -v -i ens2f0np0 
udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting select for 208.80.153.42, server 208.80.153.33
udhcpc: received DHCP NAK
udhcpc: has been called with an unknown param: nak
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: broadcasting select for 208.80.153.42, server 208.80.153.33
udhcpc: received DHCP NAK
udhcpc: has been called with an unknown param: nak

So if we wish to filter the packets we need another idea, possibly we can do this on the loopback interface as they are packets the device is generating itself?

Move to stateless DHCP relay

Alternatively we can investigate configuring the DHCP relay function in "forward only" mode on the switches instead. That is not compatible with our requirement for DHCP option-82 insertion on JunOS prior to 21.2R1 (see the end here), however the codfw switches are running 22.2R3.15, and we intend to upgrade eqiad (see T348977).

So another way forward may be to change the relay function to stateless / forward-only, which should stop the other switches generating the NAKs. We can see in that configuration if the install server will generate them or ignore, if it does generate them we can potentially set it to not authoritative to stop it from doing so.

Cookbook cookbooks.sre.hosts.reimage started by cmooney@cumin1002 for host sretest2002.wikimedia.org with OS bookworm executed with errors:

  • sretest2002 (FAIL)
    • Removed from Puppet and PuppetDB if present and deleted any certificates
    • Removed from Debmonitor if present
    • Forced PXE for next reboot
    • Host rebooted via IPMI
    • The reimage failed, see the cookbook logs for the details,You can also try typing "install-console" sretest2002.wikimedia.org to get a root shellbut depending on the failure this may not work.

@Papaul still getting an error on provisioning of the new server.

100.0% (1/1) success ratio (>= 100.0% threshold) for command: 'configure exclus...confirmed 1;exit'.
100.0% (1/1) success ratio (>= 100.0% threshold) of nodes successfully executed all commands.
Exception raised while executing cookbook sre.hosts.provision:
Traceback (most recent call last):

File "/usr/lib/python3/dist-packages/spicerack/_menu.py", line 250, in _run
  raw_ret = runner.run()
File "/srv/deployment/spicerack/cookbooks/sre/hosts/provision.py", line 193, in run
  configure_switch_interfaces(self.remote, self.netbox, self.netbox_data, self.verbose)
File "/srv/deployment/spicerack/cookbooks/sre/network/__init__.py", line 53, in configure_switch_interfaces
  run_junos_commands(remote_host, commands)
File "/srv/deployment/spicerack/cookbooks/sre/network/__init__.py", line 181, in run_junos_commands
  raise RuntimeError('JunOS config commit failed - see above - device may need Homer run')

RuntimeError: JunOS config commit failed - see above - device may need Homer run
Released lock for key /spicerack/locks/cookbooks/sre.hosts.provision:sretest2002: {'concurrency': 1, 'created': '2024-05-20 23:12:56.827304', 'owner': 'jhancock@cumin2002 [1614333]', 'ttl': 1800}
END (FAIL) - Cookbook sre.hosts.provision (exit_code=99) for host sretest2002.mgmt.codfw.wmnet with reboot policy FORCED

@Jhancock.wm it looks like we have another sretest2002 setup in b7 the switch has that configuration already so i went and delete the one in b7 since you have another one in a8.

papaul@lsw1-b7-codfw> show interfaces descriptions | match sretest2
 xe-0/0/9        up    up   sretest2002

Cookbook cookbooks.sre.hosts.reimage was started by jhancock@cumin2002 for host sretest2002.codfw.wmnet with OS bullseye

@cmooney I put the server in the wrong vlan. can you fix it for me. private1-a8 to private-a-codfw. thanks!

@Jhancock.wm @Papaul I'd been using the server in b7 for testing already, but I should be able to move over to the one in a8 instead (I assume we have the same problem with public1-a-codfw as we had with public1-b-codfw)

For this issue we don't need an OS installed so no need to do anything once it's racked and switch connection added in Netbox. So leave it to me from here nothing else needed I'll put it onto the public vlan and see if I can reproduce the issue there.

Cookbook cookbooks.sre.hosts.reimage was started by cmooney@cumin1002 for host sretest2002.wikimedia.org with OS bookworm

Mentioned in SAL (#wikimedia-operations) [2024-05-22T17:24:07Z] <topranks> Setting DHCP in codfw row A to 'forward-only' mode to troubleshoot DHCP bug T365204

Cookbook cookbooks.sre.hosts.reimage started by cmooney@cumin1002 for host sretest2002.wikimedia.org with OS bookworm executed with errors:

  • sretest2002 (FAIL)
    • Removed from Puppet and PuppetDB if present and deleted any certificates
    • Removed from Debmonitor if present
    • Forced PXE for next reboot
    • Host rebooted via IPMI
    • The reimage failed, see the cookbook logs for the details,You can also try typing "install-console" sretest2002.wikimedia.org to get a root shellbut depending on the failure this may not work.

Ok seems like we have a solution. I added the "forward-only" statement to the EVPN switches in codfw row A:

[edit routing-instances PRODUCTION forwarding-options dhcp-relay]
+      forward-only;

Then trying DHCP again in the debian-installer environment:

~ # udhcpc -v -i eno1 
udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting select for 208.80.153.10, server 208.80.153.105
udhcpc: lease of 208.80.153.10 obtained from 208.80.153.105, lease time 43200
~ #

Looking at the traffic on the install server everything was as expected. For reference this was the view from the install server before the change:

You can see the multiple DHCP DISCOVERS hit the server, it replies with an OFFER to the one with the correct option-82 info, and then a further REQUEST from the host which it responds to with an ACK. But the problem as discussed above is that the host's REQUEST causes the other switches in the row to send a NAK back to it when they see it, as it doesn't match any binding they have in their DHCP state table.

Chaning the DHCP option to "forward-only" disables the stateful function on the Junipers, and tbh is the kind of behaviour we ideally want (the stateful tracking has caused numerous annoyances over the years). With that in play we see this:

We see the multiple DISCOVERS like previous, followed by an OFFER. But this time we see multiple REQUEST messages also. This is because we get a relay from every switch in the row this time, rather than just the top-of-rack the host is connected to. But that's ok, the reason we see them is the other switches are relaying them now, rather than generating the NAKs. Even better the install server ignores the duplicate REQUESTS, but as before responds to the one from the top-of-rack with an ACK. And the host is happy.

The duplicate REQUESTS isn't ideal, but we can live with it it causes no issue. The 'forward-only' mode is desirable anyway as it will solve our issue from T306421 and allow us to remove the work-around. In fact using 'forward-only' was the original plan for the EVPN switch config, but we had to move away from it as prior to version 21.2R1 the insertion of option-82 information didn't work with it. That's clearly working on 22.2R3 which we have in codfw, so we can use it there to overcome this issue, and get T348977 done to roll out everywhere and drop the work-around for T306421.

Cookbook cookbooks.sre.hosts.reimage was started by cmooney@cumin1002 for host sretest2002.wikimedia.org with OS bookworm

cookbooks.sre.hosts.decommission executed by cmooney@cumin1002 for hosts: sretest2002.wikimedia.org

  • sretest2002.wikimedia.org (FAIL)
    • Host not found on Icinga, unable to downtime it
    • Found physical host
    • Downtimed management interface on Alertmanager
    • Unable to connect to the host, wipe of swraid, partition-table and filesystem signatures will not be performed: Cumin execution failed (exit_code=2)
    • Powered off
    • [Netbox] Set status to Decommissioning, deleted all non-mgmt IPs, updated switch interfaces (disabled, removed vlans, etc)
    • Configured the linked switch interface(s)
    • Removed from DebMonitor
    • Removed from Puppet master and PuppetDB

ERROR: some step on some host failed, check the bolded items above

@Papaul @Jhancock.wm I'm done with sretest2002 now and ran the decom cookbook so feel free to put it back in spares thanks.

Change #1035019 had a related patch set uploaded (by Cathal Mooney; author: Cathal Mooney):

[operations/homer/public@master] Set DHCP relay for EVPN switches in codfw to 'forward-only' mode

https://gerrit.wikimedia.org/r/1035019

Change #1032791 abandoned by Cathal Mooney:

[operations/homer/public@master] Drop NAK outbound from IRB interface with EVPN Anycast IRB

Reason:

Doesn't properly filter the NAKs, better solution is forward-only mode (see task)

https://gerrit.wikimedia.org/r/1032791

Change #1035019 merged by jenkins-bot:

[operations/homer/public@master] Set DHCP relay for EVPN switches in codfw to 'forward-only' mode

https://gerrit.wikimedia.org/r/1035019

Change has been pushed out in codfw where we have the issue. Closing this one for now, when we've completed the eqiad upgrade in T348977 we will roll it out there too but right now we've no similar "stretched" vlan there.