이수의 삽질 기록
article thumbnail

시리즈

- [KlosedStack #1] Intro: https://blog.isu.kim/14

- [KlosedStack #2] Vagrant + Libvirt: https://blog.isu.kim/15

- [KlosedStack #3] Vagrant + OVS https://blog.isu.kim/16

배경

지난주에 여러 인터페이스를 사용하는 서버 셋업으로 OVS + Vagrant를 구성했었다. 이후 목요일에 N 교수님께 해당 내용을 랩미팅 때 발표했었다. 그리고 돌아온 피드백.

어 좋은데, 단일 인터페이스로 안될까? 그리고 VM에서 eth0 그리고 eth1 쓰는거 말고 인터페이스 하나로 하게 하자, MASQUERADE 하면 될꺼야!

라는 피드백을 받았다. 사실 MASQUERADE 생각을 했었으나, 그동안 잘못한 점이 하나가 있었다. OVS 브릿지에 MASQUERADE를 하고, 해당 CIDR를 MASQUERADE 했긴 했다. 하지만 VM 내부에서 eth1의 게이트웨이를 브릿지로 설정하지 않아서, 이게 NAT가 안되었다... 역시 박사 학위가 있으신 분들은 다르다... (어쩌면 내가 댕청한거겠지만...)

 

그래서 이번에는 단일 인터페이스를 가지고, VM이 외부 통신 그리고 내부 통신도 가능하게 구성해보려고 한다.

토폴로지

이번에는 조금 더 간단하다.

이번에 만든 토폴로지는 위의 그림과 같다. 그림은 Neutron의 그림체를 차용해서 그렸다. 이걸 간단하게 설명하면 다음과 같다.

  1. 각 VM의 경우, eth1과 호스트의 macvtap과 인터페이스를 붙인다. 또한 VM 내부의 eth1의 IP 대역은 10.0.40.0/24 대역으로 설정해준다. 호스트 A의 VM의 경우, eth1의 IP는 10.0.40.213그리고 게이트웨이는 10.0.40.13으로 설정해준다. 마찬가지로 비슷하게 호스트 B의 VM도 설정해준다.
  2. macvtap은 지난번처럼 veth를 통해서 브릿지랑 연결해준다. 브릿지는 이번에 br-tun이라는 브릿지만 사용할 것이다. 이후 br-tun은 VXLAN을 통해 서로에게 오버레이를 만들어준다.
  3. br-tun 인터페이스에 10.0.40.13 또는 10.0.40.14를 설정해주고, 여기다가 NAT을 걸어준다. 이렇게 되면 VM이 외부 인터넷이랑 통신이 가능해질 것이다.

이렇게 설정하면, 각 VM끼리, 그리고 VM에서 외부 인터넷으로 통신이 된다.

마찬가지로, 이번에도 다시 당부하는 부분은, 나는 네트워크 전문가가 아니다. 이 셋업 때문에 살짝 삽질을 했다. 아무튼 그냥 참고만 하면 좋겠다.

br-tun 설정

지난번에는 br-inteth0을 포트로 가지고, 그리고 br-tun에 IP를 할당해주는 방식이였다. 하지만, 이번에는 br-tun만 가지고 있다. 따라서, 굳이 그런 설정 안해주고 그냥 다음을 따라하면 된다.

 

br-tun을 만들어주고, VXLAN을 연결해주자.

sudo ovs-vsctl add-br br-tun

호스트 1(192.168.100.139)에서

sudo ovs-vsctl add-port br-tun vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.168.100.196 options:df_default=true options:egress_pkt_mark=0 options:in_key=flow options:out_key=flow options:dst_port=48317 options:tag=321

호스트 2(192.168.100.196)에서

sudo ovs-vsctl add-port br-tun vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=192.168.100.139
options:df_default=true options:egress_pkt_mark=0 options:in_key=flow options:out_key=flow options:dst_port=48317 options:tag=321

이후 firewall-cmd를 통해서 VXLAN의 방화벽을 설정해주자. 지난번에도 언급했지만, ESXi의 버그 때문에, 4789번으로 VXLAN을 사용하지 못한다. 따라서 나는 48317번 UDP 포트를 사용한다. 이를 위해서 포트를 개방하고, 설정을 reload해주자.

sudo firewall-cmd --permanent --add-port=4789/udp --add-port=8472/udp --add-port=48317/udp
sudo firewall-cmd --reload

이후, 각 호스트에서 br-tun의 IP를 할당해주고, 인터페이스를 켜주자. (순서대로 호스트 1과 호스트 2의 명령어이다.)

sudo ifconfig br-tun 10.0.40.13 up
sudo ifconfig br-tun 10.0.40.14 up

이렇게 되면, 라우팅 설정이 안되어있다. 따라서, route 명령어를 통해서 10.0.40.0/24 대역을 br-tun으로 들어가게 설정해주자.

sudo ip route add 10.0.40.0/24 dev br-tun

이제 기본적으로 OVS를 통해 br-tun 끼리의 통신이 가능하다. 여기서 확인해보면, 10.0.40.13에서 10.0.40.14로 ping을 할 수 있다. 역 또한 같다.

VM 설정 + 테스트

VM에서 사용할 인터페이스들을 만들어주자. 필요한 것은 다음과 같다.

  • 한쪽은 veth1a 그리고 다른쪽은 veth1b로 연결된 veth
  • lb1이라는 이름을 가진 리눅스 브릿지
  • lb1br-tun의 포트로 가짐
sudo ip link add veth1a type veth peer name veth1b
sudo ip link add lb1 type bridge
sudo ip link set veth1b master lb1
sudo ovs-vsctl add-port br-tun lb1

이후 인터페이스를 불러오자.

sudo ifconfig lb1 up  
sudo ifconfig veth1b up

간단하다. 이후 VM을 생성해주면 된다. 예시 Vagrantfile은 다음과 같다.

Vagrant.configure("2") do |config|  
config.vm.box = "generic/ubuntu2204" # Ubuntu 22.04  
config.vm.box_check_update = false  
config.vm.network :public_network, :bridge => 'veth1a', :dev => 'veth1a', ip: "10.0.40.213"

config.vm.provider :libvirt do |libvirt|  
# Disable KVM and use pure QEMU  
libvirt.driver = "qemu"  
libvirt.memory = "2048" # Set the VM memory to 2GB  
libvirt.cpus = 2 # Set the number of CPUs to 2  
end

config.vm.provision "shell", inline: <<-SHELL  
SHELL  
end

이를 통해 Ubuntu 22.04를 가진 qemu (또는 kvm) VM을 만들 수 있다. 위의 config.vm.networkip부분을 설정해주면 VM에 원하는 ip를 할당해줄 수 있다.

 

이제 VM을 만들어보자!

vagrant up
vagrant ssh

이후 간단하게, eth1로 8.8.8.8 에 ping을 해보자. 아마 안될 것이다.

당연히 될리가 없다. 이제 하나씩 설정을 해주자.

NAT 설정

호스트에서 방화벽 그리고 포워딩 설정을 해주자.

sudo sysctl net.ipv4.ip_forward=1
sudo firewall-cmd --permanent --zone=trusted --add-source=10.0.0.0/8
sudo firewall-cmd --reload

이후 iptables를 통해서 MASQUERADE를 해주자.

sudo iptables -t nat -A POSTROUTING -s 10.0.40.0/24 -o eth0 -j MASQUERADE

VM에서 게이트웨이 설정을 해주자.

게이트웨이 설정은 다양하지만, 나는 그냥 netplan을 사용할 예정이다. Vagrant의 경우 /etc/netplan/50-vagrant.yaml를 생성한다. 따라서, 여기다가 게이트웨이 설정을 해주면 된다.

---
network:
  version: 2
  renderer: networkd
  ethernets:
    eth1:
      addresses:
      - 10.0.40.213/24
      routes:
          - to: default
            via: 10.0.40.13
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]

이렇게 설정해주면, 10.0.40.213을 사용하는 VM의 게이트웨이를 10.0.40.13으로 설정할 수 있다. 이후

sudo netplan apply

를 통해서 해당 변경 사항을 저장해주자.

검증

이후 검증을 하면 된다.

Ping 테스트

ping 8.8.8.8 -I eth1

를 통해서, ping을 해보자.

정상적으로 ping이 된다.

Curl 테스트

curl https://google.com --interface eth1

정상적으로 eth1을 통해 curl을 할 수 있다. 즉 TCP 패킷이 잘 도착한다.

이게 정말로 우리 VM 내부의 eth1을 통해서 나가는지 테스트를 해야한다. 아니면 이게 VM의 eth0을 통해서 virbr로 나가는지도 알아야한다. 그걸 보기 위해서 호스트에서 간단하게 tcpdump를 통해서 lb1을 보면 된다.

sudo tcpdump -i lb1 -vv tcp

보면 syd09s13-in-f14.1e100.net 으로 데이터가 잘 날라간다. 이게 찾아보니 구글 서버였다. 아무튼 이를 통해서 우리가 원하는 경로로 패킷이 날라감을 확인할 수 있었다.

 

이러면 생기는 문제가 있다. 바로 VM 내부에는 eth0 그리고 eth1이 둘다 있다는 것이다. 이를 처리하기 위해서 netplan으로 eth0을 날려버리자.

 

아마 기본으로는 /etc/netplan/00-installer-config.yaml 그리고 /etc/netplan/01-netcfg.yaml 이렇게 두개가 eth0을 담당하는 파일일 것이다. 우선 날려버린다.

sudo rm /etc/netplan/00-installer-config.yaml
sudo rm /etc/netplan/01-netcfg.yaml

이후 /etc/netplan/50-vagrant.yaml에다가 다음의 사항만 추가해주자.

---
network:
  version: 2
  renderer: networkd
  ethernets:
    eth1:
      addresses:
      - 10.0.40.214/24
      routes:
          - to: default
            via: 10.0.40.14
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
    eth0:
      activation-mode: off

인터넷을 찾아보니, activation-mode: off를 통해서 인터페이스를 완전히 내릴 수 있다고 한다. 이러면 우리 유저에게는 eth1만 있다고 뻥을 칠 수 있다!

보다시피, 이제 인터페이스가 하나만 남아있다. 또한 라우팅 테이블 또한 192.168.121.0/24에 해당하는것이 없어졌다. 이제는 10.0.40.0/24만 라우팅 대상이다!

이제 또 ping, curl을 해보면

문제 없이 TCP, ICMP가 모두 오간다. 

 

결론 + 다음 얘기

이를 통해서 VM이 외부로 인터페이스 하나만을 가지고 통신할 수 있음을 확인했다. 물론 환상적이고 아주 깔끔한 솔루션은 아니지만, 그래도 나름 나쁘지는 않은 것 같다. 분명 한 1달 후에 다시 이 글을 보면, 얘가 왜 이딴 생각을 했을까? 하는 의문이 들겠지만 아무튼 그렇다.

 

사실 다음 얘기는 Ceph + Vagrant 였는데, 이거 먼저 해결하고 하는게 마음이 편할 것 같아서 이거 먼저 했다. 

profile

이수의 삽질 기록

@IsuKim

두분의 주인님 밑에서 네트워크, 클라우드, 서버 삽질을 하는 학부생입니다