Document Multus CNI + Whereabouts IPAM deployment on k3s, including: - k3s path peculiarities (symlink-based multicall binary vs thick daemonset chroot) - /opt/cni/bin real-directory workaround with all plugin binaries - multus-shim/passthru symlinks to k3s CNI dir - storage-205 NAD for Longhorn 2.5G storage network (ens2, MTU 9000, whereabouts .240-.254)
6.9 KiB
title, updated, tags
| title | updated | tags | ||||||
|---|---|---|---|---|---|---|---|---|
| Multus CNI + NetworkAttachmentDefinition | 2026-04-19 |
|
개요
K3s 클러스터에 2차 네트워크 인터페이스를 Pod에 붙여줄 수 있게 해주는 meta-CNI. Flannel(기본 eth0)은 그대로 두고 k8s.v1.cni.cncf.io/networks 어노테이션으로 추가 인터페이스(net1, net2, ...) 연결.
주 용도: Longhorn storage network 분리 (192.168.205.0/24 2.5G 전용망). longhorn-storage-network도 참고.
아키텍처
Pod
├── eth0 (10.42.x.x, Flannel, 1GbE via br-uplink)
└── net1 (192.168.205.240-254, macvlan via ens2, 2.5GbE, MTU 9000)
- Multus CNI (thick daemonset): Pod 생성 시 Flannel 기본 네트워크에 추가로 NAD 기반 네트워크를 붙임
- Whereabouts: 범위 기반 IPAM (클러스터 전역 IP 충돌 방지, CRD 기반 추적)
- macvlan CNI: Pod에 ens2 부모 인터페이스의 MAC 기반 가상 인터페이스 생성
K3s 경로 특이점
K3s CNI 구조가 표준 /opt/cni/bin과 다르고 대부분 심볼릭 링크가 multicall 바이너리를 가리키는 형태라 Multus thick chroot과 충돌함. 아래 방식으로 해결:
| 경로 | 역할 |
|---|---|
/var/lib/rancher/k3s/agent/etc/cni/net.d/ |
k3s CNI conf dir (kubelet이 여기서 NetConf 읽음) |
/var/lib/rancher/k3s/data/cni/ |
k3s CNI bin dir (flannel/bridge/host-local이 multicall cni 바이너리 심볼릭) |
/var/lib/rancher/k3s/data/current/bin/cni |
실제 k3s multicall CNI 바이너리 (이름에 따라 flannel/bridge/호출 분기) |
/opt/cni/bin/ (신규, 실제 디렉토리) |
Multus/Whereabouts가 사용하는 CNI 바이너리 저장소. 모두 real binary |
/opt/cni/bin/ 내용 (각 노드 kr1/kr2/hp1/hp2):
containernetworking/plugins v1.6.2풀 셋:bandwidth,bridge,dhcp,dummy,firewall,host-device,host-local,ipvlan,loopback,macvlan,portmap,ptp,sbr,static,tap,tuning,vlan,vrfflannel← k3s multicall 바이너리 복사본 (cp /var/lib/rancher/k3s/data/current/bin/cni /opt/cni/bin/flannel)multus-shim,passthru← Multus DS init container가 배포whereabouts← Whereabouts DS가 배포
심볼릭 링크 (노드별)
K3s 기본 CNI dir과 표준 경로 브리지:
# kubelet이 k3s CNI dir에서 multus-shim 찾을 수 있게
/var/lib/rancher/k3s/data/cni/multus-shim → /opt/cni/bin/multus-shim
/var/lib/rancher/k3s/data/cni/passthru → /opt/cni/bin/passthru
# whereabouts 바이너리가 /etc/cni/net.d/whereabouts.d 기본 경로를 기대함
/etc/cni/net.d/whereabouts.d → /var/lib/rancher/k3s/agent/etc/cni/net.d/whereabouts.d
배포 정보
| 컴포넌트 | Kind | 위치 |
|---|---|---|
kube-multus-ds |
DaemonSet | kube-system |
whereabouts |
DaemonSet | kube-system |
NetworkAttachmentDefinition CRD |
CRD | cluster-scope |
ippools, overlappingrangeipreservations, nodeslicepools CRDs |
CRD | cluster-scope (whereabouts.cni.cncf.io) |
버전:
- Multus CNI:
v4.2.2(thick daemonset) - Whereabouts:
v0.9.1 - containernetworking/plugins:
v1.6.2
매니페스트 커스터마이징: 상류 manifest에서 hostPath 2개만 k3s 경로로 sed 치환:
sed -e 's|path: /etc/cni/net.d$|path: /var/lib/rancher/k3s/agent/etc/cni/net.d|g' \
-e 's|path: /etc/cni/multus/net.d$|path: /var/lib/rancher/k3s/agent/etc/cni/multus/net.d|g' \
multus-daemonset-thick.yml > multus-k3s.yml
Whereabouts도 동일(conf dir만 패치, /opt/cni/bin은 실제 디렉토리라 default 유지).
NetworkAttachmentDefinition
longhorn-system/storage-205
Longhorn 전용 2.5G 스토리지 네트워크.
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: storage-205
namespace: longhorn-system
spec:
config: |
{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "ens2",
"mode": "bridge",
"mtu": 9000,
"ipam": {
"type": "whereabouts",
"range": "192.168.205.0/24",
"range_start": "192.168.205.240",
"range_end": "192.168.205.254"
}
}
| 항목 | 값 |
|---|---|
| 부모 인터페이스 | ens2 (각 노드 2.5G NIC, 192.168.205.x/24) |
| 모드 | bridge (macvlan) |
| MTU | 9000 (jumbo frames) |
| IP 풀 | 192.168.205.240 - 192.168.205.254 (15개) |
| IPAM | whereabouts (클러스터 전역 IP 중복 체크) |
192.168.205.0/24 점유 현황 (이 NAD 도입 시점):
.100NAS (Synology) — 2.5G 스토리지 세그먼트.134hp2 /.135kr2 /.214kr1 /.227hp1 — 각 노드 ens2.240 ~ .254NAD 풀 (Longhorn instance-manager 등)
사용 방법
Pod 정의에 어노테이션 추가:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: storage-205
# 다른 네임스페이스면: k8s.v1.cni.cncf.io/networks: longhorn-system/storage-205
Pod 안에 net1 인터페이스가 whereabouts가 할당한 IP(.240-.254)로 붙음. eth0(Flannel)은 그대로.
업그레이드 시 주의
K3s 업그레이드 시 /var/lib/rancher/k3s/data/cni/ 심볼릭이 재생성될 수 있음. 아래 심볼릭 링크가 살아있는지 확인:
ls -la /var/lib/rancher/k3s/data/cni/multus-shim
ls -la /var/lib/rancher/k3s/data/cni/passthru
끊어졌으면 재생성:
sudo ln -sfn /opt/cni/bin/multus-shim /var/lib/rancher/k3s/data/cni/multus-shim
sudo ln -sfn /opt/cni/bin/passthru /var/lib/rancher/k3s/data/cni/passthru
/opt/cni/bin/는 k3s와 무관한 경로라 업그레이드 영향 없음.
트러블슈팅
failed to find plugin "X" in path [/opt/cni/bin]
Multus thick의 chroot가 /hostroot로 들어간 뒤 /opt/cni/bin/X 찾음. 원인:
/opt/cni/bin이 심볼릭이면 대상 디렉토리의 binary가 pod에 마운트 안 돼 실행 불가- 해결:
/opt/cni/bin을 real directory로 만들고 모든 플러그인을 real binary로 배치 (이 구성이 그렇게 해결됨)
config file not found (macvlan + whereabouts)
whereabouts 바이너리가 /host/etc/cni/net.d/whereabouts.d/whereabouts.conf를 찾지만 k3s는 conf를 /var/lib/rancher/k3s/agent/etc/cni/net.d/에 둠.
- 해결:
/etc/cni/net.d/whereabouts.d심볼릭 링크 생성
Multus DS pod 로그 확인
sudo kubectl -n kube-system logs -l app=multus --tail=50
테스트 Pod 예시
apiVersion: v1
kind: Pod
metadata:
name: nad-test
namespace: longhorn-system
annotations:
k8s.v1.cni.cncf.io/networks: storage-205
spec:
containers:
- name: probe
image: alpine:3.20
command: ["sh","-c","sleep 600"]
sudo kubectl -n longhorn-system exec nad-test -- ip -br addr
# eth0=10.42.x.x, net1=192.168.205.24X (whereabouts 할당)
관련 문서
- openwrt — 192.168.9.0/24 라우터
- metallb — k3s LoadBalancer (별개, service IP용)
- infra-hosts — 각 노드 ens2 IP 현황