Windows 10 에서 Vagrant + VirtualBox 로 Cent OS 7 설치하기

회사에서는 맥에서 개발하다가 집에 오면 윈도우 환경이라서 회삿일을 하기가 곤란해서 열심히 놀았더랬다. 그러다가 어디선가 vagrant 라는 게 있다고 해서 찾아보니 꽤 쓸만해 보여서 삽질을 시작했다.

이 글의 목표는 Windows 10 에서 virtualbox 에 CentOS 7 을 설치하고 redis/mysql/node.js/nginx 를 설치하는 과정을 자동화하는 데 있다.

준비 사항

  • 호스트: Windows 10 64 bit
  • 가상머신 프로바이더: Virtual Box
  • 게스트: Cent OS 7

일단 기본 패키지들부터 설치한다.

  • 가장 먼저 BIOS 에서 VT-d 옵션을 켠다.
  • virtualbox 5.1.2 를 설치한다.
  • vagrant 1.8.5 를 설치한다.
  • bash 를 사용하기 위해 github for windows 설치한다.

git shell 로 bash를 띄우고 적당한 폴더 안에서 다음 명령을 실행하자.

$ mkdir cent7
$ cd cent7
$ vagrant init centos/7
A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.

Vagrantfile 에 이후의 모든 설치 정보들이 저장된다. 이제 vagrant up 으로 설치를 시작해보자.

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'centos/7' could not be found. Attempting to find and install...
default: Box Provider: virtualbox
default: Box Version: >= 0
==> default: Loading metadata for box 'centos/7'
default: URL: https://atlas.hashicorp.com/centos/7
==> default: Adding box 'centos/7' (v1607.01) for provider: virtualbox
default: Downloading: https://atlas.hashicorp.com/centos/boxes/7/versions/1607.01/providers/virtualbox.box
default:
==> default: Successfully added box 'centos/7' (v1607.01) for 'virtualbox'!
==> default: Importing base box 'centos/7'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'centos/7' is up to date...
==> default: Setting the name of the VM: cent7_default_1471967385259_43086
"rsync" could not be found on your PATH. Make sure that rsync
is properly installed on your system and available on the PATH.

.vagrant.d/ 안에 CentOS 팀에서 virtual box + vagrant 용으로 만든 이미지(일명 베이스 박스)를 다운받고 나서, 본격적인 설치를 시작하는 와중에 에러가 발생했다. 윈도우에서 rsync 가 없다고 하니 일단 Vagrantfile 을 열고 공유 폴더를 끄거나 타입을 변경하자. 어차피 Guest Additions CD 를 설치하지 않으면 공유가 안된다. (여기서는 후자를 사용한다)

config.vm.synced_folder “.”, “/vagrant”, disabled: true
# or
config.vm.synced_folder “.”, “/vagrant”, type: “virtualbox”

다시 재도전.

$ vagrant up
Bringing machine ‘default’ up with ‘virtualbox’ provider…
==> default: Checking if box ‘centos/7’ is up to date…
==> default: Clearing any previously set network interfaces…
==> default: Preparing network interfaces based on configuration…
default: Adapter 1: nat
==> default: Forwarding ports…
default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM…
==> default: Waiting for machine to boot. This may take a few minutes…
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Remote connection disconnect. Retrying…
default:
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
default:
default: Inserting generated public key within guest…
default: Removing insecure key from the guest if it’s present…
default: Key inserted! Disconnecting and reconnecting using new SSH key…

(Update: vagrant 1.8.7 에서는 이 문제가 해결되었다.) .vagrant.d/ 에 가면 insecure_private_key 라는 ssh 용 개인키가 있는데, 이를 랜덤하게 새로 생성한 키 조합으로 바꾼 다음, 가상 머신에 공유 키를 넣어둔다. 다만 알려진 버그로 인해서 Authentication Failure 가 나는데, 이는 Virtual Box 관리자에서 직접 콘솔을 열고 vagrant/vagrant 로 들어가서 권한만 수정해주면 된다. (Update: centos/7 (virtualbox, 1608.02) 박스 이미지부터는 private key 의 위치가 /.vagrant/machines/default/virtualbox/private_key 로 변경되었다.)

$ chmod 0644 ~/.ssh/authorized_keys

공유 폴더를 사용하려면 가상 머신 내부에 virtual box guest addition 이 설치되어 있어야 한다. 이를 위한 vagrant 플러그인이 있으니 그걸 설치해두자. 의외로 느리다고 Cent OS 팀은 NFS 공유를 쓰라고 하더라..

$ vagrant plugin install vagrant-vbguest

이미 가상 머신은 떠 있는 상태인데, 게스트 이미지를 설치하려면 reload 명령을 사용한다.

$ vagrant reload
==> default: Attempting graceful shutdown of VM...
==> default: Checking if box 'centos/7' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: private key
default: Warning: Remote connection disconnect. Retrying...
==> default: Machine booted and ready!
[default] No installation found.
Loaded plugins: fastestmirror
Determining fastest mirrors
* base: ftp.daumkakao.com
* extras: ftp.daumkakao.com
* updates: mirror.premi.st
Package binutils-2.23.52.0.1-55.el7.x86_64 already installed and latest version
Package 1:make-3.82-21.el7.x86_64 already installed and latest version
Package bzip2-1.0.6-13.el7.x86_64 already installed and latest version
....
....
Copy iso file C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso into the box /tmp/VBoxGuestAdditions.iso
mount: /dev/loop0 is write-protected, mounting read-only
Installing Virtualbox Guest Additions 5.1.2 - guest version is unknown
Verifying archive integrity... All good.
Uncompressing VirtualBox 5.1.2 Guest Additions for Linux...........
VirtualBox Guest Additions installer
Copying additional installer modules ...
Installing additional modules ...
vboxadd.sh: Building Guest Additions kernel modules.
vboxadd.sh: Starting the VirtualBox Guest Additions.
Could not find the X.Org or XFree86 Window System, skipping.
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /vagrant => C:/Users/reiot/cent7
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.

원래 게스트 이미지를 설치하려면 kernel-devel 패키지를 설치하고 컴파일러도 깔아야 한다. 또한 CD 이미지를 가상 머신에 받아서 마운트 해서 스크립트를 실행해야 하는데, 이런 귀찮은 과정을 저 플러그인이 해주신다…

프로비전 준비

여기까지는 단순히 OS 만 설치하는 거고, 실제로 귀찮은 부분은 서버들을 설치하는 거다. 이 과정을 프로비전이라고 부르는데, 이제 나이가 들어서 소스 설치는 무척 귀찮으니 yum 패키지를 이용하도록 한다.

  • redis >= 3.2.3
  • mysql >= 5.7.14
  • node.js >= 6.4
  • nginx >= 1.10.1

yum 기본 패키지들은 버전이 낮아서, remi 라든지 epel-release 같은 저장소를 등록해야 한다…. 다음 내용을 Vagrantfile 에 추가하자.

  config.vm.provision "shell", inline: <<-SHELL
echo "Install system packages..."
yum -y update
yum -y install wget
yum -y install epel-release
wget http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
rpm -Uvh remi-release-7.rpm
    echo "Install redis..."
yum -y --enablerepo=remi install redis
systemctl enable redis
    echo "Install mysql..."
wget http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
yum -y install mysql57-community-release-el7-7.noarch.rpm
yum -y install mysql-community-server
systemctl enable mysqld
echo "Dont forget mysql secure..."
    echo "Install node.js..."
curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
yum install -y nodejs
    echo "Install nginx..."
printf '[nginx]\nname=nginx repo\nbaseurl=http://nginx.org/packages/centos/$releasever/$basearch/\ngpgcheck=0\nenabled=1' | tee /etc/yum.repos.d/nginx.repo
yum -y --enablerepo=remi install nginx
systemctl enable nginx
SHELL
end

이제 프로비저닝을 시작하려면 provision 명령을 사용해야 한다.

$ vagrant provision

모든 패키지를 다운받고 설치하려면 시간이 오래 걸린다. 어쨌거나 전체 과정이 끝나면, 이제 ssh 로 가상 머신에 접속해서 각 서버들이 잘 설치되었는지 확인해보자.

$ vagrant ssh
[vagrant@localhost ~]$ rediscli -v
[vagrant@localhost ~]$ mysql --version
[vagrant@localhost ~]$ node -v
[vagrant@localhost ~]$ nginx -v

공유 폴더가 잘 보이는지 확인하고 괜찮으면 sudo reboot 또는 vagrant halt & vagrant up 으로 머신을 리붓하면 기본 준비는 완료! (사실 reload == halt + up 이다)

$ vagrant halt
==> default: Attempting graceful shutdown of VM...
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'centos/7' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key
==> default: Machine booted and ready!
[default] GuestAdditions 5.1.2 running --- OK.
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /vagrant => C:/Users/reiot/cent7
default: /home/vagrant/share => C:/Users/reiot/cent7
default: /home/vagrant/Works => C:/Works
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.

참고로, 두번째 vagrant up 부터는 프로비전을 하지 않는다. 다시 접속해서 서버 설치 마무리를 해보자

$ vagrant ssh

systemctl 로 서비스가 잘 시작되었는지 체크하자.

[vagrant@localhost ~]$ systemctl | grep mysqld

mysql 사후 설치

mysql 5.7 은 기본 암호 정책이 MEDIUM 이라서 8자 이상, 대소문자/숫자/특수문자가 각 1개 이상이라 귀찮다. /etc/my.cnf 에 다음 내용을 추가하자.

validate-password=off

mysqld 서비스를 재시작하고, 임시 암호를 찾아서 새 암호를 vagrant 로 입력하자. (어차피 로컬 접속 전용이므로 너무 두려워하지 말자. )

[vagrant@localhost ~]$ sudo systemctl restart mysqld
[vagrant@localhost ~]$ sudo grep 'temporary password' /var/log/mysqld.log
[vagrant@localhost ~]$ sudo mysql_secure_installation

nginx 포트 열기

nginx 를 윈도우에서 접속하려면 포트를 열어줘야 한다. 아래 내용을 Vagrantfile 에 추가하고 reload 를 해주자.

config.vm.network “forwarded_port”, guest: 80, host: 8080

그다음 호스트 브라우저에서 http://localhost:8080 을 해서 Welcome to nginx! 를 봤다면 설치는 일단 끝난 셈이다.

putty 로 ssh 접속하기

putty 로 접속할 때 기존의 private_key 는 포맷이 달라 오류가 발생한다. puttygen 의 Load an existing private key file 로 불러와서, Save private key 로 저장하고 putty 에서는 불러들이면 된다. 여기에 자세한 설명이 있다. (혹시나 private key 의 위치를 모를 경우 vagrant ssh-config 를 사용할 것.)

Connection - Data - Auto Login username : vagrant
Connection - SSH - Auth - Private key file for authentication : ppk

mysql workbench 로 접속하기

mysql workbench 로 가상머신의 mysql에 접속하기 위해서 굳이 포트포워딩을 열 필요는 없다. 기존에 사용했던 private key 를 SSH Key File에 등록하면 된다.

기타

저 위에 ssh 권한 문제가 반복되면 귀찮기도 하니, 아예 vagrant 공식 비밀키를 다운받아서 .vagrant.d/insecure_private_key 로 복사한 다음, 랜덤 키 생성 과정을 건너뛰어 버려도 된다. 대신 Vagrantfile 에 아래 내용을 추가해야 한다.

config.ssh.insert_key = false

vagrant ssh 로 접속이 안될 때에는 다음 명령을 써보자.

$ vagrant ssh --debug
$ vagrant ssh-config

베이스 박스 이미지들은 .vagrant.d/boxes/ 에 저장된다. 두 번째 설치부터는 이미 받아둔 이미지들을 사용하며, 추후 업데이트할 수 있다.

$ vagrant box list
$ vagrant box update

공유 폴더에 쓰기 권한을 주려면 소유권을 지정해주면 된다.

config.vm.synced_folder “.”, “/home/vagrant/share”, owner: “vagrant”, group: “vagrant”

윈도우 공유 폴더에서 npm 을 설치할 때 심볼릭 링크 에러가 나는 경우, 다음 파라미터를 붙이면 된다.

[vagrant@localhost ~]$ npm install --no-bin-link

나만의 베이스 박스 이미지 만들기

매번 이 과정을 반복하기 귀찮다면, centos/7 대신 나만의 베이스 박스를 만들어둘 수도 있다. 이 글을 참조해서 가장 먼저 가상 머신 내부의 쓸데없는 파일들을 지워버리자. (dd 명령의 경우 시간이 꽤 오래 걸린다..)

[vagrant@localhost ~]$ sudo yum clean all
[vagrant@localhost ~]$ sudo dd if=/dev/zero of=/EMPTY bs=1M
[vagrant@localhost ~]$ sudo rm -f /EMPTY
[vagrant@localhost ~]$ cat /dev/null > ~/.bash_history && history -c && exit

이제 패키징을 하면 1G 정도 되는 박스 이미지가 만들어진다. 원래의 CentOS 7 이 500M 정도이니 뭔가 쓸모없는 것들이 많이 들어간 것 같다;;;;

$ vagrant package --out kingdomServer.box
==> default: Attempting graceful shutdown of VM...
==> default: Clearing any previously set forwarded ports...
==> default: Exporting VM...
==> default: Compressing package to: C:/Users/reiot/cent7/kingdomServer.box

방금 만든 박스를 .vagrant.d/boxes 에 추가하자.

$ vagrant box add kingdomServer.box  --name kingdomServer
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'kingdomServer' (v0) for provider:
box: Unpacking necessary files from: file://C:/Users/reiot/cent7/kingdomServer.box
box:
==> box: Successfully added box 'kingdomServer' (v0) for 'virtualbox'!
$ vagrant box list
centos/7 (virtualbox, 1607.01)
kingdomServer (virtualbox, 0)

관례상 버전도 있어야 할 것 같지만, 생략한다.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.