[OpenStack Project] VMware 없이 노트북 서버로 kolla-ansible OpenStack 설치 [1]

KH55S·2025년 12월 10일

OpenStack Project

목록 보기
1/8
post-thumbnail

노트북의 SSD 용량은 500GB이고, df -h /명령어를 쳐보면

사진처럼 500GB가 모두 안 잡힌 상태임을 알 수 있다. 그 이유는 다음과 같다.

  • 우분투 서버 설치 시 LVM(Logical Volume Manager) 옵션이 기본값으로 켜져 있어서 발생하는 현상
  • 우분투 서버 인스톨러는 안장성을 위해 물리 디스크 전체를 한 번에 할당하지 않고, 약 100GB(또는 절반)만 할당하고 나머지는 사용 가능한 여유 공간으로 남겨두는 경향이 있다.

    📌해결 방법
  • 물리 디스크 구조를 보여주는 lsblk 명령어로 진짜 용량 확인
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
nvme0n1                   259:0    0 476.9G  0 disk
├─nvme0n1p1               259:1    0     1G  0 part /boot/efi
├─nvme0n1p2               259:2    0     2G  0 part /boot
└─nvme0n1p3               259:3    0 473.9G  0 part
  └─ubuntu--vg-ubuntu--lv 252:0    0   100G  0 lvm  /
  • 논리 볼륨 늘리기
    sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv
     Size of logical volume ubuntu-vg/ubuntu-lv changed from 100.00 GiB (25600 extents) to <473.89 GiB (121315 extents).
     Logical volume ubuntu-vg/ubuntu-lv successfully resized.
  • 파일 시스템 늘리기
    sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
  • df -h / 로 확인

설치 과정

  • 오픈스택은 괸리망과 외부망을 물리적으로 분리해야 한다. 하지만 노트북에는 랜포트가 없고 공유기에도 남은 포트가 없기 때문에 USB 랜카드 2개와 스위칭 허브를 구매했다.
    • 구성 : 공유기 - 스위칭 허브 - USB 랜카드 2개 - 노트북에 USB로 연결 (포트 부족으로 USB 허브 사용)
    • 랜포트 1 : 데스크탑에서 대시보드 접속용
    • 랜포트 2 : IP를 할당하지 않고, OVS br-ex에 연결해서 VM이 인터넷과 연결

  • 네트워크 인터페이스 이름 확인

    $ ip a
    # 관리용 인터페이스 / IP 할당됨 / 대시보드 접속, API 통신, SSH 접속용
    126: enx0c379614f164: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu  1500 qdisc fq_codel state UP group default qlen 1000
       link/ether 0c:37:96:14:f1:64 brd ff:ff:ff:ff:ff:ff
       inet 192.168.35.100/24 brd 192.168.35.255 scope global  enx0c379614f164
          valid_lft forever preferred_lft forever
       inet6 fe80::e37:96ff:fe14:f164/64 scope link
          valid_lft forever preferred_lft forever
    
    # 외부용 인터페이스 / DOWN 상태 / VM들이 외부 인터넷으로 나가는 통로  (OVS 브리지용)
    127: enx00e04c68099c: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
       link/ether 00:e0:4c:68:09:9c brd ff:ff:ff:ff:ff:ff

  • 네트워크 인터페이스 활성화 (2가지 방법)

    # 1. IP 할당 없이 인터페이스만 켜기
    sudo ip link set enx00e04c68099c up
    sudo ip link set enx00e04c68099c promisc on
    ----------------------------------------------
    # 2. Netplan 설정
    sudo vi /etc/netplan/50-cloud-init.yaml
    network:
    ethernets:
      # 기존 관리용 인터페이스
      enx0c379614f164:
        dhcp4: false
        addresses:
          - 192.168.35.100/24
        routes:
          - to: default
            via: 192.168.35.1
        nameservers:
          addresses:
            - 8.8.8.8
            - 1.1.1.1
    
      # 추가 / addresses나 routes를 적지 않아야 OVS가 이 포트를 뺏어가도 충돌이 나지 않음
      enx00e04c68099c:
        dhcp4: false
        dhcp6: false
    
    # 적용 및 확인 / UP 상태, IP는 없어야 함
    sudo netplan apply
    ip link show enx00e04c68099c    

  • 호스트 이름과 /etc/hosts 일치 (RabbitMQ 에러 방지)
  # 현재 호스트 이름 확인
  hostname
  
  # /etc/hosts 파일 수정
  vi /etc/hosts
  192.168.35.100  hostname

  • 필수 패키치 설치 및 가상환경 구성
# 시스템 패키지 업데이트 및 필수 도구 설치
sudo apt update
sudo apt install -y git python3-dev libffi-dev gcc libssl-dev python3-venv

# 가상환경 생성 (홈 디렉토리 아래 openstack-venv)
python3 -m venv ~/openstack-venv

# 가상환경 진입 (앞으로 설치 작업은 항상 이 명령어로 진입 후 수행)
source ~/openstack-venv/bin/activate

# pip 업그레이드
pip install -U pip

# Ansible 설치 (호환성 좋은 버전 지정)
pip install 'ansible-core>=2.16,<2.17'

# Kolla-Ansible 설치 (OpenStack 2024.1 Caracal 대응 버전)
pip install "kolla-ansible>=18.0.0,<19.0.0"

  • 설정 파일 복사 : 설치된 kolla-ansible의 기본 설정 파일을 /etc/kolla로 가져온다.
# 1. 설정 디렉토리 생성
sudo mkdir -p /etc/kolla
sudo chown $USER:$USER /etc/kolla

# 2. globals.yml 등 설정 파일 복사
cp -r ~/openstack-venv/share/kolla-ansible/etc_examples/kolla/* /etc/kolla/

# 3. 인벤토리 파일 복사
cp ~/openstack-venv/share/kolla-ansible/ansible/inventory/all-in-one .

  • globals.yml 수정
$ vi /etc/kolla/globals.yml

kolla_base_distro: "ubuntu"

# 관리용 인터페이스 (IP 192.168.35.100이 있는 랜카드)
network_interface: "enx0c379614f164"

# 외부용 인터페이스 (IP 없이 UP 상태인 랜카드)
neutron_external_interface: "enx00e04c68099c"

# 오픈스택 내부 통신용 가상 IP (공유기 대역 중 안 쓰는 IP)
kolla_internal_vip_address: "192.168.35.200"

# HAProxy 활성화 (필수)
enable_haproxy: "yes"

# Cinder(블록 스토리지) 활성화 (VM에 디스크 붙이려면 필요)
enable_cinder: "yes"
enable_cinder_backend_lvm: "yes"
# (참고: Cinder를 쓰려면 빈 파티션이나 루프백 디바이스가 필요한데, 
# 복잡하면 일단 "no"로 두고 나중에 설정해도 됩니다. 여기선 "yes"로 도전!)

# Nova 가상화 타입 
# kvm-ok 쳤을 때 성공하면 kvm, 아니면 qemu
nova_compute_virt_type: "kvm"

192.168.35.200 IP가 실제로 비어 있는지 확인

sudo apt install arping
sudo arping -c 3 -I enx0c379614f164 192.168.35.200
  • IP를 가지고 있는지 물리적으로 물어보는 방식
  • Timeout이 뜨면 해당 IP 사용 가능

  • 비밀번호 생성 및 배포 준비
# 비밀번호 자동 생성 (admin 로그인 비번 등이 여기 저장됨)
kolla-genpwd

# Ansible 의존성 패키지 설치 (Galaxy)
kolla-ansible install-deps

# Bootstrap (기본 서버 세팅)
kolla-ansible -i ./all-in-one bootstrap-servers

  • 사전 점검 (Prechecks) : 설정을 바탕으로 설치가 가능한지 미리 체크한다.
    • 마지막에 failed=0이 떠야한다.
kolla-ansible -i ./all-in-one prechecks
  • 에러 원인 : Cinder를 위한 공간 부족

  • 오픈스택의 Cinder는 VM에 디스크를 붙여주기 위해 cinder-volumes라는 이름의 LVM Volume Group을 요구한다. 하지만 현재 여분의 빈 파티션이 없기 때문에 저장할 공간이 없다고 에러가 난 것이다.
  • 해결책 : 파일 하나를 디스크처럼 속여 사용
    • 150GB 빈 파일 생성
      $ sudo fallocate -l 150G /var/lib/cinder_data.img
    • 루프백 디바이스 연결 : 생성한 파일을 /dev/loop 장치에 연결
      $ sudo losetup -f --show /var/lib/cinder_data.img
       /dev/loop0
    • LVM 볼륨 그룹 생성
      # 물리 볼륨 생성
      $ sudo pvcreate /dev/loop0
       Physical volume "/dev/loop0" successfully created.
      # 볼륨 그룹 생성 (이름은 반드시 cinder-volumes)
      $ sudo vgcreate cinder-volumes /dev/loop0
       Volume group "cinder-volumes" successfully created
    • 확인
      $ sudo vgs
      cinder-volumes   1   0   0 wz--n- <150.00g <150.00g
    • 재부팅 후에도 유지 되도록 설정
      # OS 재부팅 시, 가짜 디스크 파일을 자동으로 연결해주는 스크립트 작성
      # 우분투는 부팅 시 /etc/rc.local 파일이 있으면 그 안의 명령어를 자동으로 실행한다.
      $ sudo vi /etc/rc.local        
      #!/bin/sh -e
      # 부팅 시 Cinder용 루프백 디바이스 자동 연결
      losetup -f /var/lib/cinder_data.img
      exit 0
     $ sudo chmod +x /etc/rc.local
  • 에러 원인 : Horizon 대시보드가 80번 포트를 써야 하는데, 이미 80번 포트를 쓰는 중
  • 웹서가 80번 포트를 쓰고 있는데, 기존 서비스를 끄는 대신 오픈스택이 8888 포트를 쓰도록 설정
$ vi horizon_port: "8888"
horizon_port: "8888"

  • 설치 시작 (네트워크 속도에 따라 시간이 오래 걸릴 수 있음)
kolla-ansible -i ./all-in-one deploy

  • 설치 후 클라이언트 설정 : 오픈스택 명령어를 쓰기 위한 도구 설치
# 오픈스택 클라이언트 설치
pip install python-openstackclient

# admin 인증 파일 생성
kolla-ansible post-deploy

# 인증 파일 위치로 이동 및 적용
source /etc/kolla/admin-openrc.sh
  • 설치 확인
openstack service list

+----------------------------------+-----------+----------------+
| ID                               | Name      | Type           |
+----------------------------------+-----------+----------------+
| 01f747bd66b949cb8b6ee6928e9219a5 | glance    | image          |
| 5cc9fc786815469988ba77da7fe7e75d | heat      | orchestration  |
| 5deab7db5d314019a0075520dd03fcb5 | placement | placement      |
| abd1dbf8986c437680a504d903aa8f19 | neutron   | network        |
| b38770841d974f5e9410b292500e034e | heat-cfn  | cloudformation |
| b8b3a864d4b141539aa8daa9f6a6c26b | nova      | compute        |
| bb08a051bfcb4b81b2936f4ec541f3da | keystone  | identity       |
| ce4f0042d0734cb5939e988e0fa3a354 | cinderv3  | volumev3       |
+----------------------------------+-----------+----------------+

설치 완료 후

  • 노트북 환경(192.168.35.x)에 맞춰서 VM이 생성되면 공유기 IP를 할당받고 인터넷을 쓸 수 있도록 설정
  • kolla-ansible이 제공하는 init-runonce(초기화 스크립트)를 집 네트워크에 맞게 수정
  1. 스크립트 위치 찾기
find ~/openstack-venv -name init-runonce
  1. 스크립트 수정
$ vi ~/openstack-venv/share/kolla-ansible/init-runonce

# VM들이 192.168.35.150 ~ 192.168.35.199 범위의 IP를 쓰도록 설정
# 외부 네트워크 구성 (공유기 대역)
EXT_NET_CIDR='192.168.35.0/24'
EXT_NET_RANGE='start=192.168.35.150,end=192.168.35.199'
EXT_NET_GATEWAY='192.168.35.1'


# 수정한 스크립트 실행
# 스크립트가 실행되면서 cirros 이미지를 다운받고 네트워크를 구성한다.
$ cd ~/openstack-venv/share/kolla-ansible/
$ ./init-runonce

  1. VM 생성 및 접속 테스트
# VM 생성
$ openstack server create --image cirros --flavor m1.tiny --key-name mykey --network public1 demo-instance

# 생성 상태 확인 (Status가 ACTIVE고 Networks에 public1=192.168.35.XXX가 보이면 성공)
$ openstack server list

init-runonce가 생성한 기본 구성 확인 방법

# 아래 3가지 목록 중 하나라도 비어 있으면 init-runonce 스크립트가 제대로 안 돈 것.
$ openstack image list
$ openstack network list
$ openstack flavor list
+----+-----------+-------+------+-----------+-------+-----------+
| ID | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |
+----+-----------+-------+------+-----------+-------+-----------+
| 1  | m1.tiny   |   512 |    1 |         0 |     1 | True      |
| 2  | m1.small  |  2048 |   20 |         0 |     1 | True      |
| 3  | m1.medium |  4096 |   40 |         0 |     2 | True      |
| 4  | m1.large  |  8192 |   80 |         0 |     4 | True      |
| 5  | m1.xlarge | 16384 |  160 |         0 |     8 | True      |
| 6  | m2.tiny   |   512 |    1 |         0 |     2 | True      |
+----+-----------+-------+------+-----------+-------+-----------+

SSH 연결 프로그램 새 창에서 서버 접속 후 openstack 명렁어를 내릴 때, 그 창에는 OpenStack 접속 권한이 설정되지 않아서 에러가 발생한다.

source /etc/kolla/admin-openrc.sh

대시보드에서 VM의 콘솔에 접속했을 때, 로그인 창이 안 뜨고 further output written to /dev/ttyS0 가 뜸.

  • 의미 : 화면 출력은 모니터가 아니라 직렬 포트(Serial Console)로 보내겠다.
  • virsh 명령어로 직렬 콘솔 접속 오픈스택이 설치된 서버의 터미널에서 직접 콘솔에 들어가야 한다.
    • Kolla-Ansible 환경에서는 virsh 같은 가상화 관리 명령어가 호스트(Ubuntu)에 직접 설치되지 않고, Docker 컨테이너 안에 들어있다.
      • 즉, nova_libvirt라는 컨테이너 안에서 virsh list를 실행해야 한다.
    # instance-000000xx 형태의 이름을 확인
    # 가장 숫자가 큰 것이 최근에 만든 VM
    sudo docker exec -it nova_libvirt virsh list
    # 직렬 콘솔 접속
    sudo docker exec -it nova_libvirt virsh console instance-00000005

트러블 슈팅

  • 📍Horizon 대시보드에 할당된 IP와 실제 VM의 IP가 다르다.

  • 임시 해결책 : VM 수동 IP 할당
    • DHCP가 안 되므로 수동으로 IP를 할당하면 네트워크 경로(Bridge, OVS) 자체는 살아있기 때문에 통신이 가능하다.
  # 기존 IP 삭제
  sudo ip addr flush dev eth0
  
  # IP 주소 수동 입력
  sudo ip addr add 192.168.35.161/24 dev eth0
  
  # 랜카드 켜기
  sudo ip link set eth0 up
  
  # 기본 게이트웨이 추가
  sudo ip route add default via 192.168.35.1
  
  # DNS 설정
  echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
  • DHCP 문제를 근본적으로 해결하지 않는 한, 앞으로 만드는 VM들도 IP를 자동으로 못 받을 것이다. 새 VM을 만들 때 마다 아래의 과정을 거친다.
    1. 대시보드에서 인스턴스 생성 시 할당된 IP 주소 확인
    2. VM이 켜지면 콘솔로 접속
    3. 위의 명령어를 이용해 VM에 IP를 수동으로 할당
      3-1 cirros / gocubsgo (ID/PW)

  • 새 VM을 만들어서 IP 할당 시 인터넷이 정상적으로 되는지 확인하는 과정에서 데스크탑에서 vm으로 ping은 되나, vm 내에서 인터넷이 안 되는 것을 확인했다.
    • IP를 직접 할당해도 dhcpcd 데몬이 자동으로 IP를 받아오고 있음을 확인했다.
  # 실행 중인 dhcp 관련 프로세스 확인
  ps -ef | grep dhcp
  
  # DHCP 관련 프로세스 강제 종료
  sudo kill -9 250 251 252 253 291

  • 상황 요약

    • 대시보드 : IP가 192.168.35.161로 할당되었다고 나온다.
    • 실제 VM : ip a로 확인해 보면 192.168.35.79와 같이 정해진 대역 밖의 IP가 할당된다.
    • 원인 요약 : Neutron이 할당한 IP가 적용되기 전에, 공유기가 먼저 VM에 IP를 할당함.
    • 원인 분석
      • 현재 환경은 Flat Network (Provider Network)으로, 노트북의 USB 랜카드를 통해 외부 물리 네트워크(192.168.35.0/24)와 VM을 브릿지로 직접 연결한 상태이다.
      • 이 네트워크 안에는 2개의 DHCP 서버가 존재하게 된다.
        • 물리 공유기 : 192.168.35.1
        • 오픈스택 Neutron (qdhcp) : 192.168.35.xxxx
      • VM이 부팅될 때 상황
        • VM이 DHCP Discover 브로드캐스트를 날린다.
        • 이 요청이 브릿지를 타고 물리 네트워크 전체로 퍼진다.
        • Neutron보다 물리 공유기가 더 빨리 DHCP Offer로 응답한다.
        • VM은 먼저 온 응답을 받아 .79로 IP를 세팅한다.
        • Horizon 대시보드는 .161을 할당했으니 정보 불일치가 발생한다.
  • 해결 방안 : VXLAN (Tenant Network) + Floating IP

    • 네트워크 생성 : 192.168.35.x 대역이 아닌 가상의 사설 대역 10.0.0.0/24 로 네트워크를 만든다. (VXLAN)
    • 라우터 생성 : 오픈스택 라우터를 만들고, 외부망(192.168.35.x)과 내부망(10.0.0.x)을 연결한다.
    • Floating IP 할당 : VM은 10.0.0.x IP를 받고, 외부 통신이 필요할 때만 192.168.35.x 대역의 Floating IP를 붙인다.
      • 물리 공유기의 DHCP 패킷이 VM 내부망까지 들어오지 못하므로 충돌이 발생하지 않는다.
  • 아키텍처

    • 외부 네트워크 (External/Provider Network) : 192.168.35.x 대역
    • 내부 네트워크 (Tenant/Private Network) : 10.0.0.x 대역, VM이 생성되고, 이 네트워크는 VXLAN으로 캡슐화되어 있어 물리 공유기는 이 안을 들여다볼 수 없다.
    • 라우터 (Virtual Router) : 내부와 외부를 연결하고, NAT 처리를 담당한다.

  • 해결 과정

    • 외부 네트워크 생성


      • 대시보드 > 관리 > 네트워크 > 네트워크
      • 물리적인 네트워크 : physnet1
        $ sudo grep -r "bridge_mappings" /etc/kolla/neutron-openvswitch-agent/
        /etc/kolla/neutron-openvswitch-agent/openvswitch_agent.ini:bridge_mappings = physnet1:br-ex
      • 외부 네트워크 : 체크
      • Subnet Pools : 192.168.35.200 ~ 192.168.35.240 (=Floating IP)
    • 내부 네트워크 생성

      • 대시보드 > 프로젝트 > 네트워크 > 네트워크
      • 네트워크 이름 : private_net
      • 네트워크 주소 : 10.0.0.0/24
      • 게이트웨이 IP : 10.0.0.1
      • DNS 네임서버 (DHCP 사용 체크) : 8.8.8.8
    • 라우터 생성

      • 프로젝트 > 네트워크 > 라우터
      • 라우터 이름 : router1
      • 외부 네트워크 : ext_net 선택
      • 생성된 router1 클릭 후 인터페이스 > 인터페이스 추가
        • 서브넷 : private_net 선택
    • Floating IP 연결

      • 프로젝트 > 네트워크 > Floating IP > 프로젝트에 IP 할당
        • Pool : ext_net
      • VM의 Actions 버튼 > 유동 IP 연결

학습 1

  • Private IP, Floating IP와 AWS 비교
    • Private_net (10.0.0.x) : AWS의 Private IP (VPC Subnet)와 동일한 개념. 이 IP는 오직 오픈스택 내부의 가상 네트워크 안에서만 유효하며, 물리 네트워크(공유기 대역)는 이 IP의 존재를 알지 못한다.
    • Floating IP (192.168.35.x) : AWS의 Elastic IP와 동일한 역할을 한다.
      • 현재 환경에서 192.168.35.x는 물리 공유기 입장에서는 사설 IP이지만, 오픈스택 입장에서는 공인IP로 간주된다.
      • 실제 인터넷 통신 시 : VM(10.x) -> OpenStack NAT(192.168.35.x) -> 공유기 NAT(공인 IP) -> 인터넷 순으로 2번 NAT가 발생한다.
  • router1의 역할과 연결 목적
    • L3 Routing : 서로 다른 서브넷인 private_net과 ext_net 사이에서 패킷을 라우팅한다.
    • SNAT : VM이 외부로 나갈 때, 출발지 IP를 10.0.0.x에서 라우터의 외부 인터페이스 IP(Gateway IP)로 변환한다. 이것이 없으면 패킷이 인터넷으로 나가도 돌아올 길을 찾지 못한다.
    • DNAT : 외부에서 Floating IP (192.168.35.x)로 들어오는 패킷을 목적지인 VM의 Private IP(10.0.0.x)로 변환한다.
  • VXLAN
    • 스위치는 연결된 모든 VM의 MAC 주소를 학습해야 하는데, VM이 수천 개가 되면 스위치의 MAC Table 용량이 초과된다. VXLAN은 VM의 패킷 전체를 UDP 패킷의 데이터로 감싼다.
    • Overlay Network : 물리 스위치는 겉포장인 VTEP의 IP와 MAC만 보면 되므로, 그 안에 VM이 몇 개가 있든 알 필요가 없다.
  • VTEP (Virtual Tunnel End Point)
    • VTEP : VXLAN 패킷을 캡슐화하고 역캡술화하는 주체
    • 현재 환경애서는 노트북에 설치된 OVS 자체가 VTEP 이다.
      • 정확히는 OVS의 br-tun 혹은 br-int와 연결된 터널 인터페이스가 VTEP IP를 가진다.

  • 네트워크 패킷 흐름 (VM -> 인터넷)
    • VM 내부
      • 패킷 생성 : Src 10.0.0.x, Dst 8.8.8.8
    • Linux Bridge / OVS Bridge (br-int)
      • VM의 vNIC는 호스트의 OVS br-int에 연결되어 있다.
      • 이 단계에서 패킷은 VLAN ID 혹은 Local VLAn Tag가 붙어 내부적으로 구분된다.
    • Router Namespace (qrouter-xxxx)
      • 패킷은 br-int를 타고 가상 라우터(router1)로 들어간다. (이 라우터는 리눅스 Network Namespace로 격리되어 있다.)
      • Routing : 목적지가 외부이므로 Default Gateway로 보낸다.
      • SNAT 수행 : Src IP를 10.0.0.x에서 Floating IP 192.168.35.x로 변환한다.
    • OVS External Bridge (br-ex)
      • NAT가 된 패킷(192.168.35.x -> 8.8.8.8)은 외부망 연결용 브릿지인 br-ex로 전달된다.
    • 물리 인터페이스
      • br-ex는 노트북의 USB 랜카드와 연결되어 있다.
      • 최종적으로 패킷은 일반적인 TCP/IP 패킷 형태로 USB 랜선을 타고 나간다.
    • 📌 VXLAN 네트워크를 만들었지만, 통신의 출발점(VM)과 출구(Router)가 같은 물리 머신 안에 있기 때문에 실제로 랜선을 타고 흐르는 VXLAN 캡슐화(UDP 패킷)는 발생하지 않고 메모리 상에서 처리(OVS Flow)된 후, NAT를 거쳐 일반 패킷으로 나간다. 하지만 논리적으로는 VXLAN ID(VNI)를 통해 완벽하게 격리된 환경이다.

      📌 Wireshark와 같은 프로그램으로 VXLAN(UDP 4789) 패킷을 볼 수 없다.

      • VXLAN은 Host A에서 Host B로 패킷이 넘어갈 때 캡슐화를 한다.
      • 현재 환경은 Compute Node와 Network Node가 동일한 노트북(Localhost)이다.
      • 패킷이 물리 랜선으로 나가기 전에, 내부의 OVS 브릿지에서 이미 역캡슐화와 NAT 처리가 끝난 상태로 ext_net(192.168.35.x)의 일반 패킷으로 변환되어 나간다.
      • 만약 노트북이 2개고, VM이 A노드에서 B노드로 통신한다면, 두 노드를 연결하는 물리 랜선에서 UDP Destination Port 4789로 캡슐화된 패킷을 볼 있다.
  • VTEP(OVS)의 상세 동작과 역캡슐화 메커니즘
    • VTEP은 하드웨어 장비일 수도 있지만, 오픈스택 환경에서는 Open vSwitch의 vxlan 타입 인터페이스가 VTEP 역할을 수행한다.
    • 현재 노트북 환경에서 VTEP
      • OVS 설정 내부에 있는 VXLAN 포트
      • 이 포트는 커널 레벨에서 UDP 포트 4789번(표준 VXLAN 포트)을 리스닝하고 있다.

    • 다른 컴퓨터 노드에서 노트북으로 VXLAN 패킷이 들어온다고 가정했을 때의 처리 과정
      • 1, 물리 계층 수신
        • 노트북의 물리 NIC가 패킷을 수신한다.
        • 패킷 형태 : [Ethernet | IP(Dst=노트북IP) | UDP(4789) | VXLAN(VNI=100) | Inner Ethernet | Inner IP(VM IP)]
      • 2, 커널 네트워킹 스택
        • 리눅스 커널은 Destination Port가 4789(UDP)임을 확인한다.
        • 이 포트는 OVS의 vxlan 모듈이 바인딩하고 있으므로, 커널은 이 패킷을 일반 애플리케이션이 아닌 OVS Datapath로 넘긴다.
      • 3, OVS VXALN Port 진입 (역캡슐화 시작)
        • OVS는 이 패킷이 vxlan 타입의 포트로 들어왔음을 인지한다.
        • 가장 바깥쪽의 Ethernet, Outer IP, UDP, VXLAN Header를 전부 제거한다.
        • VNI 추출 : 제거하기 직전, VXLAN 헤더에 있던 VNI(Virtual Network Identifier) 값을 읽는다.
      • 4, 메타데이터 매핑 (VNI -> Local VLAN)
        • OVS는 전역적으로 쓰이는 VNI 값을 해당 호스트 내부에서만 쓰이는 Local VLAN ID로 변환한다. (이 매핑 테이블은 br-tun에 정의되어 있다.)
        • 이유 : OVS 내부 파이프라인 처리는 VLAN 태그를 기반으로 하는 것이 효율적이기 때문
      • 5, 내부 포워딩
        • 순수한 원본 패킷(Src VM -> Dst VM)만 남은 상태
        • OVS는 이 패킷에 내부 VLAN 태그를 붙여 br-int로 보낸다.
        • br-int는 목적지 VM이 연결된 포트(Tap interface)를 찾아 패킷을 밀어 넣는다.
      • 6, VM 수신
        • VM의 가상 NIC로 패킷이 들어온다. VM은 자신이 캡슐화되었던 사실을 모른다.

학습 2

kolla-ansible로 OpenStack을 배포했을 때, docker ps 명령으로 볼 수 있는 실행 중인 컨테이너에서 keepalivedhaproxy 컨테이너에 대해 간단 학습

  • keepalived
    • 리눅스 시스템에서 VRRP (Virtual Router Redundancy Protocol) 프로토콜을 구현한 데몬이다. 핵심 기능은 고가용성을 위해 IP 주소(VIP)의 생명주기를 직접 관리하는 것이다.
  • keepalived가 하는 일
    • VRRP 패킷 전송 : 클러스터 내의 다른 노드들과 멀티캐스트 패킷을 주고받으며 자신이 살아있음을 알린다. (Master/Backup 선출)
    • IP 주소 할당/해제 : 자신이 Master 상태가 되면, 시스템의 네트워크 인터페이스에 VIP를 동적으로 추가(ip addr add)한다. 반대로 장애가 발생하거나 Backup 상태가 되면 VIP를 인터페이스에서 삭제(ip addr del)한다.
    • ARP 브로드캐스트 : VIP가 특정 MAC 주소(자신의 랜카드)에 위치함을 알리기 위해 Gratuitous ARP 패킷을 네트워크에 뿌려 갱신한다.
  • globals.yml 파일에서 kolla_internal_vip_address를 물리 IP인 .100으로 설정하면 안 되는 이유
    • 만약 VIP를 물리 IP인 .100으로 설정하면 OS의 네트워크 관리자(Netplan/NetworkManager)와 keepalived 간에 제어권 충돌이 발생한다.
      • IP 삭제 위험 : Keepalived가 재시작되거나 초기화될 때, 혹은 Backup 상태로 전환될 때 자신이 관리하는 VIP(.100)를 정리하면서 ip addr del 192.168.35.100 명령을 실행해버릴 수 있다.
      • 네트워크 단절 : 물리 IP가 삭제되면 SSH 세션을 포함한 서버의 모든 네트워크 연결이 즉시 끊긴다.
      • ARP 충돌 : OS는 물리 IP가 고정되어 있다고 생각하는데, Keepalived는 이를 VRRP 로직에 따라 제어하려 하므로 네트워크 스위치나 라우터 입장에서 해당 IP의 MAC 주소 매핑이 불안정해진다.
    • 따라서 VIP는 물리적인 인터페이스에 종속되지 않은, 별도의 독립된 IP(.200)여야 Keepalived가 안전하게 붙였다 떼었다(Floating) 할 수 있다.

  • haproxy
    • TCP/HTTP 로드밸런서 및 리버스 프록시.
    • 오픈스택의 모든 API 서비스 앞단에 위치하여 트래픽을 받아 백엔드 컨테이너로 분배한다.
    • 즉, 8888(Horizon), 5000(Keystone) 등의 포트를 열고(Listen), 들어온 트래픽을 내부의 실제 서비스 컨테이너로 로드밸런싱한다.

0개의 댓글