infra/network: add multus.md (Multus CNI + storage-205 NAD)
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)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: network 인덱스
|
title: network 인덱스
|
||||||
updated: 2026-04-16
|
updated: 2026-04-19
|
||||||
tags: [moc, network]
|
tags: [moc, network]
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ tags: [moc, network]
|
|||||||
| [[gateway-api]] | K3s Gateway API (Traefik 메인 라우팅) |
|
| [[gateway-api]] | K3s Gateway API (Traefik 메인 라우팅) |
|
||||||
| [[k3s-ingress-architecture]] | K3s 인그레스 아키텍처 (Traefik + APISIX 병렬) |
|
| [[k3s-ingress-architecture]] | K3s 인그레스 아키텍처 (Traefik + APISIX 병렬) |
|
||||||
| [[metallb]] | MetalLB K3s LoadBalancer |
|
| [[metallb]] | MetalLB K3s LoadBalancer |
|
||||||
|
| [[multus]] | Multus CNI + NAD (Pod 2차 인터페이스, storage-205 NAD) |
|
||||||
| [[openwrt]] | OpenWrt 라우터 (서울, HAProxy/nftables) |
|
| [[openwrt]] | OpenWrt 라우터 (서울, HAProxy/nftables) |
|
||||||
| [[smtp-relay]] | smtp-relay K3s 내부 SMTP 게이트웨이 (Mailgun) |
|
| [[smtp-relay]] | smtp-relay K3s 내부 SMTP 게이트웨이 (Mailgun) |
|
||||||
| [[sshpiper]] | sshpiper SSH 리버스 프록시 |
|
| [[sshpiper]] | sshpiper SSH 리버스 프록시 |
|
||||||
|
|||||||
199
infra/network/multus.md
Normal file
199
infra/network/multus.md
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
---
|
||||||
|
title: Multus CNI + NetworkAttachmentDefinition
|
||||||
|
updated: 2026-04-19
|
||||||
|
tags: [infra, k3s, multus, cni, networking, longhorn]
|
||||||
|
---
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
|
||||||
|
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`, `vrf`
|
||||||
|
- `flannel` ← 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과 표준 경로 브리지:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# 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 치환:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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 스토리지 네트워크.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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 도입 시점):
|
||||||
|
|
||||||
|
- `.100` NAS (Synology) — 2.5G 스토리지 세그먼트
|
||||||
|
- `.134` hp2 / `.135` kr2 / `.214` kr1 / `.227` hp1 — 각 노드 ens2
|
||||||
|
- `.240 ~ .254` NAD 풀 (Longhorn instance-manager 등)
|
||||||
|
|
||||||
|
## 사용 방법
|
||||||
|
|
||||||
|
Pod 정의에 어노테이션 추가:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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/` 심볼릭이 재생성될 수 있음. 아래 심볼릭 링크가 살아있는지 확인:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ls -la /var/lib/rancher/k3s/data/cni/multus-shim
|
||||||
|
ls -la /var/lib/rancher/k3s/data/cni/passthru
|
||||||
|
```
|
||||||
|
|
||||||
|
끊어졌으면 재생성:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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 로그 확인
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo kubectl -n kube-system logs -l app=multus --tail=50
|
||||||
|
```
|
||||||
|
|
||||||
|
### 테스트 Pod 예시
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
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"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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 현황
|
||||||
Reference in New Issue
Block a user