Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions bindata/network/frr-k8s/003-static-pod-rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{{ if .BGPVIPManagement }}
# RBAC for the frr-k8s static pod on control plane nodes (BGP VIP
# management). The static pod authenticates with the node kubeconfig, whose
# identity is the MCO node-bootstrapper ServiceAccount.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: frr-k8s-static-pod
rules:
- apiGroups:
- frrk8s.metallb.io
resources:
- frrconfigurations
- frrk8sconfigurations
verbs:
- get
- list
- watch
# No delete: stale state objects are removed by frr-k8s's status cleaner.
- apiGroups:
- frrk8s.metallb.io
resources:
- frrnodestates
- bgpsessionstates
verbs:
- get
- list
- watch
- create
- update
- patch
- apiGroups:
- frrk8s.metallb.io
resources:
- frrnodestates/status
- bgpsessionstates/status
verbs:
- get
- update
- patch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
Comment thread
coderabbitai[bot] marked this conversation as resolved.
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: frr-k8s-static-pod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: frr-k8s-static-pod
subjects:
- kind: ServiceAccount
name: node-bootstrapper
namespace: openshift-machine-config-operator
---
# Read-only subset of the DaemonSet SA's Role in 002-rbac.yaml.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: frr-k8s-static-pod
namespace: openshift-frr-k8s
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: frr-k8s-static-pod
namespace: openshift-frr-k8s
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: frr-k8s-static-pod
subjects:
- kind: ServiceAccount
name: node-bootstrapper
namespace: openshift-machine-config-operator
{{ end }}
11 changes: 11 additions & 0 deletions bindata/network/frr-k8s/frr-k8s.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,17 @@ spec:
requests:
cpu: 10m
memory: 20Mi
{{ if .BGPVIPManagement }}
# Control plane nodes run the MCO-rendered frr-k8s static pod instead;
# on compact/SNO this DaemonSet correctly matches zero nodes.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/master
operator: DoesNotExist
{{ end }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
nodeSelector:
kubernetes.io/os: linux
tolerations:
Expand Down
45 changes: 45 additions & 0 deletions docs/bgp_vip_management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# BGP-based VIP management

Feature gate: `BGPBasedVIPManagement` (DevPreviewNoUpgrade). BareMetal
platform only, and only when the Infrastructure CR reports
`status.platformStatus.baremetal.vipManagement: BGP`. Without all three,
everything below is inert and frr-k8s behaves exactly as before.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
The FRR additional routing capability provider
(`network.operator.openshift.io/cluster`:
`spec.additionalRoutingCapabilities.providers: [FRR]`) is a hard prerequisite - it ships the FRRConfiguration CRD; when BGP
VIP management is active without it, rendering fails explicitly.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Enhancement: openshift/enhancements#1982.

## What CNO does

When active, CNO renders a single cluster-wide `FRRConfiguration`
(`openshift-frr-k8s/bgp-vip`) from the installer-generated `bgp-vip-config`
ConfigMap:

- The CR spec carries the BGP **sessions** (neighbors, optional BFD).
- VIP **advertisement** is in `rawConfig`: `redistribute table-direct 198`
filtered to exactly the API/ingress VIP prefixes, plus per-neighbor egress
permits. kube-vip (rendered by MCO) installs a VIP route into kernel table
198 only while that node's backend health check passes, so each node
advertises a VIP only while it can serve it; withdrawal is automatic.
Advertisement cannot use the CRD's `prefixes`/`toAdvertise` surface: it
renders unconditional `network` statements and cannot express redistributed
routes (native support proposed in metallb/frr-k8s#469).

## Placement

Control plane nodes run an MCO-rendered frr-k8s **static pod** (needed at
bootstrap, before any workload can schedule). The frr-k8s DaemonSet therefore
avoids masters by role under BGP VIP management; on compact/SNO topologies it
correctly matches zero nodes. Workers keep the DaemonSet and advertise the
ingress VIP when they host healthy routers.

## RBAC

The static pod authenticates with the node kubeconfig (the MCO
node-bootstrapper ServiceAccount). `003-static-pod-rbac.yaml` grants it the
reads the frr-k8s controller's informers need and write access to
`FRRNodeState`/`BGPSessionState`. Rendered only under BGP VIP management.
Per-node write scoping is not expressible in RBAC; a ValidatingAdmissionPolicy
is planned follow-up.
Loading