Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
deaf4b6a03 | ||
|
|
2818fb56b1 |
@@ -1303,6 +1303,32 @@ EOF
|
||||
done
|
||||
ok
|
||||
|
||||
# CNI=antrea swaps the CNI for a throwaway evaluation cluster only — see
|
||||
# kubernetes/cni-eval/README.md. Unset, nothing below changes. Refused on
|
||||
# the production nodes: this installs a CNI Flux does not manage, so a real
|
||||
# cluster would come up with a network no HelmRelease owns.
|
||||
if [[ "${CNI:-cilium}" == "antrea" ]]; then
|
||||
[[ "$SITE" != "homelab" ]] \
|
||||
|| fail "CNI=antrea is for throwaway clusters (vmtest/hcloudtest), not the homelab site"
|
||||
step 0 "Installing Antrea (CNI) — evaluation override..."
|
||||
ANTREA_VALUES="$REPO_ROOT/kubernetes/cni-eval/antrea-values.yaml"
|
||||
[[ -f "$ANTREA_VALUES" ]] || fail "antrea values not found at $ANTREA_VALUES"
|
||||
# >=2.6 is a hard floor, not a preference: earlier agents fail to start
|
||||
# on Talos >=1.7 after its iptables-legacy to iptables-nft switch.
|
||||
helm repo add antrea https://charts.antrea.io >/dev/null
|
||||
helm repo update antrea >/dev/null
|
||||
helm upgrade --install antrea antrea/antrea \
|
||||
--version "${ANTREA_VERSION:->=2.6.0}" \
|
||||
--namespace kube-system \
|
||||
-f "$ANTREA_VALUES" \
|
||||
--wait --timeout 10m
|
||||
ok
|
||||
# Skips the Cilium install below without duplicating the node-Ready
|
||||
# wait that follows it.
|
||||
CNI_INSTALLED=1
|
||||
fi
|
||||
|
||||
if [[ "${CNI_INSTALLED:-0}" != "1" ]]; then
|
||||
step 0 "Installing Cilium (CNI)..."
|
||||
# Must run before the node-Ready wait below: with `cni: none` the kubelet
|
||||
# reports NotReady until a CNI is present, so that loop would time out.
|
||||
@@ -1331,6 +1357,7 @@ EOF
|
||||
--wait --timeout 10m
|
||||
rm -f "$CILIUM_VALUES"
|
||||
ok
|
||||
fi
|
||||
|
||||
step 0 "Waiting for K8s nodes..."
|
||||
expected=${#ALL_NODES[@]}
|
||||
@@ -1392,6 +1419,16 @@ EOF
|
||||
echo -e " $vm_node: partition and label ${GREEN}(OK)${NC}"
|
||||
done
|
||||
|
||||
# The CNI evaluation runs here, inside the same process: KUBECONFIG
|
||||
# points at the throwaway cluster only for the life of this phase, and
|
||||
# the VMs are destroyed the moment it ends.
|
||||
if [[ "${CNI:-cilium}" == "antrea" ]]; then
|
||||
step 0 "Running the Antrea BGP evaluation..."
|
||||
"$REPO_ROOT/kubernetes/cni-eval/run-bgp-test.sh" \
|
||||
|| fail "Antrea BGP evaluation failed — see above"
|
||||
ok
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}VM rebuild test passed.${NC} ${#ALL_NODES[@]} nodes Ready on the repo's own config."
|
||||
else
|
||||
mkdir -p "$ACCESS_STAGING"
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# CNI evaluation — Antrea
|
||||
|
||||
Throwaway-cluster harness for deciding whether Antrea can replace Cilium.
|
||||
Nothing here is reconciled by Flux and nothing here runs against the homelab.
|
||||
|
||||
## Why this exists
|
||||
|
||||
Cilium ties pod east-west traffic to the kubelet's Kubernetes node IP and gives
|
||||
no way to separate them. Three attempts on the live cluster, 2026-09-08:
|
||||
|
||||
| Attempt | Result |
|
||||
|---|---|
|
||||
| `--ipv4-node`/`--ipv6-node` via `CiliumNodeConfig` | agent logged both flags at startup, still published its `mgmt0` address |
|
||||
| `directRoutingDevice: pod0` | agent logged `Direct routing device detected direct-routing-device=pod0`, still installed `10.244.2.0/24 via 10.2.40.138 dev mgmt0` |
|
||||
| tunnel and native mode, v4 and v6 | routes and tunnel endpoints always keyed to the peer's `InternalIP` |
|
||||
|
||||
That blocks issue #576: pod traffic cannot leave the management VLAN while the
|
||||
apiserver endpoints have to stay on it, because both follow the same address.
|
||||
|
||||
Antrea documents one setting covering both paths — *"The IP address used for
|
||||
tunneling **or** routing the traffic across Nodes is decided in the following
|
||||
order of preference: 1. TransportInterface 2. TransportInterfaceCIDRs 3. The
|
||||
Node IP."* Calico can do it too. Antrea fits the rest of the requirements
|
||||
better, with one exception: **its BGP is alpha**, and BGP is load-bearing here —
|
||||
every LoadBalancer VIP reaches the LAN through it.
|
||||
|
||||
So the question this harness answers is narrow: **does Antrea's alpha
|
||||
`BGPPolicy` actually hold a session with FRR and advertise what the homelab
|
||||
needs?** If it does not, the answer is Calico and this goes no further.
|
||||
|
||||
## Stage 1 — free, local
|
||||
|
||||
The QEMU provisioner gives one flat NIC per VM (`site-qemu.yaml`: *"One NIC, no
|
||||
VLANs"*), so this stage cannot test interface pinning. It tests everything else,
|
||||
at no cost:
|
||||
|
||||
Runs from the `feat/antrea-eval` branch, which is never merged:
|
||||
`bootstrap.sh` on master is the production rebuild path.
|
||||
|
||||
**In the cluster — the way to run it.** The VMs want ~40 GiB, and
|
||||
`kubernetes/vmtest-job.yaml` records that running this on the workstation
|
||||
OOM-killed the desktop session. The eval Job is that same Job with three values
|
||||
changed: the branch, `CNI=antrea`, and the clone source — the GitHub mirror is
|
||||
private and the stock Job clones it anonymously, so this one clones the
|
||||
anonymously-readable Gitea repo instead.
|
||||
|
||||
```bash
|
||||
yq -y '(select(.kind == "Job") | .spec.template.spec.containers[0].env[] | select(.name == "BRANCH") | .value) = "feat/antrea-eval"
|
||||
| (select(.kind == "Job") | .spec.template.spec.containers[0].env) += [{"name": "CNI", "value": "antrea"}]
|
||||
| (select(.kind == "Job") | .spec.template.spec.containers[0].args[0]) |= sub("https://github.com/konairius/Homelab.git"; "https://gitea.renner.uno/k.renner/homelab.git")' \
|
||||
kubernetes/vmtest-job.yaml | kubectl apply -f -
|
||||
|
||||
kubectl -n vmtest logs -f job/vmtest
|
||||
```
|
||||
|
||||
`-y` is python-yq; go-yq emits YAML without it. The Talos-only phase needs one
|
||||
secret, `ghcr-pull`; the log prints the exact command to stream it in. The BGP
|
||||
evaluation runs inside the Job once the nodes are Ready, so PASS/FAIL is in the
|
||||
log and the VMs are destroyed when it ends. The Job cannot reach this cluster:
|
||||
it mounts no service account token. Clean up with `kubectl delete namespace vmtest`.
|
||||
|
||||
**On a workstation — only with ~40 GiB to spare.** `vmtest` destroys its VMs on
|
||||
exit and exports its isolated `KUBECONFIG` only inside its own process, so hold
|
||||
them open and point the test at them explicitly:
|
||||
|
||||
```bash
|
||||
# terminal 1 — needs sudo; holds the VMs until stopped
|
||||
VMTEST_KEEP=1 CNI=antrea ./kubernetes/bootstrap.sh vmtest
|
||||
# it prints: talosctl --talosconfig /tmp/tmp.XXXXXX/talosconfig ...
|
||||
|
||||
# terminal 2 — the kubeconfig sits next to that talosconfig
|
||||
KUBECONFIG=/tmp/tmp.XXXXXX/kubeconfig ./kubernetes/cni-eval/run-bgp-test.sh
|
||||
|
||||
# teardown
|
||||
sudo talosctl cluster destroy --name bootstrap-vmtest --state /tmp/bootstrap-vmtest
|
||||
sudo rm -rf /tmp/bootstrap-vmtest
|
||||
```
|
||||
|
||||
`run-bgp-test.sh` refuses to run without an explicit `KUBECONFIG`, and refuses
|
||||
any cluster whose API is `k8s.renner.uno` or on 10.2.40.0/24, or whose nodes are
|
||||
named `k8s-1..3`.
|
||||
|
||||
What passing means:
|
||||
|
||||
- Antrea installs and runs on Talos at all (needs >= 2.6 — earlier agents fail
|
||||
to start on Talos >= 1.7 after its iptables-nft switch).
|
||||
- The cluster reaches Ready with `cluster.proxy.disabled: true`, i.e. AntreaProxy
|
||||
genuinely replaces kube-proxy, reaching the API through KubePrism.
|
||||
- `ServiceExternalIP` allocates a LoadBalancer IP.
|
||||
- `BGPPolicy` establishes with FRR from every node and advertises the pod CIDRs
|
||||
and the LoadBalancer IP — verified by reading FRR's table, not Antrea's.
|
||||
|
||||
`run-bgp-test.sh` deploys FRR as an ordinary pod standing in for the UDM: same
|
||||
ASNs as `unifi/bgp.conf` (64512/64513), dynamic neighbours via a listen range
|
||||
rather than named node addresses. Its peer address is read from the running pod
|
||||
at apply time rather than written into the manifest.
|
||||
|
||||
## Stage 2 — billed, only if stage 1 passes
|
||||
|
||||
Hetzner nodes have two interfaces and no shared L2, so this is the only place
|
||||
the two remaining requirements can be tested:
|
||||
|
||||
```bash
|
||||
CNI=antrea ./kubernetes/bootstrap.sh hcloudtest
|
||||
```
|
||||
|
||||
Uncomment `transportInterface` and `trafficEncapMode: hybrid` in
|
||||
`antrea-values.yaml` first, pointing the former at the private-network NIC while
|
||||
`site-hcloud.yaml` keeps the kubelet node IP where it is. Then confirm:
|
||||
|
||||
- pod east-west leaves on the nominated interface while the node IP does not
|
||||
move — the property Cilium cannot express;
|
||||
- `hybrid` encapsulates across a routed network, which is what the Hetzner
|
||||
cluster needs and the homelab does not.
|
||||
|
||||
`hcloudtest` bills by the hour on three cx43s and tears down from its EXIT trap.
|
||||
If a run is killed before the trap fires, `./kubernetes/bootstrap.sh hcloudclean`
|
||||
deletes by label.
|
||||
|
||||
## What this harness does not cover
|
||||
|
||||
- **Policy migration.** 59 `CiliumNetworkPolicy` objects across 34 files, using
|
||||
`fromEntities`/`toEntities` in 15, typed ICMP in 24, and `toFQDNs` in
|
||||
`trmnl-ns.yaml`. Antrea has equivalents including FQDN egress in OSS, but the
|
||||
port is real work and is not tested here.
|
||||
- **Multus.** Required either way — Antrea's native secondary networks are VLAN
|
||||
and SR-IOV only, and all six NADs are macvlan or host-device. Unchanged by a
|
||||
CNI swap.
|
||||
- **In-place migration.** There isn't one. Talos documents CNI choice as
|
||||
bootstrap-time only, and a Sidero maintainer's guidance is *"much easier to
|
||||
redeploy the cluster from scratch"*. Adopting Antrea means a cold rebuild.
|
||||
|
||||
## Cleanup
|
||||
|
||||
```bash
|
||||
kubectl delete namespace cni-eval
|
||||
kubectl delete bgppolicy cni-eval-peer
|
||||
kubectl delete externalippool cni-eval-lb
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
# Antrea Helm values for the CNI evaluation. Not reconciled by Flux; used only
|
||||
# by `CNI=antrea ./bootstrap.sh vmtest` and `hcloudtest`.
|
||||
|
||||
# Talos blocks CAP_SYS_MODULE for workloads and builds openvswitch into its
|
||||
# kernel, so the modprobe init step is skipped rather than granted.
|
||||
agent:
|
||||
dontLoadKernelModules: true
|
||||
installCNI:
|
||||
securityContext:
|
||||
capabilities: []
|
||||
|
||||
# talos/patches/cluster.yaml sets cluster.proxy.disabled, so there is no
|
||||
# kube-proxy: AntreaProxy has to serve every Service type, and the agent has to
|
||||
# reach the API server through KubePrism rather than a Service IP.
|
||||
antreaProxy:
|
||||
proxyAll: true
|
||||
kubeAPIServerOverride: "localhost:7445"
|
||||
|
||||
# BGPPolicy is alpha and off by default. ServiceExternalIP is the LoadBalancer
|
||||
# IPAM; on by default since 2.3, named here so the manifest states it.
|
||||
featureGates:
|
||||
BGPPolicy: true
|
||||
ServiceExternalIP: true
|
||||
|
||||
# Matches --service-cluster-ip-range in talos/patches/cluster.yaml.
|
||||
serviceCIDR: 10.96.0.0/12
|
||||
serviceCIDRv6: fd10:96::/112
|
||||
|
||||
# Stage 2 only (hcloudtest, two NICs). Pins pod east-west to a named interface
|
||||
# while the kubelet node IP stays where it is — the property Cilium cannot
|
||||
# express. Left unset here because the QEMU provisioner gives one flat NIC.
|
||||
# transportInterface: ""
|
||||
# trafficEncapMode: hybrid
|
||||
@@ -0,0 +1,48 @@
|
||||
# What the test asks Antrea to advertise. Applied after frr-peer.yaml.
|
||||
# __FRR_PEER_IP__ is substituted by run-bgp-test.sh from the running FRR pod —
|
||||
# not written here, because it is a lease, not an identity.
|
||||
---
|
||||
apiVersion: crd.antrea.io/v1beta1
|
||||
kind: ExternalIPPool
|
||||
metadata:
|
||||
name: cni-eval-lb
|
||||
spec:
|
||||
ipRanges:
|
||||
- start: 10.99.99.10
|
||||
end: 10.99.99.20
|
||||
nodeSelector: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: lb-probe
|
||||
namespace: cni-eval
|
||||
annotations:
|
||||
service.antrea.io/external-ip-pool: cni-eval-lb
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
selector:
|
||||
app: frr
|
||||
ports:
|
||||
- port: 179
|
||||
targetPort: 179
|
||||
---
|
||||
apiVersion: crd.antrea.io/v1alpha1
|
||||
kind: BGPPolicy
|
||||
metadata:
|
||||
name: cni-eval-peer
|
||||
spec:
|
||||
nodeSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/os: linux
|
||||
localASN: 64513
|
||||
listenPort: 179
|
||||
advertisements:
|
||||
pod: {}
|
||||
service:
|
||||
ipTypes:
|
||||
- LoadBalancerIP
|
||||
bgpPeers:
|
||||
- address: __FRR_PEER_IP__
|
||||
asn: 64512
|
||||
port: 179
|
||||
@@ -0,0 +1,106 @@
|
||||
# FRR standing in for the UDM, so Antrea's BGP can be tested without one.
|
||||
# Mirrors unifi/bgp.conf where it matters: same ASNs, dynamic neighbours via a
|
||||
# listen range rather than named node addresses.
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: cni-eval
|
||||
labels:
|
||||
# Talos enforces baseline, which rejects the NET_ADMIN and NET_RAW zebra
|
||||
# needs. Throwaway cluster only.
|
||||
pod-security.kubernetes.io/enforce: privileged
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: frr-config
|
||||
namespace: cni-eval
|
||||
data:
|
||||
daemons: |
|
||||
bgpd=yes
|
||||
zebra=yes
|
||||
vtysh_enable=yes
|
||||
bgpd_options="-A 127.0.0.1"
|
||||
zebra_options="-A 127.0.0.1 -s 90000000"
|
||||
frr.conf: |
|
||||
frr defaults traditional
|
||||
hostname frr-eval
|
||||
log stdout informational
|
||||
!
|
||||
router bgp 64512
|
||||
bgp router-id 172.31.255.1
|
||||
no bgp ebgp-requires-policy
|
||||
bgp listen range 0.0.0.0/0 peer-group K8S
|
||||
bgp listen range ::/0 peer-group K8S
|
||||
neighbor K8S peer-group
|
||||
neighbor K8S remote-as 64513
|
||||
neighbor K8S timers 30 90
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor K8S activate
|
||||
neighbor K8S soft-reconfiguration inbound
|
||||
exit-address-family
|
||||
!
|
||||
address-family ipv6 unicast
|
||||
neighbor K8S activate
|
||||
neighbor K8S soft-reconfiguration inbound
|
||||
exit-address-family
|
||||
!
|
||||
line vty
|
||||
!
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: frr
|
||||
namespace: cni-eval
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: frr
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: frr
|
||||
spec:
|
||||
# /etc/frr must be writable for the daemons and vtysh; a ConfigMap mount
|
||||
# is not. Seeded from the image's own defaults plus the ConfigMap.
|
||||
initContainers:
|
||||
- name: seed-config
|
||||
image: quay.io/frrouting/frr:10.2.1
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- cp -a /etc/frr/. /frr-etc/ && cp /config/frr.conf /config/daemons /frr-etc/
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /config
|
||||
- name: etc
|
||||
mountPath: /frr-etc
|
||||
containers:
|
||||
- name: frr
|
||||
image: quay.io/frrouting/frr:10.2.1
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- NET_ADMIN
|
||||
- NET_BIND_SERVICE
|
||||
- NET_RAW
|
||||
ports:
|
||||
- containerPort: 179
|
||||
name: bgp
|
||||
volumeMounts:
|
||||
- name: etc
|
||||
mountPath: /etc/frr
|
||||
- name: run
|
||||
mountPath: /var/run/frr
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: frr-config
|
||||
- name: etc
|
||||
emptyDir: {}
|
||||
- name: run
|
||||
emptyDir: {}
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Verifies Antrea's alpha BGPPolicy against an FRR peer. Answers exactly one
|
||||
# question: does the session establish and carry the routes the homelab needs
|
||||
# (pod CIDRs and LoadBalancer IPs). Everything it asserts is read back from
|
||||
# FRR, not from Antrea's own view of what it advertised.
|
||||
#
|
||||
# kubernetes/cni-eval/run-bgp-test.sh
|
||||
#
|
||||
# Expects a cluster already built with CNI=antrea. Leaves the cni-eval
|
||||
# namespace behind for inspection; the cleanup line is printed at the end.
|
||||
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
RED=$'\033[0;31m'; GREEN=$'\033[0;32m'; YELLOW=$'\033[1;33m'; NC=$'\033[0m'
|
||||
fail() { echo "${RED}FAIL${NC} $*" >&2; exit 1; }
|
||||
pass() { echo "${GREEN}PASS${NC} $*"; }
|
||||
info() { echo "${YELLOW}==>${NC} $*"; }
|
||||
|
||||
# vmtest and hcloudtest export their isolated KUBECONFIG only inside their own
|
||||
# process. A shell that runs this afterwards gets the default kubeconfig, which
|
||||
# is production. Refuse unless pointed at a throwaway cluster explicitly.
|
||||
[[ -n "${KUBECONFIG:-}" ]] \
|
||||
|| fail "set KUBECONFIG to the throwaway cluster's kubeconfig — the default one is production"
|
||||
server=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
|
||||
case "$server" in
|
||||
*k8s.renner.uno*|*10.2.40.*) fail "KUBECONFIG points at production ($server) — refusing" ;;
|
||||
esac
|
||||
node_names=$(kubectl get nodes -o name)
|
||||
if grep -qx 'node/k8s-[123]' <<<"$node_names"; then
|
||||
fail "this cluster has production node names — refusing"
|
||||
fi
|
||||
pass "target is a throwaway cluster ($server)"
|
||||
|
||||
info "Checking Antrea is the running CNI..."
|
||||
kubectl -n kube-system get daemonset antrea-agent >/dev/null \
|
||||
|| fail "antrea-agent DaemonSet not found — was the cluster built with CNI=antrea?"
|
||||
|
||||
info "Confirming the BGPPolicy feature gate is on..."
|
||||
gates=$(kubectl -n kube-system get configmap antrea-config -o jsonpath='{.data.antrea-agent\.conf}')
|
||||
grep -q 'BGPPolicy: *true' <<<"$gates" \
|
||||
|| fail "BGPPolicy feature gate is not enabled in antrea-config"
|
||||
pass "BGPPolicy enabled"
|
||||
|
||||
info "Deploying the FRR peer..."
|
||||
kubectl apply -f "$DIR/frr-peer.yaml"
|
||||
kubectl -n cni-eval rollout status deployment/frr --timeout=180s \
|
||||
|| fail "FRR did not become ready"
|
||||
|
||||
# Read the address rather than assign one: the peer is a pod, and its address
|
||||
# is whatever the CNI under test gave it.
|
||||
frr_ip=$(kubectl -n cni-eval get pod -l app=frr -o jsonpath='{.items[0].status.podIP}')
|
||||
[[ -n "$frr_ip" ]] || fail "FRR pod has no IP"
|
||||
pass "FRR peer at $frr_ip"
|
||||
|
||||
info "Applying ExternalIPPool, LoadBalancer Service and BGPPolicy..."
|
||||
sed "s|__FRR_PEER_IP__|$frr_ip|" "$DIR/bgp-test.yaml" | kubectl apply -f -
|
||||
|
||||
info "Waiting for a LoadBalancer IP (ServiceExternalIP)..."
|
||||
lb=""
|
||||
for _ in $(seq 1 30); do
|
||||
lb=$(kubectl -n cni-eval get svc lb-probe -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
[[ -n "$lb" ]] && break
|
||||
sleep 5
|
||||
done
|
||||
[[ -n "$lb" ]] || fail "no LoadBalancer IP assigned after 150s — ServiceExternalIP did not allocate"
|
||||
pass "LoadBalancer IP $lb"
|
||||
|
||||
frr_pod=$(kubectl -n cni-eval get pod -l app=frr -o jsonpath='{.items[0].metadata.name}')
|
||||
|
||||
info "Waiting for BGP sessions to establish..."
|
||||
nodes=$(kubectl get nodes -o name | wc -l)
|
||||
established=0
|
||||
for _ in $(seq 1 36); do
|
||||
# The text summary shows an established peer as a prefix count, not a state
|
||||
# name; the per-neighbour JSON carries bgpState explicitly.
|
||||
neighbors=$(kubectl -n cni-eval exec "$frr_pod" -- vtysh -c 'show ip bgp neighbor json' || true)
|
||||
established=$(jq '[.[] | select(type == "object" and .bgpState == "Established")] | length' <<<"$neighbors" || echo 0)
|
||||
established=${established:-0}
|
||||
[[ "$established" -ge "$nodes" ]] && break
|
||||
sleep 5
|
||||
done
|
||||
kubectl -n cni-eval exec "$frr_pod" -- vtysh -c 'show ip bgp summary'
|
||||
[[ "$established" -ge "$nodes" ]] \
|
||||
|| fail "only $established of $nodes sessions established after 180s"
|
||||
pass "$established/$nodes sessions established"
|
||||
|
||||
info "Checking the advertised routes as FRR sees them..."
|
||||
kubectl -n cni-eval exec "$frr_pod" -- vtysh -c 'show ip bgp'
|
||||
routes=$(kubectl -n cni-eval exec "$frr_pod" -- vtysh -c 'show ip bgp json')
|
||||
|
||||
# Exact prefix keys rather than substring matches.
|
||||
advertised() { jq -e --arg p "$1" '.routes | has($p)' <<<"$routes" >/dev/null; }
|
||||
|
||||
pod_cidrs=$(kubectl get nodes -o jsonpath='{range .items[*]}{.spec.podCIDR}{"\n"}{end}')
|
||||
missing=0
|
||||
while read -r cidr; do
|
||||
[[ -z "$cidr" ]] && continue
|
||||
if advertised "$cidr"; then
|
||||
pass "pod CIDR $cidr advertised"
|
||||
else
|
||||
echo "${RED}FAIL${NC} pod CIDR $cidr NOT advertised"
|
||||
missing=1
|
||||
fi
|
||||
done <<<"$pod_cidrs"
|
||||
|
||||
if grep -qF "$lb" <<<"$routes"; then
|
||||
pass "LoadBalancer IP $lb advertised"
|
||||
else
|
||||
echo "${RED}FAIL${NC} LoadBalancer IP $lb NOT advertised"
|
||||
missing=1
|
||||
fi
|
||||
|
||||
[[ "$missing" -eq 0 ]] || fail "one or more expected prefixes were not advertised"
|
||||
|
||||
echo
|
||||
pass "Antrea BGPPolicy carried pod CIDRs and LoadBalancer IPs to FRR."
|
||||
echo "Clean up: kubectl delete namespace cni-eval && kubectl delete bgppolicy cni-eval-peer && kubectl delete externalippool cni-eval-lb"
|
||||
Reference in New Issue
Block a user