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

KH55S·2026년 2월 9일

OpenStack Project

목록 보기
7/8
  • 원래의 계획은 여러 개의 네트워크를 생성하고 라우터를 생성하여 연결 후,
  • Octavia 로드밸런서를 통해 인스턴스간 부하 분산이 동작하는 것을 확인하려고 했다.
  • 하지만 로드밸런서가 생성되지 않아, 네트워크만 생성하고 네트워크간 통신 과정을 세부적으로 확인하고자 한다.

로드밸런서 서비스를 위한 Octavia 설치

  • /etc/kolla/globals.yml 파일을 수정하여 옥타비아 서비스를 활성화
    enable_octavia: "yes"

  • Octavia 인증서 생성
    • 옥타비아는 컨트롤러와 부하 부산 장치(Amphora VM) 간의 보안 통신을 위해 전용 인증서가 필요하다.

      Octavia 인증서가 필요한 이유

      • Amphora VM : 로드밸런서 생성을 요청하면 옥타비아는 사용자의 네트워크 안에 작은 가상 머신 Amphora를 자동으로 생성한다.
      • 옥타비아 컨트롤러는 이 가상 머신에 명령을 내려 로드밸런싱 설정을 주입한다. 이때 해킹이나 변조를 막기 위해 상호 TLS(mTLS) 인증서를 사용하여 통신한다.
      • 이 인증서가 없으면 Octavia 서비스 자체가 정상적으로 구동되지 않으며, 서비스 카탈로그 등록도 실패할 수 있다.
    • 인벤토리 파일(all-in-one / multinode)이 있는 위치에서 실행 (홈 디렉토리 or /etc/kolla/)
    $ kolla-ansible -i all-in-one octavia-certificates

  • 옥타비아 배포
     $ kolla-ansible -i all-in-one deploy --tags octavia

  • 서비스 카탈로그를 조회하여 옥타이아 서비스가 정상적으로 등록되었는지 확인
    (openstack-venv) root@khsubuntuserver:/home/khs$ source /etc/kolla/admin-openrc.sh
    (openstack-venv) root@khsubuntuserver:/home/khs$ openstack service list | grep load-balancer
    | edf062b16f9e402dad50d19a6b37d6ed | octavia   | load-balancer  |
    • 동작 : openstack service list를 입력하면, CLI 도구는 현재 셸에 설정된 OS_AUTH_URL로 가서 토큰을 받아온 뒤, Keystone에 현재 이 클라우드에서 운영 중인 모든 서비스 목록을 보여달라고 요청한다.
    • 확인 대상 : 출력 결과에 load-balancer (octavia)가 있다는 것은, Keystone에 로드밸런서 요청이 들어오면 Octavia API로 보내라는 기록이 정상적으로 등재되었음을 뜻한다.

admin-openrc.sh

  • 이 파일은 오픈스택 명령어가 Keystone에 접속할 때 필요한 자격 증명(credentials) 정보를 담고 있는 셸 스크립트이다.
  • 파일 내부를 cat 명령어로 열어보면 다음과 같은 변수들이 정의되어 있다.
    • OS_AUTH_URL: Keystone 서비스의 주소 (예: http://192.168.35.200:5000)
    • OS_PROJECT_NAME: 명령을 수행할 프로젝트 이름 (예: admin)
    • OS_USERNAME / OS_PASSWORD: 접속할 사용자 이름과 비밀번호
    • OS_INTERFACE: API 통신 시 사용할 인터페이스 타입 (public, internal 등)

    source 명령어 사용 이유
  • 리눅스에서 셸 스크립트를 그냥 실행(./script.sh)하는 것과 source (또는 .) 명령어로 실행하는 것은 차이가 있다.
    • 일반 실행 : 새로운 자식 셸을 하나 띄워서 실행한다. 스크립트가 끝나면 그 안에서 설정된 변수들은 자식 셸과 함께 사라진다. 현재 타이핑하고 있는 셸에는 영향을 주지 못한다.
    • source 실행 : 스크립트의 내용을 현재 내가 사용 중인 셸에서 그대로 읽어 들인다. 파일 안에 적힌 export OS_USERNAME=admin 같은 명령어가 현재 세션에 즉시 적용되어, 이후에 입력하는 모든 오픈스택 명렁어들이 이 정보를 참조할 수 있게 된다.

  • Amphora 이미지 다운로드 및 Glance 등록
    • Amphora(암포라) 이미지 : 사용자 네트워크 안에 아주 작은 VM을 띄우고, 그 안에 HAProxy를 설치하여 실제 로드밸런싱 기능을 수행하게 한다.

    • 일반적인 OS 이미지가 아니라, Octavia 컨트롤러와 통신할 수 있는 에이전트(octavia-amphora-agent)가 포함된 특수 제작 이미지여야 한다.

    • 미리 빌드된 이미지 다운로드 및 Glance에 이미지 등록

      $ wget https://nbg1.your-objectstorage.com/osism/openstack-octavia-amphora-image/octavia-amphora-haproxy-2024.2.qcow2
      
      # 인증 정보 로드
      $ ource /etc/kolla/admin-openrc.sh
      
      # Glance에 이미지 등록 (태그를 'amphora'로 지정해야 옥타비아가 인식함)
      $ openstack image create "amphora-image" \
         --file amphora-x64-haproxy.qcow2 \
         --disk-format qcow2 \
         --container-format bare \
         --tag amphora \
         --private
         
         
       # globals.yml에서 옥타비아가 어떤 이미지를 사용할지 명시
       octavia_amp_image_tag: "amphora"

네트워크 생성

  • shared / client / application / database

  • 대시보드로 shared / client 네트워크 생성 과정


  • CLI로 application / database 네트워크 생성 과정
    • 라우터 생성 및 각 네트워크 연결
# Application 네트워크
openstack network create application_net
openstack subnet create --network application_net \
  --subnet-range 172.20.20.0/24 \
  --gateway 172.20.20.1 \
  application_subnet
+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2026-02-23T07:47:00Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | f71c1b5f-a229-4980-b188-fd1266b4411e |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | False                                |
| is_vlan_qinq              | None                                 |
| is_vlan_transparent       | None                                 |
| mtu                       | 1450                                 |
| name                      | application_net                      |
| port_security_enabled     | True                                 |
| project_id                | 74a6815c3ca94e32a06ef3e4bd86c9db     |
| provider:network_type     | vxlan                                |
| provider:physical_network | None                                 |
| provider:segmentation_id  | 702                                  |
| qos_policy_id             | None                                 |
| revision_number           | 1                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      |                                      |
| updated_at                | 2026-02-23T07:47:00Z                 |
+---------------------------+--------------------------------------+
+----------------------+--------------------------------------+
| Field                | Value                                |
+----------------------+--------------------------------------+
| allocation_pools     | 172.20.20.2-172.20.20.254            |
| cidr                 | 172.20.20.0/24                       |
| created_at           | 2026-02-23T07:47:01Z                 |
| description          |                                      |
| dns_nameservers      |                                      |
| dns_publish_fixed_ip | None                                 |
| enable_dhcp          | True                                 |
| gateway_ip           | 172.20.20.1                          |
| host_routes          |                                      |
| id                   | 7cd763b8-ae60-4c89-8c54-f212f5fb7d7c |
| ip_version           | 4                                    |
| ipv6_address_mode    | None                                 |
| ipv6_ra_mode         | None                                 |
| name                 | application_subnet                   |
| network_id           | f71c1b5f-a229-4980-b188-fd1266b4411e |
| project_id           | 74a6815c3ca94e32a06ef3e4bd86c9db     |
| revision_number      | 0                                    |
| segment_id           | None                                 |
| service_types        |                                      |
| subnetpool_id        | None                                 |
| tags                 |                                      |
| updated_at           | 2026-02-23T07:47:01Z                 |
+----------------------+--------------------------------------+  

# Database 네트워크
openstack network create database_net
openstack subnet create --network database_net \
  --subnet-range 172.20.30.0/24 \
  --gateway 172.20.30.1 \
  database_subnet


=================================================

# App 라우터 설정 (Client <-> App)
openstack router create app_router
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| admin_state_up          | UP                                   |
| availability_zone_hints |                                      |
| availability_zones      |                                      |
| created_at              | 2026-02-23T07:51:11Z                 |
| description             |                                      |
| distributed             | False                                |
| enable_ndp_proxy        | None                                 |
| external_gateway_info   | null                                 |
| flavor_id               | None                                 |
| ha                      | False                                |
| id                      | 27040221-d293-4572-9feb-bd22033f7257 |
| name                    | app_router                           |
| project_id              | 74a6815c3ca94e32a06ef3e4bd86c9db     |
| revision_number         | 1                                    |
| routes                  |                                      |
| status                  | ACTIVE                               |
| tags                    |                                      |
| updated_at              | 2026-02-23T07:51:11Z                 |
+-------------------------+--------------------------------------+
openstack router add subnet app_router application_subnet

# Client 네트워크 쪽 인터페이스 연결
openstack port create --network client_net app_router_client_port
openstack router add port app_router app_router_client_port



# DB 라우터 설정 (App <-> DB)
openstack router create db_router
openstack router add subnet db_router database_subnet

# Application 네트워크 쪽 인터페이스 연결
openstack port create --network application_net db_router_app_port
openstack router add port db_router db_router_app_port

=================================================

# Destination Subnet(172.20.20.0/24)에 대한 Next-hop 인터페이스(172.20.10.153) 지정
openstack router set --route destination=172.20.20.0/24,gateway=172.20.10.153 main_router
# Destination Subnet(172.20.30.0/24)에 대한 Next-hop 인터페이스(172.20.10.153) 지정
openstack router set --route destination=172.20.30.0/24,gateway=172.20.10.153 main_router

# 최하단 Database 서브넷(30.0/24) 도달을 위해 인접 라우터(db_router)의 ingress IP를 Gateway로 설정
openstack router set --route destination=172.20.30.0/24,gateway=172.20.20.215 app_router

# 하위 계층에서 상위 172.20.0.0/16 대역 및 인터넷 게이트웨이 방향으로의 경로 회신(Return) 설정
openstack router set --route destination=172.20.0.0/16,gateway=172.20.10.1 app_router
# 최하단 계층에서 상위 계층으로의 패킷 포워딩을 위해 상위 인터페이스(172.20.20.1)를 Gateway로 지정
openstack router set --route destination=172.20.0.0/16,gateway=172.20.20.1 db_router




$ traceroute 172.20.30.1
traceroute to 172.20.30.1 (172.20.30.1), 30 hops max, 60 byte packets
 1  host-172-20-10-1.openstacklocal (172.20.10.1)  0.239 ms  0.202 ms  0.126 ms
 2  host-172-20-10-153.openstacklocal (172.20.10.153)  1.489 ms  1.445 ms  1.410 ms
 3  172.20.30.1 (172.20.30.1)  1.375 ms  1.370 ms  1.339 ms
 
# 172.20.30.102 DB 네트워크에 속한 인스턴스의 IP
$ traceroute 172.20.30.102
traceroute to 172.20.30.102 (172.20.30.102), 30 hops max, 60 byte packets
 1  host-172-20-10-1.openstacklocal (172.20.10.1)  0.160 ms  0.144 ms  0.133 ms # main_router
 2  host-172-20-10-153.openstacklocal (172.20.10.153)  0.703 ms  0.722 ms  0.710 ms # app_router
 3  172.20.20.215 (172.20.20.215)  0.921 ms  0.912 ms  0.898 ms # db_router의 ingress IP
 4  172.20.30.102 (172.20.30.102)  1.283 ms  1.289 ms  1.297 ms # DB 인스턴스
  • 첫번째 명령의 결과 값에서 3번 홉에 172.20.30.1이 바로 나타나고 db_router의 중간 인터페이스 IP(172.20.20.215)가 생략된 이유
    • traceroute는 패킷의 TTL 값을 1씩 증가시키며 전송하고, 각 라우터가 패킷을 폐기할 때 보내는 ICMP Time Exceeded 메시지를 수집한다.
      • Hop 1 (172.20.10.1) : main_router가 패킷을 수신하고 TTL을 0으로 판단하여 응답한다.
      • Hop 2 (172.20.10.153) : app_router의 수신 인터페이스(Ingress Interface)가 패킷을 수신하고 TTL을 0으로 판단하여 응답한다.
      • Hop 3 (172.20.30.1) : app_router가 TTL 3인 패킷을 수신한 후, 라우팅 테이블을 참조하여 db_router(172.20.20.215)로 포워딩한다. 이때 db_router 입장에서 목적지 IP인 172.20.30.1은 자신의 Directly Connected Subnet에 속한 로컬 인터페이스 주소이다.

    • traceroute 결과에서 중간 IP인 172.20.20.215가 나타나려면, 목적지 IP가 172.20.30.1이 아닌 그보다 더 하위에 있는 별도의 인스턴스 IP(예: 172.20.30.x)여야한다.

    • 라우팅 이론상, 패킷의 목적지 IP 주소가 라우터가 직접 보유한 인터페이스 IP와 일치할 경우, 해당 라우터는 더 이상 TTL 값을 검사하거나 감소시키지 않고 패킷의 최종 수신자(Destination Host)로서 동작한다.
      • db_router는 172.20.30.1 이라는 IP를 실제로 소유하고 있는 장치이다.
      • 패킷이 db_router에 도착했을 때, 목적지 IP가 자기 자신이므로 TTL 기반의 Time Exceeded를 보내는 것이 아니라 최종 목적지로서 ICMP Echo Reply를 생성하여 즉시 응답한다.
      • 이 과정에서 172.20.20.215를 거치는 경로는 내부적인 포워딩 과정일 뿐, 외부로 노출되는 Hop으로 계산되지 않는다.

트러블 슈팅

  • 옥타비아 서비스 배포 과정에서 발생한 에러
$ kolla-ansible -i all-in-one deploy --tags octavia

TASK [include_role : octavia] ******************************************************************************************************************************************************************************
ERROR! couldn't resolve module/action 'firewalld'. This often indicates a misspelling, missing collection, or incorrect module path.
The error appears to be in '/home/khs/openstack-venv/share/kolla-ansible/ansible/roles/haproxy-config/tasks/main.yml': line 55, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: "Configuring firewall for {{ project_name }}"
  ^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
    with_items:
      - {{ foo }}
Should be written as:
    with_items:
      - "{{ foo }}"
  • 원인 : Ansible이 firewalld 모듈을 찾지 못함
    • kolla-ansible이 옥타비아와 HAProxy 관련 설정을 진행하면서 호스트의 방화벽을 제어하려고 시도하는데, 현재 Ansible 환경에 ansible.posix 컬렉션(firewalld 모듈이 포함됨)이 설치되어 있지 않아 발생
  • 해결
    • firewalld 모듈이 포함된 ansible.posix 컬렉션 설치
      ansible-galaxy collection install ansible.posix

  • 프로비저닝 상태가 생성 대기중 상태로 유지되며 로드밸런서가 생성되지 않는다.
    • 문제 확인 과정
      • Octavia는 로드밸런서를 만들 때 백엔드에서 Amphora라는 별도의 VM을 자동으로 생성하는데, 이름이 amphora-xxx인 인스턴스가 자동으로 생성되지 않음을 확인
    • Octavia 서비스 로그 확인
      • 컨테이너 정상 실행 및 에러 없음
# Octavia 서비스 로그 확인
$ docker logs octavia_worker
+ sudo -E kolla_set_configs
INFO:__main__:Loading config file at /var/lib/kolla/config_files/config.json
INFO:__main__:Validating config file
INFO:__main__:Kolla config strategy set to: COPY_ALWAYS
INFO:__main__:Copying service configuration files
INFO:__main__:Copying /var/lib/kolla/config_files/octavia.conf to /etc/octavia/octavia.conf
INFO:__main__:Setting permission for /etc/octavia/octavia.conf
INFO:__main__:Copying /var/lib/kolla/config_files/client.cert-and-key.pem to /etc/octavia/certs/client.cert-and-key.pem
INFO:__main__:Setting permission for /etc/octavia/certs/client.cert-and-key.pem
INFO:__main__:Copying /var/lib/kolla/config_files/client_ca.cert.pem to /etc/octavia/certs/client_ca.cert.pem
INFO:__main__:Setting permission for /etc/octavia/certs/client_ca.cert.pem
INFO:__main__:Copying /var/lib/kolla/config_files/server_ca.cert.pem to /etc/octavia/certs/server_ca.cert.pem
INFO:__main__:Setting permission for /etc/octavia/certs/server_ca.cert.pem
INFO:__main__:Copying /var/lib/kolla/config_files/server_ca.key.pem to /etc/octavia/certs/server_ca.key.pem
INFO:__main__:Setting permission for /etc/octavia/certs/server_ca.key.pem
INFO:__main__:Writing out command to execute
++ cat /run_command
+ CMD='octavia-worker --config-file /etc/octavia/octavia.conf'
+ ARGS=
+ sudo kolla_copy_cacerts
+ [[ ! -n '' ]]
+ . kolla_extend_start
++ set -o errexit
++ OCTAVIA_LOG_DIR=/var/log/kolla/octavia
++ [[ ! -d /var/log/kolla/octavia ]]
+++ stat -c %U:%G /var/log/kolla/octavia
++ [[ octavia:kolla != \o\c\t\a\v\i\a\:\k\o\l\l\a ]]
+++ stat -c %a /var/log/kolla/octavia
++ [[ 2755 != \7\5\5 ]]
++ chmod 755 /var/log/kolla/octavia
++ . /usr/local/bin/kolla_octavia_extend_start
+ echo 'Running command: '\''octavia-worker --config-file /etc/octavia/octavia.conf'\'''
Running command: 'octavia-worker --config-file /etc/octavia/octavia.conf'
+ exec octavia-worker --config-file /etc/octavia/octavia.conf
Deprecated: Option "endpoint_type" from group "neutron" is deprecated for removal (This option was replaced by the valid_interfaces option defined by keystoneauth.).  Its value may be silently ignored in the future.
Deprecated: Option "ca_certificates_file" from group "neutron" is deprecated for removal (The cafile option defined by keystoneauth1 is the new name for this option.).  Its value may be silently ignored in the future.
  • amphora Flavor 확인 및 lb-mgnt-net 네트워크 확인
$ openstack flavor list | grep amphora
결과 없음

$ openstack network list | grep lb-mgmt-net
| 81fd0f08-0d82-4177-98f2-c3b792f59b50 | lb-mgmt-net         | e214b7a5-e1f0-425e-bf4f-4e5275f6b358 |
  • 원인

    • amphora라는 이름의 Flavor가 없어서 Octavia가 VM을 생성하지 못하고 있다.

      • Octavia는 기본 설정상 amphora라는 이름을 가진 사양을 사용하여 관리용 VM를 띄운다. 이 사양이 없으면 Nova에 요청을 보내지 못한다.
    • openstack flavor create --id auto --ram 1024 --disk 5 --vcpus 1 amphora 명령으로 Octavia 전용 사양을 만들려고 시도했으나 amphora Flavor가 이미 존재한다고 나온다.

    • 이미 존재하는 amphora 사양의 상세 정보 확인

      $ openstack flavor show amphora
      +----------------------------+--------------------------------------+
      | Field                      | Value                                |
      +----------------------------+--------------------------------------+
      | OS-FLV-DISABLED:disabled   | False                                |
      | OS-FLV-EXT-DATA:ephemeral  | 0                                    |
      | access_project_ids         | []                                   |
      | description                | None                                 |
      | disk                       | 5                                    |
      | id                         | 6b27f648-e418-47b5-abe7-bbae0de91157 |
      | name                       | amphora                              |
      | os-flavor-access:is_public | False                                |
      | properties                 |                                      |
      | ram                        | 1024                                 |
      | rxtx_factor                | 1.0                                  |
      | swap                       | 0                                    |
      | vcpus                      | 1                                    |
      +----------------------------+--------------------------------------+  
      
      # os-flavor-access:is_public 값이 False로 되어있다.
      # 비공개(private) 사양으로 설정되어 있어서
      # Octavia 서비스 계정이 이 사양에 접근하지 못해 VM을 생성하지 못하는 상황.
    • 기존 사양 삭제 및 재생성

        $ openstack flavor delete amphora
        $ openstack flavor create --ram 1024 --disk 5 --vcpus 1 --public amphora
        +----------------------------+--------------------------------------+
        | Field                      | Value                                |
        +----------------------------+--------------------------------------+
        | OS-FLV-DISABLED:disabled   | False                                |
        | OS-FLV-EXT-DATA:ephemeral  | 0                                    |
        | description                | None                                 |
        | disk                       | 5                                    |
        | id                         | 3e37257f-ec2a-4d50-96e7-e950c92cbc61 |
        | name                       | amphora                              |
        | os-flavor-access:is_public | True                                 |
        | properties                 |                                      |
        | ram                        | 1024                                 |
        | rxtx_factor                | 1.0                                  |
        | swap                       | 0                                    |
        | vcpus                      | 1                                    |
        +----------------------------+--------------------------------------+
      

  • 대시보드에서 LB 생성 과정 캡쳐

0개의 댓글