13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 서버 트러블슈팅

  • [Linux] ext4 디스크 I/O 성능 저하 원인 분석 및 진단 방법

    [Linux] ext4 디스크 I/O 성능 저하 원인 분석 및 진단 방법

    [Linux] ext4 디스크 I/O 성능 저하 원인 분석 및 진단 방법

    안녕하세요, 13년차 서버실 지킴이입니다. 🤓

    어느 날 갑자기 서버가 느려졌는데, CPU나 메모리 사용량은 평온하고 네트워크 트래픽도 평소와 다를 바 없을 때, 문득 이런 생각이 들지 않으세요? “혹시 ext4의 디스크 I/O 문제인가?” 네, 정확한 추측일 수도 있어요. 리눅스 서버에서 가장 흔하게 사용되는 파일시스템인 ext4에서 성능 저하가 벌어지면 정말 당황스럽죠. 특히 서비스 운영 중이라면 심장이 덜컥 내려앉을 겁니다.

    저도 홈랩에서 이것저것 실험하다가 갑자기 디스크 읽기/쓰기 속도가 확 떨어져서 며칠 밤낮을 삽질했던 경험이 있거든요. 처음엔 설정 문제인가 싶었는데, 알고 보니 ext4 파일시스템 자체의 특성이나 잘못된 마운트 옵션, 혹은 숨겨진 병목 때문이었더라고요. 그래서 오늘은 ext4 디스크 I/O 성능 저하의 원인을 파헤치고, 어떻게 진단하고 해결할 수 있는지 제 경험을 바탕으로 솔직하게 풀어보려 합니다. 함께 리눅스 디스크 I/O 문제를 해결해 봅시다! 💡

    리눅스 서버의 ext4 파일시스템 I/O 흐름 및 잠재적 병목 지점 개요 다이어그램

    ext4 파일시스템과 디스크 I/O, 대체 뭐가 문제일까요? 🤔

    먼저, 기본적인 개념부터 짚고 넘어갈게요. 디스크 I/O(Input/Output)는 말 그대로 디스크에 데이터를 쓰고(write) 읽는(read) 작업을 말합니다. 서버 애플리케이션의 응답 속도는 이 디스크 I/O 성능에 크게 좌우되죠. 웹 서버의 로그 기록, 데이터베이스의 쿼리 처리, 캐시 파일 저장 등 거의 모든 작업이 디스크 I/O를 수반하거든요.

    ext4는 리눅스에서 가장 널리 사용되는 저널링 파일시스템(Journaling Filesystem)입니다. 저널링 덕분에 시스템 크래시(crash) 시 데이터 일관성(data consistency)을 보장하는 강력한 장점이 있지만, 이 저널링 과정 자체가 때로는 I/O 성능 오버헤드(overhead)로 작용할 수 있어요. 쉽게 말해, 데이터를 변경하기 전에 먼저 변경 내용을 저널(journal)이라는 특별한 영역에 기록하고 나서 실제 데이터 영역에 쓰는 방식이라, 안정성은 높지만 그만큼 추가적인 디스크 작업이 필요하다는 거죠.

    ext4의 성능에 영향을 미치는 주요 요소는 다음과 같습니다:

    • 저널링 모드 (Journaling Mode): data=journal, data=ordered, data=writeback 등 모드에 따라 데이터 안정성과 성능이 달라집니다.
    • 블록 사이즈 (Block Size): 파일시스템 생성 시 지정하는 데이터 처리 단위로, 작은 파일이 많으면 작은 블록 사이즈가, 큰 파일이 많으면 큰 블록 사이즈가 유리할 수 있습니다.
    • 마운트 옵션 (Mount Options): noatime, discard, barrier=0 등 다양한 옵션으로 성능을 튜닝할 수 있습니다.
    • 디스크 자체 성능: HDD냐 SSD냐, RAID 구성이냐 등 물리적인 디스크의 스펙도 중요하죠.
    • 파일 단편화 (Fragmentation): 파일이 디스크 여러 곳에 흩어져 저장되면 읽기/쓰기 성능이 저하됩니다.

    실전! ext4 디스크 I/O 성능 진단 도구 활용법 🛠️

    자, 이제 실제로 서버에서 디스크 I/O 병목을 어떻게 찾아내는지 알아볼 차례입니다. 리눅스에는 정말 유용한 도구들이 많아요. 제가 즐겨 쓰는 몇 가지를 소개합니다.

    1. iostat: 시스템 전체 디스크 I/O 통계

    iostat은 시스템 전체의 디스크 I/O 통계를 실시간으로 보여주는 강력한 도구예요. 특정 디스크의 사용률, 큐 길이, 응답 시간 등을 한눈에 파악할 수 있거든요.

    # iostat -x 1 5
    # -x: 확장 통계 정보 출력 (extended statistics)
    # 1: 1초 간격으로
    # 5: 5번 반복 출력
    
    Linux 5.15.0-78-generic (my-server) 	08/20/2023 	_x86_64_ 	(8 CPU)
    
    avg-cpu:  %user   %nice %system %iowait  %steal   %idle
               1.20    0.00    0.80    0.10    0.00   97.90
    
    Device             r/s   w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
    sda               0.10  0.00    2.00    0.00     40.00     0.00    0.20    0.20    0.00   0.20   0.00
    sdb               0.00  0.00    0.00    0.00      0.00     0.00    0.00    0.00    0.00   0.00   0.00
    

    여기서 봐야 할 핵심 지표들은 다음과 같습니다:

    • %util: 디스크 사용률입니다. 100%에 가깝다면 디스크가 항상 바쁘다는 뜻인데, 성능 병목의 강력한 신호일 수 있어요. (⚠️ 단, 고성능 NVMe SSD의 경우 100%에 가까워도 실제 성능은 좋을 수 있으니 다른 지표와 함께 봐야 합니다!)
    • avgqu-sz (Average Queue Size): 디스크 I/O 요청 큐의 평균 길이입니다. 이 값이 지속적으로 높다면 디스크가 요청을 처리하지 못하고 대기 중인 작업이 많다는 뜻이에요. 보통 1 이상이면 주의 깊게 봐야 합니다.
    • await (Average Wait Time): I/O 요청이 디스크에서 처리되기까지 걸리는 평균 시간(밀리초)입니다. 큐에서 대기하는 시간까지 포함하므로, 이 값이 높으면 응답성이 떨어진다는 의미죠.
    • svctm (Average Service Time): I/O 요청이 디스크 컨트롤러에 의해 실제로 처리되는 평균 시간(밀리초)입니다. await과 svctm의 차이가 크다면, 큐에서 대기하는 시간이 길다는 의미로 해석할 수 있어요.

    2. sar -d: 상세 디스크 활동 통계

    sar는 시스템 활동 리포트(System Activity Reporter)의 약자로, CPU, 메모리, 네트워크 등 다양한 시스템 통계를 기록하고 분석할 수 있습니다. 디스크 I/O를 보려면 -d 옵션을 사용하면 되죠.

    # sar -d 1 5
    # -d: 디스크 활동 통계 출력
    # 1: 1초 간격으로
    # 5: 5번 반복 출력
    
    Linux 5.15.0-78-generic (my-server) 	08/20/2023 	_x86_64_ 	(8 CPU)
    
    02:30:01 PM   DEV       tps  rd_sec/s  wr_sec/s  avgrq-sz  avgqu-sz  await  svctm  %util
    02:30:02 PM   sda      0.10      2.00      0.00     40.00      0.00   0.20   0.20   0.00
    02:30:02 PM   sdb      0.00      0.00      0.00      0.00      0.00   0.00   0.00   0.00
    

    iostat과 비슷한 지표들을 제공하지만, sar는 기록된 데이터를 나중에 분석할 때 유용해요. 특히 tps (초당 전송 수), rd_sec/s (초당 읽기 섹터 수), wr_sec/s (초당 쓰기 섹터 수)를 통해 디스크의 처리량(throughput)을 가늠해볼 수 있습니다. sar는 sysstat 패키지에 포함되어 있으니, 설치되어 있지 않다면 sudo apt install sysstat (Debian/Ubuntu) 또는 sudo yum install sysstat (CentOS/RHEL)로 설치해 주세요.

    3. iotop: 프로세스별 디스크 I/O 사용량

    시스템 전체나 특정 디스크의 I/O 통계를 봤는데, 어떤 프로세스가 디스크를 많이 쓰고 있는지 궁금할 때가 있습니다. 이럴 땐 iotop이 아주 유용해요. 마치 top 명령어처럼 프로세스별 I/O 사용량을 실시간으로 보여주거든요.

    # iotop
    # -o: 현재 I/O를 사용하는 프로세스만 표시
    # -P: 프로세스만 표시 (스레드 제외)
    
    Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s
    Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s
      TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
        1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % init
        2 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]
      ...
    

    iotop을 실행하면 어떤 프로세스가 디스크를 가장 많이 쓰고 있는지 바로 알 수 있어요. IO> 컬럼을 통해 I/O 대기(wait) 상태를 파악할 수 있고, 이를 통해 특정 애플리케이션이나 서비스가 디스크 병목을 유발하는 주범인지 쉽게 찾아낼 수 있습니다. 💡

    iotop 명령어로 확인하는 프로세스별 디스크 I/O 사용량

    iotop 명령어를 통해 실시간 프로세스별 디스크 I/O 사용량을 확인하는 모습

    ⚠️ 삽질 경험담: ext4 마운트 옵션과 저널링의 함정

    제가 가장 많이 삽질했던 부분 중 하나가 바로 ext4의 마운트 옵션(Mount Options)과 저널링(Journaling)이었습니다. 단순히 디스크를 마운트할 때 아무 생각 없이 기본값으로 쓰다가 나중에 피를 본 적이 많거든요. 특히 작은 파일을 빈번하게 읽고 쓰는 웹 서버나 캐시 서버에서 이런 문제가 자주 발생하더라고요.

    1. atime 업데이트 오버헤드

    기본적으로 리눅스 파일시스템은 파일에 접근(access)할 때마다 atime(access time)을 업데이트합니다. 이게 참 좋은 기능이지만, 문제는 파일에 접근할 때마다 디스크 쓰기 작업이 발생한다는 거예요. 즉, 읽기 작업인데도 쓰기 I/O가 발생해 성능 저하를 일으킬 수 있어요. 그래서 저는 특별한 이유가 없다면 noatime 옵션을 즐겨 사용합니다.

    # /etc/fstab 파일 예시
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults,noatime,errors=remount-ro 0 1
    
    # 변경 후 적용
    sudo mount -o remount /data
    

    noatime은 atime 업데이트를 완전히 비활성화합니다. 만약 atime 정보가 필요하지만 I/O 오버헤드를 줄이고 싶다면 relatime 옵션을 사용할 수도 있어요. relatime은 마지막 접근 시간이 마지막 변경 시간(mtime)보다 오래되었을 때만 atime을 업데이트합니다. 대부분의 경우 relatime으로도 충분하고, 극단적인 성능이 필요하면 noatime을 사용하죠.

    2. 저널링 모드 선택

    앞서 설명했듯이, ext4는 저널링 모드에 따라 성능과 데이터 안정성이 달라집니다. 주요 모드는 세 가지입니다.

    • data=journal: 데이터와 메타데이터(metadata) 모두 저널에 기록합니다. 가장 안전하지만, 가장 느려요. 데이터 일관성이 최우선인 경우에만 고려해볼 만합니다.
    • data=ordered (기본값): 메타데이터만 저널에 기록하고, 데이터는 메타데이터가 커밋(commit)되기 전에 디스크에 쓰여지도록 보장합니다. 안정성과 성능의 균형이 좋아서 대부분의 경우에 적합하죠.
    • data=writeback: 메타데이터만 저널에 기록하고, 데이터는 저널링되지 않습니다. 가장 빠르지만, 시스템 크래시 시 데이터 손실 위험이 있어요. 캐시 디스크나 로그 디스크처럼 데이터 손실이 치명적이지 않은 경우에 고려할 수 있습니다.

    저널링 모드 변경은 파일시스템 생성 시 또는 tune2fs 명령으로 변경 가능하지만, 마운트 옵션으로도 지정할 수 있어요. 예를 들어, 성능을 최우선으로 한다면:

    # /etc/fstab 파일 예시
    UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /cache ext4 defaults,noatime,data=writeback 0 2
    
    # 변경 후 적용
    sudo mount -o remount /cache
    

    ⚠️ data=writeback은 데이터 손실 위험이 있으니 신중하게 사용하세요!

    3. 그 외 유용한 마운트 옵션

    몇 가지 더 유용한 옵션들을 표로 정리해봤습니다.

    옵션 설명 효과 주의사항
    noatime 파일 접근 시간(atime) 업데이트 비활성화 읽기 I/O 발생 시 쓰기 I/O 감소 atime 정보가 필요한 애플리케이션에 문제 발생 가능
    relatime mtime보다 오래된 atime만 업데이트 noatime과 atime 업데이트의 절충안 대부분의 경우 noatime 대신 사용 권장
    data=writeback 데이터 저널링 비활성화 가장 빠른 쓰기 성능 시스템 크래시 시 데이터 손실 위험
    barrier=0 디스크 쓰기 배리어(write barrier) 비활성화 일부 환경에서 쓰기 성능 향상 RAID 컨트롤러 또는 가상 환경에서 데이터 손실 위험 증가, 신중히 사용
    discard TRIM 명령 활성화 (SSD에 유용) SSD 성능 유지 및 수명 연장 지속적인 TRIM으로 인한 오버헤드 발생 가능 (주기적인 fstrim 권장)
    ext4 마운트 옵션별 성능 및 데이터 안정성 비교 인포그래픽

    ext4 마운트 옵션별 성능 및 데이터 안정성 비교

    ✅ 검증 및 결과 확인: 성능 개선을 눈으로 확인하기!

    마운트 옵션을 변경했거나, 문제가 되는 프로세스를 해결했다면, 이제 정말로 성능이 개선되었는지 확인해야겠죠? 저는 주로 iostat이나 sar로 다시 한번 지표를 확인해요. 특히 await, avgqu-sz, %util 값이 어떻게 변했는지 집중해서 봅니다.

    • await 값이 5ms 미만으로 꾸준히 유지된다면 양호한 수준입니다. 10ms 이상으로 지속된다면 여전히 I/O 병목이 있을 가능성이 높아요.
    • avgqu-sz 값이 1 이하로 떨어졌는지 확인해요. 이 값이 높으면 I/O 요청이 계속 밀리고 있다는 뜻이거든요.
    • %util은 무조건 낮다고 좋은 건 아니지만, 과도하게 높으면서 다른 지표들(await, avgqu-sz)도 높다면 문제가 있다는 신호예요.

    만약 특정 애플리케이션의 성능 저하가 문제였다면, 해당 애플리케이션의 응답 시간(response time)이나 처리량(throughput) 지표를 직접 확인하는 것이 가장 정확해요. 예를 들어, 데이터베이스 쿼리 속도가 빨라졌는지, 웹 페이지 로딩 시간이 단축되었는지 등을 측정해보는 거죠. 저는 Grafana와 Prometheus를 활용해서 I/O 지표를 시각화해서 보곤 하는데, 이렇게 하면 변화 추이를 한눈에 파악하기 정말 편하더라고요. 🎉

    Grafana 대시보드에서 디스크 I/O 성능 개선 추이를 시각적으로 확인하는 예시

    마무리: 나의 ext4는 어떤 길을 가야 할까? 🚀

    ext4 디스크 I/O 성능 문제는 정말 흔하고, 처음엔 막막하게 느껴질 수 있어요. 하지만 iostat, sar, iotop 같은 도구들을 활용해서 정확한 원인을 파악하고, 적절한 마운트 옵션 튜닝이나 저널링 모드 변경을 통해 충분히 해결할 수 있습니다.

    결론적으로, “내 ext4는 어떤 설정이 최적일까?”라는 질문에 대한 답은 “어떤 데이터를, 어떻게 사용하는지에 따라 다르다”는 거예요.

    • 만약 데이터 일관성과 안전성이 최우선이라면, data=ordered (기본값)를 유지하고, noatime보다는 relatime을 고려하는 것이 좋습니다.
    • 로그 파일이나 캐시처럼 데이터 손실에 비교적 관대한 환경에서 최고의 쓰기 성능을 원한다면, data=writeback과 noatime 조합을 신중하게 테스트해볼 수 있습니다. 하지만 이 경우 백업 전략을 더욱 철저히 해야겠죠.
    • SSD를 사용 중이라면, discard 옵션을 사용하거나 주기적으로 fstrim 명령을 실행하여 성능을 유지하는 것이 좋아요.

    이번 글이 여러분의 ext4 성능 문제 해결에 작은 도움이 되었기를 바랍니다. 다음번에는 파일 단편화(fragmentation) 문제를 깊이 다루거나, 더 나아가 ZFS나 Btrfs 같은 다른 파일시스템의 성능 튜닝에 대해서도 이야기해볼까 합니다. 궁금한 점이 있다면 언제든 댓글로 남겨주세요! 저의 삽질 경험이 또 다른 글이 될 수 있으니까요. 😉

  • [Linux] 리눅스 네트워크 설정 실패 회고: 1년 운영 경험으로 배운 베스트 프랙티스

    [Linux] 리눅스 네트워크 설정 실패 회고: 1년 운영 경험으로 배운 베스트 프랙티스

    리눅스 네트워크 설정 실패 회고: 1년 운영 경험으로 배운 베스트 프랙티스

    리눅스 서버를 1년 정도 꾸준히 운영하다 보면, 결국 한 번쯤은 리눅스 네트워크 설정 실패를 겪게 되더라고요. 저도 홈랩에서 Ubuntu Server, Rocky Linux 계열, Debian 계열을 번갈아 굴리면서 꽤 여러 번 삽질했습니다 ㅎㅎ 특히 원격으로 붙어 있는 서버에서 네트워크를 잘못 건드리면, 그 순간 SSH가 끊기고 화면 앞에서 멍해지는 경험을 하게 됩니다. 이 글은 그런 실수들을 그냥 흑역사로 남기지 않고, 리눅스 서버 운영 관점에서 무엇을 조심해야 하는지 정리한 회고입니다.

    이번 글에서는 제가 실제로 자주 부딪혔던 iptables(아이피테이블즈, 리눅스 패킷 필터/방화벽) 실수, DNS(Domain Name System) 설정 꼬임, netplan(넷플랜, Ubuntu 계열 네트워크 설정 도구) 문제를 중심으로 풀어보겠습니다. 화려한 이론보다, 운영하면서 왜 망가졌는지와 어떻게 복구했는지가 더 중요하거든요.

    리눅스 네트워크 설정 실패를 설명하는 홈랩 서버 네트워크 구성 이미지

    홈랩에서 라우터, 스위치, 리눅스 서버, 관리용 노트북이 연결된 전체 네트워크 개요를 보여주는 이미지입니다.

    1. 왜 리눅스 네트워크 설정 실패가 운영에서 치명적인가

    서버에서 네트워크는 그냥 연결만 되면 끝나는 영역처럼 보이는데, 실제로는 아닙니다. 서비스 장애의 시작점이 되는 경우가 많습니다. CPU나 메모리는 눈에 보이게 올라가지만, 네트워크는 조용히 잘못되는 경우가 많거든요.

    • SSH는 되는데 외부 패키지 저장소 접근이 안 되는 경우
    • IP는 붙었는데 DNS 조회가 안 돼서 애플리케이션이 죽는 경우
    • 방화벽 규칙이 꼬여서 특정 포트만 막히는 경우
    • 재부팅 후 설정이 다르게 올라오는 경우

    여기서 중요한 포인트! 리눅스 네트워크 설정 실패는 대부분 한 번에 크게 터지지 않습니다. 처음엔 “어? 왜 이렇게 느리지?” 정도로 시작하다가, 나중엔 서비스가 안 뜨는 식으로 번지더라고요. 저도 처음엔 이게 뭔가 싶었는데, 결국 원인은 기본값을 너무 믿었던 데 있었습니다.

    2. 쉽게 말해 보는 핵심 개념: IP, Gateway, DNS, Firewall

    복잡해 보여도 네트워크는 몇 가지만 분리해서 보면 정리가 됩니다. 쉽게 말해, 서버가 네트워크에서 길을 찾고, 이름을 해석하고, 누굴 통과시킬지 결정하는 과정입니다.

    구성 요소 역할 리눅스 네트워크 설정 실패 증상
    IP Address 서버 자신의 주소 같은 대역 충돌, 접속 불가
    Gateway 다른 네트워크로 나가는 출구 외부 통신 실패
    DNS 이름을 IP로 바꾸는 해석기 도메인 접근 실패, 업데이트 실패
    Firewall 들어오고 나가는 트래픽 제어 특정 포트만 차단, 간헐적 장애

    운영 입장에서 보면 순서도 중요합니다. 보통은 링크(Link, 물리/가상 NIC 상태)가 살아 있는지 확인하고, 그다음 IP, 라우팅, DNS, 방화벽 순으로 봐야 합니다. 근데 저도 예전에는 바로 iptables부터 의심했었거든요. 실제로는 게이트웨이 한 줄이 빠진 경우가 더 많았습니다.

    3. 1년 운영하면서 가장 많이 했던 리눅스 네트워크 설정 실패 세 가지

    3-1. iptables 실수: 기본 정책부터 DROP으로 바꿨다가 SSH 차단

    iptables 실수는 진짜 한 번은 꼭 겪습니다. 저도 “보안을 좀 더 깔끔하게 하자”는 생각으로 INPUT 기본 정책을 DROP으로 바꿨다가, SSH 허용 규칙 적용 순서를 잘못 넣어서 바로 접속이 끊긴 적이 있습니다. 콘솔이 붙어 있어서 망정이지, 원격 장비였으면 더 골치 아팠을 겁니다.

    3-2. DNS 설정 꼬임: ping은 되는데 apt와 curl이 실패

    이건 초보 때보다 오히려 익숙해진 뒤에 더 자주 터지더라고요. IP 통신은 되는데 저장소 접근이 안 되면 대개 DNS 설정 문제였습니다. 특히 systemd-resolved를 쓰는 환경에서 /etc/resolv.conf를 직접 고쳐 버리면, 재부팅이나 네트워크 재시작 때 다시 꼬이는 경우가 있었습니다.

    3-3. netplan 문제: YAML 들여쓰기 하나로 네트워크가 안 올라옴

    netplan 문제는 문법 자체는 단순한데, YAML이 공백에 민감해서 생각보다 자주 발목을 잡습니다. 제가 직접 해보니, 설정을 급하게 바꾸다가 NIC 이름을 잘못 쓰거나 들여쓰기를 틀리면 부팅 후 네트워크가 예상과 다르게 올라오더라고요. 특히 ens18과 eth0를 혼동하는 케이스가 많았습니다.

    4. 실전 구현: 안전하게 네트워크 설정 바꾸는 절차

    여기서는 제가 지금도 지키는 최소한의 변경 절차를 정리해보겠습니다. 핵심은 한 번에 바꾸지 않고, 검증 가능한 작은 단위로 진행하는 겁니다.

    1. 현재 상태를 백업합니다.
    2. 활성 NIC 이름과 라우팅 테이블을 확인합니다.
    3. IP, Gateway, DNS를 한 번에 다 바꾸지 말고 순서대로 적용합니다.
    4. 원격 작업이면 세션을 하나 더 열어 둡니다.
    5. 방화벽은 허용 규칙을 먼저 넣고 기본 정책을 나중에 바꿉니다.
    6. 적용 후 즉시 ping, ss, resolvectl, journalctl로 검증합니다.
    ip -brief address
    ip route
    resolvectl status
    ss -tulpen
    sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.bak
    sudo iptables-save > ~/iptables-backup.rules

    이 정도만 해도 복구 속도가 확실히 빨라집니다. 저는 예전엔 백업 없이 바로 수정했었는데, 그게 제일 큰 실수였습니다.

    4-1. netplan 예시

    network:
      version: 2
      renderer: networkd
      ethernets:
        ens18:
          dhcp4: false
          addresses:
            - 192.168.0.50/24
          routes:
            - to: default
              via: 192.168.0.1
          nameservers:
            addresses:
              - 1.1.1.1
              - 8.8.8.8

    적용 전에 꼭 문법을 다시 보셔야 합니다. 원격 서버라면 특히 더요.

    sudo netplan generate
    sudo netplan try

    netplan try는 정말 유용합니다. 잘못 적용하면 자동으로 이전 상태로 되돌릴 수 있어서, 저처럼 리눅스 네트워크 설정 실패를 많이 겪은 사람에게는 안전벨트 같은 기능이거든요.

    리눅스 네트워크 설정 실패 대응을 위한 netplan 설정 검증 이미지

    netplan YAML 파일과 터미널에서 ip, route, resolvectl로 확인하는 과정을 함께 보여주는 이미지입니다.

    4-2. iptables 적용 예시

    sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    sudo iptables -A INPUT -i lo -j ACCEPT
    sudo iptables -P INPUT DROP
    sudo iptables -P FORWARD DROP
    sudo iptables -P OUTPUT ACCEPT

    여기서 순서가 중요합니다. 허용 규칙을 먼저 넣고 마지막에 정책을 조정해야 합니다. 저는 예전에 이 순서를 반대로 했다가 SSH가 끊겼습니다. iptables 실수의 전형적인 사례죠. “드디어 됐다!” 싶어서 정책부터 바꾸면, 바로 사고 납니다.

    4-3. DNS 점검 예시

    ping -c 2 8.8.8.8
    getent hosts example.com
    resolvectl query example.com
    cat /etc/resolv.conf

    IP로는 통신되는데 도메인만 안 되면 DNS 설정을 보시면 됩니다. 반대로 DNS 설정이 정상인데도 외부가 안 되면 라우팅이나 방화벽 쪽일 가능성이 높습니다.

    5. ⚠️ 실제 리눅스 네트워크 설정 실패 사례와 복구 과정

    이 섹션은 좀 더 현실적인 회고입니다. 보기엔 사소한데, 운영에선 꽤 아픈 문제들이었습니다.

    5-1. 게이트웨이 누락으로 내부망만 되고 외부망은 불가

    서버 간 통신은 되는데 패키지 업데이트가 안 됐습니다. 처음엔 DNS 문제인 줄 알았는데, 실제로 써보니까 기본 게이트웨이(default gateway)가 빠져 있더라고요. 내부망은 같은 서브넷이라 통신되지만, 외부로 나갈 출구가 없으니 당연히 실패한 겁니다.

    • ip route에 default 경로가 있는지 확인
    • 게이트웨이 IP가 실제 라우터 주소와 일치하는지 확인
    • 정적 라우트가 있으면 우선순위도 함께 점검

    5-2. NIC 이름 오인으로 netplan 적용 실패

    가상화 환경을 옮기고 나서 기존 설정을 그대로 썼는데 NIC 이름이 달랐습니다. 예전엔 eth0였는데 새 환경에서는 ens18로 올라왔거든요. 문법은 맞는데 적용이 안 되니 한참 헤맸습니다. 이것도 리눅스 네트워크 설정 실패의 전형적인 경우죠.

    • ip -brief link로 실제 인터페이스 이름 확인
    • 클라우드 이미지나 VM 템플릿 복제 시 이름이 바뀔 수 있음
    • 문법보다 장치 식별이 먼저라는 점을 기억

    5-3. 방화벽 저장 누락으로 재부팅 후 규칙 유실

    이것도 흔합니다. 세션 중에는 잘 되는데 재부팅하면 다시 열려 있거나 다시 막혀 있죠. 이유는 간단합니다. 런타임 규칙과 영구 저장 규칙을 분리해서 이해하지 않았기 때문입니다. 배포판마다 iptables-persistent나 별도 서비스 관리 방식이 다를 수 있으니, 현재 서버가 어떤 방식으로 규칙을 유지하는지 먼저 확인하셔야 합니다.

    6. 네트워크 베스트 프랙티스: 제가 지금은 이렇게 운영합니다

    네트워크 베스트 프랙티스는 거창한 게 아닙니다. 사고를 줄이는 습관에 가깝습니다. 1년 동안 리눅스 서버를 굴려보니 아래 원칙이 가장 효과가 좋았습니다.

    항목 예전 방식 지금 방식
    설정 변경 한 번에 수정 단계별 변경 후 즉시 검증
    방화벽 정책부터 변경 허용 규칙 먼저 적용
    DNS 안 되면 아무 파일이나 수정 현재 resolver 구조부터 확인
    netplan 바로 apply generate, try 후 적용
    운영 기록 기억에 의존 변경 로그를 간단히 남김
    • 변경 전 현재 상태를 텍스트로 저장해 둡니다.
    • 운영 서버는 콘솔 접근 수단을 반드시 확보합니다.
    • DNS와 라우팅을 분리해서 테스트합니다.
    • 보안 강화를 할 때는 서비스 영향도를 먼저 봅니다.
    • 재부팅 후에도 유지되는지 꼭 확인합니다.

    혹시 이런 경험 있으신가요? 설정은 맞는 것 같은데, 재부팅 한 번 하고 나면 갑자기 안 되는 상황이요. 그런 경우는 대부분 “현재 세션에만 반영된 상태”와 “영구 설정 파일”이 다를 때가 많습니다. 저도 처음엔 헷갈렸는데, 이 구분만 해도 리눅스 네트워크 설정 실패 문제 절반은 줄어듭니다.

    iptables 실수 방지를 위한 리눅스 네트워크 설정 실패 예방 이미지

    SSH 허용 규칙을 먼저 넣고 기본 정책을 나중에 적용하는 안전한 iptables 흐름을 설명하는 이미지입니다.

    7. 검증 방법: 적용 후 무엇을 확인해야 하나

    설정이 들어갔다고 끝이 아닙니다. 검증이 빠지면 다음 장애 때 원인을 다시 처음부터 찾게 됩니다.

    1. 링크 상태: 인터페이스가 UP인지 확인합니다.
    2. 주소 확인: IP와 서브넷이 의도대로 붙었는지 봅니다.
    3. 라우팅 확인: default route가 맞는지 확인합니다.
    4. 이름 해석: DNS 질의가 정상인지 테스트합니다.
    5. 포트 확인: 서비스가 실제로 바인딩됐는지 확인합니다.
    6. 외부 접속: 다른 장비에서 실제 접속 테스트를 합니다.
    ip -brief address
    ip route
    getent hosts github.com
    ss -tulpen
    journalctl -u systemd-networkd --since "10 minutes ago"

    저는 여기에 하나를 더 합니다. 바로 “재부팅 검증”입니다. 지금 당장 되느냐보다, 다음 부팅에서도 그대로 올라오느냐가 운영에서는 더 중요하거든요.

    IP, 라우팅, DNS, 포트 상태를 체크리스트 형태로 확인하는 검증 결과 이미지를 넣는 자리입니다.

    8. 자주 묻는 질문과 정리

    Q1. ping이 되면 네트워크는 정상 아닌가요?

    꼭 그렇지는 않습니다. ICMP는 되는데 TCP 포트가 막혀 있을 수 있고, IP는 되는데 DNS 설정이 안 될 수도 있습니다. 그래서 계층별로 봐야 합니다.

    Q2. netplan만 쓰면 리눅스 네트워크 설정 문제가 다 해결되나요?

    아닙니다. netplan은 선언형 설정 도구일 뿐이고, 실제 렌더러가 networkd인지 NetworkManager인지도 봐야 합니다. 도구를 맹신하면 오히려 원인 파악이 늦어집니다.

    Q3. iptables와 nftables 중 무엇을 써야 하나요?

    배포판과 운영 환경에 따라 다릅니다. 중요한 건 이름보다도 현재 시스템이 어떤 프레임워크를 실제로 쓰는지 확인하는 겁니다. 혼용된 상태에서 규칙을 만지는 게 더 위험하더라고요.

    리눅스 네트워크 설정 실패를 줄이는 가장 좋은 방법은 천재적인 설정이 아니라, 평범한 검증 습관입니다. 저도 1년 동안 서버를 굴리면서 별별 문제를 다 겪었는데, 결국 살아남는 방법은 백업, 단계별 적용, 즉시 검증이었습니다. 다음 글에서는 방화벽 정책을 서비스별로 나누는 방법이나, 홈랩 기준 VLAN 분리 전략도 다뤄볼 예정입니다. 이전 글에서 다뤘던 로그 확인 습관과 함께 보시면 더 도움이 되실 겁니다.

    리눅스 서버 운영에서 네트워크 베스트 프랙티스를 한눈에 정리한 요약 인포그래픽 이미지입니다.

    정리하자면 이렇습니다.

    • 리눅스 네트워크 설정 실패는 대부분 기본 개념보다 적용 순서와 검증 부족에서 시작됩니다.
    • iptables 실수는 규칙 순서와 영구 저장 여부를 먼저 확인하셔야 합니다.
    • DNS 설정은 resolver 구조를 이해하고 나서 건드려야 덜 꼬입니다.
    • netplan 문제는 YAML 문법과 NIC 이름 확인이 핵심입니다.
    • 네트워크 베스트 프랙티스는 결국 안전한 변경 절차를 습관으로 만드는 일입니다.