이쯤 되면 여러분은 KVM을 상당히 잘 다루고 있을 것입니다. 기본 소개와 중급 수준의 설치 및 사용법, 네트워크 및 스토리지 구성, 그리고 VirtualBox와 함께 KVM을 운영하는 방법까지 다양한 튜토리얼을 진행해 왔습니다. 그 다음으로 자연스러운 단계는 바로 브리지 네트워킹(bridged networking)입니다. 이를 통해 포트 포워딩 등이 필요할 때 가상 머신에 실제로 사용 가능한 외부 IP 주소를 부여할 수 있습니다.
오늘 소개할 내용은 다른 곳에서 흔히 볼 수 있는 튜토리얼들과는 조금 다릅니다. 많은 자료에서 볼 수 있는 무식한 brute-force 방식 대신, 저는 가상 머신을 외부 네트워크에 노출하는 두 가지 방법을 보여드리려 합니다. 그중 하나는 일종의 꼼수(hack)이지만, 정말 천재적인 방법입니다. 어디서도 본 적 없을 테니까요! 마지막으로 한계점과 발생 가능한 문제들에 대해서도 살펴보겠습니다.
기본 준비 사항
먼저 현실부터 짚고 넘어가겠습니다. 브리지 네트워킹은 다소 번거롭고 리눅스 명령줄에 대한 이해가 필요합니다. 하지만 때로는 브리징이 필수적입니다. 가상 머신 안에서 서버를 운영하려면, 다른 호스트들이 직접 통신할 수 있도록 외부 IP 주소를 부여하고 싶어질 것입니다.
예를 들어 보겠습니다. 라우터가 10.0.0.X 범위의 주소를 할당하고, 물리 호스트는 10.0.0.4를 사용하는데, 가상 머신은 192.168.2.133으로 실행된다고 가정합시다. 시스템이 패킷을 해석하는 방식을 변경하지 않는 한, 10.0.0 네트워크의 클라이언트는 192.168.2 네트워크의 클라이언트와 통신할 수 없습니다.
브리징을 사용하면 이 문제를 해결할 수 있습니다. 가상 머신이 라우터에 연결되어 외부 IP 주소를 받을 수 있게 됩니다. 여기서 '외부'란 물리 호스트가 사용하는 주소를 의미하며, 반드시 공인 IP일 필요는 없습니다.
기본적으로 KVM은 자체 브리지인 192.168.122.1을 생성합니다. 이 장치는 가상 머신들을 위한 가상 라우터 역할을 하며 해당 범위 내에서 IP 주소를 할당합니다. 하지만 우리는 가상 머신이 외부 주소를 임대받기를 원합니다. 이 튜토리얼에서는 192.168.2 범위를 사용합니다.
두 가지 대안 솔루션
이를 구현하는 방법은 두 가지가 있습니다.
첫째, 브리지를 직접 생성하는 방법입니다. 물리 장치 eth1과 vnet0이라는 가상 장치 두 개를 브리지로 연결합니다. 브리지가 정상 작동하는지 확인한 후, 변경 사항을 디스크의 네트워크 설정 파일에 저장합니다. 가상 머신은 라우터로부터 IP 주소를 임대받게 되며, 이는 VirtualBox에서 했던 작업과 유사합니다. 이 방법이 이 글에서 다룰 핵심 내용입니다.
둘째 방법은 성공을 보장하지는 않지만 시도해볼 만합니다. 네트워크 어댑터가 기본적으로 브리징을 지원한다면 바로 사용할 수 있습니다. 필요한 변경은 KVM의 가상 브리지에 물리 호스트가 사용하는 주소와 겹치지 않는 작은 서브넷을 할당하는 것뿐입니다.
한계점
잘못될 수 있는 요소는 많습니다. 라우터가 브리징을 지원하지 않을 수 있고, 네트워크 인터페이스가 브리징을 지원하지 않을 수도 있습니다. 할당 가능한 IP 주소 풀이 제한적이거나 방화벽이 간섭할 수 있습니다. 마지막으로 특히 우분투(Ubuntu)에서는 Network Manager가 브리지 인터페이스를 관리할 경우 문제와 충돌이 발생할 수 있습니다.
추가 참고 자료로 아래 문서들을 확인해 보세요:
- Linux Foundation의 브리지 설정 문서
- Ubuntu 커뮤니티 문서의 KVM Networking
자, 이제 앞으로 무엇을 해야 하는지 알겠습니다. 브리징은 결코 간단한 작업이 아니며 몇 가지를 고려해야 합니다. 첫째, 네트워크 어댑터가 애초에 브리징을 지원하는가? 예를 들어 일부 노트북의 무선 어댑터는 이 모드를 제대로 지원하지 않습니다. 둘째, 네트워크 설정을 직접 수정하는 것이 편안한가? 셋째, 목표가 무엇인가? 어쩌면 NAT만으로도 충분할지 모릅니다.
기본 네트워킹 개념
제 테스트 환경은 우분투지만, 이 튜토리얼은 특정 배포판에 종속되지 않기를 바랍니다. Ubuntu KVM 커뮤니티 문서를 따르는 것도 좋지만 데비안 계열 시스템에서만 작동합니다. 따라서 조금 벗어나 RedHat 계열과 SUSE 계열 시스템에도 적용 가능한 네트워킹 개념을 소개하겠습니다.
우분투 같은 데비안 계열 시스템에서는 영구 네트워크 설정이 /etc/network/interfaces에 저장됩니다. RedHat 계열과 SUSE 계열 시스템에서는 /etc/sysconfig/network 아래에 개별 파일로 저장되며, 보통 ifcfg-ethX 또는 ifcfg-eth-MAC-address 형식의 접두사를 사용합니다. ifconfig 명령으로 확인한 시스템의 실제 인터페이스 이름으로 'eth'를 대체하세요.
또한 brctl 유틸리티를 명령줄에서 사용하여 설정 파일에 변경 사항을 저장하지 않고도 브리지를 만들 수 있지만, 네트워크 서비스를 재시작할 때마다 설정이 사라집니다. 시스템 파일을 편집하기 전에 먼저 테스트해 보는 권장 방법입니다. 그리고 설정을 만지기 전에 반드시 백업하는 것도 잊지 마세요. 네트워크 설정에 대한 자세한 내용은 Linux commands 관련 글을 참조하세요.
브리지 생성
이제 시작해 볼 차례입니다. brctl, ifconfig, dhclient 명령부터 사용해 보길 권합니다. 세부 사용법까지 깊이 설명하지는 않겠습니다. 요청이 많다면 별도의 튜토리얼을 준비하겠습니다. 일반적인 순서는 다음과 같습니다(sudo 또는 root 권한으로). 브리지 이름은 br0, 물리/가상 장치는 eth0/eth1, DHCP는 스위치나 라우터에서 임대받는다고 가정합니다:
ifconfig eth0 0.0.0.0
ifconfig eth1 0.0.0.0
brctl addbr br0
brctl addif br0 eth0
brctl addif br0 eth1
dhclient br0
가상 어댑터는 가상 머신을 생성하고 시작하기 전에는 존재하지 않을 수 있다는 점에 유의하세요. 따라서 지금 당장 가상 어댑터를 추가할 필요가 없습니다. 고급 옵션에서 브리지 네트워킹을 선택하면 KVM이 자동으로 처리해 줍니다.
브리지 인터페이스가 DHCP 서버로부터 외부 주소를 임대받는 것이 보인다면 올바른 방향으로 가고 있는 것입니다. 가정용 사용자에게 DHCP 서버는 라우터입니다. 인터넷에 직접 연결된 환경이라면 ISP가 사용자당 하나의 IP만 허용할 수 있으므로 불가능할 수도 있습니다.
브리지 인터페이스가 활성화되면 네트워크 기능이 기존과 동일하게 유지되는지 확인하세요. /etc/resolv.conf를 편집하고 라우팅 테이블을 수정해야 할 수도 있습니다.
여기까지 잘 작동한다면 변경 사항을 네트워크 설정 파일에 저장할 차례입니다. 제 예제는 일반적인 형태로 커뮤니티 문서의 예제와 매우 유사합니다. 예를 들어 여러 홉이나 순환 경로를 올바르게 처리하려면 브리지에서 STP(Spanning Tree Protocol)를 활성화해야 할 수 있습니다.
이번 사례에서는 /etc/network/interface 파일을 편집하여 br0을 추가합니다. STP가 필요하면 bridge_stp off를 bridge_stp on으로 변경하세요. btctl show 명령으로 브리지의 동작을 확인할 수 있습니다.
그리고 STP 재미있는 화면 하나 - 좀 수상하게 들리나요?
가상 머신 생성
생성 방법은 이미 배웠으므로 새로운 내용은 아닙니다. 마지막 단계의 Advanced options에서 네트워크 주소 할당 방식을 변경하고, 가상 어댑터에 다른 장치와 충돌하지 않는 고유한 MAC 주소가 지정되었는지 확인하세요.
운이 좋다면 특별한 브리지 설정 없이도 네트워크 어댑터가 기본적으로 브리징을 지원할 수 있습니다. 하지만 아마 운이 좋지 않을 가능성이 크니, 힘든 키보드 작업을 각오하세요.
모든 것이 정상 작동하는지 확인하려면:
핑(ping)이 된다면 해킹도 가능하다는 말이 있죠. VirtualBox에서 했던 작업과 거의 동일합니다. 이제 서비스를 외부에 노출하고 데이터를 공유하는 등 필요한 작업을 마음껏 할 수 있습니다. 즐겁게 활용하세요.
대안 설정 (실패할 수 있지만 천재적인 방법)
운이 나쁠 수도 있습니다. Network Manager가 협조하지 않거나 설정에 온갖 문제가 생길 수 있습니다. 이런 경우, 브리징을 기본 지원하는 것으로 판단되는 물리 장치에 라우팅되는 별도의 가상 네트워크 어댑터를 만들어 볼 수 있습니다. IP 주소 충돌에 주의하세요.
마지막으로, 이것이 잘 작동한다면 아주 더러운 꼼수를 시도해 볼 수 있습니다. 기존 네트워크와 동일한 /24 공간을 공유하는 가상 네트워크를 만드는 것입니다. 예를 들어 라우터가 192.168.2.0 네트워크에 있다면, 192.168.2.160부터 시작하는 가상 네트워크를 만들고 16개 주소 정도의 작은 범위만 할당합니다. 라우터가 해당 범위의 주소를 다른 클라이언트에 절대 할당하지 않도록 하세요.
예시: 저는 192.168.2.160/28 네트워크를 만들었습니다. 라우터가 이 범위의 주소를 임대하지 않을 것으로 예상하면서 DHCP 할당 범위를 제한했습니다. 그런 다음 가상 네트워크를 물리 장치, 이 경우 무선 어댑터 eth1로 라우팅합니다.
이제 위와 마찬가지로 eth1로 라우팅되는 가상 머신을 생성합니다. 온라인이 되면 멋진 협력을 확인할 수 있습니다. 호스트는 .102 주소를, 가상 NIC virbr1은 .161 주소를, 가상 머신은 .168 주소를 받았습니다.
그리고 같은 네트워크에 있는 .103 주소의 물리 Windows 7 머신에서, 무선으로 연결된 우분투 Lucid 머신의 .161 가상 어댑터로 핑을 보낸 결과입니다. 둘 다 같은 라우터를 통해 연결되어 있으며, 이 설정이 얼마나 깔끔하고 영리한지 보여줍니다. 항상 작동하지는 않지만, 작동할 때는 정말 천재적입니다.
기존 가상 머신
이미 존재하는 가상 머신의 경우 /etc/libvirt/ 아래의 설정을 수정하여 변경할 수도 있습니다. 각 가상 머신은 별도의 .xml 설정 파일을 가지고 있습니다. 변경 사항이 적용되려면 가상 머신을 전원 껐다 켜기(power cycle)해야 합니다. 예를 들면 다음과 같습니다:
<interface type='bridge'>
<mac address='00:11:22:33:44:55'/>
<source bridge='br0'/>
</interface>
결론
KVM 브리지 네트워킹 설정은 그다지 직관적이지 않습니다. 2~3년 전의 VirtualBox만큼 친숙하지 않은 수준입니다. 하지만 관리 가능하며, 실제 한계는 네트워크 토폴로지에 대한 이해도와 기능성에 달려 있습니다. 시간이 지나면 분명 더 좋아질 것입니다.
운이 좋다면 네트워크 어댑터가 기본적으로 브리징을 지원할 것입니다. 그렇지 않다면 브리지 어댑터를 생성하고 물리 및 가상 네트워크 장치를 할당해야 합니다. 그 후 DNS, DHCP 또는 라우팅 관련 잠재적 문제를 해결하세요. 마지막으로, 과감한 꼼수로 네트워크 범위를 활용해 서브넷 안의 서브넷을 만들고, IP 주소가 절대 겹치지 않도록 한 뒤 가상 어댑터를 물리 장치로 라우팅하는 방법도 시도해 볼 수 있습니다.
이 튜토리얼은 기본적이면서도 영리한 비법을 담고 있지만, 다루지 못한 수많은 문제가 남아 있을 수 있습니다. 질문, 제안 또는 KVM에서 까다로운 네트워크 설정을 극복하는 팁이 필요하시면 메일을 보내주세요. 새로운 문제들을 다루는 후속 How-to를 준비할 수도 있습니다.
감사합니다.