Skip to content
Published on

Linux 커널 파라미터 튜닝 가이드: sysctl + Boot Params, 안전한 변경과 롤백

Authors
  • Name
    Twitter

들어가며

커널 파라미터 튜닝은 서버 성능과 안정성에 직접적 영향을 미치는 작업이다. 잘못된 값 하나가 OOM Kill을 유발하거나, 네트워크 연결을 끊거나, 보안 취약점을 만들 수 있다.

이 글에서는 **sysctl(런타임 파라미터)**과 **부트 파라미터(커널 커맨드라인)**를 구분하여 각 항목의 의미·권장값·적용 방법을 정리하고, 프로덕션 환경에서의 안전한 변경 절차와 롤백 전략을 제시한다.


1. 커널 파라미터의 두 가지 경로

구분sysctl (런타임)Boot Params (부트 시)
적용 시점즉시 (재부팅 불필요)다음 부팅 시
설정 파일/etc/sysctl.d/*.conf/etc/default/grubgrub.cfg
확인 명령sysctl <param>cat /proc/cmdline
영구 적용sysctl.d + sysctl -pgrub2-mkconfig / update-grub
롤백이전 값 복원GRUB 이전 엔트리 선택
범위/proc/sys/ 하위 항목커널 부팅 옵션 전체

2. 안전한 변경 절차 (프로덕션 프로토콜)

2.1 변경 전 체크리스트

#!/usr/bin/env bash
# pre-tuning-check.sh - 튜닝 전 상태 백업

BACKUP_DIR="/root/kernel-tuning-backup/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"

# 1. 현재 sysctl 전체 덤프
sysctl -a > "$BACKUP_DIR/sysctl-before.txt" 2>/dev/null

# 2. 현재 부트 파라미터
cat /proc/cmdline > "$BACKUP_DIR/cmdline-before.txt"

# 3. GRUB 설정 백업
cp /etc/default/grub "$BACKUP_DIR/grub-before"
[[ -d /etc/sysctl.d ]] && cp -r /etc/sysctl.d "$BACKUP_DIR/sysctl.d-before"

# 4. 시스템 상태 스냅샷
free -h > "$BACKUP_DIR/memory-before.txt"
ss -s > "$BACKUP_DIR/socket-stats-before.txt"
vmstat 1 5 > "$BACKUP_DIR/vmstat-before.txt"
cat /proc/net/sockstat > "$BACKUP_DIR/sockstat-before.txt"

echo "백업 완료: $BACKUP_DIR"

2.2 변경 단계

1. 스테이징 환경에서 테스트
2. Canary 서버 1대에 적용 → 모니터링 (최소 24시간)
3. 문제 없으면 그룹 단위 Rolling 적용
4. 적용 후 메트릭 비교 (before vs after)

2.3 롤백 절차

# sysctl 롤백 - 백업에서 특정 파라미터 복원
PARAM="net.core.somaxconn"
OLD_VALUE=$(grep "^${PARAM}" /root/kernel-tuning-backup/latest/sysctl-before.txt | awk '{print $3}')
sysctl -w "${PARAM}=${OLD_VALUE}"

# 전체 sysctl 롤백
while IFS='= ' read -r key value; do
  sysctl -w "${key}=${value}" 2>/dev/null
done < /root/kernel-tuning-backup/latest/sysctl-before.txt

# 부트 파라미터 롤백 - GRUB 이전 설정 복원
cp /root/kernel-tuning-backup/latest/grub-before /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg  # RHEL
# update-grub                            # Ubuntu

3. 네트워크 튜닝

3.1 TCP 연결 관리

# /etc/sysctl.d/10-network.conf

# TCP 백로그 - 고트래픽 서버 필수
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# TCP 소켓 버퍼 (바이트)
# min / default / max
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 262144 16777216
net.ipv4.tcp_wmem = 4096 262144 16777216

# TCP 혼잡 제어
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# TIME_WAIT 관리
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_tw_buckets = 2000000

# Keepalive (로드밸런서 뒤 서버)
net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 6

3.2 네트워크 파라미터 설명표

파라미터기본값권장값설명
net.core.somaxconn409665535listen() 백로그 최대값
net.ipv4.tcp_max_syn_backlog102465535SYN 큐 최대 크기
net.core.rmem_max21299216MB수신 소켓 버퍼 최대
net.core.wmem_max21299216MB송신 소켓 버퍼 최대
net.ipv4.tcp_congestion_controlcubicbbr혼잡 제어 알고리즘
net.ipv4.tcp_tw_reuse0(2)1TIME_WAIT 소켓 재사용
net.ipv4.tcp_fin_timeout6015FIN-WAIT-2 타임아웃
net.ipv4.tcp_keepalive_time720060Keepalive 시작 시간(초)
net.ipv4.ip_local_port_range32768-609991024-65535아웃바운드 포트 범위

3.3 BBR 활성화

# BBR 커널 모듈 로드
modprobe tcp_bbr
echo "tcp_bbr" >> /etc/modules-load.d/bbr.conf

# sysctl 적용
sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr

# 확인
sysctl net.ipv4.tcp_congestion_control
# net.ipv4.tcp_congestion_control = bbr

BBR vs CUBIC: BBR은 패킷 손실 기반이 아닌 대역폭 추정 기반 혼잡 제어로, 특히 장거리·고지연 네트워크에서 성능이 크게 향상된다.


4. 메모리 튜닝

4.1 가상 메모리 관리

# /etc/sysctl.d/20-memory.conf

# Swap 사용 성향 (0=최소, 100=적극)
# DB 서버: 1-10, 웹 서버: 10-30
vm.swappiness = 10

# Dirty page 비율 - 디스크 쓰기 지연
vm.dirty_ratio = 40              # 전체 메모리 대비 dirty page 최대 비율
vm.dirty_background_ratio = 10   # 백그라운드 flush 시작 비율

# OOM 관련
vm.overcommit_memory = 0         # 0=기본(휴리스틱), 1=항상허용, 2=제한
vm.panic_on_oom = 0              # OOM 시 패닉 여부 (0=OOM Killer 실행)

# 최대 메모리 맵 영역 (Elasticsearch, MongoDB 등)
vm.max_map_count = 262144

# 파일시스템 캐시 해제 (긴급 시에만)
# echo 3 > /proc/sys/vm/drop_caches  # 1=pagecache, 2=dentries+inodes, 3=all

4.2 메모리 파라미터 가이드

파라미터DB 서버웹/API 서버ML 워크로드
vm.swappiness1~510~301
vm.dirty_ratio402040
vm.dirty_background_ratio10510
vm.overcommit_memory001
vm.max_map_count26214465530262144

4.3 Huge Pages

# Transparent Huge Pages (THP) - DB에서는 비활성화 권장
# 부트 파라미터로 설정
# GRUB_CMDLINE_LINUX에 추가:
# transparent_hugepage=never

# 런타임 확인·변경
cat /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# Static Huge Pages (Oracle DB, DPDK 등)
# /etc/sysctl.d/20-memory.conf
vm.nr_hugepages = 1024  # 2MB * 1024 = 2GB

# 확인
grep -i huge /proc/meminfo

5. 파일시스템·I/O 튜닝

# /etc/sysctl.d/30-fs.conf

# 최대 열린 파일 수 (시스템 전체)
fs.file-max = 2097152

# inotify 감시 제한 (IDE, 파일 감시 서비스)
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 8192

# AIO (비동기 I/O) 최대 요청 수
fs.aio-max-nr = 1048576

ulimit 연동

# /etc/security/limits.d/99-app.conf
# sysctl의 fs.file-max 와 함께 설정해야 효과

*    soft    nofile    1048576
*    hard    nofile    1048576
*    soft    nproc     65535
*    hard    nproc     65535
*    soft    memlock   unlimited
*    hard    memlock   unlimited

I/O 스케줄러 설정

# 현재 스케줄러 확인
cat /sys/block/sda/queue/scheduler

# SSD: none 또는 mq-deadline 권장
echo mq-deadline > /sys/block/sda/queue/scheduler

# 영구 설정 (udev rule)
# /etc/udev/rules.d/60-scheduler.rules
# ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
# ACTION=="add|change", KERNEL=="sd*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
스케줄러디스크 타입특징
none (noop)NVMe SSD오버헤드 최소
mq-deadlineSATA SSD지연 시간 보장
bfqHDD공정 대역폭 분배
kyber고속 SSD읽기/쓰기 지연 제어

6. 보안 관련 파라미터

# /etc/sysctl.d/40-security.conf

# ASLR (Address Space Layout Randomization)
kernel.randomize_va_space = 2  # 0=끔, 1=부분, 2=완전

# SysRq 제한 (긴급 복구용만 허용)
kernel.sysrq = 176  # 비트마스크: sync + remount-ro + reboot

# 코어 덤프 제한
kernel.core_pattern = |/bin/false
fs.suid_dumpable = 0

# dmesg 접근 제한
kernel.dmesg_restrict = 1

# 커널 포인터 숨김
kernel.kptr_restrict = 2

# BPF 제한 (비특권 사용자)
kernel.unprivileged_bpf_disabled = 1

# 네트워크 보안
net.ipv4.conf.all.rp_filter = 1           # Reverse Path Filtering
net.ipv4.conf.all.accept_redirects = 0     # ICMP 리다이렉트 거부
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0  # Source Routing 거부
net.ipv4.conf.all.log_martians = 1         # 의심 패킷 로깅
net.ipv4.icmp_echo_ignore_broadcasts = 1   # Smurf 공격 방어

# IP 포워딩 (라우터/컨테이너 호스트가 아니면 비활성)
net.ipv4.ip_forward = 0
# 컨테이너 호스트일 경우:
# net.ipv4.ip_forward = 1

보안 파라미터 체크리스트

파라미터보안 권장값CIS Benchmark비고
kernel.randomize_va_space2필수ASLR 완전 활성화
kernel.dmesg_restrict1권장일반 사용자 dmesg 차단
kernel.kptr_restrict2권장커널 주소 노출 방지
net.ipv4.conf.all.rp_filter1필수IP 스푸핑 방지
net.ipv4.conf.all.accept_redirects0필수MITM 방지
net.ipv4.conf.all.log_martians1권장비정상 패킷 감사
fs.suid_dumpable0필수SUID 코어덤프 방지

7. 부트 파라미터 (Kernel Command Line)

7.1 설정 방법

# 현재 부트 파라미터 확인
cat /proc/cmdline

# RHEL / Rocky
vi /etc/default/grub
# GRUB_CMDLINE_LINUX="... 추가할_파라미터"
grub2-mkconfig -o /boot/grub2/grub.cfg

# Ubuntu
vi /etc/default/grub
# GRUB_CMDLINE_LINUX_DEFAULT="... 추가할_파라미터"
update-grub

7.2 주요 부트 파라미터

파라미터용도
transparent_hugepage=nevernever / always / madviseDB 서버 THP 비활성화
mitigations=autooff / auto / auto,nosmtCPU 취약점 완화 제어
numa_balancing=disabledisable / enableNUMA 자동 밸런싱
isolcpus=2-7CPU 목록특정 CPU를 스케줄러에서 격리
nohz_full=2-7CPU 목록Tick-less 모드 (실시간 워크로드)
intel_iommu=onon / offIOMMU 활성화 (SR-IOV, VFIO)
iommu=ptpt / offIOMMU pass-through
default_hugepagesz=1G2M / 1G기본 Huge Page 크기
hugepagesz=1G hugepages=16크기 + 개수1GB Huge Page 할당
crashkernel=256M크기kdump 메모리 예약
audit=10 / 1커널 감사 로그

7.3 CPU 취약점 완화 vs 성능

# 현재 적용된 완화 목록 확인
grep -r . /sys/devices/system/cpu/vulnerabilities/ 2>/dev/null

# 완화 비활성화 (벤치마크·격리 환경에서만!)
# GRUB_CMDLINE_LINUX에 추가:
# mitigations=off

# 성능 영향 (워크로드에 따라 다름)
# mitigations=auto: 시스콜 집약 워크로드에서 5~30% 오버헤드
# mitigations=off: 보안 위험 - 프로덕션 비권장

주의: mitigations=off는 Spectre/Meltdown/MDS 등의 보안 완화를 모두 비활성화한다. 격리된 벤치마크 환경에서만 사용하고, 프로덕션에서는 절대 사용하지 마라.


8. 워크로드별 튜닝 프로파일

8.1 웹 서버 / API 서버

# /etc/sysctl.d/99-web-server.conf

# 네트워크
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 6
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# 파일
fs.file-max = 2097152

# 메모리
vm.swappiness = 10

8.2 데이터베이스 서버

# /etc/sysctl.d/99-database.conf

# 메모리
vm.swappiness = 1
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
vm.overcommit_memory = 0
vm.max_map_count = 262144

# 파일
fs.file-max = 2097152
fs.aio-max-nr = 1048576

# 네트워크 (내부 통신 위주)
net.core.somaxconn = 65535
net.ipv4.tcp_keepalive_time = 60

# Huge Pages (PostgreSQL, Oracle 등)
# vm.nr_hugepages 계산: shared_buffers / 2MB + 약간의 여유
# 예: shared_buffers=8GB → vm.nr_hugepages = 4200
vm.nr_hugepages = 4200

부트 파라미터:

transparent_hugepage=never

8.3 컨테이너 호스트 (Docker/K8s)

# /etc/sysctl.d/99-container-host.conf

# IP 포워딩 필수
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

# 네트워크
net.core.somaxconn = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.netfilter.nf_conntrack_max = 1048576

# inotify (Pod 다수 실행 시)
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 8192

# PID 제한
kernel.pid_max = 4194304

# 파일
fs.file-max = 2097152

9. 자동화와 검증

Ansible로 sysctl 관리

# roles/sysctl/tasks/main.yml
- name: Apply sysctl parameters
  ansible.posix.sysctl:
    name: "{{ item.key }}"
    value: "{{ item.value }}"
    sysctl_file: /etc/sysctl.d/99-tuning.conf
    reload: true
    state: present
  loop: "{{ sysctl_params | dict2items }}"

# roles/sysctl/defaults/main.yml
sysctl_params:
  net.core.somaxconn: 65535
  net.ipv4.tcp_max_syn_backlog: 65535
  vm.swappiness: 10
  fs.file-max: 2097152

적용 후 검증 스크립트

#!/usr/bin/env bash
# verify-tuning.sh - 튜닝 값 검증

declare -A EXPECTED=(
  ["net.core.somaxconn"]="65535"
  ["net.ipv4.tcp_congestion_control"]="bbr"
  ["vm.swappiness"]="10"
  ["fs.file-max"]="2097152"
)

FAILED=0
for param in "${!EXPECTED[@]}"; do
  actual=$(sysctl -n "$param" 2>/dev/null)
  expected="${EXPECTED[$param]}"
  if [[ "$actual" != "$expected" ]]; then
    echo "FAIL: $param = $actual (expected: $expected)"
    (( FAILED++ ))
  else
    echo "OK:   $param = $actual"
  fi
done

echo "---"
if (( FAILED > 0 )); then
  echo "검증 실패: ${FAILED}건"
  exit 1
else
  echo "모든 파라미터 검증 통과"
fi

10. 트러블슈팅

증상확인 명령관련 파라미터
"Too many open files"ulimit -n, sysctl fs.file-maxfs.file-max, limits.conf
"Connection refused" (백로그 초과)ss -lnt, netstat -s | grep overflownet.core.somaxconn
TIME_WAIT 폭증ss -stcp_tw_reuse, tcp_fin_timeout
OOM Kill 빈발dmesg | grep -i oom, /proc/meminfovm.swappiness, vm.overcommit_memory
높은 I/O waitiostat -x 1, vmstat 1vm.dirty_ratio, I/O 스케줄러
"Cannot allocate memory" (mmap)sysctl vm.max_map_countvm.max_map_count
nf_conntrack 테이블 포화dmesg | grep conntrack, sysctl net.netfilter.nf_conntrack_countnf_conntrack_max

마무리

커널 파라미터 튜닝의 핵심 원칙을 정리한다.

  1. 측정 먼저, 튜닝 나중: 병목이 확인되지 않은 상태에서 값을 변경하지 마라.
  2. 한 번에 하나씩: 여러 파라미터를 동시에 변경하면 효과를 분리할 수 없다.
  3. 반드시 백업: 변경 전 현재 값을 기록하라. 롤백 경로 없는 변경은 하지 마라.
  4. Canary 적용: 전체 서버에 한꺼번에 적용하지 말고 1~2대에서 먼저 검증하라.
  5. 문서화: 왜 이 값으로 변경했는지, 어떤 효과를 확인했는지 기록하라.

올바른 튜닝은 서버 성능을 극적으로 개선할 수 있지만, 잘못된 튜닝은 장애의 직접 원인이 된다. 항상 안전하게, 점진적으로, 측정 가능하게 접근하자.