반응형

🚨 문제 상황: NAS 데이터 이전 중 발생한 배드섹터와 rsync 멈춤 현상

노후화된 NAS 장비를 새 장비로 교체하거나 데이터를 마이그레이션 할 때 가장 많이 사용하는 도구가 바로 rsync입니다. 하지만 소스(원본) NAS의 하드디스크에 배드섹터(Bad Sector)나 파일 시스템 손상이 있는 경우, rsync가 특정 파일에서 진행되지 않고 무한 대기(Hang) 상태에 빠지거나 에러를 뿜으며 연결이 끊어지는 답답한 상황이 발생합니다.

이때 급한 마음에 디스크를 통째로 복제하는 dd 명령어를 떠올리기 쉽지만, 이는 매우 위험한 선택입니다. 오늘은 배드섹터가 존재하는 악조건 속에서 데이터를 가장 안전하게 마이그레이션하는 두 가지 실무 전략을 정리해 보겠습니다.


❌ 왜 일반적인 dd 명령어 사용을 비추천할까?

서비스를 중지(Offline)한 상태라 하더라도, 배드섹터가 있는 디스크에 일반 dd 명령어를 사용하는 것은 강력히 비권장합니다. 그 이유는 다음과 같습니다.

  1. 동일한 I/O 에러 발생: dd 역시 배드섹터 구간을 만나면 읽기 오류로 명령어가 중단되거나 시스템 전체가 먹통이 됩니다.
  2. 파티션 및 RAID 정보 충돌: NAS는 제조사마다 OS 영역, 스왑, 데이터 영역의 파티션 구조가 다릅니다. dd로 디스크를 통째로 밀어버리면 타겟 NAS의 OS나 RAID 정보까지 덮어써져 부팅 불능 상태가 될 수 있습니다.
  3. 비효율적인 전송 시간: 파일의 유무와 상관없이 빈 공간까지 모두 복사하므로 시간이 기하급수적으로 늘어납니다.

따라서 데이터의 성격(일반 파일 vs 통짜 볼륨)에 따라 아래의 해결책 1 또는 해결책 2를 선택해야 합니다.


🛠️ 해결책 1. 파일 레벨 마이그레이션: rsync 무한 루프 스크립트 적용 (추천)

일반적인 문서, 이미지, 동영상 파일(SMB/NFS 공유)을 넘기는 상황이라면 rsync에 타임아웃(Timeout)과 무한 재시도 로직을 장착하는 것이 가장 확실합니다.

배드섹터가 있는 파일에서 잠시 멈췄다가 강제로 끊어내고, 다음 정상 파일부터 이어받기를 수행하는 강력한 쉘 스크립트입니다.

📌 rsync 자동 재시도 쉘 스크립트 (migration.sh)

Bash
 
#!/bin/bash

echo "🚀 배드섹터 대응 NAS 마이그레이션을 시작합니다..."

# rsync가 완전히 성공(종료 코드 0)할 때까지 무한 반복하는 루프
while [ 1 ]
do
    # 핵심 옵션: --timeout=60 (60초 응답 없으면 강제 종료 후 루프 재시작)
    # --inplace 및 --partial 옵션으로 끊긴 부분부터 이어받기 수행
    rsync -avh \
          --update \
          --ignore-errors \
          --partial \
          --inplace \
          --timeout=60 \
          --log-file=/var/log/nas_mig.log \
          /source_dir/ \
          /target_dir/
    
    # rsync 종료 코드 확인
    if [ "$?" = "0" ] ; then
        echo "✅ 마이그레이션이 성공적으로 완료되었습니다."
        break # 루프 탈출
    else
        echo "⚠️ 배드섹터/네트워크 오류(타임아웃) 발생! 10초 대기 후 이어받습니다..."
        sleep 10
    fi
done

💡 실무 꿀팁: 백그라운드로 스크립트를 실행한 뒤, /var/log/nas_mig.log 파일에서 rsync error나 Input/output error 키워드만 추출(grep)해보세요. 어떤 파일이 배드섹터 때문에 복사를 실패했는지 정확히 리스트업 할 수 있습니다.


🛠️ 해결책 2. 블록 레벨 마이그레이션: ddrescue를 활용한 디스크 복제

만약 NAS를 가상머신(VM) 저장소나 데이터베이스용 iSCSI LUN으로 사용 중이라면, 파일 단위 복사가 불가능하므로 디스크(블록) 단위로 복원해야 합니다. 이때는 dd가 아닌 **데이터 복구 전용 도구인 ddrescue**를 사용해야 합니다.

ddrescue는 배드섹터를 만나면 즉시 건너뛰고 정상 데이터부터 빠르게 복사한 뒤, 나중에 건너뛴 배드섹터 영역만 다시 찾아가 정밀 타격(Scraping)을 시도하는 지능형 복구 툴입니다.

📌 ddrescue 2단계 복구 시나리오

주의사항: 절대 원본 고장 디스크를 마운트(Mount)하지 마시고, 타겟 디스크의 용량이 원본보다 같거나 커야 합니다. (원본: /dev/sda, 대상: /dev/sdb 가정)

1단계: 정상 데이터부터 대피시키기 (Fast Pass) 배드섹터를 긁어내려 애쓰지 않고(-n), 정상적인 블록들만 최대한 빠르게 대상 디스크로 넘깁니다.

Bash
 
# -f: 물리 디스크 강제 덮어쓰기 허용 / -n: 배드섹터 스크래핑 건너뛰기
# /root/rescue.map 파일은 작업 지도로 반드시 필요함!
ddrescue -f -n /dev/sda /dev/sdb /root/rescue.map

2단계: 건너뛴 배드섹터 정밀 복구 (Scraping & Retry) 1단계가 끝나면 동일한 맵 파일(rescue.map)을 사용하여, 앞서 실패했던 구간만 Direct I/O(-d) 모드로 최대 3번(-r3) 재시도합니다.

Bash
 
ddrescue -d -f -r3 /dev/sda /dev/sdb /root/rescue.map

📝 마무리 요약

  • NAS 간 마이그레이션 시 배드섹터가 의심된다면 절대 일반 dd를 사용하지 마세요.
  • 파일/폴더 기반 동기화는 rsync 타임아웃 옵션 + 무한 루프 스크립트가 정답입니다.
  • 디스크 통짜 복제가 불가피한 환경이라면 ddrescue를 이용해 Multi-pass 복구를 진행하세요.

데이터 마이그레이션은 엔지니어에게 가장 피 말리는 작업 중 하나입니다. 위 가이드가 무사히 데이터를 넘기는 데 도움이 되길 바랍니다.

반응형
반응형

CentOS 7, 이제 정말 끝났다

2024년 6월 30일, CentOS 7이 공식 지원 종료(EOL, End of Life)를 맞이했습니다. 이후로는 보안 패치와 버그 수정이 전혀 제공되지 않습니다. 아직도 CentOS 7을 운영 중인 서버가 있다면 보안 취약점에 그대로 노출된 상태라는 의미입니다. 더 이상 미룰 수 없는 상황에서 가장 현실적인 대안으로 꼽히는 것이 바로 Rocky LinuxAlmaLinux입니다.

두 배포판 모두 RHEL(Red Hat Enterprise Linux)과 1:1 바이너리 호환을 목표로 만들어진 무료 엔터프라이즈 리눅스입니다. 이 글에서는 두 배포판의 차이점을 비교하고, CentOS 7에서 마이그레이션하는 실전 절차를 정리합니다.

왜 CentOS 8이 아닌 CentOS 7이 문제인가

많은 분들이 혼동하는 부분입니다. CentOS 8은 이미 2021년 12월에 지원이 종료됐고, Red Hat은 CentOS를 롤링 릴리즈 방식의 CentOS Stream으로 전환했습니다. CentOS Stream은 RHEL의 업스트림 개발 브랜치 성격이라 기존 CentOS처럼 안정적인 엔터프라이즈 서버 운영에는 적합하지 않습니다. 결국 CentOS의 공백을 메우기 위해 커뮤니티 주도로 탄생한 것이 Rocky Linux와 AlmaLinux입니다.

Rocky Linux vs AlmaLinux — 탄생 배경

Rocky Linux

Rocky Linux는 CentOS의 공동 창립자인 Gregory Kurtzer가 주도해 만든 배포판입니다. "CentOS가 원래 하려던 것을 우리가 한다"는 철학으로 시작했으며, Rocky Enterprise Software Foundation(RESF)이 운영합니다. RHEL 소스 코드를 기반으로 1:1 바이너리 호환성을 보장하며, 커뮤니티 중심의 거버넌스 구조를 강조합니다.

  • 개발 주체: Rocky Enterprise Software Foundation(RESF), 커뮤니티 중심
  • 최신 버전: Rocky Linux 9.x (RHEL 9 기반)
  • 지원 기간: 메이저 버전 기준 10년 (Rocky Linux 8: 2029년까지, 9: 2032년까지)
  • 특징: FIPS 140-2/3 인증, 강력한 커뮤니티 생태계

AlmaLinux

AlmaLinux는 웹 호스팅 기업 CloudLinux가 주도해 만든 배포판으로, AlmaLinux OS Foundation이 운영합니다. 기업 후원이 탄탄한 편이며, Red Hat이 RHEL 소스 공개 정책을 변경한 이후에는 RHEL 1:1 호환 대신 ABI(Application Binary Interface) 호환 방식으로 전환해 독립성을 강화했습니다.

  • 개발 주체: AlmaLinux OS Foundation (CloudLinux 후원)
  • 최신 버전: AlmaLinux 9.x (RHEL 9 기반)
  • 지원 기간: 메이저 버전 기준 10년 (AlmaLinux 8: 2029년까지, 9: 2032년까지)
  • 특징: FIPS 140-3 인증, ELevate 마이그레이션 툴 제공, 기업 지원 옵션 있음

두 배포판 핵심 비교

  • RHEL 호환성: Rocky Linux는 바이너리 1:1 호환 / AlmaLinux는 ABI 호환 (실사용 환경에서 차이 거의 없음)
  • 거버넌스: Rocky Linux는 순수 커뮤니티 중심 / AlmaLinux는 기업(CloudLinux) 후원 기반
  • 마이그레이션 툴: AlmaLinux의 ELevate 툴이 더 성숙하고 다양한 경로 지원
  • 기업 지원: AlmaLinux는 유료 상업 지원 옵션 제공 / Rocky Linux는 커뮤니티 중심
  • 패키지 업데이트 속도: 두 배포판 모두 RHEL 패치 후 수일 내 반영으로 큰 차이 없음

결론적으로 어느 쪽을 선택해도 실제 운영 환경에서 체감 차이는 거의 없습니다. 순수 커뮤니티를 선호하면 Rocky Linux, 기업 지원과 안정적인 마이그레이션 툴을 원하면 AlmaLinux를 권장합니다.

마이그레이션 전 반드시 해야 할 준비

  • 전체 백업: 시스템 스냅샷 또는 전체 백업 필수. 마이그레이션 실패 시 롤백 수단이 없으면 복구 불가.
  • 운영 중인 패키지 목록 확인: rpm -qa > /root/pkg_list_before.txt 로 현재 설치 패키지 기록
  • 서드파티 저장소 확인: EPEL, Remi, SCLo 등 외부 저장소 패키지는 마이그레이션 후 재설치 필요할 수 있음
  • 테스트 서버에서 먼저 검증: 동일 구성의 테스트 서버에서 마이그레이션 절차를 먼저 수행하고 이상 없을 때 운영 서버에 적용
  • 커널 및 패키지 최신화: yum update -y 후 재부팅으로 최신 상태 유지

AlmaLinux ELevate로 CentOS 7 마이그레이션 (권장)

AlmaLinux가 제공하는 ELevate 프로젝트는 CentOS 7에서 AlmaLinux 8로의 인플레이스(In-place) 업그레이드를 지원하는 공식 툴입니다. 재설치 없이 기존 서버에서 직접 OS를 전환할 수 있습니다.

ELevate 마이그레이션 절차

# 1. ELevate 저장소 설치
sudo yum install -y http://repo.almalinux.org/elevate/elevate-release-latest-el7.noarch.rpm

# 2. leapp 및 데이터 패키지 설치
sudo yum install -y leapp-upgrade leapp-data-almalinux

# 3. 사전 점검 실행 (실제 업그레이드 없이 문제 항목만 탐지)
sudo leapp preupgrade

# 4. 점검 리포트 확인
cat /var/log/leapp/leapp-report.txt

preupgrade 실행 후 리포트에서 inhibitor(차단 요소)로 표시된 항목은 반드시 해결해야 업그레이드가 진행됩니다. 자주 나오는 차단 요소는 다음과 같습니다.

# PAM 설정 관련 차단 요소 해결 예시
sudo rmmod pata_acpi

# GRUB 설정 확인
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# 5. 차단 요소 해결 후 실제 업그레이드 실행
sudo leapp upgrade

# 6. 재부팅 (업그레이드는 재부팅 중 자동 진행, 10~30분 소요)
sudo reboot

재부팅 완료 후 AlmaLinux 8로 전환된 것을 확인합니다.

cat /etc/os-release
rpm -qa | grep almalinux

Rocky Linux 직접 설치 후 데이터 이전 방식

인플레이스 마이그레이션 대신 새 서버에 Rocky Linux를 클린 설치하고 데이터와 서비스를 이전하는 방식도 많이 사용됩니다. 인플레이스 방식보다 안전하며, 레거시 설정이 그대로 이전되는 부작용이 없습니다.

  • Rocky Linux 9.x ISO 다운로드 후 설치 (rockylinux.org/download)
  • 기존 서버의 애플리케이션 설정 파일, 데이터 디렉터리 rsync로 이전
  • 패키지 목록 기반 재설치: yum install $(cat /root/pkg_list_before.txt | awk '{print $1}')
  • 서비스 기동 및 검증 후 DNS/로드밸런서 전환

마이그레이션 후 점검 사항

  • SELinux 상태 확인: sestatus — 정책이 변경됐을 경우 서비스 접근 거부 발생 가능
  • 방화벽 규칙 확인: firewall-cmd --list-all
  • 서비스 자동 시작 확인: systemctl list-unit-files --state=enabled
  • 크론탭 이전 확인: crontab -l, /etc/cron.d/ 내용 점검
  • 애플리케이션 정상 동작 확인: 웹서버, DB, 미들웨어 순서로 기동 및 로그 점검

마무리

CentOS 7 EOL은 단순한 버전 업그레이드가 아니라 서버 운영 기반 자체를 재정비하는 기회입니다. Rocky Linux와 AlmaLinux 모두 훌륭한 대안이며, 어떤 배포판을 선택하든 체계적인 백업과 테스트 검증을 거친 마이그레이션이 가장 중요합니다. 아직 CentOS 7 서버가 남아있다면 지금 바로 마이그레이션 계획을 수립하시기 바랍니다.

반응형
반응형

SSH가 안 된다 — 어디서부터 봐야 할까

리눅스 서버 관리에서 SSH 접속 문제만큼 긴장되는 상황도 없습니다. 특히 원격지에 있는 서버에서 Connection refused 오류가 뜨거나, 접속은 되는데 패스워드 입력 화면까지 수십 초가 걸리는 경우 막막하게 느껴질 수 있습니다. 하지만 SSH 접속 문제는 원인이 몇 가지로 압축됩니다. 아래 5가지 항목을 순서대로 점검하면 대부분의 문제를 빠르게 해결할 수 있습니다.

점검 1 — SSH 데몬(sshd) 서비스 상태 확인

가장 먼저 확인해야 할 것은 SSH 서비스 자체가 실행 중인지 여부입니다. 서비스가 죽어있으면 어떤 설정을 바꿔도 접속이 불가능합니다. 콘솔 또는 BMC(iLO/XCC) 접근이 가능하다면 서버에 직접 로그인해 확인합니다.

systemctl status sshd           # 서비스 상태 확인
systemctl start sshd            # 서비스 시작
systemctl enable sshd           # 부팅 시 자동 시작 등록

상태가 failed 또는 inactive라면 서비스를 시작하고, 왜 죽었는지 로그를 확인합니다.

journalctl -u sshd -n 50        # 최근 50줄 sshd 로그 확인
journalctl -u sshd --since "1 hour ago"  # 최근 1시간 로그

자주 보이는 오류 메시지와 원인은 다음과 같습니다.

  • error: Could not load host key: SSH 호스트 키 파일 손상 또는 없음 → ssh-keygen -A로 재생성
  • Address already in use: 22번 포트를 다른 프로세스가 점유 → ss -tlnp | grep 22로 확인
  • Permission denied on /etc/ssh/sshd_config: 설정 파일 권한 문제 → chmod 600 /etc/ssh/sshd_config

점검 2 — 포트 및 방화벽 설정 확인

sshd는 실행 중인데 외부에서 접속이 안 된다면 방화벽이 SSH 포트를 차단하고 있을 가능성이 높습니다. 또한 기본 22번 포트가 아닌 다른 포트로 변경된 경우도 있습니다.

sshd 리스닝 포트 확인

ss -tlnp | grep sshd             # sshd가 어느 포트에서 리스닝 중인지 확인
grep -i "^Port" /etc/ssh/sshd_config  # 설정 파일에서 포트 확인

방화벽 규칙 확인 및 허용

# firewalld 사용 환경 (RHEL/CentOS/Rocky)
firewall-cmd --list-all
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload

# ufw 사용 환경 (Ubuntu/Debian)
ufw status
ufw allow 22/tcp
ufw reload

# iptables 직접 사용 환경
iptables -L -n | grep 22
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

클라우드 환경(AWS, Azure, GCP)이라면 OS 방화벽과 별도로 보안 그룹(Security Group) 또는 네트워크 ACL에서도 인바운드 22번 포트가 허용되어 있는지 반드시 확인해야 합니다. OS 방화벽은 열려있어도 클라우드 레이어에서 막혀있는 경우가 매우 흔합니다.

점검 3 — SSH 접속 지연 원인: DNS 역조회 문제

접속은 되는데 패스워드 입력 화면까지 10~30초 이상 지연된다면 거의 대부분 DNS 역조회(Reverse DNS Lookup) 문제입니다. sshd는 기본적으로 접속을 시도한 클라이언트 IP에 대해 역방향 DNS 조회를 수행하는데, 이 조회가 실패하거나 타임아웃되면 그만큼 접속이 지연됩니다.

vi /etc/ssh/sshd_config

아래 항목을 추가하거나 수정합니다.

UseDNS no
GSSAPIAuthentication no
systemctl restart sshd

UseDNS no는 역방향 DNS 조회를 비활성화하고, GSSAPIAuthentication no는 Kerberos 기반 인증 시도를 끄는 설정으로, 사내 Kerberos 환경이 아닌 경우 불필요한 대기 시간을 유발합니다. 두 설정 적용 후 재시작하면 접속 지연이 즉시 해소되는 경우가 대부분입니다.

점검 4 — TCP Wrapper 및 hosts.deny 설정 확인

최신 리눅스 배포판에서는 비중이 줄었지만, 오래된 시스템이나 보안 정책이 적용된 환경에서는 TCP Wrapper(/etc/hosts.allow, /etc/hosts.deny)가 SSH 접속을 차단하는 경우가 있습니다.

cat /etc/hosts.deny
cat /etc/hosts.allow

hosts.deny에 아래와 같은 설정이 있으면 SSH 접속이 전면 차단됩니다.

ALL : ALL              # 모든 서비스, 모든 IP 차단
sshd : ALL             # SSH만 전체 차단

특정 IP만 허용하려면 hosts.allow에 추가합니다.

# hosts.allow — 특정 대역만 SSH 허용
sshd : 192.168.1.0/255.255.255.0
sshd : 10.0.0.0/255.0.0.0

# 또는 전체 허용으로 임시 해제
sshd : ALL

TCP Wrapper는 hosts.allow가 hosts.deny보다 우선 적용된다는 점을 기억하세요. allow에 명시된 항목은 deny 설정에 관계없이 접속이 허용됩니다.

점검 5 — sshd_config 설정 오류 및 인증 문제

설정 파일을 수정한 뒤 sshd를 재시작했는데 접속이 안 된다면 설정 파일 문법 오류를 의심해야 합니다. sshd는 설정 오류가 있으면 재시작 자체가 실패하거나 조용히 이전 설정으로 유지되는 경우가 있습니다.

설정 파일 문법 검사

sshd -t                          # 설정 파일 문법 검사 (오류 시 메시지 출력)
sshd -T | grep -i "permitroot"   # 현재 적용된 설정값 확인

자주 확인해야 할 sshd_config 항목

PermitRootLogin no               # root 직접 로그인 차단 여부
PasswordAuthentication yes       # 패스워드 인증 허용 여부
AllowUsers user1 user2           # 특정 사용자만 SSH 허용 (미설정 시 전체 허용)
AllowGroups sshusers             # 특정 그룹만 SSH 허용
MaxAuthTries 3                   # 인증 시도 횟수 제한

AllowUsers 또는 AllowGroups 설정이 있는 경우, 해당 목록에 없는 계정은 패스워드가 맞아도 접속이 거부됩니다. 계정이 추가됐는데 접속이 안 된다면 이 항목을 먼저 확인하세요.

공개키 인증 실패 시 권한 점검

키 기반 인증을 사용하는데 접속이 거부된다면 파일 권한 문제일 가능성이 높습니다.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh

sshd는 ~/.sshauthorized_keys의 권한이 너무 열려있으면 보안상 키 인증을 거부합니다. 권한이 700/600이어야 정상 동작합니다.

빠른 점검 순서 요약

  • Connection refused: sshd 서비스 상태 → 방화벽/포트 → TCP Wrapper 순서로 점검
  • 접속 지연 (타임아웃): UseDNS no, GSSAPIAuthentication no 설정 즉시 적용
  • 패스워드 맞는데 거부: AllowUsers/AllowGroups, PasswordAuthentication 항목 확인
  • 키 인증 실패: ~/.ssh 및 authorized_keys 권한(700/600) 확인
  • 설정 변경 후 문제 발생: sshd -t로 문법 검사 후 재시작

마무리

SSH 접속 문제는 원인이 다양해 보이지만 서비스 → 포트/방화벽 → DNS → TCP Wrapper → 설정 파일 순서로 레이어를 좁혀가면 빠르게 해결됩니다. 특히 원격 서버의 sshd_config를 수정할 때는 반드시 기존 세션을 유지한 채로 새 세션 접속 테스트를 먼저 하고, 문제없을 때 기존 세션을 닫는 습관을 들이는 것이 중요합니다. 설정 실수로 모든 SSH 세션이 끊기면 BMC 콘솔 없이는 복구가 어려워집니다.

반응형
반응형

디스크가 꽉 찼다 — 지금 당장 무엇을 해야 하나

리눅스 서버 운영 중 갑자기 애플리케이션이 로그를 못 쓴다거나, 파일 저장이 안 된다거나, 심한 경우 서비스가 아예 다운되는 상황이 발생합니다. 원인을 추적하다 보면 상당수가 디스크 사용률 100%에서 비롯된 문제입니다. 당황하지 않고 체계적으로 접근하면 대부분 30분 안에 해결할 수 있습니다. 원인 파악부터 즉시 조치, 재발 방지까지 단계별로 정리합니다.

1단계 — 디스크 상태 전체 파악

가장 먼저 어느 파티션이 꽉 찼는지 확인합니다.

df -h

출력 결과에서 Use% 항목이 100%인 마운트 포인트를 찾습니다. 자주 문제가 되는 파티션은 /, /var, /home, /tmp입니다.

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   50G     0 100% /
/dev/sdb1       200G   80G  120G  40% /data

여기서 한 가지 더 확인해야 할 것이 있습니다. 디스크 용량은 남아있는데 파일 생성이 안 되는 경우라면 inode 고갈을 의심해야 합니다.

df -i

IUse% 항목이 100%라면 inode가 부족한 것입니다. 이 경우 실제 디스크 공간이 남아있어도 파일을 새로 만들 수 없습니다. 소용량 파일이 수백만 개 이상 쌓인 환경(로그, 캐시, 세션 파일)에서 주로 발생합니다.

2단계 — 어디서 공간을 잡아먹는지 찾기

문제 파티션을 찾았다면 그 안에서 가장 많은 공간을 차지하는 디렉터리를 추적합니다.

대용량 디렉터리 찾기

du -sh /* 2>/dev/null | sort -rh | head -20

루트(/)가 꽉 찬 경우 위 명령으로 1차 범위를 좁히고, 용량이 큰 디렉터리 안으로 반복해서 파고들어 갑니다.

du -sh /var/* 2>/dev/null | sort -rh | head -20
du -sh /var/log/* 2>/dev/null | sort -rh | head -20

대용량 파일 직접 찾기

find / -xdev -type f -size +1G 2>/dev/null | xargs ls -lh
find /var -type f -size +500M 2>/dev/null | xargs ls -lh

-xdev 옵션은 다른 파일 시스템으로 넘어가지 않고 현재 마운트 포인트 안에서만 탐색합니다. 루트 파티션 점검 시 필수 옵션입니다.

삭제됐지만 공간이 반환되지 않은 파일 찾기

실무에서 자주 놓치는 함정이 있습니다. 파일을 삭제했는데 df에서 공간이 줄지 않는 경우입니다. 이는 프로세스가 해당 파일을 열어두고 있어 실제로 공간이 반환되지 않은 상태이기 때문입니다.

lsof +L1 | grep -i deleted

출력 결과에서 SIZE 컬럼이 큰 항목을 확인합니다. 해결 방법은 해당 프로세스를 재시작하거나, 열린 파일 디스크립터를 통해 파일 내용을 비우는 것입니다.

# 예: PID 1234번 프로세스가 /var/log/app.log를 잡고 있는 경우
> /proc/1234/fd/3       # 파일 디스크립터 번호는 lsof 출력에서 확인

3단계 — 즉시 공간 확보 방법

로그 파일 정리

디스크 풀의 가장 흔한 원인입니다. 무작정 삭제하지 말고, 확인 후 조치합니다.

ls -lh /var/log/*.log | sort -k5 -rh | head -20

# 오래된 압축 로그 삭제 (30일 이상)
find /var/log -name "*.gz" -mtime +30 -delete
find /var/log -name "*.log.*" -mtime +30 -delete

# 특정 로그 파일 내용만 비우기 (삭제 아님 — 서비스 유지 중 안전)
> /var/log/application.log

journal 로그 정리 (systemd 환경)

journalctl --disk-usage           # 현재 journal 용량 확인
journalctl --vacuum-time=7d       # 7일 이전 journal 삭제
journalctl --vacuum-size=500M     # 500MB 이하로 줄이기

패키지 캐시 정리

# Ubuntu / Debian
apt-get clean
apt-get autoremove

# RHEL / CentOS
yum clean all
dnf clean all

/tmp 및 코어 덤프 정리

find /tmp -mtime +7 -delete        # 7일 이상 된 임시 파일 삭제
find / -name "core" -type f -size +100M 2>/dev/null -delete  # 코어 덤프 삭제

inode 고갈 해결

inode가 부족한 경우 소용량 파일이 대량으로 쌓인 디렉터리를 찾아 정리합니다.

# 디렉터리별 파일 수 확인
find / -xdev -type d 2>/dev/null | while read d; do
  echo "$(find "$d" -maxdepth 1 -type f | wc -l) $d"
done | sort -rn | head -20

# PHP 세션 파일 등 오래된 소용량 파일 정리 예시
find /var/lib/php/sessions -type f -mtime +7 -delete

4단계 — 재발 방지 설정

logrotate 설정 점검

로그가 무한정 쌓이지 않도록 logrotate가 올바르게 동작하는지 확인합니다.

cat /etc/logrotate.d/application   # 애플리케이션 logrotate 설정 확인
logrotate -d /etc/logrotate.conf   # 드라이런 — 실제 실행 없이 동작 확인

logrotate 설정의 핵심 항목은 rotate(보존 개수), size 또는 daily/weekly(순환 기준), compress(압축 여부)입니다.

디스크 사용률 모니터링 알림 설정

디스크가 80% 이상이 되면 미리 알림을 받도록 간단한 cron 스크립트를 설정합니다.

#!/bin/bash
THRESHOLD=80
df -h | grep -vE '^Filesystem|tmpfs|cdrom' | while read line; do
  USAGE=$(echo "$line" | awk '{print $5}' | tr -d '%')
  MOUNT=$(echo "$line" | awk '{print $6}')
  if [ "$USAGE" -ge "$THRESHOLD" ]; then
    echo "[ALERT] $MOUNT 디스크 사용률: ${USAGE}%" | \
    mail -s "[디스크 경고] $(hostname)" admin@example.com
  fi
done
# crontab에 등록 (매 시간 실행)
0 * * * * /usr/local/bin/disk_check.sh

마무리

리눅스 디스크 풀 문제는 당황스럽지만, df → du → lsof 순서로 범위를 좁혀가는 체계적 접근이면 대부분 빠르게 해결됩니다. 특히 삭제해도 공간이 안 줄어드는 lsof +L1 케이스와 inode 고갈은 놓치기 쉬운 함정이니 반드시 기억해 두세요. 사후 조치만큼 중요한 것이 logrotate와 모니터링 알림 설정을 통한 재발 방지입니다.

반응형
반응형

리눅스 파일에는 시간이 세 개 있다

리눅스에서 파일을 다루다 보면 ls -l 명령어로 날짜 정보를 확인할 때가 많습니다. 그런데 사실 리눅스 파일 시스템은 파일 하나당 세 가지 타임스탬프를 별도로 관리합니다. 바로 atime(접근 시간), mtime(수정 시간), ctime(변경 시간)입니다. 이 세 가지는 이름이 비슷해서 혼동하기 쉽지만, 각각 전혀 다른 상황에서 갱신됩니다.

단순히 개념을 아는 것을 넘어, 백업 스크립트 작성, 보안 감사, 성능 최적화 등 실무에서 이 차이를 정확히 알아야 하는 상황이 자주 생깁니다. 세 가지 타임스탬프의 정확한 정의와 동작 방식, 그리고 실무 활용법까지 정리합니다.

세 가지 타임스탬프 정의

atime — Access Time (접근 시간)

파일의 내용이 마지막으로 읽힌 시각입니다. cat, less, grep 등으로 파일 내용을 읽으면 atime이 갱신됩니다. 파일을 수정하지 않고 단순히 열어보기만 해도 변경된다는 점이 핵심입니다.

  • 갱신 시점: 파일 내용 읽기 (cat, less, grep, cp의 소스 파일 등)
  • 갱신되지 않는 경우: 파일 속성만 조회 (ls -l, stat)
  • 주의: 현대 리눅스는 성능 이슈로 relatime 옵션을 기본 적용 — mtime이나 ctime보다 atime이 오래됐을 때만 갱신

mtime — Modify Time (수정 시간)

파일의 내용(데이터)이 마지막으로 변경된 시각입니다. 파일을 편집하거나 새로운 내용을 추가·삭제할 때 갱신됩니다. ls -l로 기본 출력되는 날짜가 바로 mtime입니다.

  • 갱신 시점: 파일 내용 쓰기 (vi 저장, echo 리다이렉션, 프로그램이 파일에 데이터 기록)
  • 갱신되지 않는 경우: 파일 권한 변경(chmod), 소유자 변경(chown), 파일명 변경(mv)
  • mtime이 변경되면 ctime도 반드시 함께 변경됨

ctime — Change Time (변경 시간)

파일의 inode 정보가 마지막으로 변경된 시각입니다. 여기서 많은 분들이 헷갈리는데, ctime은 "Created Time(생성 시간)"이 아닙니다. 파일 내용뿐 아니라 권한, 소유자, 링크 수 등 메타데이터 변경까지 모두 추적합니다.

  • 갱신 시점: 파일 내용 변경(mtime 갱신 시 포함), chmod, chown, ln(하드링크 추가), mv(같은 파일 시스템 내)
  • 갱신되지 않는 경우: 파일 내용 읽기만 하는 경우
  • ctime은 사용자가 임의로 변경할 수 없음 — 보안 감사에서 중요한 이유

타임스탬프 확인 방법

ls -l은 mtime만 보여줍니다. 세 가지 타임스탬프를 모두 확인하려면 stat 명령어를 사용합니다.

stat filename.txt

출력 예시는 다음과 같습니다.

  File: filename.txt
  Size: 1024
Access: 2025-03-15 09:00:00.000  ← atime
Modify: 2025-03-14 18:30:00.000  ← mtime
Change: 2025-03-14 18:30:05.000  ← ctime

각 타임스탬프를 기준으로 파일을 찾으려면 find 명령어의 옵션을 다르게 사용합니다.

find /var/log -mtime -1      # mtime 기준 — 최근 1일 이내 내용이 수정된 파일
find /etc -ctime -7          # ctime 기준 — 최근 7일 이내 속성이 변경된 파일
find /home -atime +30        # atime 기준 — 30일 이상 접근하지 않은 파일

atime 성능 이슈와 마운트 옵션

atime은 파일을 읽을 때마다 디스크에 쓰기 작업이 발생한다는 단점이 있습니다. 읽기 작업이 많은 서버에서는 이 오버헤드가 성능에 영향을 줄 수 있어, 리눅스는 마운트 옵션으로 atime 동작을 제어합니다.

  • strictatime: 파일 접근 시 항상 atime 갱신. 가장 정확하지만 성능 부하 최대.
  • relatime (기본값): mtime 또는 ctime보다 atime이 오래됐을 때만 갱신. 성능과 정확성의 균형.
  • noatime: atime을 전혀 갱신하지 않음. 성능 최적화 목적. 빈번한 읽기가 발생하는 고성능 서버에 적용.
  • nodiratime: 디렉터리의 atime만 갱신하지 않음.
# /etc/fstab에서 noatime 적용 예시
/dev/sda1  /  ext4  defaults,noatime  0 1

실무 활용 시나리오

백업 스크립트 — mtime 활용

증분 백업(Incremental Backup)을 구현할 때 mtime을 기준으로 변경된 파일만 선별합니다. 파일 내용이 실제로 바뀐 것만 추적하기 때문에 가장 정확합니다.

find /data -mtime -1 -type f | xargs tar -czf /backup/incremental_$(date +%F).tar.gz

보안 감사 — ctime 활용

해커가 파일 내용을 수정한 뒤 touch 명령으로 mtime을 위조하더라도, ctime은 시스템 내부에서 관리되므로 사용자가 임의로 변경할 수 없습니다. 침해사고 분석 시 ctime을 기준으로 의심 파일을 추려내는 이유가 여기에 있습니다.

# 최근 24시간 이내 ctime이 변경된 시스템 파일 탐지
find /etc /bin /usr/bin -ctime -1 -type f

스토리지 정리 — atime 활용

오랫동안 아무도 접근하지 않은 파일을 찾아 아카이브하거나 삭제할 때 atime을 기준으로 삼습니다.

# 180일 이상 접근하지 않은 파일 목록 출력
find /home -atime +180 -type f -ls

세 타임스탬프 비교 요약

  • atime: 파일 내용을 읽으면 갱신 / noatime으로 비활성화 가능 / 장기 미접근 파일 탐지에 활용
  • mtime: 파일 내용을 쓰면 갱신 / ls -l 기본 출력값 / 증분 백업 기준으로 활용
  • ctime: 내용·메타데이터 모두 변경 시 갱신 / 사용자 임의 변경 불가 / 보안 감사 기준으로 활용

마무리

ctime, mtime, atime은 단순한 날짜 정보가 아니라 파일 시스템이 파일의 상태 변화를 추적하는 핵심 메커니즘입니다. 세 가지의 차이를 명확히 이해하고 find 명령어와 조합하면 백업 자동화, 보안 감사, 스토리지 최적화 등 다양한 실무 작업의 정확도와 효율을 크게 높일 수 있습니다.

반응형
반응형

재해복구, 숫자로 말해야 한다

장애가 발생했을 때 "최대한 빨리 복구하겠습니다"라는 말은 운영 계획이 아닙니다. 얼마나 빨리, 어느 시점까지라는 구체적인 수치가 있어야 비로소 복구 계획이 됩니다. 재해복구(DR, Disaster Recovery) 센터 구축의 출발점은 바로 두 가지 지표, RPO(Recovery Point Objective, 목표 복구 시점)RTO(Recovery Time Objective, 목표 복구 시간)를 정의하는 것입니다.

이 두 숫자는 DR 인프라의 규모, 비용, 기술 선택 전부를 결정하는 기준이 됩니다. 개념을 정확히 이해하고 자사 환경에 맞게 설정하는 방법을 정리합니다.

RPO란 무엇인가 — 데이터 손실을 얼마나 허용할 것인가

RPO는 재해 발생 시 어느 시점까지의 데이터를 복원할 수 있어야 하는가를 정의하는 지표입니다. 쉽게 말해, "데이터를 최대 몇 시간치까지 잃어도 괜찮은가"입니다.

  • RPO = 0: 데이터 손실 제로. 재해 발생 직전까지의 모든 데이터가 복원돼야 함. 실시간 동기 복제(Synchronous Replication) 필수.
  • RPO = 1시간: 최대 1시간치 데이터 손실 허용. 1시간 주기 비동기 복제 또는 스냅샷으로 대응 가능.
  • RPO = 24시간: 하루치 데이터 손실 허용. 일 1회 백업으로도 충족 가능.

RPO가 짧을수록 복제 주기가 짧아지고, 그만큼 네트워크 대역폭과 스토리지 비용이 증가합니다. 특히 RPO = 0을 목표로 하는 동기 복제는 DR 사이트와의 거리가 멀어질수록 네트워크 지연(Latency)으로 인해 운영계 성능에 직접 영향을 줄 수 있습니다.

RTO란 무엇인가 — 서비스를 얼마나 빨리 재개해야 하는가

RTO는 재해 발생 이후 서비스가 정상 운영으로 복구되기까지 허용되는 최대 시간입니다. "장애 발생부터 서비스 재개까지 몇 시간 안에 완료해야 하는가"로 이해하면 됩니다.

  • RTO = 수 분: Hot Standby 구성. DR 서버가 항상 가동 중이며 즉시 절체 가능. 가장 높은 비용.
  • RTO = 수 시간: Warm Standby 구성. DR 서버는 기동 상태지만 트래픽을 받지 않다가 장애 시 전환.
  • RTO = 수십 시간 이상: Cold Standby 구성. DR 서버는 꺼져 있으며 장애 시 부팅부터 시작. 비용은 낮지만 복구 시간이 김.

RTO가 짧을수록 DR 인프라를 운영계와 유사한 수준으로 상시 유지해야 하므로 비용이 급격히 올라갑니다. RTO 목표 설정 시에는 기술적 가능성뿐 아니라 서비스 중단으로 인한 비즈니스 손실 비용과 DR 구축·운영 비용을 함께 비교해야 합니다.

RPO·RTO와 DR 구성 방식의 관계

RPO와 RTO 목표값에 따라 적합한 DR 구성 방식이 달라집니다.

Active-Passive (Warm/Cold Standby)

운영 사이트가 장애 시 DR 사이트로 전환하는 구성입니다. DR 사이트는 평상시 트래픽을 처리하지 않습니다.

  • RPO: 복제 주기에 따라 수 분 ~ 수 시간
  • RTO: 수십 분 ~ 수 시간 (Warm), 수 시간 이상 (Cold)
  • 비용: 중간 ~ 낮음

Active-Active (Hot Standby)

운영 사이트와 DR 사이트가 동시에 트래픽을 처리하며, 한쪽이 장애 나도 나머지가 즉시 전체 부하를 수용합니다.

  • RPO: 0 (동기 복제 기반)
  • RTO: 수 분 이내 (자동 절체 구성 시 수 초)
  • 비용: 가장 높음 (운영계 동일 수준의 DR 인프라 필요)

백업 기반 DR (Backup & Restore)

정기 백업 데이터를 DR 사이트로 전송하고, 장애 시 복원하는 가장 기본적인 방식입니다.

  • RPO: 백업 주기에 따라 수 시간 ~ 24시간 이상
  • RTO: 수 시간 ~ 수십 시간 (데이터 규모에 따라 상이)
  • 비용: 가장 낮음

RPO·RTO 설정 시 고려해야 할 사항

시스템 등급 분류부터 시작하라

모든 시스템에 동일한 RPO·RTO를 적용하는 것은 과잉 투자입니다. 시스템을 비즈니스 중요도에 따라 등급으로 분류하고, 등급별로 다른 목표값을 설정하는 것이 현실적입니다.

  • 1등급 (Critical): 결제, 핵심 거래 시스템 — RPO 0~15분, RTO 15분~1시간
  • 2등급 (Essential): 내부 업무 시스템 — RPO 1~4시간, RTO 4~8시간
  • 3등급 (Normal): 개발·테스트 환경 — RPO 24시간, RTO 24~48시간

목표값은 반드시 실제 훈련으로 검증하라

문서상의 RTO와 실제 복구에 걸리는 시간은 다를 수 있습니다. 정기적인 DR 훈련(DRT, Disaster Recovery Test)을 통해 목표값이 실제로 달성 가능한지 검증하고, 미달 시 구성을 보완해야 합니다. 연 1회 이상 실전 절체 훈련을 수행하는 것을 권장합니다.

마무리

RPO와 RTO는 DR 구축의 시작이자 끝입니다. 이 두 숫자가 명확하지 않으면 DR 인프라에 얼마를 투자해야 하는지, 어떤 기술을 선택해야 하는지 결정할 수 없습니다. 비즈니스 요구사항을 기반으로 RPO·RTO를 먼저 정의하고, 그에 맞는 기술과 인프라를 역순으로 설계하는 접근법이 성공적인 DR 구축의 핵심입니다.

반응형
반응형

네트워크 문제, 어디서부터 시작해야 할까?

리눅스 서버를 운영하다 보면 "갑자기 외부에서 접속이 안 된다", "특정 포트가 응답하지 않는다", "패킷이 어디선가 막힌다" 같은 상황을 반드시 마주치게 됩니다. 이럴 때 당황하지 않고 체계적인 순서로 명령어를 실행할 수 있느냐가 숙련된 엔지니어와 그렇지 않은 사람의 차이입니다.

이 글에서는 실무에서 자주 쓰는 네트워크 트러블슈팅 명령어를 레이어별로 정리하고, 각 명령어가 어떤 상황에서 유효한지 함께 설명합니다.

1단계 — 기본 연결 확인: ping / traceroute

가장 먼저 해야 할 건 물리적·논리적 연결 자체가 살아있는지 확인하는 것입니다.

ping

ICMP 패킷을 보내 응답 시간과 패킷 손실률을 확인합니다.

ping -c 4 8.8.8.8          # 4번만 보내고 종료
ping -i 0.2 -c 20 192.168.1.1  # 0.2초 간격으로 20번 전송
  • 응답 없음: 방화벽에서 ICMP가 차단됐거나 호스트 자체가 다운된 상태
  • 패킷 손실 발생: 네트워크 구간 어딘가에 불안정한 링크 존재
  • RTT가 비정상적으로 높음: 대역폭 포화 또는 라우팅 문제 의심

traceroute / tracepath

패킷이 목적지까지 어느 경로로 이동하는지, 어느 구간에서 지연이 발생하는지 확인합니다.

traceroute -n 8.8.8.8        # DNS 조회 없이 IP로만 표시 (빠름)
tracepath google.com          # 루트 권한 없이 사용 가능

특정 홉(hop)에서 * * *가 반복된다면 해당 구간에서 패킷이 차단되거나 응답하지 않는 것입니다. 그 이후 홉이 정상이면 단순 ICMP 차단일 가능성이 높습니다.

2단계 — 인터페이스 및 라우팅 확인: ip / ss / netstat

ip 명령어

ifconfig는 구형 명령어입니다. 현대 리눅스에서는 ip 명령어를 사용하는 것이 표준입니다.

ip addr show                  # 전체 인터페이스 IP 확인
ip addr show eth0             # 특정 인터페이스만 확인
ip link show                  # 인터페이스 UP/DOWN 상태 확인
ip route show                 # 라우팅 테이블 전체 출력
ip route get 8.8.8.8          # 특정 목적지로 가는 경로 확인

ip route get은 특정 IP로 트래픽이 어느 인터페이스를 통해 나가는지 한 줄로 보여주는 매우 실용적인 명령어입니다.

ss — 소켓 상태 확인

netstat의 후속 명령어로 훨씬 빠르고 상세한 정보를 제공합니다.

ss -tlnp          # TCP 리스닝 포트 + 프로세스 이름
ss -ulnp          # UDP 리스닝 포트
ss -s             # 소켓 통계 요약
ss -tnp state established  # 현재 연결된 TCP 세션 전체
  • -t: TCP, -u: UDP
  • -l: 리스닝 상태만, -n: 숫자(IP/포트)로 표시, -p: 프로세스 정보 포함

3단계 — DNS 문제 진단: dig / nslookup / resolvectl

외부 접속이 안 될 때 DNS 해석 자체가 실패하는 경우가 생각보다 많습니다.

dig

가장 상세한 DNS 조회 결과를 보여주는 표준 도구입니다.

dig google.com                     # 기본 A 레코드 조회
dig google.com MX                  # MX 레코드 조회
dig @8.8.8.8 google.com            # 특정 DNS 서버(8.8.8.8)에 직접 질의
dig +short google.com              # IP 결과만 간단히 출력
dig +trace google.com              # 루트 DNS부터 전체 해석 과정 추적

dig +trace는 DNS 위임 체계 전체를 추적하므로, 특정 레코드가 왜 잘못 응답되는지 원인을 찾을 때 매우 유용합니다.

resolvectl (systemd-resolved 환경)

resolvectl status          # 현재 DNS 설정 및 상태 확인
resolvectl query google.com  # DNS 조회

4단계 — 포트 및 서비스 연결 확인: telnet / nc / curl

nc (netcat) — 포트 연결 테스트

특정 호스트의 포트가 열려있는지 가장 직접적으로 확인하는 방법입니다.

nc -zv 192.168.1.100 80       # TCP 포트 80 열려있는지 확인
nc -zv -u 192.168.1.100 53    # UDP 포트 53 확인
nc -zv 192.168.1.100 8080-8090  # 포트 범위 스캔

curl — HTTP/HTTPS 레벨 진단

curl -v https://example.com              # 전체 요청/응답 헤더 출력
curl -I https://example.com             # 헤더만 확인
curl -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com
# 응답코드와 응답시간만 출력
curl --resolve example.com:443:1.2.3.4 https://example.com
# 특정 IP로 강제 접속 (DNS 우회 테스트)

5단계 — 패킷 수준 분석: tcpdump

위 명령어로도 원인을 찾지 못했다면 실제 패킷을 직접 들여다봐야 합니다.

tcpdump -i eth0 -nn               # eth0 인터페이스 전체 패킷 캡처
tcpdump -i eth0 port 80 -nn       # 80 포트 트래픽만 필터
tcpdump -i eth0 host 192.168.1.100 -nn  # 특정 호스트 트래픽만
tcpdump -i eth0 -w /tmp/capture.pcap    # 파일로 저장 (Wireshark 분석용)

-nn 옵션은 DNS 역조회와 포트명 변환을 생략해 출력 속도를 높여줍니다. 실시간 트래픽이 많은 환경에서는 필수 옵션입니다.

트러블슈팅 흐름 정리

네트워크 문제를 만났을 때 아래 순서로 접근하면 빠르게 원인을 좁힐 수 있습니다.

  • 1. ping — 기본 연결 확인
  • 2. traceroute — 경로 및 지연 구간 확인
  • 3. ip addr / ip route — 인터페이스, 라우팅 테이블 점검
  • 4. ss -tlnp — 서비스가 포트를 정상적으로 리스닝하는지 확인
  • 5. dig — DNS 해석 문제 여부 확인
  • 6. nc / curl — 실제 포트 및 HTTP 응답 확인
  • 7. tcpdump — 패킷 레벨 분석으로 최종 원인 규명

마무리

네트워크 트러블슈팅은 레이어를 낮춰가며 원인을 좁히는 과정입니다. 모든 명령어를 외울 필요는 없지만, 각 명령어가 OSI 어느 계층을 담당하는지 이해하고 있다면 문제 상황에서 빠르게 판단할 수 있습니다. 여기서 소개한 명령어들을 테스트 환경에서 직접 실행해보며 익혀두는 것을 강력히 권장합니다.

반응형
반응형

IBM Spectrum Scale(GPFS)란 무엇인가?

IBM Spectrum Scale(구 GPFS, General Parallel File System)은 IBM이 개발한 고성능 병렬 분산 파일 시스템입니다. 수천 개의 노드가 동시에 하나의 파일 시스템에 접근할 수 있으며, HPC(고성능 컴퓨팅), 빅데이터 분석, AI 워크로드 환경에서 폭넓게 사용됩니다. 페타바이트 규모의 데이터를 안정적으로 처리할 수 있다는 점이 핵심 강점이지만, 그만큼 성능 문제가 발생했을 때 원인을 찾는 과정이 복잡합니다.

이 글에서는 실무 운영 환경에서 바로 적용할 수 있는 Spectrum Scale 성능 모니터링 방법과 자주 발생하는 문제의 트러블슈팅 접근법을 정리합니다.

기본 상태 점검 명령어

Spectrum Scale 문제가 발생하면 가장 먼저 클러스터 전체의 기본 상태를 확인해야 합니다.

클러스터 및 노드 상태 확인

mmgetstate -a                  # 전체 노드의 GPFS 데몬 상태 확인
mmlscluster                    # 클러스터 기본 정보 출력
mmlsnode -a                    # 노드 목록 및 역할 확인
mmdiag --network               # 네트워크 연결 상태 진단

mmgetstate -a 실행 시 노드 상태가 active가 아닌 arbitrating이나 down으로 표시된다면 해당 노드부터 우선 점검해야 합니다.

파일 시스템 상태 확인

mmlsfs all                     # 전체 파일 시스템 설정 정보
mmlsmount all -L               # 마운트 상태 및 마운트된 노드 확인
mmlsdisk  -L          # 디스크(NSD) 상태 확인
mmdf                  # 파일 시스템 사용량 확인

mmlsdisk에서 디스크 상태가 failed 또는 missing으로 표시되면 즉각 스토리지 레이어를 점검해야 합니다. 이 상태가 지속되면 데이터 접근 불가 또는 성능 급저하로 이어집니다.

성능 모니터링: mmpmon 활용

Spectrum Scale의 핵심 성능 모니터링 도구는 mmpmon입니다. 실시간으로 I/O 통계를 수집하고 분석할 수 있습니다.

기본 I/O 통계 수집

echo "io_s" | mmpmon -p -r 0   # 전체 I/O 통계 출력
echo "fs_io_s" | mmpmon -p -r 0  # 파일 시스템별 I/O 통계
echo "nsd_io_s" | mmpmon -p -r 0  # NSD(디스크)별 I/O 통계

출력 항목 중 주목해야 할 값은 다음과 같습니다.

  • _br_ / _bw_: 읽기/쓰기 바이트 수 (처리량 확인)
  • _rdc_ / _wrc_: 읽기/쓰기 요청 횟수
  • _oc_: open 호출 횟수 (메타데이터 부하 지표)
  • _cc_: close 호출 횟수

주기적 통계 수집 스크립트

실시간 추이를 보려면 일정 간격으로 mmpmon을 반복 실행해 비교하는 방식이 효과적입니다.

#!/bin/bash
while true; do
  echo "=== $(date '+%Y-%m-%d %H:%M:%S') ==="
  echo "fs_io_s" | mmpmon -p -r 0 | grep "_fs_io_s_"
  sleep 10
done

이 스크립트를 백그라운드로 실행하면서 성능 이슈 발생 전후 값을 비교하면 어느 파일 시스템에서 부하가 집중되는지 빠르게 파악할 수 있습니다.

메타데이터 성능 문제 진단

Spectrum Scale 환경에서 성능 저하의 원인 중 상당수는 메타데이터 병목입니다. 특히 소용량 파일이 수백만 개 이상 존재하거나, open/stat/readdir 호출이 집중될 때 발생합니다.

메타데이터 관련 점검

mmlsconfig  | grep -i meta  # 메타데이터 설정 확인
mmlsfileset  -L             # 필레셋 구성 확인
echo "io_s" | mmpmon -p -r 0 | grep _oc_  # open 호출 횟수 확인
  • 메타데이터 전용 NSD가 분리되어 있는지 확인 (메타데이터와 데이터 디스크 분리는 성능의 핵심)
  • inode 크기 설정이 워크로드에 적합한지 검토 (기본값 4096 bytes)
  • 디렉터리 내 파일 수가 수십만 개를 넘는 경우 해시 디렉터리 구조 적용 검토

네트워크 성능 문제 진단

GPFS는 노드 간 통신에 인터커넥트 네트워크를 적극 활용합니다. InfiniBand 또는 이더넷 성능 저하가 전체 파일 시스템 성능에 직접 영향을 줍니다.

네트워크 진단 명령어

mmdiag --network               # 클러스터 내 노드 간 네트워크 연결 진단
mmnetverify                    # 네트워크 성능 검증 (패킷 손실, 대역폭)
mmlsconfig | grep subnets      # 서브넷 구성 확인

InfiniBand 환경이라면 별도로 ibstat, perfquery 명령어로 포트 상태와 오류 카운터를 확인하고, 오류 카운터가 지속적으로 증가하면 케이블 또는 HCA 교체를 검토해야 합니다.

자주 발생하는 문제와 해결 방법

1. 파일 시스템 마운트 불가

  • mmgetstate -a로 모든 노드 데몬 상태 확인
  • 쿼럼(Quorum) 미달 여부 점검 — 전체 노드의 과반수 이상이 active 상태여야 마운트 가능
  • /var/adm/ras/mmfs.log.latest 로그에서 구체적 오류 메시지 확인

2. 특정 노드에서 성능 저하

  • 해당 노드의 CPU, 메모리, 네트워크 사용률 확인 (top, sar, ss)
  • mmdiag --network로 해당 노드의 네트워크 연결 상태 점검
  • pagepool 설정 확인: mmlsconfig | grep pagepool (권장값: 물리 메모리의 25~50%)

3. 디스크 응답 지연

  • mmlsdisk -L로 NSD 상태 확인
  • 스토리지 컨트롤러 레벨에서 I/O 대기 시간(latency) 별도 모니터링
  • NSD 서버 노드 부하 집중 여부 확인 후 NSD 서버 분산 검토

핵심 로그 파일 위치

트러블슈팅 시 반드시 확인해야 하는 로그 파일 경로입니다.

  • /var/adm/ras/mmfs.log.latest: GPFS 데몬 메인 로그 (가장 중요)
  • /var/adm/ras/mmfs.log.previous: 이전 로그 (재시작 전 이벤트 추적)
  • /var/log/messages: 커널 및 시스템 레벨 이벤트 확인

마무리

IBM Spectrum Scale은 강력한 만큼 운영 복잡도도 높습니다. 평소에 mmpmon으로 베이스라인 성능 수치를 축적해두는 것이 가장 중요합니다. 문제가 발생했을 때 비교할 기준값이 없으면 트러블슈팅 시간이 크게 늘어납니다. 클러스터 상태 점검, 성능 통계 수집, 로그 분석을 루틴화하면 대부분의 문제를 조기에 발견하고 대응할 수 있습니다.

반응형
반응형

네트워크 문제, 어디서부터 시작해야 할까?

리눅스 서버를 운영하다 보면 "갑자기 외부에서 접속이 안 된다", "특정 포트가 응답하지 않는다", "패킷이 어디선가 막힌다" 같은 상황을 반드시 마주치게 됩니다. 이럴 때 당황하지 않고 체계적인 순서로 명령어를 실행할 수 있느냐가 숙련된 엔지니어와 그렇지 않은 사람의 차이입니다.

이 글에서는 실무에서 자주 쓰는 네트워크 트러블슈팅 명령어를 레이어별로 정리하고, 각 명령어가 어떤 상황에서 유효한지 함께 설명합니다.

1단계 — 기본 연결 확인: ping / traceroute

가장 먼저 해야 할 건 물리적·논리적 연결 자체가 살아있는지 확인하는 것입니다.

ping

ICMP 패킷을 보내 응답 시간과 패킷 손실률을 확인합니다.

ping -c 4 8.8.8.8          # 4번만 보내고 종료
ping -i 0.2 -c 20 192.168.1.1  # 0.2초 간격으로 20번 전송
  • 응답 없음: 방화벽에서 ICMP가 차단됐거나 호스트 자체가 다운된 상태
  • 패킷 손실 발생: 네트워크 구간 어딘가에 불안정한 링크 존재
  • RTT가 비정상적으로 높음: 대역폭 포화 또는 라우팅 문제 의심

traceroute / tracepath

패킷이 목적지까지 어느 경로로 이동하는지, 어느 구간에서 지연이 발생하는지 확인합니다.

traceroute -n 8.8.8.8        # DNS 조회 없이 IP로만 표시 (빠름)
tracepath google.com          # 루트 권한 없이 사용 가능

특정 홉(hop)에서 * * *가 반복된다면 해당 구간에서 패킷이 차단되거나 응답하지 않는 것입니다. 그 이후 홉이 정상이면 단순 ICMP 차단일 가능성이 높습니다.

2단계 — 인터페이스 및 라우팅 확인: ip / ss / netstat

ip 명령어

ifconfig는 구형 명령어입니다. 현대 리눅스에서는 ip 명령어를 사용하는 것이 표준입니다.

ip addr show                  # 전체 인터페이스 IP 확인
ip addr show eth0             # 특정 인터페이스만 확인
ip link show                  # 인터페이스 UP/DOWN 상태 확인
ip route show                 # 라우팅 테이블 전체 출력
ip route get 8.8.8.8          # 특정 목적지로 가는 경로 확인

ip route get은 특정 IP로 트래픽이 어느 인터페이스를 통해 나가는지 한 줄로 보여주는 매우 실용적인 명령어입니다.

ss — 소켓 상태 확인

netstat의 후속 명령어로 훨씬 빠르고 상세한 정보를 제공합니다.

ss -tlnp          # TCP 리스닝 포트 + 프로세스 이름
ss -ulnp          # UDP 리스닝 포트
ss -s             # 소켓 통계 요약
ss -tnp state established  # 현재 연결된 TCP 세션 전체
  • -t: TCP, -u: UDP
  • -l: 리스닝 상태만, -n: 숫자(IP/포트)로 표시, -p: 프로세스 정보 포함

3단계 — DNS 문제 진단: dig / nslookup / resolvectl

외부 접속이 안 될 때 DNS 해석 자체가 실패하는 경우가 생각보다 많습니다.

dig

가장 상세한 DNS 조회 결과를 보여주는 표준 도구입니다.

dig google.com                     # 기본 A 레코드 조회
dig google.com MX                  # MX 레코드 조회
dig @8.8.8.8 google.com            # 특정 DNS 서버(8.8.8.8)에 직접 질의
dig +short google.com              # IP 결과만 간단히 출력
dig +trace google.com              # 루트 DNS부터 전체 해석 과정 추적

dig +trace는 DNS 위임 체계 전체를 추적하므로, 특정 레코드가 왜 잘못 응답되는지 원인을 찾을 때 매우 유용합니다.

resolvectl (systemd-resolved 환경)

resolvectl status          # 현재 DNS 설정 및 상태 확인
resolvectl query google.com  # DNS 조회

4단계 — 포트 및 서비스 연결 확인: telnet / nc / curl

nc (netcat) — 포트 연결 테스트

특정 호스트의 포트가 열려있는지 가장 직접적으로 확인하는 방법입니다.

nc -zv 192.168.1.100 80       # TCP 포트 80 열려있는지 확인
nc -zv -u 192.168.1.100 53    # UDP 포트 53 확인
nc -zv 192.168.1.100 8080-8090  # 포트 범위 스캔

curl — HTTP/HTTPS 레벨 진단

curl -v https://example.com              # 전체 요청/응답 헤더 출력
curl -I https://example.com             # 헤더만 확인
curl -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com
# 응답코드와 응답시간만 출력
curl --resolve example.com:443:1.2.3.4 https://example.com
# 특정 IP로 강제 접속 (DNS 우회 테스트)

5단계 — 패킷 수준 분석: tcpdump

위 명령어로도 원인을 찾지 못했다면 실제 패킷을 직접 들여다봐야 합니다.

tcpdump -i eth0 -nn               # eth0 인터페이스 전체 패킷 캡처
tcpdump -i eth0 port 80 -nn       # 80 포트 트래픽만 필터
tcpdump -i eth0 host 192.168.1.100 -nn  # 특정 호스트 트래픽만
tcpdump -i eth0 -w /tmp/capture.pcap    # 파일로 저장 (Wireshark 분석용)

-nn 옵션은 DNS 역조회와 포트명 변환을 생략해 출력 속도를 높여줍니다. 실시간 트래픽이 많은 환경에서는 필수 옵션입니다.

트러블슈팅 흐름 정리

네트워크 문제를 만났을 때 아래 순서로 접근하면 빠르게 원인을 좁힐 수 있습니다.

  • 1. ping — 기본 연결 확인
  • 2. traceroute — 경로 및 지연 구간 확인
  • 3. ip addr / ip route — 인터페이스, 라우팅 테이블 점검
  • 4. ss -tlnp — 서비스가 포트를 정상적으로 리스닝하는지 확인
  • 5. dig — DNS 해석 문제 여부 확인
  • 6. nc / curl — 실제 포트 및 HTTP 응답 확인
  • 7. tcpdump — 패킷 레벨 분석으로 최종 원인 규명

마무리

네트워크 트러블슈팅은 레이어를 낮춰가며 원인을 좁히는 과정입니다. 모든 명령어를 외울 필요는 없지만, 각 명령어가 OSI 어느 계층을 담당하는지 이해하고 있다면 문제 상황에서 빠르게 판단할 수 있습니다. 여기서 소개한 명령어들을 테스트 환경에서 직접 실행해보며 익혀두는 것을 강력히 권장합니다.

반응형

+ Recent posts