구름

AWS EBS 볼륨(NVMe) 자동 식별(자동 마운트) 본문

Code/EC2 UserData

AWS EBS 볼륨(NVMe) 자동 식별(자동 마운트)

Cloudest 2021. 4. 12. 00:37
 

Cloudest - 블로그 이사했습니다

노션으로 블로그를 옮겼습니다.

흥미로운 포스팅이 올라옵니다!

cloudest.oopy.io

💡
준비물 : AWS 계정 및 EC2 생성에 대한 전반적인 이해도

 

시작 전

  • Why ?
    • AWS를 처음 배울 때 많이 사용하는 프리티어가 속한 t2 인스턴스 타입은 EBS 생성시 EBS 디바이스 이름이 /dev/xvd*의 형식으로 생성된다. ( ex. /dev/xvdb , /dev/xvde )

      하지만 비교적 최근에 출시된 t3, r5, c5와 같은 인스턴스 타입은 Nitro 시스템 기반으로 EBS 생성시 NVMe 블록 디바이스로 표시된다. ( ex. /dev/nvme1n1 , /dev/nvme2n1 )

      문제는 순서다. /dev/xvdb와 같은 볼륨은 생성시 부여하는 디바이스 이름과 순서가 일치하기 때문에 서버에 접속하지 않고도 자동으로 Mount 작업을 쉽게 해줄 수 있다.
    • 하지만 nvme1n1, nvme2n1과 같은 형식으로 생성되는 EBS의 경우 순서가 맞지 않을 뿐더러, 새로운 볼륨이 추가되는경우 순서가 뒤바뀌는 상황도 발생한다.

      콘솔, CLI 환경에서는 여전히 디바이스 이름을 /dev/xvda, /dev/xvdb와 같은 형식으로 부여하기 때문에 xvda = nvme0n1, xvdb = nvme1n1과 같이 규칙성이 있다면 불편함이 없겠지만, 각각 10, 20, 30, 40, 50gb의 볼륨을 xvdb,xvdc,xvdd,xvde,xvdf로 생성했을 때 nvme*n0의 순서는 랜덤이라는 것이다.
    • 해당 EBS들을 적절하게 연결하기 위해서 나는 매번 서버에 접속해서 mkfs, lsblk, blkid, nvme-cli등의 명령어를 통해 직접 콘솔과 비교해서 마운트를 해줘야했고 그게 번거로워서 자동화 하는 방법을 찾게됐다.
      NVMe 볼륨 때문에 고통받는 여러 사람들

     

  • NVMe
    • NVMe가 뭐길래 이렇게 불편한데 사용하는걸까?
    • 위키피디아의 NVMe 설명 : 한마디로 기존 볼륨보다 성능이 좋기 때문에 사용한다. NVMe는  PCI 익스프레스(PCIe) 버스에 부착된 비휘발성 기억 매체 접근을 위한 논리 장치 인터페이스 사양이다.
      "NVM"은 "비휘발성 메모리"(non-volatile memory)를 뜻하며, 보통 솔리드 스테이트 드라이브(SSD) 형태로 출시되는 플래시 메모리를 가리킨다. 설계 상, NVM 익스프레스는 현대의 SSD에서 볼 수 있는 여러 수준의 병렬화를 허용하며 이로써 호스트 하드웨어와 소프트웨어에 의해 완전히 이용될 수 있다. 그 결과, NVM 익스프레스는 입출력 부하를 줄이고 길이가 긴 다중 명령 큐, 감소된 레이턴시를 포함하여 이전 논리 장치 인터페이스에 비해 다양한 성능 개선을 이루게 된다.
      NVM 익스프레스 장치는 표준 크기의 PCI 익스프레스 확장 카드와, U.2 단자(이전 이름: SFF-8639)를 통해 4 레인의 PCI 익스프레스 인터페이스를 제공하는 2.5인치 폼 팩터 장치로 존재한다. 내부적으로 마운트된 컴퓨터 확장 카드를 위한 SATA 익스프레스 스토리지 장치와 M.2 사양 또한 NVM 익스프레스를 논리 장치 인터페이스로서 지원한다.

     

  • 불편한 NVMe 형식의 EBS를 자동으로 마운트 할 수 있는 방법을 알아보자.

 

EBS 자동 마운트

  • 시나리오
    1. EBS 생성
      • 이 포스팅에서 EBS는 다음과 같이 생성했다.
        ###  EBS  ###
        디바이스 이름 |  용량    |    경로 
        /dev/sdh      11gb      /test/gb11
        /dev/sdi      22gb      /test/gb22
        /dev/sdj      33gb      /test/gb33
        /dev/sdk      44gb      /test/gb44
    1. nvme*n1 형식의 디바이스를 /dev/sdb* 형식으로 맵핑해서 링크를 만드는 스크립트
      non_ebs_mapping=("/dev/sdb1" "/dev/sdc1" "/dev/sdd1" "/dev/sde1" "/dev/sdf1" "/dev/sdg1")
      
      #알파벳 숫자 즉 26번 반복 (적게 해도 무관하다)
      for i in `seq 0 26`; do
          nvme_block_device="/dev/nvme$n1"
      
          # nvme*n1중 존재하는 블럭만 조건문 실행
          if [ -e  $nvme_block_device ]; then
      
              # ebs 정보를 통해 블럭디바이스 이름과 매핑한다.
              mapping_device=$(/usr/sbin/ebsnvme-id $ --block-dev)
      
              # EBS만 걸러내야 한다. 즉 non_ebs_mapping를 사용해 걸러준다.
              if [[ -z "$mapping_device" ]]; then
                  mapping_device="$"
              fi
      
              # 간혹 /dev/sde 와같은 형식이 아닌 /sde와 같은 형식으로 나오는 경우 /dev/*로 수정
      				# EBS를 직접 생성하면서 Attach하는 경우에 이런 경우가 있었던 것 같다.
              if [[ "$mapping_device" != /dev/* ]]; then
                  mapping_device="/dev/$"
              fi
      
              # 매핑 디바이스 경로가 이미 존재하는 경우 스킵한다. 
              if [ -e $mapping_device ]; then
                  echo "path exists: $"
      
              # 경로가 존재하지 않으면 심볼릭 링크를 생성해준다.
              else
                  echo "symlink created: $ to $"
                  ln -s $nvme_block_device $mapping_device
              fi
          fi
      done
      이 스크립트를 통해 nvme0n1 부터 nvme26n1 까지 조사한 후 존재하는 모든 EBS의 nvme 볼륨에 대한 실제 /dev/sd* 디바이스 이름으로 링크를 생성해준다. ( /dev/sde를 부르면 실제론 nvme1n1이 불러와지는 효과)
      • 해당 스크립트를 실행할 때 /usr/sbin/ebsnvme-id 파일이 필요하다. 해당 파일에서 디바이스 이름을 읽어오기 때문
    1. 생성된 링크에 라벨링을 통해 볼륨에 라벨을 지정한다. ( 라벨 → 링크 → 볼륨 원본 )
    1. 라벨 정보로 /etc/fstab에 등록하여 마운트
    1. 이 모든 작업을 EC2를 생성할 때 자동으로 진행하기
  • Userdata 작성
    #!/bin/bash
    #이 스크립트는 EBS 마운트에 관한 Userdata 스크립트만 다룬다.
    #내용 이외의 다른 내용은 사용자가 알아서 추가해야함
    
    #파일 시스템 생성 (4개만 테스트해서 그냥 작성했지만 수가많아지면 반복문 작성도 가능하다.)
    mkfs -t xfs /dev/nvme1n1
    mkfs -t xfs /dev/nvme2n1
    mkfs -t xfs /dev/nvme3n1
    mkfs -t xfs /dev/nvme4n1
    
    # 깃허브에서 nvme를 식별할 2개의 파일 다운 
    # 파이썬 파일 실행을 위한 파이썬 설치
    zypper install -y python
    wget https://gist.githubusercontent.com/wwdcr2/131ae0d087c78ec242f55737b9e53ac8/raw/07772083fa1c2e567ed422eb401ac7783487d1c7/ebsnvme-id -P /usr/sbin
    wget https://raw.githubusercontent.com/wwdcr2/LinuxFile/master/nvme-to-block-mapping -P /usr/sbin/
    
    # 설치한 파일들의 권한 설정
    chmod 755 /usr/sbin/ebsnvme-id 
    chmod 755 /usr/sbin/nvme-to-block-mapping
    
    # 스크립트 실행 및 
    /usr/sbin/nvme-to-block-mapping
    
    # 생성된 /dev/sd* 링크에 라벨을 붙인다.
    xfs_admin -L ebs1 /dev/sdh
    xfs_admin -L ebs2 /dev/sdi
    xfs_admin -L ebs3 /dev/sdj
    xfs_admin -L ebs4 /dev/sdk
    
    # 라벨을 통해 EBS를 fstab에 등록한다. 
    echo "LABEL=ebs1 /test/gb11 xfs defaults,nofail 1 0" >> /etc/fstab
    echo "LABEL=ebs2 /test/gb22 xfs defaults,nofail 1 0" >> /etc/fstab
    echo "LABEL=ebs3 /test/gb33 xfs defaults,nofail 1 0" >> /etc/fstab
    echo "LABEL=ebs4 /test/gb44 xfs defaults,nofail 1 0" >> /etc/fstab
    
    # 마운트 될 디렉터리를 생성한다.
    mkdir -p /test/gb11
    mkdir -p /test/gb22
    mkdir -p /test/gb33
    mkdir -p /test/gb44
    
    #마운트
    mount -a
  • 결과
    • df -hT 명령어로 확인해보면 Size와 Mount 경로가 일치하는 것을 볼 수 있다.
    • 또한 순서대로 생성함과 무관하게 /dev/nvme*n1는 랜덤하게 생성됨을 확인할 수 있다.

     

 

결과

  • 수동작업이 시간이 엄청나게 오래 걸리는 것은 아니지만 수동 작업은 언제나 실수를 부를 수 있다.
  • UUID를 통해 마운트 작업을 하다보면 생각보다 머리가 아프고 볼륨이 같은 EBS 끼리는 또 구분하느라 귀찮은데, 이 문제를 생성시에 마운트하는 작업으로 간단히 해결해서 효율이 늘어날 것으로 예상된다.
  • 서버 생성 후 추후에 볼륨을 추가하더라도 스크립트 실행을 통해 간단하게 새로운 볼륨을 마운트할 수 있을 것이다.

 

nvme1n1
Comments