OpenStack이란
OpenStack이란 분산된 컴퓨팅, 네트워크, 스토리지 리소스 풀을 관리하고, API나 대시보드를 통해 가상화된 리소스를 On-Demand로 사용할 수 있도록 하는 오픈소스 클라우드 컴퓨팅 플랫폼입니다.
가장 성공한 오픈소스SW 프로젝트 중 하나이며, 각각 다른 역할을 수행하는 여러 개의 서비스(OSS)로 나뉘어 구성되기 때문에 요구사항에 따라 필요한 서비스만을 선택하여 최적의 플랫폼을 구축할 수 있습니다.
리눅스와 가상화, 클라우드에 대해 관심을 갖고 학습하는 과정에서 자연스럽게 오픈스택에 대해 관심이 생기게 되었고, 실제로 클라우드 시스템이 어떤 과정과 원리로 구축되는지 이해하고 그 과정에서 리눅스와 가상화, 네트워크 등에 대한 이해를 높이고자 OpenStack을 이용해 로컬 환경에 클라우드 시스템을 수동으로 구축해보게 되었습니다.
OpenStack을 이용한 클라우드 시스템 구축 과정
처음엔 PackStack을 이용해 빠르게 오픈스택을 설치 및 배포한 뒤 Nova와 Neutron과 같은 필수 서비스에 대해 학습하여 오픈스택 구성 요소들에 대한 이해를 높인 후 수동 구축에 도전하고자 하였으나, 대부분의 자료가 CentOS 7 기준으로 작성되어 최신 버전인 RHEL9과 CentOS Stream 9에서 PackStack을 사용해 오픈스택을 구축하는 방법에 대한 자료가 부족했고, 일부 자료를 보고 따라해봐도 올바르게 구축되지 않았습니다.
오픈스택의 서비스들과 구축 방법에 대한 지식이 아예 없는 상태에서 이러한 에러의 이유를 찾기는 힘들었고, 차라리 처음부터 수동으로 오픈스택 구축을 실습하며 오픈스택의 서비스들과 구축 방법에 대한 이해를 높이는 것이 낫겠다고 생각하게 되었습니다.
그러나 오픈스택의 아키텍처나 서비스들에 대한 이해없이 공식 문서만 보고 수동으로 구축하기에는 트러블 슈팅이 너무 어려워 헤매던 중, 과학기술 정보통신부 및 정보통신기획평가원의 'SW중심대학사업' 지원을 받아 제작된 "[2024] OpenStack을 이용한 클라우드 시스템 구축" 영상을 Youtube에서 찾게 되어 해당 영상을 참고해 성공적으로 오픈스택을 이용해 로컬 환경에 클라우드 시스템을 구축해볼 수 있었습니다.
오픈스택 구축에 어려움을 겪는 분들이나 추후에 다시 수동으로 구축해야 하는 경우를 위해, 시스템 구축 과정과 제가 이해한 내용에 대해 작성하게 되었습니다.
1. 환경 구성
PC: macOS (Sequoia 15.0.1), 6 core CPU (Intel Core i7), 16GB RAM
VirtualBox VM: 4 core CPU, 6 GB RAM, 40 GB Storage
Linux: Ubuntu 22.04.5
OpenStack: 2023.1 (Antelope)
VM으로 controller, compute 노드를 생성한 뒤 각각 NAT 네트워크의 10.0.0.11, 10.0.0.31 IP address를 할당하였고, 네트워킹 옵션 중 Self-Service Networks를 선택하여 다음 이미지와 같이 가상 네트워크 구현 작업을 처리하는 network agents가 별도의 네트워크 노드가 아닌 컨트롤러 노드에 위치하도록 Core component들을 각 노드에 설치 및 배포하였습니다.
네트워크 설정
공유기 네트워크: 192.168.10.0/24 (Gateway: 192.168.10.254)
NAT 네트워크: 10.0.0.0/24
HOST IP 주소: 192.168.10.106
Controller 노드 IP 주소: 10.0.0.11
Compute 노드 IP 주소: 10.0.0.31
VirtualBox에서 NAT 네트워크를 만든 뒤 각 노드의 어댑터 1(enp0s3)에 연결해주었고,
어댑터 2(enp0s8)에는 어댑터에 브리지를 선택해 연결하여 가상 머신이 호스트의 네트워크 장치를 통해 Provider network와 통신이 가능하도록 설정했습니다.
이후 다음과 같이 netplan을 수정하고 변경된 네트워크 설정을 적용하였고,
cat << EOF > /etc/netplan/00-installer-config.yaml
network:
ethernets:
enp0s3:
addresses: [10.0.0.11/24]
routes:
- to: default
via: 10.0.0.1
nameservers:
addresses: [8.8.8.8]
enp0s8:
dhcp4: no
dhcp6: no
version: 2
EOF
sudo netplan apply
보안을 위해 ssh의 포트를 7890으로 변경한 후, NAT 네트워크에 포트포워딩 규칙을 추가하여 호스트에서 ssh로 VM에 접속할 수 있도록 설정했습니다.
최종 네트워크 구성은 다음과 같습니다.
환경 구성
위와 같은 네트워크 구성을 갖는 controller 노드와 compute 노드에 ssh로 접근하여 오픈스택 구축을 위해 필요한 환경을 구성하였고, 모든 명령은 root 권한으로 실행하였고 비밀번호를 설정해야 하는 경우에는 모두 "openstack"으로 비밀번호를 설정했습니다.
호스트나 노드의 사양과 네트워크 구성, OS와 각종 도구들의 버전이 다를 경우 그에 맞게 값을 변경하여 환경을 구성해야 합니다.
Controller 노드:
1. 미러 사이트 설정 (선택)
미러 사이트는 특정 웹사이트의 내용을 복제하여 다른 서버에 저장해 놓은 사이트입니다. 원본 서버의 부하를 분산하고, 사용자에게 더 빠른 속도로 콘텐츠를 제공하기 위해 사용됩니다. 특히, 소프트웨어 다운로드, ISO 이미지 등 대용량 파일을 다운로드할 때 미러 사이트를 활용하면 더욱 효율적입니다.
cd /etc/apt
cp sources.list sources.list.v1
sed -i 's/http:\/\/kr.archive.ubuntu.com/https:\/\/ftp.kaist.ac.kr/g' /etc/apt/sources.list
apt update
2. Time Zone 설정
timedatectl set-timezone Asia/Seoul
timedatectl
3. 커널 버전 자동 업데이트 금지, 보안 업데이트 자동 수행 (선택)
apt-mark hold $(uname -r)
apt install unattended-upgrades
dpkg-reconfigure unattended-upgrades
4. nfs 설정 (선택)
controller와 compute 노드 간 파일 공유를 위해 nfs를 통해 /nfs 디렉토리를 공유하도록 설정했습니다.
apt install -y nfs-kernel-server nfs-common
mkdir -p /nfs/
chown nobody:nogroup /nfs
echo "/nfs 10.0.0.0/24(rw,all_squash,sync,no_subtree_check)" >> /etc/exports
exportfs -avr
showmount -e
5. /etc/hosts 수정
vi /etc/hosts
위와 같이 controller에 루프백 주소 대신 NAT 네트워크에서 controller 노드에 할당된 IP 주소를 매핑하고, compute 노드의 호스트 네임과 compute 노드에 할당된 IP 주소를 매핑해주었습니다.
Compute 노드:
controller 노드를 복제하여 compute 노드를 만든 뒤,
hostnamectl을 이용해 호스트 네임을 compute로 변경하고,
netplan을 수정하여 compute 노드에 10.0.0.31 IP 주소를 할당하고, NAT 네트워크에 포트포워딩 규칙을 추가해주었습니다.
이후 compute 노드의 /nfs 디렉토리에 controller 노드의 /nfs 디렉토리를 마운트하였고,
echo "10.0.0.11:/nfs /nfs nfs noauto 0 0" >> /etc/fstab
mount /nfs
mount -l | grep nfs
ping을 이용해 controller와 compute 노드 간 통신이 가능한 것을 확인하였습니다.
6. NTP 설정
controller 노드:
apt install chrony -y
echo "allow 10.0.0.0/24" >> /etc/chrony/chrony.conf
systemctl restart chrony
compute 노드:
apt install chrony -y
vi /etc/chrony/chrony.conf
# server controller iburst를 추가한 후, pool로 시작하는 줄을 모두 삭제
systemctl restart chrony
7. OpenStack 패키지 (공통)
repository 추가
add-apt-repository cloud-archive:antelope
apt update
클라이언트 설치
apt install python3-openstackclient -y
8. SQL 데이터베이스
대부분의 OpenStack 서비스는 SQL 데이터베이스를 사용하여 정보를 저장합니다. 데이터베이스는 일반적으로 컨트롤러 노드에서 실행됩니다.
apt install mariadb-server python3-pymysql -y
cat << EOF > /etc/mysql/mariadb.conf.d/99-openstack.cnf
[mysqld]
bind-address = 10.0.0.11
default-storage-engine = innodb
innodb_file_per_table = on
max_connections = 4096
collation-server = utf8_general_ci
character-set-server = utf8
EOF
service mysql restart
mysql_secure_installation
# 모두 디폴트 설정 값을 사용하기 위해 enter만 입력하였고, root password는 openstack으로 설정하였음.
9. 메시지 큐
OpenStack은 메시지 큐를 사용하여 서비스 간의 작업과 상태 정보를 조정합니다. 메시지 큐 서비스는 일반적으로 컨트롤러 노드에서 실행됩니다.
apt install rabbitmq-server -y
# rabbitmqctl add_user openstack RABBIT_PASS
rabbitmqctl add_user openstack openstack
rabbitmqctl set_permissions openstack ".*" ".*" ".*"
10. Memcached
서비스에 대한 Identity 서비스 인증 메커니즘은 Memcached를 사용하여 토큰을 캐시합니다. Memcached 서비스는 일반적으로 컨트롤러 노드에서 실행됩니다
apt install memcached python3-memcache -y
vi /etc/memcached.conf
# -l 127.0.0.1를 -l 10.0.0.11로 변경
systemctl restart memcached
11. etcd
OpenStack 서비스는 분산 키 잠금, 구성 저장, 서비스 활성 상태 추적 및 기타 시나리오를 위해 etcd를 사용합니다.
apt install etcd -y
cp /etc/default/etcd /etc/default/etcd.backup
cat << EOF > /etc/default/etcd
ETCD_NAME="controller"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-01"
ETCD_INITIAL_CLUSTER="controller=http://10.0.0.11:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.0.0.11:2379"
EOF
systemctl enable etcd
systemctl restart etcd
12. 위 과정을 모두 진행한 뒤, systemctl status --all로 실패한 서비스가 있는지 확인하여 환경 구성을 마무리하였습니다.
2. Minimal deployment
OpenStack 시스템은 별도로 설치된 몇 가지 주요 서비스로 구성되어 있습니다. 이러한 서비스는 클라우드 요구 사항에 따라 함께 작동하며 Compute, Identity, Networking, Image, Block Storage, Object Storage, Telemetry, Orchestration 및 Database 서비스를 포함합니다.
이러한 개별 OpenStack 서비스 중, 오픈스택 플랫폼이 클라우드 시스템으로서 동작하기 위해 필요한 최소한의 서비스를 설치하였습니다.
기본적으로는 공식 문서를 보며 설치를 진행하였고,
트러블 슈팅이나 공식 문서만으로는 이해하기 힘든 부분은 과학기술 정보통신부 및 정보통신기획평가원의 'SW중심대학사업' 지원을 받아 제작된 "[2024] OpenStack을 이용한 클라우드 시스템 구축" 영상을 보며 진행하였습니다.
기본적으로 오픈스택 서비스의 설치 및 구성은 다음과 같은 과정으로 모두 비슷하게 진행됩니다.
1. 데이터베이스 생성 및 권한 부여
2. 사용자 및 엔드포인트 구성
3. 패키지 설치 및 설정 파일 수정
4. DB, 서비스 초기화
5. (일부) Apache HTTP 서버 설정
6. 서비스 동작 확인
서비스의 설정 파일 수정 시 백업 파일을 만들어 놓는 것이 좋고, 중간에 실수할 경우 트러블 슈팅이 어렵고 오래 걸리므로 실수하지 않게 공식 문서를 꼼꼼히 읽으며 진행해야 합니다.
- Keystone
Keystone은 OpenStack 클라우드 환경에서 인증과 권한 관리를 담당하는 핵심 서비스로, OpenStack의 다른 서비스들에 대한 API 요청을 중앙에서 관리하고 인증 및 권한 검사를 수행합니다.
사용자, 프로젝트, 서비스 등 다양한 엔티티(entity)에 대한 인증을 수행하여 접근 권한을 부여하고, 각 사용자와 프로젝트에 대한 권한을 정의하고 관리하며, 허용된 작업 범위를 제한합니다.
1. 데이터베이스 생성 및 권한 부여
mysql
CREATE DATABASE keystone;
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \
IDENTIFIED BY 'openstack';
2. 패키지 설치 및 설정 파일 수정
설정 파일 수정하는 부분은 제가 공식 문서를 보며 수정한 후 제대로 동작하는 것을 확인한 설정으로 설정 파일을 덮어쓰도록 작성하였습니다.
따라서 단순히 구축해보는 것이 목표가 아니라면 각 설정의 의미를 파악하며 공식 문서를 보고 직접 수정해보는 것이 좋을 것 같습니다.
apt install keystone -y
cat << EOF > /etc/keystone/keystone.conf
[DEFAULT]
log_dir = /var/log/keystone
[database]
connection = mysql+pymysql://keystone:openstack@controller/keystone
[token]
provider = fernet
EOF
3. DB, 서비스 초기화 및 엔드포인트 구성
su -s /bin/sh -c "keystone-manage db_sync" keystone
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
keystone-manage credential_setup --keystone-user keystone --keystone-group keystone
keystone-manage bootstrap --bootstrap-password openstack \
--bootstrap-admin-url http://controller:5000/v3/ \
--bootstrap-internal-url http://controller:5000/v3/ \
--bootstrap-public-url http://controller:5000/v3/ \
--bootstrap-region-id RegionOne
4. Apache HTTP 서버 설정
echo "ServerName controller" >> /etc/apache2/apache2.conf
systemctl restart apache2
5. 서비스 동작 확인
cat << EOF > admin-openrc
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
EOF
. admin-openrc
openstack domain create --description "An Example Domain" example
openstack project create --domain default \
--description "Service Project" service
- Glance
Glance란 OpenStack 클라우드 환경에서 가상 머신 이미지를 관리하는 서비스입니다.
1. 데이터베이스 생성 및 권한 부여
mysql
CREATE DATABASE glance;
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \
IDENTIFIED BY 'openstack';
2. 사용자 및 엔드포인트 구성
. admin-openrc
openstack user create --domain default --password-prompt glance
# User Password: openstack
openstack role add --project service --user glance admin
openstack service create --name glance \
--description "OpenStack Image" image
openstack endpoint create --region RegionOne \
image public http://controller:9292
openstack endpoint create --region RegionOne \
image internal http://controller:9292
openstack endpoint create --region RegionOne \
image admin http://controller:9292
3. 패키지 설치 및 설정 파일 수정
apt install glance -y
cat << EOF > /etc/glance/glance-api.conf
[DEFAULT]
[database]
connection = mysql+pymysql://glance:openstack@controller/glance
[glance_store]
stores = file,http
default_store = file
filesystem_store_datadir = /var/lib/glance/images/
[file]
disk_formats = ami,ari,aki,vhd,vhdx,vmdk,raw,qcow2,vdi,iso,ploop.root-tar
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = glance
password = openstack
[paste_deploy]
flavor = keystone
EOF
4. DB, 서비스 초기화
su -s /bin/sh -c "glance-manage db_sync" glance
service glance-api restart
5. 서비스 동작 확인
. admin-openrc
wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img
glance image-create --name "cirros" \
--file cirros-0.4.0-x86_64-disk.img \
--disk-format qcow2 --container-format bare \
--visibility=public
glance image-list
- Placement
Placement는 OpenStack 클라우드 환경에서 컴퓨팅 자원(CPU, 메모리, 디스크 등)을 할당하는 과정을 최적화하는 서비스입니다. 즉, 새로운 인스턴스(가상 머신)가 생성될 때, 어떤 컴퓨트 노드에 할당해야 가장 효율적인지 결정하는 역할을 수행합니다.
1. 데이터베이스 생성 및 권한 부여
mysql
CREATE DATABASE placement;
GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \
IDENTIFIED BY 'openstack';
2. 사용자 및 엔드포인트 구성
. admin-openrc
openstack user create --domain default --password-prompt placement
# User Password: openstack
openstack role add --project service --user placement admin
openstack service create --name placement \
--description "Placement API" placement
openstack endpoint create --region RegionOne \
placement public http://controller:8778
openstack endpoint create --region RegionOne \
placement internal http://controller:8778
openstack endpoint create --region RegionOne \
placement admin http://controller:8778
3. 패키지 설치 및 설정 파일 수정
apt install placement-api -y
cat << EOF > /etc/placement/placement.conf
[DEFAULT]
[placement_database]
connection = mysql+pymysql://placement:openstack@controller/placement
[api]
auth_strategy = keystone
[keystone_authtoken]
auth_url = http://controller:5000/v3
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = placement
password = openstack
EOF
4. DB, 서비스 초기화
su -s /bin/sh -c "placement-manage db sync" placement
service apache2 restart
5. 서비스 동작 확인
. admin-openrc
placement-status upgrade check
- Nova
Nova란 OpenStack 클라우드 플랫폼에서 가상 서버를 생성, 관리하는 컴퓨팅 서비스입니다. 마치 물리적인 서버를 관리하는 것처럼, Nova를 통해 가상 머신(VM)을 쉽게 생성하고, 시작, 중지, 재부팅 등 다양한 작업을 수행할 수 있습니다.
Controller 노드:
1. 데이터베이스 생성 및 권한 부여
mysql
CREATE DATABASE nova_api;
CREATE DATABASE nova;
CREATE DATABASE nova_cell0;
GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \
IDENTIFIED BY 'openstack';
2. 사용자 및 엔드포인트 구성
. admin-openrc
openstack user create --domain default --password-prompt nova
# User Password: openstack
openstack role add --project service --user nova admin
openstack service create --name nova \
--description "OpenStack Compute" compute
openstack endpoint create --region RegionOne \
compute public http://controller:8774/v2.1
openstack endpoint create --region RegionOne \
compute internal http://controller:8774/v2.1
openstack endpoint create --region RegionOne \
compute admin http://controller:8774/v2.1
3. 패키지 설치 및 설정 파일 수정
apt install nova-api nova-conductor nova-novncproxy nova-scheduler -y
cat << EOF > /etc/nova/nova.conf
[DEFAULT]
lock_path = /var/lock/nova
state_path = /var/lib/nova
transport_url = rabbit://openstack:openstack@controller:5672/
my_ip = 10.0.0.11
[api]
auth_strategy = keystone
[api_database]
connection = mysql+pymysql://nova:openstack@controller/nova_api
[database]
connection = mysql+pymysql://nova:openstack@controller/nova
[glance]
api_servers = http://controller:9292
[keystone_authtoken]
www_authenticate_uri = http://controller:5000/
auth_url = http://controller:5000/
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = nova
password = openstack
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
[placement]
region_name = RegionOne
project_domain_name = Default
project_name = service
auth_type = password
user_domain_name = Default
auth_url = http://controller:5000/v3
username = placement
password = openstack
[service_user]
send_service_user_token = true
auth_url = http://controller:5000/
auth_strategy = keystone
auth_type = password
project_domain_name = Default
project_name = service
user_domain_name = Default
username = nova
password = openstack
[vnc]
enabled = true
server_listen = 10.0.0.11
server_proxyclient_address = 10.0.0.11
[cells]
enable = False
[os_region_name]
openstack = RegionOne
EOF
4. DB, 서비스 초기화
su -s /bin/sh -c "nova-manage api_db sync" nova
su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova
su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova
su -s /bin/sh -c "nova-manage db sync" nova
service nova-api restart
service nova-scheduler restart
service nova-conductor restart
service nova-novncproxy restart
5. 서비스 동작 확인
su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova
Compute 노드:
패키지 설치 및 설정 파일 수정
#apt-get update
apt install nova-compute -y
cat << EOF > /etc/nova/nova.conf
[DEFAULT]
log_dir = /var/log/nova
lock_path = /var/lock/nova
state_path = /var/lib/nova
transport_url = rabbit://openstack:openstack@controller
my_ip = 10.0.0.31
[api]
auth_strategy = keystone
[api_database]
connection = sqlite:////var/lib/nova/nova_api.sqlite
[database]
connection = sqlite:////var/lib/nova/nova.sqlite
[glance]
api_servers = http://controller:9292
[keystone_authtoken]
www_authenticate_uri = http://controller:5000/
auth_url = http://controller:5000/
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = nova
password = openstack
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
[placement]
region_name = RegionOne
project_domain_name = Default
project_name = service
auth_type = password
user_domain_name = Default
auth_url = http://controller:5000/v3
username = placement
password = openstack
[service_user]
send_service_user_token = true
auth_url = http://controller:5000/
auth_strategy = keystone
auth_type = password
project_domain_name = Default
project_name = service
user_domain_name = Default
username = nova
password = openstack
[vnc]
enabled = true
server_listen = 0.0.0.0
server_proxyclient_address = 10.0.0.31
novncproxy_base_url = http://controller:6080/vnc_auto.html
[cells]
enable = False
[os_region_name]
openstack = RegionOne
EOF
cat << EOF > /etc/nova/nova-compute.conf
[DEFAULT]
compute_driver=libvirt.LibvirtDriver
[libvirt]
virt_type=qemu
EOF
service nova-compute restart
Controller 노드:
셀 데이터베이스에 컴퓨트 노드 추가
. admin-openrc
openstack compute service list --service nova-compute
# compute 호스트 검색
su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova
# 자동 compute 호스트 검색 interval 설정
# vi /etc/nova/nova.conf 후 다음의 2줄 추가
# [scheduler]
# discover_hosts_in_cells_interval = 300
- Neutron
Neutron은 OpenStack 클라우드 환경에서 가상 네트워크를 생성하고 관리하는 서비스입니다. 마치 물리적인 네트워크 장비를 사용하여 네트워크를 구성하듯이, Neutron을 통해 가상 네트워크, 서브넷, 라우터 등을 생성하고 관리하여 가상 머신들이 서로 통신할 수 있도록 합니다.
Controller 노드:
1. 데이터베이스 생성 및 권한 부여
mysql
CREATE DATABASE neutron;
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \
IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \
IDENTIFIED BY 'openstack';
2. 사용자 및 엔드포인트 구성
. admin-openrc
openstack user create --domain default --password-prompt neutron
# User Password: openstack
openstack role add --project service --user neutron admin
openstack service create --name neutron \
--description "OpenStack Networking" network
openstack endpoint create --region RegionOne \
network public http://controller:9696
openstack endpoint create --region RegionOne \
network internal http://controller:9696
openstack endpoint create --region RegionOne \
network admin http://controller:9696
3. 패키지 설치 및 설정 파일 수정
apt install neutron-server neutron-plugin-ml2 \
neutron-openvswitch-agent neutron-l3-agent neutron-dhcp-agent \
neutron-metadata-agent -y
cat << EOF > /etc/neutron/neutron.conf
[DEFAULT]
core_plugin = ml2
service_plugins = router
transport_url = rabbit://openstack:openstack@controller
auth_strategy = keystone
notify_nova_on_port_status_changes = true
notify_nova_on_port_data_changes = true
[agent]
root_helper = "sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf"
[database]
connection = mysql+pymysql://neutron:openstack@controller/neutron
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = neutron
password = openstack
[nova]
auth_url = http://controller:5000
auth_type = password
project_domain_name = Default
user_domain_name = Default
region_name = RegionOne
project_name = service
username = nova
password = openstack
[oslo_concurrency]
lock_path = /var/lib/neutron/tmp
EOF
cat << EOF > /etc/neutron/plugins/ml2/ml2_conf.ini
[DEFAULT]
[ml2]
type_drivers = flat,vlan,vxlan
tenant_network_types = vxlan
mechanism_drivers = openvswitch,l2population
extension_drivers = port_security
[ml2_type_flat]
flat_networks = provider
[ml2_type_vxlan]
vni_ranges = 1:1000
EOF
ovs-vsctl add-br br-provider
ovs-vsctl add-port br-provider enp0s8
cat << EOF > /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[ovs]
bridge_mappings = provider:br-provider
local_ip = 10.0.0.11
[agent]
tunnel_types = vxlan
l2_population = True
[securitygroup]
enable_security_group = true
firewall_driver = openvswitch
#firewall_driver = iptables_hybrid
EOF
cat << EOF > /etc/neutron/l3_agent.ini
[DEFAULT]
interface_driver = openvswitch
EOF
cat << EOF > /etc/neutron/dhcp_agent.ini
[DEFAULT]
interface_driver = openvswitch
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
enable_isolated_metadata = true
EOF
cat << EOF > /etc/neutron/metadata_agent.ini
[DEFAULT]
nova_metadata_host = controller
metadata_proxy_shared_secret = openstack
EOF
cat << EOF >> /etc/nova/nova.conf
[neutron]
auth_url = http://controller:5000
auth_type = password
project_domain_name = Default
user_domain_name = Default
region_name = RegionOne
project_name = service
username = neutron
password = openstack
service_metadata_proxy = true
metadata_proxy_shared_secret = openstack
EOF
4. DB, 서비스 초기화
su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \
--config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
service nova-api restart
service neutron-server restart
service neutron-openvswitch-agent restart
service neutron-dhcp-agent restart
service neutron-metadata-agent restart
service neutron-l3-agent restart
5. 서비스 동작 확인
systemctl status --all
Compute 노드:
패키지 설치 및 설정 파일 수정
apt install neutron-openvswitch-agent -y
cat << EOF > /etc/neutron/neutron.conf
[DEFAULT]
core_plugin = ml2
transport_url = rabbit://openstack:openstack@controller
auth_strategy = keystone
[agent]
root_helper = "sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf"
[database]
#connection = sqlite:////var/lib/neutron/neutron.sqlite
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
auth_url = http://controller:5000
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = neutron
password = openstack
[oslo_concurrency]
lock_path = /var/lib/neutron/tmp
EOF
ovs-vsctl add-br br-provider
ovs-vsctl add-port br-provider enp0s8
cat << EOF > /etc/neutron/plugins/ml2/openvswitch_agent.ini
[DEFAULT]
[ovs]
bridge_mappings = provider:br-provider
local_ip = 10.0.0.31
[agent]
tunnel_types = vxlan
l2_population = True
[securitygroup]
enable_security_group = true
firewall_driver = openvswitch
#firewall_driver = iptables_hybrid
EOF
cat << EOF >> /etc/nova/nova.conf
[neutron]
auth_url = http://controller:5000
auth_type = password
project_domain_name = Default
user_domain_name = Default
region_name = RegionOne
project_name = service
username = neutron
password = openstack
EOF
서비스 재시작
service nova-compute restart
service neutron-openvswitch-agent restart
- Horizon
Horizon은 OpenStack 클라우드 플랫폼을 사용자 친화적인 웹 인터페이스를 통해 관리할 수 있도록 해주는 서비스입니다. Horizon을 통해 클라우드 환경의 다양한 자원(가상 서버, 네트워크, 스토리지 등)을 직관적으로 생성, 관리, 모니터링 할 수 있습니다.
1. 패키지 설치 및 설정 파일 수정
cd /var/www
git clone https://opendev.org/openstack/horizon -b stable/2023.1 --depth=1
cd horizon
wget https://opendev.org/openstack/requirements/raw/branch/stable/2023.1/upper-constraints.txt
sed -i '/horizon/d' upper-constraints.txt
apt install python3-pip apache2 libapache2-mod-wsgi-py3 -y
sudo pip3 install -c upper-constraints.txt .
cp openstack_dashboard/local/local_settings.py.example openstack_dashboard/local/local_settings.py
vi openstack_dashboard/local/local_settings.py
# 다음 내용을 추가 또는 수정, ALLOWED_HOSTS의 두번째 주소는 본인 host의 IP 주소로 수정
# WEBROOT = "/horizon/"
# ALLOWED_HOSTS = ['10.0.0.11','192.168.10.106', ]
# OPENSTACK_HOST = "10.0.0.11:5000"
# TIME_ZONE = "Asia/Seoul"
# CACHES = {
# 'default': {
# 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
# 'LOCATION': '10.0.0.11:11211',
# },
# }
sudo apt install gettext
./manage.py compilemessages
./manage.py collectstatic
# yes
./manage.py compress --force
2. 서비스 배포
./manage.py make_web_conf --wsgi
./manage.py make_web_conf --apache > /etc/apache2/sites-available/horizon.conf
cat << EOF > /etc/apache2/sites-available/horizon.conf
<VirtualHost *:80>
ServerAdmin webmaster@openstack.org
ServerName openstack_dashboard
DocumentRoot /var/www/horizon/
LogLevel warn
ErrorLog /var/log/apache2/openstack_dashboard-error.log
CustomLog /var/log/apache2/openstack_dashboard-access.log combined
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^/$ /horizon/ [R=301,L]
WSGIScriptReloading On
WSGIDaemonProcess openstack_dashboard_website processes=5
WSGIProcessGroup openstack_dashboard_website
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIScriptAlias /horizon /var/www/horizon/openstack_dashboard/horizon_wsgi.py
<Location "/horizon">
Require all granted
</Location>
Alias /horizon/static /var/www/horizon/static
<Location "/horizon/static">
SetHandler None
</Location>
</Virtualhost>
EOF
sudo a2ensite horizon
sudo a2enmod rewrite
sudo service apache2 restart
a2dissite 000-default
systemctl reload apache2
chown www-data:www-data /var/www/horizon/ -R
3. 서비스 동작 확인
NAT 네트워크에 포트포워딩 규칙 추가한 후,
웹 브라우저를 통해 dashboard에 접근할 수 있습니다.
3. Instance 생성 및 테스트
가상 네트워크 생성
인스턴스가 네트워크를 통해 다른 인스턴스나 외부 네트워크와 통신하기 위해서는 먼저 위와 같이 인스턴스 간의 통신을 위한 Self-service virtual network와 인스턴스와 외부 네트워크 간 통신을 위한 Provider virtual network를 만들어야 합니다.
프로젝트->네트워크->네트워크로 이동한 후, 네트워크 생성 버튼을 통해 가상 네트워크를 생성할 수 있습니다.
먼저 다음과 같이 admin.internal 네트워크(Self-service virtual network)에 8.8.8.8을 DNS 네임 서버로 설정하고 admin.subnet(172.16.0.0/24)을 생성한 뒤,
관리->네트워크->네트워크로 이동해 Provider virtual network를 만들었습니다.
VM 외부의 Provider Physical network를 공유할 수 있도록 다음과 같이 공유기 네트워크 설정에 맞춰 서브넷을 설정했습니다.
이제 Self-service virtual network를 통해 해당 네트워크에 속한 인스턴스 간에는 통신이 가능하며, 공유기 네트워크를 통해 외부 네트워크와 통신이 가능한 Provider virtual network를 생성하였으므로, Floating IP를 할당받은 뒤 이를 인스턴스에 연결한다면 해당 인스턴스는 외부와의 통신이 가능합니다.
그러나 외부 네트워크 통신을 위해 이러한 방법을 사용한다면 인스턴스가 공유기로부터 직접 IP 주소를 할당받아서 사용하는 것이기 때문에, 공유기 네트워크를 사용하는 다양한 기기들과 공유기의 한정적인 IP를 공유한다는 문제가 있으며, 인스턴스 수가 크게 늘어난다면 유의미한 문제가 발생할 수 있습니다.
따라서 Provider virtual network와 Self-service virtual network를 가상 라우터로 연결한 뒤, 가상라우터의 NAT 포트포워딩 설정을 통해 외부 네트워크와 인스턴스를 연결하는 것이 일반적으로 더 좋은 방법이라 볼 수 있습니다.
이를 위해 다음과 같이 외부 네트워크를 Provider virtual network로 설정하여 가상 라우터를 생성하고, (자동으로 외부 네트워크(provider) 쪽의 인터페이스가 추가됨)
가상 내부 네트워크(admin.internal) 쪽의 인터페이스를 추가해준 뒤,
다음과 같은 네트워크 토폴로지를 확인할 수 있었습니다.
Instance 생성
인스턴스를 생성하기 위해서는 먼저 인스턴스가 사용할 Flavor와 이미지가 필요합니다.
따라서 관리->Compute->Flavor로 이동하여, admin 프로젝트에서 사용하기 위해 다음과 같은 사양의 Flavor를 생성하였고,
인스턴스가 사용할 Ubuntu 이미지를 생성한 뒤,
cd /nfs
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
. admin-openrc
openstack image create --file noble-server-cloudimg-amd64.img --progress --public --disk-format qcow2 ubuntu.24.04.image
해당 Flavor와 이미지를 사용해 인스턴스를 생성하였습니다.
참고) 인스턴스 생성 시, 키 페어를 생성해야 ssh로 인스턴스에 접근할 수 있습니다. 특히 인스턴스 생성에 사용한 기본 우분투 이미지에는 기본 패스워드가 없기 때문에 키 페어로만 로그인이 가능합니다.
인스턴스가 외부 네트워크로 접근은 가능하지만 host PC에서 인스턴스에 ssh로 접근하기 위해서는 2가지 설정이 추가로 필요합니다.
먼저 보안 그룹 규칙 수정이 필요합니다.
위와 같이 default 보안 그룹은 모든 ip 주소와 포트에 대해 outbound traffic을 허용하지만 inbound traffic은 default 보안 그룹에서의 traffic만 허용합니다.
따라서 기존의 inbound traffic에 대한 규칙을 삭제한 후 모든 경로(또는 host IP 주소)에서의 traffic을 허용하는 규칙을 추가해주어야 합니다.
만약 floating IP를 인스턴스에 연결한다면 보안 그룹 규칙 수정만으로도 host에서 인스턴스로 접근이 가능하나, Provider virtual network와 가상 라우터로 연결된 Self-service virtual network의 IP 주소만 할당된 인스턴스에 host에서 접근하고 싶다면 가상 라우터와 게이트웨이에 대해 iptables로 포트포워딩을 설정해야합니다.
# controller 노드에서 수행
# 라우터 이름 확인
ip netns
# 게이트웨이 이름 확인
ip netns exec {router-name} ifconfig
# iptables로 가상 라우터에 포트포워딩 규칙 추가
sudo ip netns exec $router iptables -A PREROUTING -t nat -i $gateway -p tcp --dport 22136 -j DNAT --to 20.0.0.136:22
위 설정을 완료한 후, 인스턴스 생성 시 사용한 키 페어를 이용해 provider나 NAT 네트워크의 노드에서 ssh로 오픈스택 인스턴스에 접근할 수 있습니다.
트러블 슈팅
인스턴스 콘솔
인스턴스 콘솔 접근 시 다음과 같이 제대로 동작하지 않는 것을 확인할 수 있습니다.
horizon 대시보드의 인스턴스 콘솔을 사용하기 위해서는 다음과 같이 compute의 /etc/nova/nova.conf 파일의 novncproxy_base_url의 controller 부분을 host의 IP 주소로 수정해준 뒤 서비스를 재시작하고,
NAT 네트워크 (Management)에 다음과 같이 포트포워딩 규칙을 추가해주어야 합니다.
horizon dashboard
openstack cli를 이용할 때는 정상 동작하지만 horizon dashboard에서는 각 서비스에 대해 제대로 접근하지 못하는 오류가 있었습니다.
다음과 같이 하나의 오픈스택 서비스에 대해 동일한 이름으로 여러개의 서비스를 생성했을 경우 발생함을 확인하였고, 특히 그 중 엔드포인트가 없는 서비스를 선택해 horizon이 접근하는 경우 발생했습니다.
따라서 중복된 서비스 중 엔드포인트가 없는 서비스를 삭제하여 해결할 수 있었습니다.
이외에도 크고 작은 오류들이 많이 발생했으나 어려운 오류들은 상기한 영상을 참고해 해결할 수 있었고, 대부분의 작은 오류들은 /var/log의 에러 로그들을 확인하며 트러블 슈팅할 수 있었습니다.
회고
처음엔 오픈스택과 이를 구성하는 기본적인 서비스들에 대해 핵심적인 지식과 기술만 학습하려 하였으나, 구축 과정에서부터 어려움을 겪게 되었고 다행히 참고할 수 있는 자료를 찾게 되어 오픈스택을 이용해 수동으로 클라우드 시스템을 구축해볼 수 있었습니다.
물론 공식 문서에 수동 구축 과정이 상세히 설명되어 있으나 오픈스택을 처음 접하는 사람이 공식 문서만을 보고 구축하긴 힘들 것이라 생각합니다.
이러한 이유로 글을 작성하게 되었고, 작성 과정에서 영상을 보며 따라해볼 때와는 다르게 자잘한 오류들이 많이 발생하여 이를 해결하며 리눅스와 네트워크, 오픈스택과 오픈소스SW에 대해 좀 더 이해할 수 있는 경험이 되었습니다.
앞으로 오픈스택, 구축에 사용되는 다양한 OSS의 버전이 업데이트 되면서 이번 구축 과정에서는 경험하지 못한, 예상치 못한 오류들이 발생할 것이라 생각합니다. 그러나 이 경험을 바탕으로 공식문서를 포함한 다양한 자료들을 활용한다면 충분히 이를 해결하고 성공적으로 구축할 수 있을 것이라 생각합니다.
다음으로는 원래 목표했던 것처럼 Nova, Neutron 등 오픈스택의 필수 서비스들에 대해 더 학습하고, 구축 과정에서 사용된 도구들과 이러한 도구들이 내부적으로 어떤 방식으로 동작하여 가상 네트워크와 인스턴스를 생성하는지에 대해 더 학습해야겠다고 느끼게 되었습니다.
참고자료
https://docs.openstack.org/install-guide/
https://www.openstack.org/software/
https://docs.openstack.org/neutron/2023.1/admin/deploy-ovs-selfservice.html
박현찬. [전북대학교 SW중심대학사업단]. (2024, 10). [2024] OpenStack을 이용한 클라우드 시스템 구축. YouTube. https://www.youtube.com/playlist?list=PLpiZz61rRNHXfCQC2-wfINlW9iO2PeOT7
'Cloud engineering' 카테고리의 다른 글
Kernel of Linux 정리 - Introduction (0) | 2024.12.16 |
---|---|
리눅스 기본 요소들을 이용해 Pod 생성하기 (0) | 2024.11.09 |
kubeadm으로 구축한 쿠버네티스 클러스터에 모니터링 시스템 구축하기 (0) | 2024.10.15 |
kubeadm으로 구축한 쿠버네티스 환경에서 GitOps 구축하기 (2) | 2024.10.08 |
kubeadm 이용해 K8s cluster 구축하기 (3) | 2024.09.30 |