Helm이 Kubernetes 위의 워크로드를 관리하는 도구라면, Kubespray/AWX(Ansible)는 Kubernetes 클러스터 그 자체와 하부 인프라를 프로비저닝하는 도구입니다.
Helm의 values.yaml에 1:1로 대응되는 Kubespray의 설정 관리 체계와, OS 커널 파라미터 등 노드 레벨의 설정을 엔터프라이즈 환경에서 관리하는 Best Practice를 정리해 드립니다.
values.yaml에 해당하는 것Kubespray는 내부적으로 Ansible 기반으로 동작하므로, Helm의 values.yaml에 정확히 대응되는 것은 Ansible의 인벤토리 변수 파일(Inventory Variables, group_vars)입니다.
Kubespray 프로젝트 디렉터리 내의 inventory/mycluster/group_vars/ 하위 파일들이 바로 그것입니다.
inventory/mycluster/
├── inventory.ini (또는 hosts.yaml) # 노드 IP, 호스트명, 롤(마스터, 워커) 정의
└── group_vars/
├── all/ # [모든 노드 공통 설정]
│ ├── all.yml # 프록시(에어갭), 사내 Nexus 레지스트리 미러, HTTP 프록시 등
│ ├── docker.yml / containerd.yml# 컨테이너 런타임 옵션 (Cgroup 드라이버, 레지스트리 미러)
│ └── offline.yml # 에어갭 다운로드 URL, 로컬 바이너리 경로
└── k8s_cluster/ # [Kubernetes 클러스터 컴포넌트 설정]
├── k8s-cluster.yml # K8s 버전, Service/Pod CIDR, 네트워크 플러그인(Cilium 등)
├── k8s-net-cilium.yml # CNI 상세 옵션 (Native Routing, eBPF Host Routing 등)
└── addons.yml # Metrics Server, Local Path Provisioner 등 기본 애드온
values.yaml vs Kubespray group_vars 비교| 구분 | Helm (values.yaml) | Kubespray (group_vars/*.yml) |
|---|---|---|
| 관리 대상 | Deployment, Service, ConfigMap 등 K8s 리소스 | kube-apiserver, kubelet, containerd, CNI, OS 파라미터 |
| 설정 주입 방식 | helm install -f my-values.yaml | ansible-playbook -i inventory/mycluster cluster.yml |
| AWX(타워) 연동 | Helm CLI 인자 또는 ArgoCD Repo | AWX Survey Variable 또는 Git 기반 Extra Vars |
| 버전 관리 | Git (GitOps) | Git (인벤토리 전용 Git 저장소 분리 권장) |
AWX에서의 실무 운영 팁:
Kubespray 소스 코드가 들어있는 Git 저장소와 사내 클러스터별 인벤토리(inventory/mycluster) 저장소를 별도 Git Repo로 분리합니다. AWX에서는 인벤토리 Repo를 바라보게 하고, 설정 변경이 필요할 때 Git PR을 거쳐 Merge한 뒤 AWX Job Template을 실행하도록 파이프라인을 구성합니다.
K8s 상위 컴포넌트(apiserver, kubelet)와 달리, OS 커널 파라미터(sysctl), 디스크 마운트 옵션, HugePages, CPU 거버너, Ulimit 등은 "노드 레벨(Host OS)"의 영역입니다.
대규모 베어메탈/온프레미스 환경에서 이를 관리하는 표준 접근법 3가지와 권장 조합입니다.
Kubespray 자체에 노드 커널 파라미터를 주입할 수 있는 변수 슬롯이 내장되어 있습니다.
inventory/mycluster/group_vars/all/all.yml# Kubespray 실행 시 /etc/sysctl.d/99-sysctl.conf에 자동 반영됨
sysctl_file_spec:
- name: 99-kubernetes-custom.conf
rules:
- { name: net.core.somaxconn, value: 65535 }
- { name: net.netfilter.nf_conntrack_max, value: 2097152 }
- { name: vm.max_map_count, value: 2621440 }
- { name: fs.inotify.max_user_watches, value: 1048576 }
- { name: net.ipv4.conf.all.rp_filter, value: 2 }
인프라 운영 성숙도가 높은 엔터프라이즈 환경에서 가장 널리 쓰이는 표준 아키텍처입니다. "OS 베이스라인 설정"과 "K8s 설치"를 완전히 독립된 라이프사이클로 분리합니다.
[ 신규 베어메탈 노드 인도 ]
│
▼
[ Step 1: Base OS Provisioning (AWX/Ansible) ]
- 사내 공통 보안 정책 적용
- /etc/security/limits.d/ (Ulimit) 설정
- /etc/sysctl.d/99-k8s.conf (네트워크/메모리 커널 파라미터)
- NIC 점보 프레임 (MTU 9000), 링 버퍼(Ring Buffer 4096) 설정
- GPU 노드인 경우: NVIDIA Driver .run, Fabric Manager 설치
│ (인수 테스트 통과)
▼
[ Step 2: K8s Clustering (Kubespray Playbook) ]
- Containerd, Kubelet 배포
- etcd, Control Plane 구성
- CNI(Cilium) 배포
os-baseline-tuning이라는 별도의 Ansible Job Template을 만듭니다. 이 플레이북은 사내 공통 템플릿(templates/sysctl.conf.j2)을 배포하고 sysctl --system을 실행하는 역할만 담당합니다.노드가 이미 K8s 클러스터에 조인된 이후, K8s GitOps 파이프라인(ArgoCD)을 통해 호스트 OS 커널 파라미터를 선언적으로 관리하는 방식입니다.
/etc/sysctl.d에 파일을 쓰고 nsenter로 호스트 네임스페이스에서 sysctl을 적용합니다.apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-tuning-operator
namespace: kube-system
spec:
selector:
matchLabels:
app: node-tuning
template:
metadata:
labels:
app: node-tuning
spec:
hostPID: true
containers:
- name: sysctl-tuner
image: nexus.internal:8082/ubi9/ubi-minimal:latest
securityContext:
privileged: true
command: ["/bin/sh", "-c"]
args:
- |
cat <<EOF > /host/etc/sysctl.d/99-k8s.conf
net.core.somaxconn = 65535
net.netfilter.nf_conntrack_max = 2097152
vm.max_map_count = 2621440
EOF
nsenter --target 1 --mount --uts --ipc --net --pid -- sysctl --system
sleep infinity
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /
nodeSelector)을 통해 GPU 노드, 스토리지 전용 노드별로 서로 다른 sysctl을 자동 적용하기 매우 좋습니다.kube-apiserver, CNI, etcd 등):group_vars/*.yml을 Git 저장소로 형상 관리하고, AWX를 통해 변경 사항을 제어합니다.===
요약
목표: RHEL 10.2 기반 NVIDIA B300·Intel E810 노드의 전달 전 검수(check-in)용 표준 인수테스트 및 커널 설정.
대상: Intel Xeon 서버, B300 GPU, Intel E810 NIC, RHEL 10.2, Kubernetes 클러스터(Cilium, AIStor/MinIO), Keycloak/Vault 등 일반 앱.
테스트 포인트: 스위치→물리 NIC→PCIe→CPU/NUMA→커널 네트워크 스택→CNI(eBPF)→파드 네트워크 경로 검증, CPU/메모리 부하 검증 등.
절차: BIOS/하드웨어 설정 확인, OS/커널 튜닝 적용, Kubernetes 노드 설정 검증, 단계별 T1~Tn 테스트 수행(하드웨어→네트워크→K8s).
커널 파라미터: net.core.netdev_max_backlog, rmem_max/wmem_max, tcp_rmem/wmem, somaxconn, swappiness, dirty_ratio, CPU governor 등.
Kubernetes 설정: systemd cgroup, --kube-reserved/--system-reserved, CPU Manager static, Topology Manager 정책, hugepages.
모니터링: Prometheus(node_exporter, cAdvisor, kubelet, Cilium 지표 등) 기반 CPU·메모리·네트워크·인터럽트·패킷 손실 등 감시.
문서출처: RHEL/Tuned 성능가이드, Intel NIC 성능 안내, Kubernetes 공식 문서, Cilium 요구사항 등.
1. 하드웨어/BIOS 점검
BIOS 설정: CPU 전원관리(performance 모드), 모든 C-State 비활성(혹은 C1만 허용, intel_idle.max_cstate=1 커널 파라미터), 에러검출(ECC) 최소화, CPU 토폴로지 수동 설정(예: MADT Core Enumeration을 Linear로), 인터럽트/타이머를 특정 코어에 제한(Reserved CPUs).
CPU: Turbo Boost 정상, SpeedStep/performance governor(cpupower frequency-set -g performance), SMT(Hyper-threading) 고려(성능 테스트 후 결정).
NIC/PCIe:
lspci: PCIe 슬롯 대역폭(x8/x16) 확인.
ethtool -i : 드라이버(ice), 펌웨어 버전 확인. 공식 Intel i225/ice 드라이버 권장.
링크 속도/모드: 25GbE 혹은 RoCE 사용시 RDMA 모드 등 확인.
리던던시: 2포트 NIC인 경우 bonding(LACP)시 승리/라운드로빈 설정 및 mode=802.3ad 확인.
IRQ와 NUMA: 인터럽트가 NUMA 노드에 고루 분배되도록 irqbalance 활성화하거나, 필요시 특정 코어로 고정(예: Tuned net-iplus 프로파일). Intel 권장: IRQ affinity 수동 설정(채널 수 조정) 및 CPU affinity 조정.
GPU: NVIDIA 드라이버, Fabric Manager, NVSwitch 정상 로드.
mermaid
복사
flowchart LR
Switch[외부 네트워크 (스위치)] --> NIC[Intel E810 NIC]
NIC -->|PCIe x8| PCIe[PCIe 버스]
PCIe --> CPU[Intel Xeon CPU]
CPU --> Kernel["커널 네트워크 스택"]
Kernel --> Cilium[Cilium eBPF 데이터경로]
Cilium --> PodNetwork[파드 네트워크 인터페이스]
PodNetwork --> Application[컨테이너 애플리케이션]
그림: 물리 NIC에서 파드 네트워크에 이르는 데이터 경로. 하드웨어→커널→CNI(eBPF)→파드.
(※ 위 수치는 일반적인 레퍼런스 예시입니다. 실제 환경 부하에 따라 유연 조정하고, 각 설정 변경 전후 성능/모니터링을 수행하십시오.)
ID 테스트 (목적) 사전조건 명령어/컨테이너 측정 지표 PASS 기준
T1 OS 기본 검증 (CPU, 메모리, 커널) 노드 부팅 완료, BIOS 설정 완료 lscpu, free -m, uname -r, dmesg CPU 수, 메모리 크기, 커널 버전, XID 에러 하드웨어 사양 일치, XID 에러 없음
T2 NIC/드라이버 확인 (링크/속도, 오프로드) NIC 연결(케이블, 스위치) 완료 ethtool -i eth0, ethtool -S eth0, ethtool -k eth0 드라이버/펌웨어 버전, 속도, 오프로드 상태 최신 드라이버·펌웨어, 링크 25Gbps, 오프로드 정상
T3 IRQ/NUMA 분포 점검 irqbalance 실행 중 grep "eth0" /proc/interrupts, numactl --hardware 인터럽트별 CPU 분포, NUMA 노드별 CPU IRQ가 NUMA 노드에 고르게 분배됨
T4 PCIe 대역폭 테스트 NVMe 빈 슬롯에서 전용 PCIe 장치 준비 lspci -vvv, sudo lspci -s <장치>: -xxx PCIe 버스 속도(x8/x16), 비트폭 PCIe 링크가 x8 (최소)로 동작
T5 네트워크 대역폭 (iperf3) 노드간 물리 경로 열려있음 서버: iperf3 -s, 클라이언트: iperf3 -c -t 30 -P 4 Throughput (Gbps), 지연 양방향/단방향 대역폭 기대치 달성 (예: ≥20 Gbps)
T6 패킷 드롭/RSS/NIC 큐 테스트 MTU=9000 설정 (스위치 포함) tc -s qdisc show dev eth0, pktgen 모듈 이용 예: echo 100000 > /proc/sys/net/core/netdev_max_backlog drops 카운터, RX 큐별 패킷 분배 netdev_max_backlog 확대 후 drops=0, RSS 큐 활성화
T7 RDMA 성능(선택: RoCE) RoCE 설정, PFC 지원 스위치 RDMA 툴 ib_write_bw, ib_read_bw 실행 RDMA Throughput, RNR-NA/NACK 오차 기대 대역폭(약 40 Gbps) 달성, 에러 없음
T8 K8s 노드 기능 검증 Kubernetes 구성 완료 kubectl get nodes, kubectl describe node Ready 상태, Kubelet flags, 리소스 할당 Node Ready, kube-reserved/system-reserved 적용
T9 파드 네트워크(지연/MTU) CNI(Cilium) 정상 기동 파드에서 ping -s 8972 <다른노드IP> , iperf3 최대 MTU 도달 가능, 지연 정도 MTU 9000 유지, 지터/패킷 손실 없음
T10 CPU/메모리 부하 테스트 스레드/코어 동시점유 컨테이너 stress-ng --cpu 8 --vm 2 --vm-bytes 50% --timeout 60s CPU util, 메모리 사용률, 응답 시간 CPU 100% 활용, 지연 및 에러 없음
T11 메모리 대역폭(예: STREAM) (옵션) Intel MKL/Kernellib STREAM 벤치마크 또는 numactl 를 이용한 메모리 스트레스 GB/s, NUMA 노드 간 대역폭 메모리 대역폭 사양 근접 또는 결함 없음
각 테스트 수행 시 Node Exporter/cAdvisor를 통해 CPU 이용률, 메모리 등 리소스 사용률을 동시에 모니터링하여 병목점 여부를 파악합니다.
T1: 하드웨어/BIOS 점검
T2: NIC/IRQ 검사
T3: PCIe/NUMA 검사
T4: 네트워크 대역폭
T5: 패킷 드롭/RSS 테스트
T6: RDMA 테스트
T7: K8s 노드 설정 확인
T8: 파드 네트워크/MTU 테스트
T9: CPU/메모리 부하 테스트
T10: 메모리 벤치마크
코드 표시
그림: 테스트 흐름 다이어그램. 하드웨어부터 K8s, 애플리케이션까지 단계별 검증.
T4/5 네트워크 테스트: Throughput이 기대치의 ≥90% 이상, 에러/재전송(iperf3 -e 결과) 0.
T6 RDMA: 기대 대역폭(예: 50G 케이블→40Gbps 이상) 달성, ibv_rc_pingpong RTT 안정적.
T8 K8s 설정: kubectl get nodes 상태 Ready, kube-reserved/system-reserved 설정이 kubectl describe node 에 반영.
T10 CPU 스트레스: CPUutil ≥99%, 메모리 작업 완료, 노드 캐시/페이지캐시 과도 사용 없음. 시스템 응답 가능.
T11 메모리 벤치: STREAM 메모리 대역폭이 명세의 ≥80% 이상. NUMA 간 대역폭 불균형 없음.
문제 발생 시 Grafana 대시보드로 직관 확인:
CPU/메모리 대시보드: nodecpu_seconds_total, node_memory_MemAvailable_bytes, node_swaptime_seconds_total 등.
네트워크 대시보드: node_networkbytes_total, drop/err, NIC별 큐 대기수, 인터럽트 분포.
Kube 리소스 대시보드: kube_node_status_capacity, kube_pod_container_resource_requests, container_memory_working_set_bytes 등으로 예약/사용 비교.
Cilium 대시보드: 활성 파드/엔드포인트, 흐름수, BPF 코드로드 시간, conntrack 테이블 사용량.
RDMA 대시보드: QP별 throughput/latency, ib_tx_rate, ib_rx_rate. 예: RoCE PFC가 제대로 작동하지 않으면 패킷 drop/Latency 급증.
예시 PASS/FAIL 경보:
네트워크 PASS: node_network_receive_drop_total 증가 없음, rx/tx throughput 일정, node_network_carrier_changes_total 없음.
메모리 PASS: node_memory_MemAvailable_bytes 충분, node_memory_Slab, node_memory_Buffers 정상, node_vmstat_pgmajfault 저수준.
CPU PASS: node_cpu_seconds_total 가 높은 부하 구간에서 균일 분포, C-state 진입 최소화.
디스크 PASS: (필요 시) node_disk_io_time_seconds_total 저, 파일시스템 메타데이터 잠김 없음.
6. 결론
이 표준안은 NVIDIA B300 + Intel E810 + RHEL 10.2 + Kubernetes(Cilium) 기반 대규모 클러스터의 노드 인수 검증에 초점을 둡니다. 각 테스트는 하드웨어와 네트워크, OS, Kubernetes 설정까지 단계별로 분리하여 문제 원인을 빠르게 진단할 수 있습니다. 제안된 커널 및 시스템 설정은 고성능 네트워킹과 컨테이너 워크로드에 대한 일반적인 베이스라인이며, 실사용 패턴에 따라 추가 조정이 필요할 수 있습니다.
참고자료: Red Hat RHEL 성능 조정 가이드, Intel NIC 성능 가이드, Kubernetes 공식 운영 가이드, Cilium 시스템 요구사항 등.
===
대규모 K8s 클러스터(수백~수천 노드 단위, 고성능 AIStor/DB/보안 스택 연동 환경)에서 노드를 인도받았을 때, 향후 Cilium eBPF 네트워크, OpenEBS/CNPG 로컬 I/O, 플랫폼 컴포넌트(Keycloak, Vault, Kyverno 등)의 병목을 사전에 차단하기 위한 하드웨어/OS 인수 테스트 프레임워크와 표준 베이스라인 커널 파라미터 셋입니다.
하드웨어 결함이나 초기 설정 오류가 클러스터 조인 후 Pod Eviction, etcd Split-brain, 네트워크 플래핑으로 번지는 것을 방지하기 위해 4개 레이어로 나누어 점검합니다.
numactl --hardware
lscpu | grep -E "Socket|Core\(s\)|NUMA node|Model name"
dmesg | grep -iE "mce|edac|hardware error|corrected"
stress-ng --cpu 0 --vm 4 --vm-bytes 80% --timeout 10m --metrics-brief
lspci -vvv -s <NIC_PCI_ADDR> | grep -E "LnkCap|LnkSta"
cat /sys/class/net/<ETH>/device/numa_node
ethtool <ETH> | grep -E "Speed:|Duplex:|Link detected:"
ethtool -g <ETH> # Current와 Maximum 비교
# DF(Don't Fragment) 플래그를 설정하고 8972바이트(ICMP 헤더 28 포함 = 9000) 송신
ping -M do -s 8972 -c 5 <GATEWAY_OR_PEER_IP>
ethtool -S <ETH> | grep -iE "drop|discard|error|miss"
OpenEBS LocalPV, etcd, CNPG(PostgreSQL), Kafka 저널이 사용할 로컬 디스크의 수명과 I/O 성능을 확인합니다.
nvme smart-log /dev/nvme0n1 | grep -E "critical_warning|temperature|percentage_used|media_errors"
fio --name=fsync-test --filename=/var/lib/test-wal --size=512M \
--rw=randwrite --bs=4k --direct=1 --fdatasync=1 --runtime=15 --time_based
rm -f /var/lib/test-wal
chronyc tracking | grep -E "RMS offset|System time"
free -m | grep -i swap # Total이 0이어야 함
스위치에서 출발한 대용량 패킷이 물리 NIC, 커널 softirq, Cilium eBPF 엔진을 거쳐 Pod 내부 소켓에 도달하기까지의 패킷 손실을 막고, 메모리 집약적 워크로드(AIStor, StarRocks, CNPG) 구동을 위해 권장되는 파라미터 세트입니다.
/etc/sysctl.d/99-k8s-platform-baseline.conf 파일로 영구 반영합니다.
### ====================================================================
### 1. 파일 시스템 & Inotify 확장
### 용도: 수천 개 컨테이너, Fluentbit/Vector 로그 수집기, Kyverno/Vault 감시
### ====================================================================
fs.file-max = 20971520
fs.nr_open = 20971520
fs.inotify.max_user_watches = 1048576
fs.inotify.max_user_instances = 8192
### ====================================================================
### 2. 가상 메모리(VM) & NUMA 튜닝
### 용도: CNPG/AIStor/StarRocks 대용량 mmap 지원 및 백그라운드 지연 스파이크 차단
### ====================================================================
vm.swappiness = 0
vm.overcommit_memory = 1
vm.panic_on_oom = 0
# DB, 벡터 검색, Java 힙 할당을 위한 VMA 슬롯 확장
vm.max_map_count = 2621440
# [중요] 백그라운드 페이지 마이그레이션으로 인한 P99 레이턴시 튐 방지
kernel.numa_balancing = 0
# 메모리 단편화 완화
vm.min_free_kbytes = 1048576
### ====================================================================
### 3. 네트워크 코어 & 큐(Queue) 확장
### 용도: 25G/100G 고속 환경에서 NAPI softirq 큐 포화 및 패킷 드롭 방지
### ====================================================================
# NIC 링 버퍼에서 커널로 넘겨받는 큐 크기 확장
net.core.netdev_max_backlog = 100000
# 소켓 listen 대기열 확장 (Keycloak, Vault, Webhook 일시적 트래픽 집중 대응)
net.core.somaxconn = 65535
# 1회 softirq 인터럽트 처리 주기당 처리할 패킷 수 상향 (time_squeeze 방지)
net.core.netdev_budget = 600
net.core.netdev_budget_usecs = 4000
# BDP(Bandwidth-Delay Product)를 수용할 수 있는 최대 소켓 버퍼 (16MB 할당)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.core.optmem_max = 2048576
### ====================================================================
### 4. TCP/IP 스택 & 연결 관리
### 용도: 대규모 Pod-to-Pod 통신, ZeroWindow 방지, BBR 혼잡 제어
### ====================================================================
net.ipv4.tcp_window_scaling = 1
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# TCP 버퍼 오토튜닝 [min default max] (최대 16MB)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# 로컬 아웃바운드 포트 고갈 방지
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_syn_backlog = 3240000
net.ipv4.tcp_max_tw_buckets = 1440000
# 세션 유지 및 고스트 커넥션 신속 회수
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
### ====================================================================
### 5. 라우팅, BGP ECMP, CNI(Cilium) & Conntrack 필수 설정
### 용도: 비대칭 라우팅 패킷 드롭 방지 및 수십만 동시 연결 추적
### ====================================================================
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
# BGP/ECMP 다중 경로 및 Cilium DSR 사용 시 패킷 드롭 방지 (Loose Mode)
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2
# iptables/br_netfilter 브리지 트래픽 전달
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
# 연결 추적(Conntrack) 테이블 포화 방지 (기본 65,536에서 2백만으로 확장)
net.netfilter.nf_conntrack_max = 2097152
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 3600
# 대규모 클러스터 Pod IP 수용을 위한 ARP 캐시 테이블 확장
net.ipv4.neigh.default.gc_thresh1 = 8192
net.ipv4.neigh.default.gc_thresh2 = 32768
net.ipv4.neigh.default.gc_thresh3 = 65536
초기 노드 인수 시 세팅한 베이스라인은 향후 상위 스택을 얹었을 때 다음과 같이 연계되어 튜닝 기준점이 됩니다.
[ 물리 계층 (HW/Switch) ] ── NIC Ring Buffer (4096) / MTU 9000 / PCIe NUMA 바인딩
│
[ OS 커널 (Sysctl) ] ── netdev_budget / tcp_rmem(16M) / rp_filter=2 / numa_balancing=0
│
[ K8s / CNI 계층 ] ── Cilium Native Routing (BPF Host Routing) / Kubelet CPU Manager (static)
│
[ 스토리지 / 인프라 앱 ] ── OpenEBS (NVMe Direct I/O) / MinIO AIStor (Drive 병렬성)
│
[ 플랫폼 애플리케이션 ] ── Kyverno (Webhook somaxconn) / Vault (mmap) / Goldilocks (VPA 프로파일링)
net.ipv4.conf.all.rp_filter = 2와 BBR 세팅 덕분에 BGP Control Plane 및 BPF Host Routing을 통한 veth 바이패스 최적화가 병목 없이 활성화됩니다.net.core.somaxconn = 65535와 net.netfilter.nf_conntrack_max 설정이 Connection refused나 SYN 패킷 드롭을 방어합니다.vm.max_map_count와 Guaranteed QoS(정수 코어 바인딩)를 적용함으로써, Cgroups CFS Quota에 의한 인위적 CPU Throttling을 방지하고 골디락스를 통해 파드별 권장 리소스를 오버프로비저닝 없이 정밀 측정할 수 있습니다.==
인수(Acceptance) 단계에서는 "고장 유무 확인 + 튜닝 기준선(baseline) 확보"가 목적이므로, GPU 클러스터처럼 며칠씩 burn-in 하는 수준은 아니지만 ①스펙/재고 검증 → ②HW 스트레스/건전성 → ③OS/커널 기본값 → ④네트워크(스위치~NIC) 검증 순으로 체크리스트를 잡는 게 효율적입니다.
dmidecode -t system/bios/processor/memory, lscpu, lspci -vvv, lsblk -o NAME,SIZE,MODEL,ROTA → 발주 스펙(CPU 모델/코어수, DIMM 개수·용량·속도, NIC 모델·포트수, 디스크 종류/용량)과 실물 일치 여부stress-ng --cpu $(nproc) --timeout 10-30m --metrics 로 전 코어 부하 → 크래시/throttling 여부turbostat 또는 sensors로 온도/클럭 다운(thermal throttling) 관찰numactl -H로 NUMA 노드/코어 매핑이 스펙과 일치하는지stress-ng --vm 4 --vm-bytes 90% --timeout 10-20m 또는 memtester로 비트 오류 검출dmidecode -t memory로 DIMM 슬롯 채널 밸런스(성능에 큰 영향) 확인edac-util, mcelog, ras-mc-ctl --summarymlc(Intel Memory Latency Checker) 또는 STREAM 벤치마크로 대역폭 baseline 기록 → 이후 노드간 편차 비교용smartctl -a /dev/sdX / nvme smart-log /dev/nvme0 → Health/Wear/에러 카운터fio로 순차/랜덤 R/W IOPS·처리량·latency baseline 확보 (예: fio --name=test --rw=randrw --bs=4k --iodepth=32 --numjobs=4 --size=10G --runtime=60)ethtool <iface> → Link speed/duplex, 협상 결과가 스위치 포트 설정과 일치하는지(예: 100G 풀듀플렉스)ethtool -S <iface> 로 rx/tx error, dropped, overrun 카운터가 0인지ethtool -i <iface>로 driver/firmware 버전, ethtool -k로 offload(GRO/TSO/LRO/checksum) 설정 확인ethtool -l/-L로 RX/TX 큐 개수(RSS) 확인 → 코어 수 대비 큐 개수 부족하면 이후 병목 원인lldpctl 또는 lldpad)ping -M do -s 8972 <gateway> (9000 MTU 가정)cat /proc/net/bonding/bond0로 슬레이브 상태, 케이블 뽑아서 failover 테스트iperf3 실측 처리량이 이론치(예: 100G의 90%+) 나오는지 → 이게 실제 "스위치→Pod" 병목 분석의 기준선이 됨swapoff -a 및 /etc/fstab에서 swap 제거(K8s 필수)timedatectl/chronyc tracking으로 NTP 동기화 상태(수 ms 이내)overlay, br_netfilter, ip_vs, ip_vs_rr, nf_conntrackulimit -n(open files), ulimit -u(nproc) 기본값 확인이 항목들을 스크립트로 묶어 노드별 결과를 표로 남겨두면, 이후 "이 노드만 유독 latency가 높다" 같은 이상치를 인수 시점 기록과 비교해 빠르게 원인 분리할 수 있습니다.
아래는 "일단 이 값으로 시작해서 실측하며 조정"하는 baseline 성격입니다. 워크로드 특성(커넥션 수, conntrack 규모, RDMA 사용 여부)에 따라 추후 조정이 필요합니다.
네트워크 – 소켓/버퍼
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 250000
net.core.netdev_budget = 600
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.optmem_max = 65536
네트워크 – IPv4/TCP
net.ipv4.ip_forward = 1
net.ipv4.tcp_max_syn_backlog = 32768
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_mtu_probing = 1
net.ipv4.neigh.default.gc_thresh1 = 8192
net.ipv4.neigh.default.gc_thresh2 = 16384
net.ipv4.neigh.default.gc_thresh3 = 32768
브리지/netfilter (kube-proxy iptables/Cilium eBPF 공존 대비)
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_buckets = 262144
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
※ conntrack buckets/max는 위 huaweicloud 자료처럼 nf_conntrack_count / 0.7 기준으로 노드 실제 커넥션 수에 맞춰 재산정 권장. Cilium을 eBPF 데이터플레인(kube-proxy replacement)으로 쓰면 conntrack 의존도가 낮아지므로 이후 실측 후 낮춰도 됨.
메모리/VM
vm.max_map_count = 262144
vm.swappiness = 0
vm.overcommit_memory = 1
vm.min_free_kbytes = 65536
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
파일시스템/디스크립터
fs.file-max = 2097152
fs.nr_open = 1048576
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 8192
fs.aio-max-nr = 1048576
커널 일반
kernel.pid_max = 4194304
kernel.threads-max = 4194304
kernel.panic = 10
kernel.panic_on_oops = 1
추가로 커널 파라미터는 아니지만 baseline에 같이 점검할 항목
performance (cpufreq가 ondemand/powersave면 job 시작 시 클럭 램프업 지연 → CPU 병목 원인)madvise 권장 (DB 계열은 never 검토)irqbalance 끄고 NIC 큐를 코어에 수동 pin, RSS 큐 수가 vCPU 대비 충분한지 (스위치→Pod 경로 병목의 상당수가 여기서 발생)net.core.busy_poll/busy_read는 극한 저지연 요구시에만 검토 (일반은 off)이 baseline을 노드 인수 시점에 적용/기록해두고, 이후 Cilium(특히 eBPF datapath, XDP 여부), CNPG/OpenEBS 같은 스토리지 IO 헤비 워크로드, Vault/Keycloak 같은 latency 민감 서비스별로 conntrack, ulimit, RSS 큐 배분 등을 개별 튜닝해나가는 구조가 맞습니다.
==
인프라팀이 OS 설치까지 마쳐 인도한 물리 노드를, DevOps 관점에서 K8s 클러스터에
투입하기 전 HW(NIC 포함)/OS/커널 기본 상태를 점검하고, 이후 성능 튜닝의
baseline으로 남기기 위한 스크립트 2종입니다.
node_check.sh 각 노드에서 실행하는 점검 스크립트 (raw 로그 + summary.csv 생성)
aggregate_report.py 여러 노드의 summary.csv를 모아 통계/이상치를 뽑는 스크립트
README.md 이 문서 (사용법 + 판단 기준)
[각 노드] [집계 서버/작업 PC]
node_check.sh 실행
-> /var/log/node-accept/<host>_<ts>/
├─ summary.csv 결과 디렉터리를 한 곳에 모음
└─ raw/*.log (scp/rsync/ansible fetch 등)
results/
node01_<ts>/summary.csv
node02_<ts>/summary.csv
...
python3 aggregate_report.py results/
-> results/_aggregate_report/
AGGREGATE_SUMMARY.md
FAIL_WARN_NODES.csv
OUTLIERS.csv
# 기본 실행 (부하 테스트는 CPU/메모리만 기본 ON, fio/iperf3는 기본 OFF)
sudo ./node_check.sh
# fio까지 켜고 싶으면 스크립트 상단 RUN_STORAGE_FIO=1 로 바꾸거나,
# 대상 경로를 지정해서 환경변수로 오버라이드
sudo FIO_TESTDIR=/data/fio-test RUN_STORAGE_FIO=1 ./node_check.sh
# iperf3까지 켜려면 상대 서버(다른 노드 등)를 지정
sudo IPERF_TARGET=10.0.0.5 RUN_NIC_IPERF=1 ./node_check.sh
결과는 /var/log/node-accept/<hostname>_<timestamp>/ 아래에 생성됩니다.
(경로는 RESULT_ROOT 환경변수로 바꿀 수 있음)
각 노드의 결과 디렉터리를 한 곳(results/)에 모은 뒤:
python3 aggregate_report.py results/ --out report/ --zscore 2.0
--zscore : 클수록 이상치 판정이 둔감해짐(기본 2.0). 신규 클러스터라 노드 수가RUN_*=1/0 으로 점검RUN_XXX 스위치 하나 추가 → ② check_xxx() 함수run_and_log로 raw 로그 남기고 record로 summary.csv에 한 줄main()의 호출부에 한 줄 추가.main()의 해당 호출 줄만 지우거나 스위치를 0으로 두면 됩니다record 함수 형식: record <category> <check> <value> <unit> <status> <note>status는 PASS/WARN/FAIL/INFO 중 하나만 사용하세요. 아래 3번 표와aggregate_report.py가 이 값을 그대로 신뢰합니다.스크립트가 자체적으로 PASS/FAIL을 낼 수 있는 항목과, 절대 기준이 없어
여러 노드를 모아야 이상치를 알 수 있는(INFO) 항목을 구분했습니다.
| 카테고리 | 체크 | 판단 기준 | 근거 |
|---|---|---|---|
| os | kmod_overlay, kmod_br_netfilter | 모듈 로드 여부 | K8s(kubelet/CNI)가 요구하는 필수 커널 모듈. 미로드시 파드 네트워킹/컨테이너 런타임 자체가 불안정 |
| os | net.ipv4.ip_forward | 1이어야 PASS | 컨테이너 간 라우팅에 필수. 0이면 사실상 K8s 노드로 못 씀 |
| os | swap_total | 0이어야 PASS(설정 가능) | kubelet은 기본적으로 swap이 켜진 노드에서 정상 스케줄링을 보장하지 않음 |
| os | vm.max_map_count | >=262144면 PASS, 미만 WARN | Elasticsearch/일부 DB·워크로드의 요구 최소치(262144)를 기준값으로 채택. 클러스터에 그런 워크로드가 없다면 WARN 정도로만 취급해도 무방 |
| nic | <if>_link_detected | yes면 PASS | 케이블/포트 결선 여부의 1차 확인 |
| nic | <if>_speed | THRESH_NIC_MIN_SPEED_MBPS 이상이면 PASS | 스위치 포트와의 speed/duplex 협상 실패(예: 100G 포트인데 실제론 25G로 링크업) 조기 발견용. 클러스터의 실제 설계 속도로 스크립트 상단 값을 반드시 맞출 것 |
| nic | <if>_error_counters | ethtool -S 의 err/drop/discard 계열 합이 0이면 PASS | 0이 아니면 케이블 불량, SFP 문제, MTU 불일치 등 물리 계층 이슈 가능성 |
| memory | ecc_errors | Corrected/Uncorrected 에러 미검출시 PASS | ECC correctable 에러가 반복 누적되면 DIMM 불량 전조 신호인 경우가 많음 |
| storage | smarthealth* | SMART PASSED면 PASS | 디스크 자체 진단 결과. FAIL이면 즉시 교체 대상 |
| cpu / memory | stress_test | stress-ng 정상 종료(크래시/재부팅 없음)면 PASS | burn-in 목적의 최소 확인. 장시간(수시간~24시간) burn-in이 필요하면 *_STRESS_DURATION 값을 늘려서 재실행 |
| time | chrony_offset_sec | 100ms 미만이면 PASS | K8s/etcd/인증서 클럭 스큐 이슈를 예방하기 위한 보수적 기준 |
| storage | fio_randread/write_iops | 절대 기준 없음 → INFO | 디스크 모델/구성에 따라 정상 범위가 다름. aggregate_report.py가 fleet 평균 대비 편차(z-score)로 "이 노드만 유독 느림"을 잡아냄 |
| nic | iperf3_throughput | 절대 기준 없음 → INFO | 스위치 포트/케이블/광모듈 조합에 따라 이론치 대비 실측 편차가 있을 수 있어, 노드간 상대 비교로 이상치를 판단하는 것이 더 신뢰도 높음 |
| inventory | system_vendor/model/bios_version | INFO만 기록 | 발주 스펙서와의 대조는 사람이 최종 확인해야 하는 영역이라 텍스트로만 남김 |
위 임계값들은 스크립트 상단
THRESH_*변수로 모아뒀으니, 클러스터/장비
스펙이 바뀌면 그 값만 조정하면 됩니다.
체크 항목별로 전체 노드의 상태 분포(PASS/WARN/FAIL/INFO 개수)와, 숫자값이면
min/max/mean/stdev를 보여줍니다. "클러스터 전체적으로 어떤 항목이 자주
걸리는지" 한눈에 보는 용도.
node_check.sh가 이미 절대 기준으로 FAIL/WARN 판정한 항목들을 노드별로 나열한
액션 리스트입니다. FAIL부터 우선 조치하세요.
절대 기준이 없는 INFO성 수치(예: fio IOPS, iperf3 처리량)에 대해 fleet 평균/
표준편차 대비 z-score를 계산해, |z| >= --zscore인 노드를 뽑습니다.
zscore가 음수(-)면 fleet 평균보다 낮은 값 → 대개 "저성능 의심" 노드CATEGORY_HINTS(스크립트 상단)에 항목을 등록하면 "높을수록 좋음/낮을수록이 baseline 점검은 커널/K8s/Cilium/애플리케이션(Keycloak, OpenEBS, CNPG,
Vault, Kyverno, Goldilocks 등) 단위의 심화 튜닝을 시작하기 전 "출발선이
고르게 맞춰졌는지" 확인하는 용도입니다. 여기서 잡힌 FAIL/WARN/이상치를
해소한 뒤에 커널 sysctl 세부 튜닝, Cilium eBPF datapath 설정, 워크로드별
리소스 요청/제한(Goldilocks) 조정 등으로 넘어가는 순서를 권장합니다.