Skip to content

Commit

Permalink
Update DHCP broadcast interface handling: (#88)
Browse files Browse the repository at this point in the history
## Description


Use 127.1.1.1/32 for the DHCP broadcast interface instead of the load balancer IP. Using the load balancer IP can cause instability with that address and routing to Kubernetes services. And as we only send broadcast packets from this interface the IP is needed but doesn't need to be in the subnet.

Make the DHCP broadcast interface name static. The dynamic number that was added to the name causes restarts on every Helm install/upgrade and is not needed.

Add ipvlan support for the DHCP broadcast interface. This allows deployment where creating and broadcasting a new Mac address can be prohibited or rejected. VMware for example by default sets forged transmits to reject and causes packets for the macvlan interface to be dropped.

Allow enabling/disabling of listening for DHCP broadcast traffic. In environments where a DHCP relay agent is employed, it can be useful to not listen for broadcast traffic at all.

## Why is this needed



Fixes: #

## How Has This Been Tested?





## How are existing users impacted? What migration steps/scripts do we need?





## Checklist:

I have:

- [ ] updated the documentation and/or roadmap (if required)
- [ ] added unit or e2e tests
- [ ] provided instructions on how to upgrade
  • Loading branch information
mergify[bot] authored Apr 1, 2024
2 parents dcdac9b + aa9ae1c commit 64c4157
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
36 changes: 27 additions & 9 deletions tinkerbell/stack/templates/nginx.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
{{- if .Values.stack.enabled }}
{{- $sourceInterface := .Values.stack.relay.sourceInterface -}}
{{- $macvlanInterfaceName := printf "%s%s" "macvlan" (randNumeric 2) -}}
{{- $ifaceModes := dict "ipvlan" "" "macvlan" "" -}}
{{- $dhcpInterfaceType := .Values.stack.relay.interfaceMode -}}
{{- if not (hasKey $ifaceModes $dhcpInterfaceType) -}}
{{- fail "invalid value at .stack.relay.interfaceMode: valid modes include ipvlan and macvlan" -}}
{{- end -}}
{{- $dhcpInterfaceName := printf "%s0" $dhcpInterfaceType -}}
{{- $listenBroadcast := true -}}
{{- if not (quote .Values.stack.relay.listenBroadcastTraffic | empty) -}}
{{- $listenBroadcast = .Values.stack.relay.listenBroadcastTraffic -}}
{{- end -}}
{{- if not $listenBroadcast -}}
{{- $dhcpInterfaceName = "eth0" -}}
{{- end -}}
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -74,7 +86,7 @@ spec:
{{- end }}
- name: {{ .Values.stack.relay.name }}
image: {{ .Values.stack.relay.image }}
args: ["-m", "{{ .Values.stack.relay.presentGiaddrAction }}", "-c", "{{ .Values.stack.relay.maxHopCount }}", "-id", "{{ $macvlanInterfaceName }}", "-iu", "eth0", "-U", "eth0", "smee.{{ .Release.Namespace }}.svc.{{ .Values.stack.clusterDomain }}."]
args: ["-m", "{{ .Values.stack.relay.presentGiaddrAction }}", "-c", "{{ .Values.stack.relay.maxHopCount }}", "-id", "{{ $dhcpInterfaceName }}", "-iu", "eth0", "-U", "eth0", "smee.{{ .Release.Namespace }}.svc.{{ .Values.stack.clusterDomain }}."]
ports:
- containerPort: 67
protocol: UDP
Expand Down Expand Up @@ -103,8 +115,9 @@ spec:
path: {{ .Values.stack.hook.downloadsDest }}
type: DirectoryOrCreate
{{- end }}
{{- if $listenBroadcast }}
initContainers:
- name: relay-macvlan-interface
- name: relay-broadcast-interface
command:
- /bin/sh
- -c
Expand All @@ -118,18 +131,23 @@ spec:
if [ -z "$srcInterface" ]; then
srcInterface=$(nsenter -t1 -n ip route | awk '/default/ {print $5}' | head -n1)
fi
# Create a macvlan interface. TODO: If this fails, try again with a different name?
nsenter -t1 -n ip link add {{ $macvlanInterfaceName }} link ${srcInterface} type macvlan mode bridge
# Create the interface. TODO: If this fails, try again with a different name?
{{- if eq $dhcpInterfaceType "ipvlan" }}
nsenter -t1 -n ip link add {{ $dhcpInterfaceName }} link ${srcInterface} type ipvlan mode l2
{{- else }}
nsenter -t1 -n ip link add {{ $dhcpInterfaceName }} link ${srcInterface} type macvlan mode bridge
{{- end }}
# Move the interface into the POD.
pid=$(echo $$)
nsenter -t1 -n ip link set {{ $macvlanInterfaceName }} netns ${pid} || nsenter -t1 -n ip link delete {{ $macvlanInterfaceName }}
# Set the macvlan interface up
ip link set {{ $macvlanInterfaceName }} up
nsenter -t1 -n ip link set {{ $dhcpInterfaceName }} netns ${pid} || nsenter -t1 -n ip link delete {{ $dhcpInterfaceName }}
# Set the interface up
ip link set {{ $dhcpInterfaceName }} up
# Set the IP address
ip addr add {{ .Values.stack.loadBalancerIP }}/32 dev {{ $macvlanInterfaceName }} noprefixroute
ip addr add 127.1.1.1/32 dev {{ $dhcpInterfaceName }} noprefixroute
image: alpine
securityContext:
privileged: true
{{- end }}
{{- if .Values.stack.service.enabled }}
---
apiVersion: v1
Expand Down
9 changes: 7 additions & 2 deletions tinkerbell/stack/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ stack:
kubevip:
enabled: true
name: kube-vip
image: ghcr.io/kube-vip/kube-vip:v0.6.3
image: ghcr.io/kube-vip/kube-vip:v0.7.2
imagePullPolicy: IfNotPresent
roleName: kube-vip-role
roleBindingName: kube-vip-rolebinding
Expand All @@ -49,7 +49,12 @@ stack:
# sourceInterface is the Host/Node interface to use for listening for DHCP broadcast packets.
# When unset, the interface from the default route will be used.
# sourceInterface: eno1
# TODO(jacobweinstock): add feature to be able to disable listening for broadcast traffic.
# enable/disable listening for broadcast traffic. Useful when the environment employs DHCP relay agent(s).
# default is true.
listenBroadcastTraffic: true
# interfaceMode determines how we create the interface needed to listen for DHCP broadcast traffic.
# by default macvlan is used. ipvlan is the only other option.
interfaceMode: macvlan

# -- Overrides
# The values defined here override those in the individual charts. Some of them require tweaking
Expand Down

0 comments on commit 64c4157

Please sign in to comment.