Skip to content

KR_Linux_Kernel

somaz edited this page Mar 30, 2026 · 1 revision

리눅스 커널 관리 & 파라미터 튜닝 (Q7-Q8)

Q8: 리눅스 커널 파라미터 튜닝

질문: 리눅스에서 자주 사용하는 커널 파라미터(sysctl)를 설명하고, 네트워크 성능 최적화와 시스템 안정성 향상을 위한 주요 설정값을 제시하세요.

답변:

1. sysctl 기본 사용법

# 모든 커널 파라미터 확인
sysctl -a

# 특정 파라미터 확인
sysctl net.ipv4.ip_forward
sysctl vm.swappiness

# 파라미터 변경 (임시)
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w vm.swappiness=10

# 파라미터 변경 (영구)
sudo vi /etc/sysctl.conf
sudo sysctl -p  # 적용

2. 네트워크 성능 최적화

# /etc/sysctl.conf 또는 /etc/sysctl.d/99-network.conf

# ===== TCP/IP 스택 최적화 =====

# net.core.rmem_max: TCP 수신 버퍼의 최대 크기
# - 기본값: 212992 (약 208KB)
# - 권장값: 134217728 (128MB) - 10Gbps 고속 네트워크 환경
# - 설명: 네트워크 카드에서 받은 패킷을 저장하는 커널 버퍼의 최대 크기
# - 효과: 대용량 파일 전송, 스트리밍 서비스에서 처리량 향상
# - 주의: 메모리 부족 시 OOM 가능성, 시스템 RAM 고려 필요
net.core.rmem_max = 134217728

# net.core.wmem_max: TCP 송신 버퍼의 최대 크기
# - 기본값: 212992 (약 208KB)
# - 권장값: 134217728 (128MB)
# - 설명: 애플리케이션에서 보내는 데이터를 네트워크 카드로 전송하기 전 임시 저장
# - 효과: 고대역폭 환경에서 송신 성능 향상
# - 사용 사례: CDN 서버, 비디오 스트리밍, 대용량 파일 서버
net.core.wmem_max = 134217728

# net.core.rmem_default / wmem_default: 소켓 생성 시 기본 버퍼 크기
# - 설명: 애플리케이션이 명시적으로 버퍼 크기를 지정하지 않을 때 사용
# - 권장값: 16MB (일반적인 웹 트래픽에 적합)
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216

# net.ipv4.tcp_rmem / tcp_wmem: 소켓별 TCP 버퍼 자동 튜닝 (최소, 기본, 최대)
# - 형식: min default max
# - tcp_rmem = 4096 87380 134217728
#   * 4096 (4KB): 최소 버퍼 - 메모리 부족 시에도 보장
#   * 87380 (85KB): 기본 버퍼 - 일반적인 연결에 사용
#   * 134217728 (128MB): 최대 버퍼 - 고속 네트워크에서 자동 확장
# - 설명: 커널이 네트워크 상태에 따라 동적으로 버퍼 크기 조정
# - 효과: Bandwidth-Delay Product (BDP) 최적화
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728

# ===== 연결 대기열 관리 =====

# net.core.somaxconn: listen() 시스템 콜의 backlog 파라미터 최대값
# - 기본값: 128 (매우 작음!)
# - 권장값: 65535 (고부하 웹 서버)
# - 설명: accept() 전 대기 중인 완전히 연결된(ESTABLISHED) 소켓 큐 크기
# - 문제: 값이 작으면 "connection refused" 에러 발생
# - 효과: 트래픽 급증 시에도 연결 손실 방지
# - 예시: Nginx의 listen 80 backlog=65535;와 연계
net.core.somaxconn = 65535

# net.core.netdev_max_backlog: 네트워크 장치 입력 큐 크기
# - 기본값: 1000
# - 권장값: 100000 (10Gbps 환경)
# - 설명: NIC에서 커널로 전달된 패킷을 처리하기 전 대기하는 큐
# - 문제: 값이 작으면 패킷 드롭 (ifconfig에서 RX dropped 증가)
# - 확인: netstat -s | grep "dropped"
# - 사용 사례: DDoS 방어, 고 PPS(Packets Per Second) 환경
net.core.netdev_max_backlog = 100000

# net.ipv4.tcp_max_syn_backlog: SYN_RECV 상태 소켓 대기열 크기
# - 기본값: 128-1024 (배포판마다 다름)
# - 권장값: 8192
# - 설명: SYN을 받았지만 아직 ACK를 받지 못한 반쯤 연결된(Half-open) 소켓 큐
# - 문제: 값이 작으면 SYN Flood 공격에 취약
# - 효과: 대량의 동시 연결 요청 처리 (웹 서버 부팅 직후 트래픽 폭증)
# - 보안: tcp_syncookies와 함께 사용
net.ipv4.tcp_max_syn_backlog = 8192

# ===== TIME_WAIT 소켓 최적화 =====

# net.ipv4.tcp_tw_reuse: TIME_WAIT 소켓을 새 연결에 재사용
# - 기본값: 0 (비활성화)
# - 권장값: 1 (클라이언트 측에서 활성화)
# - 설명: 외부 서버로 나가는(outbound) 연결 시 TIME_WAIT 소켓 즉시 재사용
# - 문제 해결: "Cannot assign requested address" 에러 방지
# - 시나리오: API Gateway, Reverse Proxy가 백엔드 서버로 다량의 요청
# - 주의: 서버 측(inbound)에는 영향 없음, NAT 환경에서 문제 가능성
# - 확인: ss -tan | grep TIME_WAIT | wc -l
net.ipv4.tcp_tw_reuse = 1

# net.ipv4.tcp_fin_timeout: FIN-WAIT-2 상태 유지 시간
# - 기본값: 60초
# - 권장값: 30초
# - 설명: TCP 연결 종료 시 FIN-WAIT-2 상태에서 대기하는 시간
# - 효과: 비정상 종료된 연결의 리소스를 빠르게 회수
# - 주의: 너무 짧으면 (예: 5초) 느린 클라이언트 문제 발생 가능
net.ipv4.tcp_fin_timeout = 30

# ===== TCP Keepalive 설정 =====

# net.ipv4.tcp_keepalive_time: 유휴 연결에 keepalive 프로브 전송 시작 시간
# - 기본값: 7200초 (2시간)
# - 권장값: 600초 (10분)
# - 설명: 마지막 데이터 전송 후 연결이 살아있는지 확인하기까지의 시간
# - 효과: 좀비 연결(Zombie Connection) 조기 탐지
# - 사용 사례: 로드 밸런서, 데이터베이스 연결 풀, SSH 세션 유지
net.ipv4.tcp_keepalive_time = 600

# net.ipv4.tcp_keepalive_intvl: keepalive 프로브 재전송 간격
# - 기본값: 75초
# - 권장값: 30초
# - 설명: 응답이 없을 때 다음 프로브를 보내는 간격
net.ipv4.tcp_keepalive_intvl = 30

# net.ipv4.tcp_keepalive_probes: keepalive 프로브 최대 재시도 횟수
# - 기본값: 9회
# - 권장값: 3회
# - 설명: 응답이 없을 때 연결을 끊기 전까지 시도 횟수
# - 계산: 총 대기 시간 = keepalive_time + (keepalive_intvl * keepalive_probes)
#        = 600 + (30 * 3) = 690초 (약 11.5분) 후 연결 종료
net.ipv4.tcp_keepalive_probes = 3

# ===== TCP Fast Open (TFO) =====

# net.ipv4.tcp_fastopen: TCP 3-way handshake 최적화
# - 기본값: 0 (비활성화)
# - 권장값: 3 (클라이언트 + 서버 모두 활성화)
# - 값의 의미:
#   * 1: 클라이언트만 활성화 (외부 서버 연결 시)
#   * 2: 서버만 활성화 (들어오는 연결 수락)
#   * 3: 클라이언트 + 서버 (비트 OR: 1 | 2 = 3)
# - 원리: SYN 패킷에 데이터 포함 → RTT(Round Trip Time) 1회 절약
# - 효과: 연결 지연 감소 (HTTP 요청이 많은 환경에서 체감 향상)
# - 요구사항: 클라이언트와 서버 모두 지원 필요 (커널 3.7+)
# - 보안: TFO Cookie로 SYN Flood 방어
net.ipv4.tcp_fastopen = 3

# ===== IP 포워딩 =====

# net.ipv4.ip_forward: IPv4 패킷 포워딩 활성화
# - 기본값: 0 (비활성화)
# - 권장값: 1 (라우터, NAT, 쿠버네티스 노드)
# - 설명: 다른 네트워크로 패킷을 전달할 수 있게 함
# - 필수 시나리오:
#   * 쿠버네티스 워커 노드 (Pod 간 통신)
#   * Docker 브릿지 네트워크
#   * VPN 게이트웨이
#   * NAT 라우터
# - 확인: cat /proc/sys/net/ipv4/ip_forward
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

# ===== 로컬 포트 범위 =====

# net.ipv4.ip_local_port_range: 외부 연결 시 사용할 임시(ephemeral) 포트 범위
# - 기본값: 32768 60999 (약 28,000개)
# - 권장값: 10000 65535 (약 55,000개)
# - 설명: 클라이언트가 외부 서버로 연결 시 자동 할당되는 소스 포트
# - 문제: 범위가 좁으면 "Cannot assign requested address" 에러
# - 시나리오: Reverse Proxy, API Gateway가 백엔드로 대량 연결
# - 계산: 동시 연결 수 = (포트 범위) / (TIME_WAIT 시간 / 연결 지속 시간)
# - 예시: 1초당 1000개 요청, TIME_WAIT 30초 → 최소 30,000 포트 필요
# - 확인: ss -tan | awk '{print $4}' | grep -oP ':\d+$' | sort | uniq -c
net.ipv4.ip_local_port_range = 10000 65535

3. 보안 관련 설정

# ===== SYN Flood 공격 방어 =====

# net.ipv4.tcp_syncookies: SYN Cookie 메커니즘 활성화
# - 기본값: 1 (대부분 배포판에서 기본 활성화)
# - 권장값: 1 (필수)
# - 원리:
#   1. 정상: 클라이언트 SYN → 서버 SYN-ACK (큐에 저장) → 클라이언트 ACK
#   2. 공격: 수천 개의 SYN → 큐 가득참 → 정상 연결 거부
#   3. SYN Cookie: SYN-ACK의 시퀀스 번호에 연결 정보 암호화 저장 → 큐 불필요
# - 효과: tcp_max_syn_backlog 초과 시에도 연결 수락 가능
# - 단점: TCP 옵션(Window Scaling 등) 일부 손실 가능
# - 확인: netstat -s | grep "SYNs to LISTEN sockets dropped"
net.ipv4.tcp_syncookies = 1

# net.ipv4.tcp_max_syn_backlog: SYN Flood 방어용 백업 대기열
# - tcp_syncookies와 함께 사용하여 공격 방어 강화
net.ipv4.tcp_max_syn_backlog = 8192

# ===== ICMP Redirect 공격 방지 =====

# net.ipv4.conf.*.accept_redirects: ICMP Redirect 메시지 수락 여부
# - 기본값: 1 (수락)
# - 권장값: 0 (거부)
# - 공격 시나리오:
#   1. 공격자가 위조된 ICMP Redirect 메시지 전송
#   2. 피해자의 라우팅 테이블 변경
#   3. 트래픽이 공격자를 경유 → MitM (Man-in-the-Middle) 공격
# - 예시: "더 나은 경로가 있어요" 메시지로 속여서 게이트웨이 변경
# - 필수 적용: 프로덕션 서버, 라우터
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# ===== Source Routing 공격 방지 =====

# net.ipv4.conf.*.accept_source_route: Source Routing 패킷 수락 여부
# - 기본값: 0 (대부분 배포판에서 비활성화)
# - 권장값: 0 (거부)
# - 공격 원리:
#   * Source Routing: 송신자가 패킷 경로를 지정 (일반적으로 라우터가 결정)
#   * 공격자가 임의 경로 지정 → 방화벽 우회, 스푸핑
# - 효과: IP 스푸핑 공격 차단
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# ===== ICMP Echo (Ping) 응답 =====

# net.ipv4.icmp_echo_ignore_all: Ping 요청 무시
# - 기본값: 0 (응답함)
# - 권장값: 0 (일반 서버), 1 (고보안 서버)
# - 장점: 네트워크 스캔 회피 (Nmap 등)
# - 단점: 네트워크 디버깅 어려움 (traceroute, ping 불가)
# - 권장: 방화벽에서 ICMP 제어하는 것이 더 나음
net.ipv4.icmp_echo_ignore_all = 0

# net.ipv4.icmp_echo_ignore_broadcasts: 브로드캐스트 Ping 무시
# - 기본값: 1 (무시)
# - 권장값: 1 (필수)
# - 공격: Smurf Attack (브로드캐스트 Ping으로 DDoS 증폭)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# ===== IP 스푸핑 방지 (Reverse Path Filtering) =====

# net.ipv4.conf.*.rp_filter: 역경로 필터링
# - 기본값: 0 (비활성화) 또는 1
# - 권장값: 1 (Strict Mode)
# - 값의 의미:
#   * 0: 비활성화 (위험!)
#   * 1: Strict Mode - 들어온 인터페이스로 응답 패킷도 나가는지 확인
#   * 2: Loose Mode - 응답 경로가 라우팅 테이블에 존재하는지만 확인
# - 원리: 패킷의 소스 IP가 위조되었는지 라우팅 테이블로 검증
# - 예시:
#   * eth0으로 10.0.0.5에서 온 패킷 수신
#   * 라우팅 테이블 확인: 10.0.0.5로 가는 경로가 eth0인가?
#   * 아니면 → 스푸핑된 패킷으로 판단하여 드롭
# - 효과: DDoS 공격의 소스 IP 위조 차단
# - 주의: 비대칭 라우팅 환경에서는 2(Loose Mode) 사용
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# ===== 보안 로깅 =====

# net.ipv4.conf.*.log_martians: 비정상 패킷 로그 기록
# - 기본값: 0 (로그 안 남김)
# - 권장값: 1 (로그 남김)
# - Martian Packets: 
#   * 예약된 IP 주소 (0.0.0.0, 127.0.0.0/8, 224.0.0.0/4)
#   * 브로드캐스트 주소
#   * 멀티캐스트 주소
#   * 잘못된 소스 IP
# - 로그 위치: /var/log/kern.log 또는 dmesg
# - 예시: "martian source 192.168.1.1 from 10.0.0.5"
# - 용도: 네트워크 공격 탐지, 설정 오류 디버깅
# - 주의: 로그가 많으면 디스크 I/O 증가
net.ipv4.conf.all.log_martians = 1

# ===== SYN/ACK 재전송 =====

# net.ipv4.tcp_synack_retries: SYN-ACK 재전송 횟수
# - 기본값: 5회 (약 180초 대기)
# - 권장값: 2회 (약 7초 대기)
# - 설명: 클라이언트가 ACK를 보내지 않을 때 SYN-ACK 재전송 횟수
# - 효과: SYN Flood 공격 시 리소스 빠르게 회수
# - 재전송 간격: 1초, 2초, 4초, 8초, 16초 (지수 백오프)
net.ipv4.tcp_synack_retries = 2

# net.ipv4.tcp_syn_retries: SYN 재전송 횟수 (클라이언트 측)
# - 기본값: 6회 (약 127초)
# - 권장값: 3회 (약 7초)
# - 설명: 외부 서버로 연결 시 SYN 패킷 재전송 횟수
net.ipv4.tcp_syn_retries = 3

4. 메모리 관리

# ===== Swappiness =====

# vm.swappiness: Swap 사용 적극성 (0~100)
# - 기본값: 60
# - 권장값: 
#   * 0: Swap 최소화 (데이터베이스 서버, Redis, Elasticsearch)
#   * 10: 성능 중시 (웹 서버, 애플리케이션 서버)
#   * 60: 기본값 (데스크톱, 일반 서버)
#   * 100: 적극적 Swap (메모리 부족 환경)
# - 원리:
#   * 값이 높을수록 → 커널이 적극적으로 메모리를 Swap으로 이동
#   * 값이 낮을수록 → RAM을 최대한 활용, Swap은 최후의 수단
# - 효과:
#   * 0: OOM Killer 발동 가능성 증가하지만 성능 최상
#   * 10: 성능과 안정성의 균형 (프로덕션 권장)
#   * 60: 디스크 I/O 증가로 성능 저하 가능
# - 확인:
#   * cat /proc/sys/vm/swappiness
#   * free -h (Swap 사용량 확인)
#   * vmstat 1 (si/so 컬럼으로 Swap In/Out 모니터링)
# - 주의: 
#   * 0으로 설정해도 Swap이 완전히 비활성화되는 것은 아님
#   * swapoff -a로 완전히 비활성화 가능 (쿠버네티스 권장)
vm.swappiness = 10

# ===== Dirty Page 관리 =====

# vm.dirty_ratio: 전체 메모리 대비 더티 페이지 비율 임계값 (%)
# - 기본값: 20 (20%)
# - 권장값: 15
# - 설명:
#   * Dirty Page: 수정되었지만 아직 디스크에 쓰이지 않은 페이지 캐시
#   * 임계값 도달 시 → 프로세스 블록되고 강제로 디스크에 쓰기 시작
# - 문제: 값이 너무 크면 (예: 40%) → 한꺼번에 디스크 쓰기 → 시스템 응답 지연
# - 예시: 32GB RAM, dirty_ratio=15 → 4.8GB 더티 페이지 누적 시 강제 쓰기
# - 효과: 쓰기 성능과 시스템 응답성의 균형
# - 확인:
#   * cat /proc/meminfo | grep Dirty
#   * watch -n 1 'cat /proc/meminfo | grep -E "Dirty|Writeback"'
vm.dirty_ratio = 15

# vm.dirty_background_ratio: 백그라운드 쓰기 시작 비율 (%)
# - 기본값: 10 (10%)
# - 권장값: 5
# - 설명:
#   * 이 값 도달 시 → pdflush/flush 커널 스레드가 백그라운드로 디스크에 쓰기 시작
#   * 프로세스는 블록되지 않음 (계속 실행 가능)
# - 원리:
#   1. 더티 페이지 5% 도달 → 백그라운드 쓰기 시작 (부드럽게)
#   2. 더티 페이지 15% 도달 → 강제 쓰기 (프로세스 블록)
# - 효과: 디스크 I/O를 미리미리 분산시켜 응답 지연 방지
vm.dirty_background_ratio = 5

# vm.dirty_expire_centisecs: 더티 페이지 만료 시간 (centiseconds, 1/100초)
# - 기본값: 3000 (30초)
# - 권장값: 3000
# - 설명: 이 시간보다 오래된 더티 페이지는 우선적으로 디스크에 쓰기
# - 효과: 데이터 손실 방지 (정전 시 최대 30초 데이터만 손실)
# - 시나리오: 파일 쓰기 → 30초 이내 정전 → 데이터 손실
vm.dirty_expire_centisecs = 3000

# vm.dirty_writeback_centisecs: pdflush 스레드 실행 간격 (centiseconds)
# - 기본값: 500 (5초)
# - 권장값: 500
# - 설명: pdflush 커널 스레드가 깨어나서 더티 페이지를 확인하는 주기
# - 효과: 디스크 쓰기 빈도 조절
# - 주의: 값을 0으로 설정하면 백그라운드 쓰기 비활성화 (위험!)
vm.dirty_writeback_centisecs = 500

# ===== OOM (Out Of Memory) Killer =====

# vm.overcommit_memory: 메모리 오버커밋 정책
# - 기본값: 0 (휴리스틱)
# - 값의 의미:
#   * 0: 휴리스틱 - 커널이 요청을 평가하여 판단 (기본값)
#   * 1: 항상 허용 - 물리 메모리보다 많은 할당 허용 (위험!)
#   * 2: 엄격 제한 - Swap + RAM * overcommit_ratio까지만 허용
# - 설명:
#   * 프로세스가 malloc()로 메모리 요청 → 실제 사용 전까지 물리 메모리 미할당
#   * 오버커밋: 총 할당 요청 > 실제 물리 메모리
# - 시나리오:
#   * Mode 0: 일반 서버 (균형)
#   * Mode 1: 과학 계산 (메모리 많이 할당하지만 적게 사용)
#   * Mode 2: 데이터베이스 (예측 가능한 메모리 사용)
# - 확인: cat /proc/meminfo | grep Committed
vm.overcommit_memory = 0

# vm.overcommit_ratio: overcommit_memory=2일 때 허용 비율 (%)
# - 기본값: 50 (50%)
# - 설명: 최대 할당 = Swap + (RAM * overcommit_ratio / 100)
# - 예시: 32GB RAM, 8GB Swap, ratio=50 → 최대 24GB (8 + 32*0.5)
vm.overcommit_ratio = 50

# vm.panic_on_oom: OOM 발생 시 커널 패닉 여부
# - 기본값: 0 (OOM Killer 실행)
# - 권장값: 0 (일반 서버), 1 (클러스터 노드)
# - 설명:
#   * 0: OOM Killer가 메모리를 많이 쓰는 프로세스 종료
#   * 1: 즉시 커널 패닉 → 시스템 재부팅
# - 사용 사례:
#   * 0: 단일 서버 (프로세스 하나만 죽이고 시스템 유지)
#   * 1: HA 클러스터 (노드 전체 재시작하여 페일오버)
vm.panic_on_oom = 0

# vm.oom_kill_allocating_task: OOM 발생 시 메모리 요청한 프로세스 종료
# - 기본값: 0 (가장 큰 프로세스 종료)
# - 설명:
#   * 0: OOM Score가 가장 높은 프로세스 종료
#   * 1: 메모리를 요청한 프로세스 즉시 종료
vm.oom_kill_allocating_task = 0

# ===== Huge Pages (대용량 메모리 애플리케이션) =====

# vm.nr_hugepages: Huge Page 개수
# - 기본값: 0 (비활성화)
# - 권장값: 계산 필요 (애플리케이션 메모리 / 2MB)
# - 설명:
#   * 일반 페이지: 4KB
#   * Huge Page: 2MB (x86_64)
#   * TLB (Translation Lookaside Buffer) 미스 감소 → 성능 향상
# - 계산:
#   * Oracle DB 10GB SGA 필요 → 10240 MB / 2 MB = 5120 Huge Pages
# - 확인:
#   * cat /proc/meminfo | grep -i huge
#   * hugeadm --pool-list
# - 사용 사례:
#   * Oracle Database (SGA)
#   * PostgreSQL (shared_buffers)
#   * Redis (대용량 인스턴스)
#   * SAP HANA
# - 주의: 
#   * 시스템 부팅 시 미리 할당 (Swap 불가)
#   * 너무 많이 설정하면 일반 애플리케이션 메모리 부족
vm.nr_hugepages = 0

# vm.hugetlb_shm_group: Huge Page를 사용할 수 있는 그룹 GID
# - 설명: 이 그룹에 속한 사용자만 Huge Page 사용 가능
# - 예시: oracle 그룹 GID=1001
vm.hugetlb_shm_group = 0

# ===== Transparent Huge Pages (THP) =====

# 참고: THP는 sysctl이 아닌 /sys/kernel/mm/transparent_hugepage/에서 설정
# - 확인: cat /sys/kernel/mm/transparent_hugepage/enabled
# - 비활성화 (Redis, MongoDB, Oracle 권장):
#   echo never > /sys/kernel/mm/transparent_hugepage/enabled
#   echo never > /sys/kernel/mm/transparent_hugepage/defrag
# - 이유: THP는 동적 할당으로 지연(latency) 발생 가능

5. 파일 시스템 및 커널 제한

# 파일 디스크립터 제한
fs.file-max = 2097152                       # 시스템 전체 최대 FD
fs.nr_open = 1048576                        # 프로세스당 최대 FD

# inotify 제한 (파일 감시)
fs.inotify.max_user_watches = 524288        # 사용자당 최대 감시 수
fs.inotify.max_user_instances = 512         # 인스턴스 수

# AIO (비동기 I/O)
fs.aio-max-nr = 1048576

# 커널 메시지 버퍼
kernel.printk = 4 4 1 7                     # 콘솔 로그 레벨

# 코어 덤프 설정
kernel.core_uses_pid = 1                    # 코어 덤프에 PID 포함
kernel.core_pattern = /var/crash/core.%e.%p.%h.%t

6. 쿠버네티스/Docker 환경 최적화

# ===== 브릿지 네트워크 설정 (필수!) =====

# net.bridge.bridge-nf-call-iptables: 브릿지 트래픽 iptables 처리
# - 기본값: 0 (비활성화) 또는 1
# - 권장값: 1 (쿠버네티스 필수)
# - 설명:
#   * Pod 간 통신 패킷이 Linux 브릿지를 통과할 때 iptables 규칙 적용 여부
#   * 쿠버네티스 Service (kube-proxy)가 iptables로 로드 밸런싱 구현
# - 문제: 비활성화 시 Service Discovery 작동 안 함
# - 필수 시나리오:
#   * 쿠버네티스 모든 노드 (마스터 + 워커)
#   * Docker Swarm
#   * Calico, Flannel, Weave 네트워크 플러그인
# - 확인:
#   * lsmod | grep br_netfilter (모듈 로드 확인)
#   * modprobe br_netfilter (모듈 로드)
# - 주의: br_netfilter 커널 모듈이 먼저 로드되어야 함
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

# ===== IP 포워딩 (필수!) =====

# net.ipv4.ip_forward: Pod 간 패킷 라우팅
# - 쿠버네티스에서 필수 (Pod to Pod, Pod to Service 통신)
# - 확인: sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

# ===== Conntrack (연결 추적) 테이블 =====

# net.netfilter.nf_conntrack_max: Conntrack 테이블 최대 항목 수
# - 기본값: 65536 (너무 작음!)
# - 권장값: 1048576 (100만, 대규모 클러스터)
# - 설명:
#   * Conntrack: iptables가 상태 기반 방화벽을 위해 연결 추적
#   * 각 TCP/UDP 연결마다 항목 생성 (5-tuple: src IP, src port, dst IP, dst port, protocol)
# - 쿠버네티스 시나리오:
#   * 100개 Pod × 10개 Service × 100 연결 = 100,000+ 항목
#   * NodePort, LoadBalancer 사용 시 더 많은 항목
# - 문제: 초과 시 "nf_conntrack: table full, dropping packet" 에러
# - 확인:
#   * cat /proc/sys/net/netfilter/nf_conntrack_count (현재 사용)
#   * cat /proc/sys/net/netfilter/nf_conntrack_max (최대값)
#   * conntrack -L | wc -l (실제 연결 수)
# - 로그: dmesg | grep conntrack
# - 계산: 대략 메모리 1GB당 25,000 항목 가능
net.netfilter.nf_conntrack_max = 1048576
net.nf_conntrack_max = 1048576

# net.netfilter.nf_conntrack_tcp_timeout_established: TCP 연결 타임아웃
# - 기본값: 432000 (5일!)
# - 권장값: 86400 (1일) 또는 3600 (1시간)
# - 설명: ESTABLISHED 상태 TCP 연결이 Conntrack 테이블에 유지되는 시간
# - 효과: 오래된 연결 빠르게 제거하여 테이블 공간 확보
# - 주의: 너무 짧으면 (예: 300초) 장시간 유지되는 연결 끊김
net.netfilter.nf_conntrack_tcp_timeout_established = 86400

# net.netfilter.nf_conntrack_tcp_timeout_time_wait: TIME_WAIT 타임아웃
# - 기본값: 120초
# - 권장값: 30초
# - 설명: TIME_WAIT 상태 연결이 Conntrack에 유지되는 시간
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30

# ===== ARP (Address Resolution Protocol) 테이블 =====

# net.ipv4.neigh.default.gc_thresh1: ARP 테이블 소프트 최소값
# - 기본값: 128 (너무 작음!)
# - 권장값: 8192
# - 설명: 이 값 이하에서는 가비지 컬렉션 실행 안 함
# - 문제: 값이 작으면 "Neighbour table overflow" 에러
# - 쿠버네티스: Pod마다 IP 주소 → ARP 항목 급증
net.ipv4.neigh.default.gc_thresh1 = 8192

# net.ipv4.neigh.default.gc_thresh2: ARP 가비지 컬렉션 시작
# - 기본값: 512
# - 권장값: 32768
# - 설명: 이 값 초과 시 가비지 컬렉션 시작 (오래된 항목 제거)
net.ipv4.neigh.default.gc_thresh2 = 32768

# net.ipv4.neigh.default.gc_thresh3: ARP 테이블 하드 최대값
# - 기본값: 1024
# - 권장값: 65536
# - 설명: 절대 초과 불가, 초과 시 새 항목 거부
# - 확인: 
#   * ip -s neigh show (ARP 테이블 확인)
#   * arp -an | wc -l (항목 수)
net.ipv4.neigh.default.gc_thresh3 = 65536

# ===== 파일 디스크립터 =====

# fs.file-max: 시스템 전체 최대 파일 디스크립터
# - 기본값: 수십만 (시스템마다 다름)
# - 권장값: 2097152 (200만)
# - 쿠버네티스: 각 Pod마다 다수의 FD 사용 (소켓, 파일)
# - 확인:
#   * cat /proc/sys/fs/file-nr (사용중 / 사용가능 / 최대)
#   * lsof | wc -l (열린 파일 수)
fs.file-max = 2097152

# fs.inotify.max_user_watches: inotify 감시 파일 수
# - 기본값: 8192 (매우 작음!)
# - 권장값: 524288
# - 설명: 파일 변경 감지 (kubectl logs -f, ConfigMap 자동 리로드)
# - 문제: 초과 시 "too many open files" 또는 "no space left on device" (디스크는 충분한데도)
# - 사용 사례:
#   * kubectl logs -f (실시간 로그)
#   * Prometheus 파일 감시
#   * IDE (VS Code, IntelliJ)
# - 확인: 
#   * cat /proc/sys/fs/inotify/max_user_watches
#   * find /proc/*/fd -lname anon_inode:inotify | wc -l (사용 중)
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512

# ===== Swap 비활성화 (쿠버네티스 권장) =====

# vm.swappiness: 쿠버네티스에서는 0 권장
# - 설명: 
#   * 쿠버네티스는 메모리 리소스 제한(limits)을 정확히 추적 필요
#   * Swap 사용 시 메모리 사용량 예측 불가 → Pod Eviction 오작동
# - 공식 권장: Swap 완전 비활성화 (swapoff -a)
# - 대안: vm.swappiness=0 (커널에 따라 여전히 일부 Swap 사용 가능)
vm.swappiness = 0

# ===== PID 제한 =====

# kernel.pid_max: 시스템 최대 프로세스 ID
# - 기본값: 32768
# - 권장값: 4194304 (대규모 클러스터)
# - 쿠버네티스: 많은 Pod + Container → 많은 프로세스
# - 확인: cat /proc/sys/kernel/pid_max
kernel.pid_max = 4194304

# ===== 네트워크 성능 =====

# net.core.somaxconn: Ingress Controller, Service 처리량
# - 쿠버네티스 Ingress (Nginx, Traefik)는 높은 backlog 필요
net.core.somaxconn = 65535

# net.ipv4.tcp_max_syn_backlog: NodePort, LoadBalancer 트래픽
net.ipv4.tcp_max_syn_backlog = 8192

# ===== 보안 (선택적) =====

# net.ipv4.conf.all.rp_filter: Calico, Flannel에서 문제 발생 가능
# - Loose Mode (2) 권장 (비대칭 라우팅 허용)
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2

쿠버네티스 노드 적용 예시:

# /etc/sysctl.d/99-kubernetes.conf
# 브릿지 네트워크 (필수)
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

# IP 포워딩 (필수)
net.ipv4.ip_forward = 1

# Conntrack (대규모 클러스터)
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 86400

# ARP 테이블
net.ipv4.neigh.default.gc_thresh1 = 8192
net.ipv4.neigh.default.gc_thresh2 = 32768
net.ipv4.neigh.default.gc_thresh3 = 65536

# 파일 시스템
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288

# 메모리
vm.swappiness = 0
vm.overcommit_memory = 1

# 프로세스
kernel.pid_max = 4194304

# 네트워크
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192

# 적용
sudo modprobe br_netfilter
sudo sysctl --system

확인 스크립트:

#!/bin/bash
echo "=== 쿠버네티스 커널 파라미터 확인 ==="

echo "1. 브릿지 설정:"
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables

echo "2. IP 포워딩:"
sysctl net.ipv4.ip_forward

echo "3. Conntrack:"
echo "  현재: $(cat /proc/sys/net/netfilter/nf_conntrack_count)"
echo "  최대: $(cat /proc/sys/net/netfilter/nf_conntrack_max)"

echo "4. ARP 테이블:"
echo "  항목 수: $(ip neigh show | wc -l)"
sysctl net.ipv4.neigh.default.gc_thresh3

echo "5. 파일 디스크립터:"
cat /proc/sys/fs/file-nr
sysctl fs.inotify.max_user_watches

echo "6. Swap:"
sysctl vm.swappiness
free -h | grep Swap

7. 실무 적용 예제

고성능 웹 서버 (Nginx/Apache):

# /etc/sysctl.d/99-web-server.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 100000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10000 65535
vm.swappiness = 10
fs.file-max = 2097152

# 적용
sudo sysctl -p /etc/sysctl.d/99-web-server.conf

데이터베이스 서버 (MySQL/PostgreSQL):

# /etc/sysctl.d/99-database.conf
vm.swappiness = 1                           # Swap 최소화
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
kernel.shmmax = 68719476736                 # 공유 메모리 최대값 (64GB)
kernel.shmall = 4294967296
fs.file-max = 2097152

# Huge Pages (예: 10GB)
vm.nr_hugepages = 5120

쿠버네티스 워커 노드:

# /etc/sysctl.d/99-kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
net.netfilter.nf_conntrack_max = 1048576
vm.swappiness = 0
fs.inotify.max_user_watches = 524288
fs.file-max = 2097152

8. 커널 파라미터 확인 및 검증

# 현재 설정 확인
sysctl -a | grep tcp_rmem
sysctl net.ipv4.tcp_tw_reuse

# 적용된 설정 검증
cat /proc/sys/net/ipv4/tcp_tw_reuse
cat /proc/sys/vm/swappiness

# 부팅 시 자동 적용 확인
sudo sysctl --system

# 설정 파일 위치
/etc/sysctl.conf                # 전통적 위치
/etc/sysctl.d/*.conf            # 우선 적용 (권장)
/run/sysctl.d/*.conf            # 런타임 설정
/usr/lib/sysctl.d/*.conf        # 시스템 기본값

9. 주요 파라미터 빠른 참조표

파라미터 기본값 권장값 용도
vm.swappiness 60 10 웹/DB 서버
net.core.somaxconn 128 65535 고성능 웹 서버
net.ipv4.tcp_tw_reuse 0 1 TIME_WAIT 재사용
fs.file-max 수십만 2097152 파일 디스크립터
net.ipv4.ip_forward 0 1 라우터/쿠버네티스
net.netfilter.nf_conntrack_max 65536 1048576 쿠버네티스
fs.inotify.max_user_watches 8192 524288 IDE/빌드 툴

주의사항:

  • 변경 전 반드시 백업 필요
  • 프로덕션 환경은 테스트 후 적용
  • 시스템 재부팅 시에도 유지되는지 확인 (/etc/sysctl.conf 또는 /etc/sysctl.d/)

참고 자료

참고 자료

Clone this wiki locally