26M22a

Young-Kyoo Kim·2026년 5월 22일

결론부터 말하면, 그대로 “일괄 적용”은 비추천입니다.
다만 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)

1. 25G×2 bond에서 가장 중요한 점

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에 따라 달라진다고 설명합니다. (레드햇 문서)

2. 그대로 적용해도 대체로 괜찮은 항목

전용 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)

3. 그대로 적용하면 위험하거나 별도 검증이 필요한 항목

A. NIC tuning은 bond가 아니라 “물리 slave NIC” 기준으로 적용

문서의 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)

B. MTU 9000은 “전 구간”이 맞아야 함

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 문서)

C. flow control / PFC off는 network team과 같이 맞춰야 함

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 정책과 함께 검토해야 합니다.

D. interrupt coalescing 값은 50G에서는 낮춰서 테스트

문서 예시는 다음처럼 고정 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가 나빠질 수 있습니다.

E. 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

F. IOMMU off는 bare-metal 전용 storage node에서만

문서는 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, 강한 보안 격리가 필요하면 보류하는 게 맞습니다.

4. 25G×2 환경에서 내가 권장하는 적용 방식

1단계: 먼저 baseline 측정

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)

2단계: 안전한 OS 튜닝 먼저 적용

# 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를 봐야 합니다.

3단계: bond slave NIC에 적용

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)

5. 최종 판단

우리 환경에서는 “그대로 적용”이 아니라 “선별 적용 + 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, 재확인 주기 때문에 증상이 더 길게 보이는 것일 가능성이 있습니다.

1. TX는 괜찮고 RX drop만 많은 이유

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 문서)

2. 지금 가장 먼저 봐야 할 것은 “어떤 RX drop인가”

bond0rx_dropped만 보면 판단이 어렵습니다. 아래 4가지를 분리해야 합니다.

위치의미조치 방향
slave NIC rx_discards, rx_out_of_buffer, rx_queue_*_dropsNIC/RX ring/driver 레벨에서 못 받아서 버림ring, RSS queue, IRQ/NUMA, coalescing
/proc/net/softnet_stat dropkernel backlog가 차서 버림netdev_max_backlog, netdev_budget, softIRQ CPU 확보
switch port TX_DRP/RX_DRP, per-queue dropswitch queue/microburst/congestionswitch buffer, hashing, queue mapping, MTU
Cilium drop / Hubble dropCNI/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 처리 속도보다 빨리 차는 상황일 수 있다고 설명합니다. (레드햇 문서)

3. 바로 수집해야 할 증거

장애가 발생한 노드, 특히 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_budgetnet.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

4. 우선순위 높은 조치

4.1 slave NIC의 RX ring부터 확인/확대

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 일부에 먼저 적용하는 게 좋습니다. (레드햇 문서)

4.2 RX queue / RSS / IRQ affinity 확인

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가 순간적으로 밀릴 수 있습니다.

4.3 interrupt coalescing은 “latency vs drop” 균형으로 조정

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 지연이 늘어나는지”까지 같이 봐야 합니다.

4.4 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 증가”를 같이 봐야 합니다.

4.5 MTU는 반드시 end-to-end로 검증

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가 흔들릴 수 있습니다.

5. LACP/switch 쪽에서 꼭 확인할 것

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)

6. 지금은 적용을 미루는 게 좋은 항목

아래는 지금 문제의 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)

7. 업체에 물어볼 핵심 질문

업체가 “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)

8. 제 판단상 우선순위

현재 증상 기준으로는 이렇게 진행하는 게 가장 안전합니다.

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이 실제로 어디서 증가하는지”를 잡는 것입니다.

0개의 댓글