프로젝트 좀보이드(Project Zomboid) 서버 고도화② - Openstack 클러스터 구축
서버 구축기
이번 시간에는 openstack 클러스터를 설치해보기로 하겠다.
당직(当職)의 서버 컴퓨터의 사양은 대략 이러하다.
- CPU: AMD Ryzen R5 3600x(6Core)
- RAM: DDR4 32GB
- SSD: Samsung 512GB(PM9A1, PCIe 4.0)
- OS: Rocky Linux 9.7
Openstack 운영 환경은 보통 콘트롤러 노드용 컴퓨터 3개, 콤퓨트 노드용 컴퓨터를 1개 이상 두는데, 지금은 그럴 시간과 돈이 들지 않으니 한 컴퓨터에 콘트롤러와 콤퓨트를 모두 설치하기로 한다.
본 작업은 Rocky 9.7 최소 설치를 전제로 하고 있다.
번외-콘트롤러를 3개 놓는 이유
쉽게 말하면 다수결 원칙이다.
콘트롤러 노드는 보통 대장 역할을 수행하는 놈이 하나 있고(마스터), 나머지들이 이를 따르는 식으로 진행된다.
근데 만일 이 대장이 다른 콘트롤러와 연결이 끊기면? 남은 콘트롤러 노드는 “아이고, 대장과 연락이 안 되네. 이제부터 내가 대장이다”라고 결정해버린다.
문제는 연결이 끊긴 대장도 자기 나름대로 “어? 부하들이랑 연락이 안 되네. 나라도 계속 명령을 내려야지”라고 생각한다는 것이다. 이렇게 되면 클러스터 안에 대장이 두 명이 되어버려서 서로 다른 명령을 내리게 될 수 있다.
이렇게 되면, 전체 시스템 입장에선 누구 말을 들어야 할지 몰라 데이터가 완전히 꼬여버릴 것이다.
그래서 다수결 원칙이 적용되는 것이다. 만일 콘트롤러가 2개면, 서로 통신이 안 될 때 남은 1대만으로는 전체의 과반수를 넘기지 못한다.
결국 2개 노드 모두 자신이 대장인지 확신할 수 없으니, 데이터가 꼬이는 대참사를 막기 위해 서로 스스로 멈춰버린다.
즉, 장애에 대비하려고 이중화를 했는데 정작 1대만 통신이 끊겨도 시스템 전체가 멈춰버리는 것이다.
하지만 3대, 즉 홀수로 구성하면 떨어져 나간 대장은 “나 혼자니까 과반수(3대 중 최소 2대)가 안 되네. 내가 가짜일 수 있으니 가만히 있어야겠다”라며 스스로 멈춰버린다.
반면 아직 연결되어 있는 2대는 “우리가 2명이니까 과반수가 넘네! 우리가 다수결로 이겼으니 새로 대장을 뽑고 계속 일하자!”라고 판단하여 시스템을 계속 운영하게 된다.
결론적으로, 서버 1대가 완전히 고장 나거나 통신이 끊기는 상황을 버텨내면서도 데이터가 꼬이지 않게 방어할 수 있는 최소한의 다수결 머릿수가 바로 ‘3명’이므로 콘트롤러를 최소 3개 이상 홀수 개로 구성하는 것이 되겠다.
참고로 이는 당연하겠지만, 쿠버네티스 마스터 노드에도 적용되는 원칙이다.
사전 작업
방화벽 열기
ssh 원격 접속을 위해, 10022 포트를 방화벽에서 열고, sshd 설정에서 접속 포트를 22번에서 10022번에서 바꾸기로 한다.
1
2
# 방화벽에서 10022 포트 접속 허용
firewall-cmd --permanent --zone=public --add-port=10022/tcp
1
2
3
4
5
# Rocky Linux이기 때문에 SELINUX에 등록도 필요
semanage port -a -t ssh_port_t -p tcp 10022
# 만약 semanage 명령어가 없다 하면 아래 항목 설치
dnf install policycoreutils-python-utils -y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# sshd 설정 수정
vi /etc/ssh/sshd_config
...
# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
Port 10022 # 이 부분 22에서 10022로 변경
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
...
systemctl resatrt sshd
IP 고정
호스트를 껐다 켰을 때 IP가 맘대로 바뀌면(DHCP) 안 되니까, IP를 수동으로 지정해 줘야 한다.
당직의 컴퓨터는 KT 공유기에 묶여있어서, 기본 내부 IP 대역은 172.30.1.0/24, 게이트웨이는 172.30.1.254이다.
여기서는 호스트 IP를 172.30.1.86으로 하는 것으로 가정하겠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
nmcli connection show
# enp..., eth... 로 시작하는 것이 인터페이스명
# IP 정보 수정
nmcli connection modify <인터페이스명> ipv4.addresses 172.30.1.86/24
nmcli connection modify <인터페이스명> ipv4.gateway 172.30.1.254
nmcli connection modify <인터페이스명> ipv4.dns "168.126.63.1 8.8.8.8"
nmcli connection modify <인터페이스명> ipv4.method manual
# 인터페이스 재시작
nmcli connection up <인터페이스명>
# 바뀐 IP 확인
ip a
호스트네임 설정
rabbitmq 등 openstack에서 사용하는 요소들이 호스트네임을 기반으로 통신하는 경우가 많아서, 지정해주기로 한다. 여기서는 controller라고 하기로 가정.
1
2
3
4
5
6
7
8
9
# 현재 호스트네임 변경
hostnamectl set-hostname controller
# 영구 반영
vi /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.30.1.86 controller # 이 항목 추가
SELINUX 정책 변경 및 NTP 동기화
SELINUX로 인해 프로세스가 막히지 않도록 enforcing(정책 위배시 차단) 모드에서 permissive(정책 위배시 로그만 남김)으로 변경하고, 시간 오류 방지를 위해 타임서버와 동기화시켜주기로 한다.
1
2
3
4
5
6
7
8
9
10
11
12
# 지금 Permissive로 변경
setenforce 0
# 영구 반영
vi /etc/selinux/config
...
# To revert back to SELinux enabled:
#
# grubby --update-kernel ALL --remove-args selinux
#
SELINUX=permissive # 이 부분 변경
...
1
2
3
dnf install chrony -y
systemctl enable --now chronyd
chronyc sources
openstack repository 및 클라이언트 설치
사전 준비가 완료되었다. 이제 openstack 요소들을 설치하기 위한 레포지토리를 등록하자.
openstack의 버전은 현재 가장 많이 쓰이는 caracal 버전을 기준으로 한다.(2024.01 LTSC)
1
2
dnf config-manager --set-enabled crb
dnf install -y centos-release-openstack-caracal
openstack 명령어를 실행하기 위한 openstack 클라이언트도 설치해 준다.
1
2
dnf update -y
dnf install -y python3-openstackclient
db 설치
지난 시간에서 openstack의 모든 상태 관리는 db에서 한다 했으므로 db 설치는 필수이다.
보통은 mariadb(mysql의 오픈소스 포크 버젼)를 사용하니 mariadb를 설치해 주자.
1
dnf install -y mariadb mariadb-server python3-PyMySQL
설치가 완료되면 mariadb에 openstack 전용 설정 파일을 만들어 준다. mariadb의 설정 파일은 /etc/my.cnf.d에 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# my.cnf.d 아래 cnf 파일을 생성해 설정을 구분할 수 있음
# 실제 설정 파일인 /etc/my.cnf가 my.cnf.d 안에 있는 항목들을 읽어들이는 것
vi /etc/my.cnf.d/openstack.cnf
[mysqld]
bind-address = 172.30.1.86 # 호스트 IP
default-storage-engine = innodb # 가장 안정적인 innodb로 사용
innodb_file_per_table = on
max_connections = 4096
collation-server = utf8_general_ci
character-set-server = utf8
# 저장(:wq)한 뒤 mariadb 활성화
systemctl enable --now mariadb
rabbitmq 설치
지난 시간에서 openstack 요소 간 통신은 메세지 큐를 통해 한다 했으므로 mq 설치도 필수이다.
보통은 rabbitmq를 사용하므로 rabbitmq도 설치해 주자.
1
2
dnf install -y rabbitmq-server
systemctl enable --now rabbitmq-server
openstack이 사용할 rabbitmq 계정을 생성하고 권한을 부여해야 한다.
여기서는 rabbitmq를 포함, 모든 openstack 요소들의 비밀번호를 openstack으로 통일하겠다.
1
2
rabbitmqctl add_user openstack openstack # id openstack, pw openstack
rabbitmqctl set_permissions openstack ".*" ".*" ".*" # 모든 권한(읽쓰실) 부여
keystone 설치와 구성
openstack 요소 중 가장 먼저 설치해야할 것은 keystone이다.
메모리 캐쉬 서버 설치
memcached는 메모리 기반 캐쉬 서버로, keystone이 각 요소들에게 발행하는 토큰을 임시로 저장하는 곳이다.
없어도 되지만, 그럼 keystone이 db, 즉 보조기억장치에서 직접 받아오게 되므로 병목이 생기게 된다.
1
dnf install -y memcached python3-memcached
1
2
3
4
5
6
7
8
9
10
vi /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1,172.30.1.86" # 이 부분에 호스트 IP를 추가
# 저장한 뒤 memcached 활성화
systemctl enable --now memcached
keystone 설치
드디어 openstack의 첫 요소, keystone을 설치한다.
keystone을 가장 먼저 설치하는 이유는 지난번에 말했듯이, Openstack의 모든 요소는 keystone을 통해 서로의 신원을 파악하기 때문이다.
keystone을 설치하지 않고 nova나 neutron을 설치하면 통신할 때,
“우리가 같은 클러스터에 속하는 게 맞아?”를 확인하지 못하는 상호 불신 상황이 생겨버린다.
openstack은 고깔해파리에 비유했듯이, 각자 자기 일만 하는 객체들이 서로 상부상조하면서 하나의 시스템을 이루는 것이다.
(이를 고상한 말로 MSA(마이크로-서비스 아키텍춰)라고 한다)
따라서 ‘개인주의’를 지향하는 요소들이 ‘같은 시스템에 속하는 게 맞는 것인지’를 확인하기 위한 최소한의 장치가 keystone인 것이다.
Keystone DB 생성
openstack의 모든 구성 요소 정보는 db를 통해 이루어진다 했으므로,
keystone을 포함 각 요소를 설치할 때는 가장 먼저 db에 해당 테이블을 생성해야 한다.
1
2
# root 계정으로 db 접속: mariadb는 mysql과 호환되므로 mysql 명령어를 사용
mysql -u root
1
2
3
4
5
CREATE DATABASE keystone;
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'openstack';
FLUSH PRIVILEGES;
exit;
(sql은 한 줄씩 실행하세요~)
IDENTIFIED BY '' 부분의 ’‘은 DB의 비밀번호를 뜻한다.
앞서 말했듯이 모든 요소의 비밀번호는 openstack으로 통일한다 했으므로 openstack~
keystone용 db가 생성되었으면, keystone을 설치해 준다!
keystone은 아파치 웹 서버에서 작동하는 python 어플리케이션이기 때문에, httpd와 WSGI(웹 서버 게이트웨이 인터페이스)를 설치해 준다.
- httpd: 아파치 웹 서버를 실행시키는 프로세스
- python3-mod_wsgi: python 웹 어플리케이션을 웹 서버랑 연결시켜주는 프로세스(인터페이스)
1
dnf install -y openstack-keystone httpd python3-mod_wsgi
다음은 설정을 건드려줘야 하는데,
1
2
3
4
5
6
7
8
9
10
11
vi /etc/keystone/keystone.conf
...
[database]
#keystone:(keystone db 암호)@(호스트 IP 주소) 순으로 작성
connection = mysql+pymysql://keystone:openstack@172.30.1.86/keystone
[token]
# 암호화 방식: fernet
provider = fernet
...
해당 내용을 추가하고 저장한 다음,
1
2
3
4
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
으로 db를 초기화하고(su -s), 암호화 키를 만든 다음(keystone-manage)
1
2
3
4
5
keystone-manage bootstrap --bootstrap-password (관리자 비밀번호) \
--bootstrap-admin-url http://172.30.1.86:5000/v3/ \
--bootstrap-internal-url http://172.30.1.86:5000/v3/ \
--bootstrap-public-url http://172.30.1.86:5000/v3/ \
--bootstrap-region-id RegionOne
keystone은 계정 관리도 하기 때문에, 이 클러스터의 마스터 계정(admin)을 생성해준다.
1
2
3
4
5
echo "ServerName 172.30.1.86" >> /etc/httpd/conf/httpd.conf
ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/
systemctl enable --now httpd
keystone의 실행 준비를 한 다음(keystone 웹 어플을 apache 웹 서버에 올리는 작업),
keystone을 실행시켜 준다.
작동 테스트
keystone에 접속하기 위해서는 아까 만든 어드민 계정 접속 정보를 입력해 줘야 한다.
근데 매번 입력하기 귀찮으니 접속 정보 환경 변수가 저장된 admin-openrc 파일을 만들어 주자.
1
2
3
4
5
6
7
8
9
10
vi ~/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=(관리자 비밀번호)
export OS_AUTH_URL=http://172.30.1.86:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
그래서 이를 source 명령어를 통해 불러온 다음 실행(openstack token issue)를 하면…
1
2
source ~/admin-openrc
openstack token issue
토큰이 잘 발급되면 성공이다!
다음 시간에는 나머지 요소들(glance, neutron, nova) 설치를 진행해 보겠다~
