결론부터 말하면, 그대로 “일괄 적용”은 비추천입니다.
다만 AIStor 전용 storage node이고, 트래픽이 host network / 전용 data network 위주라면 가이드의 상당수는 적용해도 됩니다. 대신 25G×2 bond = 항상 50G처럼 동작한다고 보면 안 되고, 특히 bond mode, LACP hash, MTU, Cilium, conntrack, IOMMU 쪽은 환경에 맞게 조정해야 합니다.
MinIO 문서 자체도 이 가이드가 100G/400G 네트워크와 NVMe storage를 쓰는 high-bandwidth deployment를 위한 OS/hardware tuning이라고 설명합니다. 즉, 50G 환경에서도 참고할 수는 있지만 값들이 400G 기준으로 다소 aggressive합니다. (MinIO AIStor Documentation)
802.3ad/LACP라면 aggregate로는 50G에 가까이 쓸 수 있지만, 단일 TCP flow가 50G를 쓰는 구조는 아닙니다. Linux bonding 문서 기준으로 balance-rr을 제외한 일반적인 load-balancing bond mode에서는 단일 connection이 하나의 물리 NIC 이상의 대역폭을 쓰지 못합니다. 802.3ad도 단일 connection은 보통 한 member link, 즉 여기서는 25G 수준에 묶입니다. (Kernel.org)
AIStor는 내부 node 간 통신, 여러 client, 여러 HTTP connection, multipart, erasure set 통신 등으로 다중 flow가 많기 때문에 전체적으로는 2개 NIC를 모두 활용할 가능성이 큽니다. 하지만 특정 client가 단일 stream 또는 적은 connection으로 대용량 GET/PUT을 하면 “왜 50G가 안 나오지?”가 정상일 수 있습니다.
따라서 먼저 아래를 확인해야 합니다.
BOND=bond0
cat /proc/net/bonding/$BOND
cat /sys/class/net/$BOND/bonding/mode
cat /sys/class/net/$BOND/bonding/xmit_hash_policy
cat /sys/class/net/$BOND/bonding/slaves
권장 방향은 보통 mode=802.3ad + LACP switch 구성 + 적절한 xmit_hash_policy입니다. Red Hat 문서도 802.3ad는 LACP port grouping이 필요하고, 송신 포트 선택은 transmit hash policy에 따라 달라진다고 설명합니다. (레드햇 문서)
전용 AIStor storage node라면 아래는 비교적 무난합니다.
| 항목 | 판단 | 코멘트 |
|---|---|---|
CPU governor performance | 적용 가능 | storage 전용 node라면 latency 안정성 측면에서 유리. 전력/발열은 증가 |
THP madvise, swappiness=0 | 적용 가능 | MinIO 가이드 방향과 맞음 |
| TCP buffer max 64MiB | 적용 가능 | 50G에서는 과한 값일 수 있지만 max 값이라 보통 문제는 적음 |
ip_local_port_range=1024 65535 | 적용 가능 | 대규모 connection 환경에 유리 |
tcp_fin_timeout=15, tcp_mtu_probing=1 | 적용 가능 | 보통 무난 |
| MTU 9000 | 조건부 권장 | end-to-end 검증 필수 |
| flow control / pause frame off | 전용 TCP storage fabric이면 권장 | switch와 같이 맞춰야 함 |
| ring buffer max | 적용 가능 | 단, NIC 최대값 확인 필요 |
MINIO_API_ODIRECT 기본 유지 | 권장 | production에서 off는 비추천 |
MinIO 문서는 TCP buffer max를 64MiB로 두고, 400G 환경에서 큰 TCP window가 필요하다고 설명합니다. 50G에서는 이 값이 꼭 필요하지는 않지만, autotuning의 상한을 넉넉히 두는 성격이라 대체로 안전한 편입니다. (MinIO AIStor Documentation)
문서의 ethtool -A, ethtool -G, ethtool -K, ethtool -C는 IP가 올라간 bond0만 보고 적용하면 빠질 수 있습니다. 실제로는 bond의 slave NIC에 적용해야 합니다.
BOND=bond0
for NIC in $(cat /sys/class/net/$BOND/bonding/slaves); do
echo "### $NIC"
ethtool $NIC | egrep 'Speed|Duplex|Link detected'
ethtool -g $NIC
ethtool -a $NIC
ethtool -k $NIC | egrep 'large-receive-offload|generic-receive-offload'
done
MinIO 문서도 NIC 설정은 tuned profile과 별도로 적용하고, 각 변경을 독립적으로 테스트하라고 명시합니다. (MinIO AIStor Documentation)
MTU 9000은 50G에서도 충분히 의미가 있습니다. 다만 host만 9000으로 바꾸면 안 되고, AIStor node, client, switch port, LAG/port-channel, VLAN, Cilium 경로까지 맞아야 합니다. MinIO 문서도 switch는 9100 이상, host는 MTU 9000을 권장하고, ping -M do -s 8972로 end-to-end 검증하라고 합니다. (MinIO AIStor Documentation)
# host/node 간 jumbo frame 검증
ping -M do -s 8972 -c 3 <remote-data-ip>
우리처럼 Cilium을 쓴다면 더 주의가 필요합니다. Cilium VXLAN encapsulation은 packet당 50 bytes overhead가 있어 payload MTU가 줄어들고, jumbo frame으로 이를 완화할 수 있습니다. (Cilium 문서) 또한 Cilium Helm의 MTU 값은 host NIC MTU를 바꾸는 게 아니라 cilium_*, cilium_vxlan, lxc_health 같은 Cilium interface MTU에 영향을 주는 값입니다. (Cilium 문서)
MinIO 문서는 TCP storage traffic에서는 Ethernet pause frame이 head-of-line blocking을 만들 수 있어 rx off tx off를 권장하고, switch 쪽에서도 PFC/flow control을 끄라고 합니다. (MinIO AIStor Documentation)
다만 같은 fabric에서 RoCE/RDMA, GPU Direct RDMA, lossless storage, 다른 서비스가 같이 쓰고 있다면 일괄 off는 위험합니다. AIStor 전용 TCP data fabric이면 off가 맞고, 공유 fabric이면 switch QoS/PFC 정책과 함께 검토해야 합니다.
문서 예시는 다음처럼 고정 coalescing을 둡니다.
ethtool -C $NIC adaptive-rx off adaptive-tx off \
rx-usecs 128 tx-usecs 64 \
rx-frames 256 tx-frames 256
MinIO 문서도 latency를 낮추려면 rx-usecs를 32–64, rx-frames를 64–128로 낮추고, throughput을 높이려면 더 키우라고 합니다. (MinIO AIStor Documentation)
50G 환경에서는 처음부터 128/256으로 고정하기보다 다음 순서가 좋습니다.
# 1차: 비교적 균형
ethtool -C $NIC adaptive-rx off adaptive-tx off rx-usecs 64 tx-usecs 32 rx-frames 128 tx-frames 128
# 2차: throughput 위주 테스트
ethtool -C $NIC adaptive-rx off adaptive-tx off rx-usecs 128 tx-usecs 64 rx-frames 256 tx-frames 256
대용량 PUT/GET 위주면 높은 값이 유리할 수 있고, small object, HEAD/STAT, LIST, 인증/메타데이터성 요청이 많으면 latency가 나빠질 수 있습니다.
nf_conntrack disable은 Kubernetes/Cilium 환경에서는 그대로 하면 안 됨MinIO 문서는 dedicated storage server에서는 nf_conntrack module을 아예 load하지 않는 것이 이상적이라고 하지만, firewall rule이 필요하면 nf_conntrack_max와 timeout을 조정하라고 합니다. (MinIO AIStor Documentation)
그러나 Kubernetes/Cilium node에서는 이걸 그대로 blacklist하면 위험합니다. Cilium도 “no conntrack iptables rule”은 direct routing + full kube-proxy replacement 조건에서만 유효하다고 설명합니다. (Cilium 문서)
따라서 AIStor가 Kubernetes 위에서 동작한다면 우선은 conntrack disable이 아니라 sizing/timeout 조정 쪽이 안전합니다.
sysctl -w net.netfilter.nf_conntrack_max=800000
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=300
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=20
문서는 intel_iommu=off 또는 amd_iommu=off를 권장하면서, IOMMU는 VM passthrough와 device isolation에 유용하다고 설명합니다. (MinIO AIStor Documentation)
따라서 다음 조건이면 적용 가능성이 있습니다.
- bare-metal
- AIStor 전용 node
- VM passthrough / SR-IOV / device isolation 정책 없음
- 보안팀이 DMA isolation 비활성화를 허용
반대로 Kubernetes 노드에서 다른 workload, SR-IOV, PCI passthrough, 강한 보안 격리가 필요하면 보류하는 게 맞습니다.
MinIO의 network/storage performance 문서는 hperf, dperf, warp를 각각 network, drive, S3 application layer benchmark 도구로 설명하고, 성능 검증을 upgrade 전후 baseline/회귀 확인에 쓰라고 합니다. (MinIO AIStor Documentation)
최소한 아래 3개는 전후 비교하세요.
# AIStor internal mesh network test
mc support perf net ALIAS
# drive baseline
dperf -v /data/disk{1..20}
# S3 application benchmark
warp mixed \
--host ENDPOINT \
--access-key ACCESS_KEY \
--secret-key SECRET_KEY \
--tls \
--obj.size 10MiB \
--objects 2000 \
--concurrent 20 \
--duration 10m \
--get-distrib 45 \
--put-distrib 30 \
--stat-distrib 15 \
--delete-distrib 10 \
--autoterm
mc support perf net은 MinIO cluster internal mesh를 이용한 빠른 network throughput test로 문서에 제시되어 있습니다. (MinIO AIStor Documentation)
# TCP buffer
sysctl -w net.core.wmem_max=67108864
sysctl -w net.core.rmem_max=67108864
sysctl -w net.ipv4.tcp_rmem="4096 1048576 67108864"
sysctl -w net.ipv4.tcp_wmem="4096 1048576 67108864"
# connection handling
sysctl -w net.core.netdev_max_backlog=250000
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_fin_timeout=15
sysctl -w net.ipv4.tcp_mtu_probing=1
# memory
sysctl -w vm.swappiness=0
sysctl -w vm.vfs_cache_pressure=50
sysctl -w vm.dirty_background_ratio=3
sysctl -w vm.dirty_ratio=10
sysctl -w vm.max_map_count=524288
netdev_max_backlog=250000은 400G 기준 값이라 50G에서는 과할 수 있습니다. 그래도 queue overflow 방지에는 도움이 될 수 있지만, queueing latency를 숨길 수 있으므로 적용 후 softnet_stat, NIC drop counter, latency를 봐야 합니다.
BOND=bond0
for NIC in $(cat /sys/class/net/$BOND/bonding/slaves); do
echo "Tuning $NIC"
# Pause frame off
ethtool -A $NIC rx off tx off
# Ring buffer: 실제 max 확인 후 적용
ethtool -g $NIC
ethtool -G $NIC rx 8192 tx 8192 2>/dev/null || true
# LRO/GRO 확인
ethtool -k $NIC | egrep 'large-receive-offload|generic-receive-offload'
# Coalescing은 50G 기준으로 중간값부터 테스트
ethtool -C $NIC adaptive-rx off adaptive-tx off \
rx-usecs 64 tx-usecs 32 \
rx-frames 128 tx-frames 128
done
MinIO 문서는 ring buffer를 최대화하라고 하면서도 현재/최대값은 ethtool -g로 확인하라고 합니다. Mellanox/NVIDIA ConnectX 계열에서는 private flag 변경 후 ring buffer가 default로 돌아갈 수 있어 재적용하라는 주의도 있습니다. (MinIO AIStor Documentation)
우리 환경에서는 “그대로 적용”이 아니라 “선별 적용 + canary 검증”이 맞습니다.
가장 추천하는 기준은 이렇습니다.
적용 권장:
- CPU performance governor
- THP madvise
- swappiness=0
- TCP buffer max 64MiB
- ephemeral port range 확대
- tcp_fin_timeout / tcp_mtu_probing
- MTU 9000, 단 end-to-end 검증 후
- pause frame off, 단 전용 TCP storage fabric일 때
- ring buffer max, 단 NIC max 확인 후
- O_DIRECT 기본값 유지
조정/검증 후 적용:
- netdev_max_backlog=250000
- busy_read/busy_poll=50
- interrupt coalescing 128/64
- LRO on
- xmit_hash_policy
- Cilium MTU
- switch queue/TC mapping
그대로 적용 비추천:
- nf_conntrack blacklist
- IOMMU off
- balance-rr 사용
- MTU 9000을 host만 변경
- bond0에만 ethtool 적용하고 slave NIC 미적용
특히 25G×2 LACP에서는 단일 flow 50G를 기대하지 말고, AIStor/warp 테스트도 concurrency를 충분히 줘야 합니다. 운영 반영은 “전체 노드 일괄”보다 1개 rack 또는 일부 node canary → mc support perf net/warp/dperf 비교 → drop/latency/CPU 확인 → 전체 확대 순서가 안전합니다.
==
지금 말씀하신 조합이면, 저는 AIStor 튜닝 가이드를 일반 성능개선용으로 적용하는 단계가 아니라, RX path drop/softIRQ 병목을 장애 원인 후보 1순위로 두고 진단 + 부분 튜닝하는 단계로 보겠습니다.
특히 아래 흐름이 꽤 그럴듯합니다.
RX microburst 또는 RX queue/ring overflow
→ NIC RX drop 또는 softnet backlog drop
→ ksoftirqd / CPU softIRQ 일시 급등
→ pod 간 HTTP/RPC/health/peer check 지연 또는 timeout
→ 일부 AIStor pod가 peer를 일시적으로 불안정하게 판단
→ EC read/write tolerance 또는 quorum 관련 metric 일시 저하
→ 운 나쁘면 5xx 발생
2~3분 지속되는 quorum/tolerance 저하는 단순한 “순간 packet drop” 자체라기보다는, 초기 packet loss 이후 AIStor 내부 peer 상태 확인, retry, backoff, 재확인 주기 때문에 증상이 더 길게 보이는 것일 가능성이 있습니다.
LACP layer3+4라고 해도 Linux bond의 xmit_hash_policy는 기본적으로 송신 slave 선택 정책입니다. 즉, 내 서버에서 나가는 TX 분산은 괜찮아도, 서버로 들어오는 RX 분산은 상대 switch의 port-channel hashing 정책에 의해 결정됩니다. Linux bonding 문서도 layer3+4가 L4 port까지 hash에 사용해 peer와의 트래픽을 여러 slave로 나눌 수 있지만, 단일 connection은 여러 slave에 걸쳐 나뉘지 않는다고 설명합니다. 또한 layer3+4는 완전한 802.3ad 준수 방식은 아닐 수 있다고 명시합니다. (Kernel.org)
따라서 “bonding 50G”라고 해도 실제로는 다음 상황이 생길 수 있습니다.
- TX: host 쪽 layer3+4 hash로 두 NIC에 비교적 잘 분산
- RX: switch 쪽 hash 결과가 한쪽 25G link 또는 일부 RX queue에 쏠림
- 전체 bond 사용률은 50G 미만인데도 특정 slave NIC / 특정 RX queue에서 drop
특히 Cilium이 VXLAN/Geneve overlay를 쓰고 있으면 switch가 inner flow를 잘 못 보고 outer header 기준으로만 hash할 수 있습니다. Cilium 문서도 VXLAN encapsulation은 packet당 약 50 bytes overhead를 추가하며, native routing은 encapsulation 없이 Linux routing을 사용한다고 설명합니다. (Cilium 문서)
bond0의 rx_dropped만 보면 판단이 어렵습니다. 아래 4가지를 분리해야 합니다.
| 위치 | 의미 | 조치 방향 |
|---|---|---|
slave NIC rx_discards, rx_out_of_buffer, rx_queue_*_drops | NIC/RX ring/driver 레벨에서 못 받아서 버림 | ring, RSS queue, IRQ/NUMA, coalescing |
/proc/net/softnet_stat drop | kernel backlog가 차서 버림 | netdev_max_backlog, netdev_budget, softIRQ CPU 확보 |
switch port TX_DRP/RX_DRP, per-queue drop | switch queue/microburst/congestion | switch buffer, hashing, queue mapping, MTU |
| Cilium drop / Hubble drop | CNI/BPF/policy/MTU/conntrack 쪽 | Cilium datapath/MTU/conntrack 확인 |
Red Hat 문서도 40Gbps 이상 고속 NIC에서는 기본 network adapter/kernel 설정이 packet drop과 성능 저하 원인이 될 수 있고, RX ring은 NIC와 driver 사이에서 incoming packet을 kernel이 처리할 때까지 보관하는 지점이라고 설명합니다. 또한 drop/discard counter가 높으면 buffer가 kernel 처리 속도보다 빨리 차는 상황일 수 있다고 설명합니다. (레드햇 문서)
장애가 발생한 노드, 특히 quorum 메시지가 난 pod가 올라간 node에서 아래를 1초 단위로 잡아보는 게 좋습니다.
BOND=bond0
SLAVES=$(cat /sys/class/net/${BOND}/bonding/slaves)
echo "Bond mode/hash"
cat /proc/net/bonding/${BOND}
echo "Per-interface basic counters"
for NIC in ${BOND} ${SLAVES}; do
echo "### ${NIC}"
ip -s link show ${NIC}
cat /sys/class/net/${NIC}/statistics/rx_packets
cat /sys/class/net/${NIC}/statistics/rx_dropped
cat /sys/class/net/${NIC}/statistics/rx_errors
done
echo "NIC hardware counters"
for NIC in ${SLAVES}; do
echo "### ${NIC}"
ethtool -S ${NIC} | egrep -i \
'rx.*drop|rx.*discard|rx.*error|rx.*miss|rx.*out|rx.*buffer|queue.*drop|pause|crc|align|over'
done
echo "Softnet drop per CPU"
awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t
echo "SoftIRQ CPU"
mpstat -P ALL 1 5
/proc/net/softnet_stat에서 두 번째 column이 증가하면 backlog queue full로 인한 drop입니다. Red Hat 문서는 이 경우 net.core.netdev_max_backlog를 늘리는 방향을 제시하고, softirqd가 한 번의 NAPI polling cycle에서 packet을 충분히 처리하지 못하면 net.core.netdev_budget와 net.core.netdev_budget_usecs 조정을 고려할 수 있다고 설명합니다. (레드햇 문서)
Prometheus 쪽으로는 최소 아래를 같은 timestamp에 겹쳐 보세요.
# node별 softirq CPU
sum by (instance) (
rate(node_cpu_seconds_total{mode="softirq"}[1m])
)
# bond/slave NIC RX drop
rate(node_network_receive_drop_total{device=~"bond0|eno.*|ens.*|enp.*"}[1m])
# RX error
rate(node_network_receive_errs_total{device=~"bond0|eno.*|ens.*|enp.*"}[1m])
# TX/RX traffic이 한쪽 slave로 쏠리는지
rate(node_network_receive_bytes_total{device=~"eno.*|ens.*|enp.*"}[1m])
rate(node_network_transmit_bytes_total{device=~"eno.*|ens.*|enp.*"}[1m])
# AIStor quorum/tolerance metric과 5xx
minio_cluster_erasure_set_read_tolerance
minio_cluster_erasure_set_write_tolerance
AIStor 가이드도 ring buffer를 최대화하라고 하고, 현재/최대값은 ethtool -g로 확인하라고 합니다. 또한 ConnectX 계열 NIC에서는 private flag 변경 후 ring buffer가 기본값으로 되돌아갈 수 있어 재적용이 필요하다고 설명합니다. (MinIO AIStor Documentation)
BOND=bond0
for NIC in $(cat /sys/class/net/$BOND/bonding/slaves); do
echo "### $NIC current/max ring"
ethtool -g $NIC
done
현재 RX가 1024 이하이고 max가 4096/8192/16384라면 canary node에서 먼저 올려보세요.
for NIC in $(cat /sys/class/net/bond0/bonding/slaves); do
ethtool -G $NIC rx 8192 tx 8192
done
주의할 점은, Red Hat 문서도 driver에 따라 ring buffer 변경이 짧은 network interruption을 만들 수 있다고 설명합니다. 운영 중 전체 노드 일괄 적용은 피하고, 문제가 자주 나는 rack/node 일부에 먼저 적용하는 게 좋습니다. (레드햇 문서)
RX drop과 softIRQ spike가 같이 보인다면 “NIC가 못 받는 문제”라기보다 RX queue를 drain하는 CPU가 순간적으로 못 따라가는 문제일 수 있습니다. AIStor 문서도 NIC interrupt를 해당 PCIe slot과 가까운 NUMA node에 pinning해야 하며, remote NUMA interrupt 처리는 packet마다 memory access latency를 추가한다고 설명합니다. (MinIO AIStor Documentation)
확인:
for NIC in $(cat /sys/class/net/bond0/bonding/slaves); do
echo "### $NIC NUMA"
cat /sys/class/net/$NIC/device/numa_node
echo "### $NIC channels"
ethtool -l $NIC
echo "### $NIC IRQ"
grep -i "$NIC" /proc/interrupts | head -20
done
numactl -H
봐야 할 포인트는 다음입니다.
- RX queue가 1~2개만 active인지
- 특정 CPU 몇 개에만 IRQ가 몰리는지
- NIC NUMA node와 softIRQ 처리 CPU가 다른 socket인지
- AIStor pod CPU 사용과 ksoftirqd가 같은 CPU set에서 경쟁하는지
Kubernetes 위에서 AIStor를 돌린다면 kernel softIRQ는 pod CPU limit 안에서만 도는 게 아닙니다. node 전체 CPU 자원에서 처리됩니다. 그래서 storage node에 다른 workload가 섞여 있거나, system-reserved CPU가 부족하면 pod CPU는 여유 있어 보여도 RX 처리용 CPU가 순간적으로 밀릴 수 있습니다.
AIStor 가이드는 fixed interrupt coalescing 예시로 rx-usecs 128, rx-frames 256을 제시하고, 낮은 latency가 필요하면 rx-usecs 32-64, rx-frames 64-128로 낮추며, throughput이 필요하면 더 높이라고 설명합니다. (MinIO AIStor Documentation)
현재는 quorum check/peer check가 문제이므로 너무 크게 잡으면 latency가 늘 수 있습니다. 저는 canary로 아래 순서를 권합니다.
# 1차: 균형형
for NIC in $(cat /sys/class/net/bond0/bonding/slaves); do
ethtool -C $NIC adaptive-rx off adaptive-tx off \
rx-usecs 64 tx-usecs 32 \
rx-frames 128 tx-frames 128
done
그래도 RX drop이 계속 있고 softIRQ가 너무 튀면 다음을 테스트합니다.
# 2차: drop/throughput 완화 쪽
for NIC in $(cat /sys/class/net/bond0/bonding/slaves); do
ethtool -C $NIC adaptive-rx off adaptive-tx off \
rx-usecs 128 tx-usecs 64 \
rx-frames 256 tx-frames 256
done
small object, HEAD, LIST, IAM/STS 요청이 많은 환경에서는 coalescing을 너무 크게 하면 tail latency가 나빠질 수 있습니다. 따라서 “drop은 줄었지만 quorum check 지연이 늘어나는지”까지 같이 봐야 합니다.
netdev_max_backlog, netdev_budget는 softnet drop이 있을 때만AIStor 가이드는 400G 기준으로 net.core.netdev_max_backlog=250000을 제시합니다. 이 값은 CPU가 incoming packet을 바로 처리하지 못할 때 queue를 키워 drop을 줄이기 위한 설정입니다. (MinIO AIStor Documentation)
50G 환경에서는 바로 250000으로 가기보다 canary에서 단계적으로 올리는 게 좋습니다.
# 1차
sysctl -w net.core.netdev_max_backlog=65536
sysctl -w net.core.netdev_budget=600
sysctl -w net.core.netdev_budget_usecs=8000
# 2차 후보
sysctl -w net.core.netdev_max_backlog=131072
sysctl -w net.core.netdev_budget=1000
sysctl -w net.core.netdev_budget_usecs=10000
단, backlog를 크게 하면 drop은 줄지만 queueing latency를 숨기는 효과도 생길 수 있습니다. quorum check가 민감한 환경에서는 “drop 감소”와 “p99/p999 latency 증가”를 같이 봐야 합니다.
AIStor 문서는 host MTU 9000, switch MTU 9100 이상을 권장하고, ping -M do -s 8972로 end-to-end 검증하라고 합니다. (MinIO AIStor Documentation)
ping -M do -s 8972 -c 3 <remote-node-data-ip>
Cilium tunnel mode라면 overlay overhead 때문에 pod MTU가 host MTU와 다를 수 있습니다. Cilium 문서에 따르면 VXLAN은 packet당 약 50 bytes overhead를 추가합니다. (Cilium 문서)
따라서 아래 조합을 봐야 합니다.
# host
ip link show bond0
ip link show <slave-nic>
# cilium
kubectl -n kube-system get cm cilium-config -o yaml | egrep -i 'mtu|tunnel|routing|native|vxlan|geneve'
kubectl -n kube-system exec ds/cilium -- cilium-dbg status 2>/dev/null | egrep -i 'MTU|Routing|Tunnel'
MTU mismatch가 있으면 평소에는 멀쩡하다가 특정 크기/특정 path/특정 재전송 상황에서만 pod 간 check가 흔들릴 수 있습니다.
switch에서 다음을 확인해야 합니다.
- port-channel의 RX/TX가 두 member link에 균등한지
- 장애 시점에 특정 member link만 RX drop/TX drop이 증가하는지
- port-channel load-balance가 src-dst-ip-port인지
- VXLAN/Geneve inner header hashing을 지원/활성화하는지
- per-queue drop 또는 buffer drop이 있는지
- PFC/flow-control/lossless profile이 적용되어 있지 않은지
AIStor 문서도 switch 쪽에서 jumbo frame, multi-queue scheduling, PFC/flow control 비활성화, lossy buffer profile, 그리고 TX_DRP, RX_DRP, per-queue distribution 모니터링을 권장합니다. (MinIO AIStor Documentation)
중요한 점은, flow control을 켜서 RX drop을 숨기는 방식은 조심해야 합니다. AIStor 문서는 TCP storage traffic에서는 pause frame이 head-of-line blocking을 만들 수 있고, TCP가 이미 flow 단위 congestion control을 하므로 Ethernet-level pause frame은 해롭다고 설명합니다. (MinIO AIStor Documentation)
아래는 지금 문제의 1차 조치로는 비추천입니다.
- nf_conntrack blacklist/disable
- IOMMU off
- MINIO_API_ODIRECT off
- flow control/PFC on
- 전체 노드에 AIStor tuned profile 일괄 적용
AIStor 문서는 전용 storage server에서는 nf_conntrack 미사용을 이상적으로 제시하지만, Kubernetes/Cilium 환경에서는 service, policy, NAT, host firewall 구성에 따라 영향이 클 수 있습니다. 따라서 disable보다는 먼저 nf_conntrack_count, nf_conntrack_max, dmesg의 table full 여부를 확인하는 쪽이 안전합니다. (MinIO AIStor Documentation)
MINIO_API_ODIRECT=off도 피해야 합니다. AIStor 문서는 O_DIRECT 기본값이 on이고, production에서 off는 page cache가 무제한 커져 memory pressure/OOM을 유발할 수 있어 권장하지 않는다고 설명합니다. (MinIO AIStor Documentation)
업체가 “pod 간 check가 원활하지 않아 일시 발생하는 것 같다”고 했다면, 저는 아래를 구체적으로 요구하겠습니다.
1. 어떤 check인가?
- HTTP health check인지, internode RPC인지, disk/drive check인지
2. 어느 방향인가?
- pod A → pod B timeout인지
- 여러 pod → 특정 pod timeout인지
- 특정 node에 올라간 pod들만 timeout인지
3. timeout/error 종류는 무엇인가?
- connection refused
- connect timeout
- read timeout
- TLS handshake timeout
- EOF / reset by peer
- DNS 문제
- drive not found / disk timeout
4. check timeout/retry/backoff 값은?
- 왜 2~3분 지속되는지 설명 가능한 내부 주기가 있는지
5. MINIO_MAX_IDLE_CONNS_PER_HOST 또는 internode connection pool 관련 권장값이 있는지
AIStor 문서상 MINIO_MAX_IDLE_CONNS_PER_HOST는 node 간 idle/active HTTP connection 수를 조정해 node 간 concurrency를 조절하는 설정입니다. 다만 이건 root cause 해결 후 보조적으로 봐야지, RX drop이 있는 상태에서 먼저 만질 항목은 아닙니다. (MinIO AIStor Documentation)
현재 증상 기준으로는 이렇게 진행하는 게 가장 안전합니다.
1순위
- 장애 시점의 slave NIC별 RX drop / queue drop / out_of_buffer 확인
- /proc/net/softnet_stat second column 증가 여부 확인
- switch port-channel member별 RX/TX/drop/per-queue drop 확인
- AIStor quorum 저하 pod가 특정 node/NIC/switch leaf에 몰리는지 확인
2순위
- slave NIC RX ring max 적용
- RSS queue/channel 수 확인 및 조정
- IRQ/NUMA affinity 정리
- coalescing 64/128 → 128/256 순서로 canary
- netdev_max_backlog/netdev_budget 단계적 증가
3순위
- Cilium tunnel/native routing, MTU, VXLAN overhead 검증
- switch hashing이 overlay inner flow를 보는지 확인
- 필요 시 Cilium native routing 또는 underlay routing 구조 검토
보류
- nf_conntrack disable
- IOMMU off
- flow control/PFC on
- AIStor 전체 tuned profile 일괄 적용
요약하면, RX drop이 꽤 있고 softIRQ spike와 quorum/tolerance 저하가 시간상 맞물린다면 우연으로 보기 어렵습니다. 지금은 AIStor 자체 설정 문제라기보다 host RX 처리 능력, LACP RX 분산, switch queue/microburst, Cilium overlay/MTU를 한 묶음으로 봐야 합니다.
가장 먼저 할 일은 bond0이 아니라 각 slave NIC + softnet + switch member port 기준으로 “drop이 실제로 어디서 증가하는지”를 잡는 것입니다.