VM Resizing + Ansible 자동화(2) 너 적용 안되고 있었구나!?

왜? 다 이유가 있구나? 🛠️

안녕하세요! 오늘은 제가 최근 물뮤(MoolMeow) 프로젝트를 위한 쿠버네티스 환경을 구축하면서 겪었던 VM 디스크 리사이징 문제와 그 해결 과정을 공유하려고 합니다. Vagrant와 VirtualBox를 사용하는 많은 개발자분들이 한 번쯤 겪을 수 있는 문제라 생각해요! 🤔

📌 문제 상황

저는 Mac Mini에서 Vagrant와 VirtualBox를 사용해 쿠버네티스 클러스터를 구축하고 있었습니다. 마스터 노드에는 128GB, 워커 노드에는 64GB의 디스크 공간을 할당하려고 했죠.

# Vagrantfile 설정
NODES = [
  { hostname: "k8s-master", ip: "192.168.56.10", memory: 8192, cpus: 4, disk_size: "128GB" },
  { hostname: "k8s-worker", ip: "192.168.56.11", memory: 4096, cpus: 2, disk_size: "64GB" }
]

vagrant-disksize 플러그인을 설치하고, VM을 생성했는데… 🧐

VM 내부에서 디스크 공간을 확인해보니 여전히 기본 크기(약 60GB)로 설정되어 있었습니다!

$ df -h /
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv   60G  5.2G   51G  10% /

뭐가 문제였을까요? 🤔

🧩 문제 원인

문제의 원인은 크게 두 가지였습니다:

1. 디스크 확장 != 파티션 확장

Vagrant에서 disk_size를 설정하면 물리적 디스크 크기만 증가하고, 파티션과 파일시스템은 자동으로 확장되지 않습니다. Ubuntu VM은 LVM(Logical Volume Manager)을 사용하는 구조로 되어 있어서:

물리 디스크(/dev/sda) → 파티션(/dev/sda3) → PV → VG → LV → 파일시스템(ext4)

이 모든 계층을 차례로 확장해주어야 했습니다!

2. Ansible 자동화의 함정

이 과정을 Ansible로 자동화하려 했는데, parted 명령이 제대로 동작하지 않았습니다. 왜냐하면:

  • parted는 GPT 디스크를 변경할 때 Fix/Ignore? 프롬프트를 표시
  • Ansible에서는 이런 인터랙티브 프롬프트 처리가 까다로움
  • 명령어와 응답 입력 순서가 꼬여서 "invalid token" 에러 발생

🛠️ 해결 과정

여러 시도 끝에 찾아낸 해결 방법을 공유합니다!

시도했던 방법들 (실패) ❌

  1. parted--pretend-input-tty 플래그와 heredoc 사용

    parted /dev/sda --pretend-input-tty <<EOF
    Fix
    resizepart 3
    100%
    Yes
    quit
    EOF
    
  2. echo -e로 입력 전달

    echo -e "Fix\nresizepart 3\n100%\nYes" | parted /dev/sda --pretend-input-tty
    

하지만 이런 방법들은 입력 순서가 꼬여서 제대로 작동하지 않았습니다. 😞

최종 해결 방법 (성공) ✅

핵심은 GPT 수정과 파티션 리사이징을 분리하는 것이었습니다!

# master.yml (Ansible 플레이북)
- name: Fix GPT table first
  shell: |
    echo "Fix" | parted /dev/sda ---pretend-input-tty print
  register: gpt_fix
  ignore_errors: true
  changed_when: false

- name: Resize partition 3 to use all available space
  shell: |
    echo "100%" | parted /dev/sda ---pretend-input-tty resizepart 3
  register: parted_result
  changed_when: "'Error' not in parted_result.stdout"

그 다음 LVM 계층을 차례로 확장했습니다:

- name: PV 리사이즈
  shell: pvresize /dev/sda3

- name: LV 확장
  shell: lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
  register: lv_result
  changed_when: "'extended' in lv_result.stdout"

- name: 파일시스템 리사이즈 (ext4 전용)
  shell: resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
  register: fs_result
  changed_when: "'resized' in fs_result.stdout or 'nothing to do' in fs_result.stdout"

🎉 결과

드디어 성공! 확인해보니:

$ df -h /
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv  123G  5.2G  112G   5% /

마스터 노드는 128GB, 워커 노드는 64GB로 원하는 대로 설정되었습니다! 🙌

📝 배운 점

이 과정에서 몇 가지 중요한 교훈을 얻었습니다:

  1. 가상 디스크 확장 != 파일시스템 확장: VM의 디스크 크기를 늘리는 것은 여러 단계의 프로세스입니다.
  2. 인터랙티브 명령 자동화의 어려움: parted와 같은 인터랙티브 명령은 자동화할 때 주의해야 합니다.
  3. LVM 이해의 중요성: 리눅스 볼륨 관리 계층구조를 이해하면 문제 해결이 수월해집니다.
  4. 명령 분리의 힘: 복잡한 인터랙티브 명령은 단순한 여러 단계로 나누는 것이 효과적입니다.

🔍 참고: 전체 리사이징 과정 요약

전체 과정을 요약하면 다음과 같습니다:

  1. 디스크 확장: Vagrant에서 disk_size 설정
  2. GPT 테이블 수정: partedFix 옵션 사용
  3. 파티션 확장: parted resizepart/dev/sda3 확장
  4. PV 확장: pvresize /dev/sda3
  5. LV 확장: lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
  6. 파일시스템 확장: resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

이 모든 과정이 Ansible로 자동화되어 이제 VM을 프로비저닝할 때마다 원하는 크기의 디스크를 사용할 수 있게 되었습니다! 😄


여러분도 Vagrant나 다른 가상화 환경에서 비슷한 문제를 겪고 계시다면, 이 글이 도움이 되길 바랍니다. 궁금한 점이나 추가 팁이 있으시면 댓글로 알려주세요! 💬

Why?There was a reason for everything 🛠️

Hello everyone! Today I’d like to share my recent experience with VM disk resizing issues in my MoolMeow project’s Kubernetes setup. This is a common challenge many developers face when working with Vagrant and VirtualBox! 🤔

📌 The Problem

I was building a Kubernetes cluster on my Mac Mini using Vagrant and VirtualBox. I wanted to allocate 128GB of disk space to the master node and 64GB to the worker node.

# Vagrantfile configuration
NODES = [
  { hostname: "k8s-master", ip: "192.168.56.10", memory: 8192, cpus: 4, disk_size: "128GB" },
  { hostname: "k8s-worker", ip: "192.168.56.11", memory: 4096, cpus: 2, disk_size: "64GB" }
]

I installed the vagrant-disksize plugin and provisioned the VMs, but when I checked the disk space inside the VM, it was still at the default size (around 60GB)! 🧐

$ df -h /
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv   60G  5.2G   51G  10% /

What went wrong? 🤔

🧩 The Root Cause

There were two main issues:

1. Disk Expansion Is Not Partition Expansion

When you set the disk_size in Vagrant, it only increases the physical disk size, but partitions and filesystems don’t automatically expand. Ubuntu VMs use LVM (Logical Volume Manager), creating a layered structure:

Physical disk(/dev/sda) → Partition(/dev/sda3) → PV → VG → LV → Filesystem(ext4)

I needed to expand each of these layers sequentially!

2. Ansible Automation Challenges

When trying to automate this process with Ansible, the parted command didn’t work properly because:

  • parted displays a Fix/Ignore? prompt when modifying GPT disks
  • Handling interactive prompts in Ansible is tricky
  • The command and response input sequences got confused, resulting in an "invalid token" error

🛠️ My Troubleshooting Journey

After several attempts, I found a solution!

Failed Attempts ❌

  1. Using parted with the --pretend-input-tty flag and heredoc:

    parted /dev/sda --pretend-input-tty <<EOF
    Fix
    resizepart 3
    100%
    Yes
    quit
    EOF
    
  2. Passing inputs with echo -e:

    echo -e "Fix\nresizepart 3\n100%\nYes" | parted /dev/sda --pretend-input-tty
    

These approaches failed because of input sequence issues. 😞

The Working Solution ✅

The key insight was to separate the GPT table modification from the partition resizing:

# master.yml (Ansible playbook)
- name: Fix GPT table first
  shell: |
    echo "Fix" | parted /dev/sda ---pretend-input-tty print
  register: gpt_fix
  ignore_errors: true
  changed_when: false

- name: Resize partition 3 to use all available space
  shell: |
    echo "100%" | parted /dev/sda ---pretend-input-tty resizepart 3
  register: parted_result
  changed_when: "'Error' not in parted_result.stdout"

Then I expanded each LVM layer sequentially:

- name: Resize Physical Volume
  shell: pvresize /dev/sda3

- name: Extend Logical Volume
  shell: lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
  register: lv_result
  changed_when: "'extended' in lv_result.stdout"

- name: Resize filesystem (ext4 specific)
  shell: resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
  register: fs_result
  changed_when: "'resized' in fs_result.stdout or 'nothing to do' in fs_result.stdout"

🎉 The Results

Success at last! Checking the disk space:

$ df -h /
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv  123G  5.2G  112G   5% /

The master node was now at 128GB and the worker node at 64GB, exactly as intended! 🙌

📝 Key Lessons Learned

This troubleshooting process taught me several valuable lessons:

  1. Virtual Disk Expansion ≠ Filesystem Expansion: Increasing a VM’s disk size is a multi-step process.
  2. Interactive Command Automation Challenges: Commands like parted require special handling when automated.
  3. LVM Understanding is Critical: Understanding Linux volume management architecture makes troubleshooting much easier.
  4. The Power of Command Separation: Breaking down complex interactive commands into simpler sequential steps is effective.

🔍 Complete Resizing Workflow Summary

The entire process can be summarized as:

  1. Disk Expansion: Configure disk_size in Vagrant
  2. GPT Table Modification: Use the Fix option in parted
  3. Partition Expansion: Expand /dev/sda3 with parted resizepart
  4. PV Extension: Run pvresize /dev/sda3
  5. LV Extension: Run lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
  6. Filesystem Extension: Run resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

Now with this automated in Ansible, I can provision VMs with the desired disk sizes every time! 😄


If you’re facing similar issues with Vagrant or other virtualization environments, I hope this post helps. Feel free to share your own tips or questions in the comments! 💬

답글 남기기