VProfile 프로젝트의 로컬 멀티 VM 환경을 구성하고, 각 서버의 역할과 연결 구조를 이해하는 과정이다.
이번 단계의 핵심은 애플리케이션 기능 자체보다, 왜 서비스를 여러 계층으로 분리하는지, 그리고 그 구조를 반복 가능한 환경으로 어떻게 구성하는지를 이해하는 데 있다.
VProfile은 다음과 같이 구성된다.
web01 — Nginxapp01 — Tomcatdb01 — MySQLmc01 — Memcachermq01 — RabbitMQ처음에는 "하나의 큰 서버에 전부 올리면 되지 않나?"라는 생각이 들 수 있다. 하지만 실제 서비스 구조에서는 역할 분리와 장애 격리를 위해 계층을 나누는 것이 일반적이다.
각 서버는 서로 다른 책임을 가진다.
Nginx는 요청을 받는 진입점Tomcat은 Java 애플리케이션 실행MySQL은 데이터 저장Memcache는 캐시RabbitMQ는 메시지 브로커이렇게 역할을 나누면 설정, 배포, 장애 대응의 범위를 좁히기 쉽다.
예를 들어 Tomcat에서 메모리 누수가 발생하면 같은 VM의 자원을 계속 점유하게 된다. 만약 Nginx, Tomcat, MySQL이 모두 한 머신에 있다면 다음과 같은 문제가 생길 수 있다.
Nginx는 느려진 Tomcat을 upstream으로 보다가 timeout, 502, 504를 낼 수 있음MySQL도 같은 VM 자원을 사용하므로 메모리 부족과 swap 영향으로 응답이 느려질 수 있음즉 하나의 계층 문제를 다른 계층까지 전파하지 않으려면, 물리적 또는 논리적 경계를 나누는 편이 유리하다.
강의에서는 Nginx를 앞단의 load balancer로 두고, Tomcat을 애플리케이션 실행 서버로 둔다.
Nginx는 다음 역할을 담당한다.
여기서 중요한 점은 부하를 없애는 것이 아니라, 부하를 분산하는 것이라는 점이다. 즉 여러 애플리케이션 서버가 있다면 Nginx가 요청을 적절히 나누어 전달한다.
Tomcat은 Java 웹 애플리케이션을 실행하는 서버다. 즉 앞단에서 요청을 직접 받기보다는, 뒤에서 실제 비즈니스 로직을 수행하는 계층에 가깝다.
정리하면 다음과 같다.
Nginx = 요청 받기, 분산, 프록시Tomcat = Java 웹 애플리케이션 실행학습 중 헷갈렸던 부분 중 하나는 Apache httpd와 Tomcat을 같은 종류로 묶어 생각한 점이었다.
하지만 Apache httpd는 Nginx와 같은 웹서버 계열이고, Tomcat은 Java 웹 애플리케이션 실행 서버다.
즉 강의의 구조는:
Nginx를 앞단 진입점으로 두고Tomcat을 앱 실행 계층으로 분리한 형태라고 이해하는 편이 정확하다.
강의에서는 애플리케이션에 storage가 필요할 때 NFS를 사용할 수 있다고 설명한다.
NFS(Network File System)는 여러 서버가 네트워크를 통해 같은 파일 시스템을 공유해서 쓰게 해주는 방식이다. 그래서 shared storage라고 부른다.
이 구조가 필요한 이유는, app01, app02처럼 같은 역할의 앱 서버 여러 대가 있을 때 업로드 파일을 공통으로 참조해야 할 수 있기 때문이다.
주의할 점은 다음과 같다.
DB에 저장NFS 같은 shared storage에 저장 가능이 맥락에서 서버 클러스터는 같은 역할을 하는 서버 여러 대의 그룹으로 이해하면 된다.
예:
app01, app02, app03 → 애플리케이션 서버 클러스터이렇게 구성하면 다음 장점이 있다.
멀티 VM 환경을 구성하기 위해 vagrant-hostmanager 플러그인을 설치한다.
vagrant plugin install vagrant-hostmanager
이 플러그인의 역할은 호스트와 VM의 /etc/hosts를 자동으로 관리하는 것이다. 즉 각 VM의 hostname과 IP를 자동으로 매핑해 db01, app01, web01 같은 이름으로 접근할 수 있게 해준다.
PDF에 나온 아래 문장과 직접 연결된다.
"INFO: All the vm's hostname and /etc/hosts file entries will be automatically updated."
Vagrant.configure("2") do |config|
config.hostmanager.enabled = true
config.hostmanager.manage_host = true
### DB vm ####
config.vm.define "db01" do |db01|
db01.vm.box = "bandit145/centos_stream9_arm"
db01.vm.hostname = "db01"
db01.vm.network "private_network", ip: "192.168.56.25"
db01.vm.provider "vmware_desktop" do |vmware|
vmware.gui = true
vmware.allowlist_verified = true
end
end
### Memcache vm ####
config.vm.define "mc01" do |mc01|
mc01.vm.box = "bandit145/centos_stream9_arm"
mc01.vm.hostname = "mc01"
mc01.vm.network "private_network", ip: "192.168.56.24"
mc01.vm.provider "vmware_desktop" do |vmware|
vmware.gui = true
vmware.allowlist_verified = true
end
end
### RabbitMQ vm ####
config.vm.define "rmq01" do |rmq01|
rmq01.vm.box = "bandit145/centos_stream9_arm"
rmq01.vm.hostname = "rmq01"
rmq01.vm.network "private_network", ip: "192.168.56.23"
rmq01.vm.provider "vmware_desktop" do |vmware|
vmware.gui = true
vmware.allowlist_verified = true
end
end
### tomcat vm ###
config.vm.define "app01" do |app01|
app01.vm.box = "bandit145/centos_stream9_arm"
app01.vm.hostname = "app01"
app01.vm.network "private_network", ip: "192.168.56.22"
app01.vm.provider "vmware_desktop" do |vb|
vb.memory = "1024"
vb.gui = true
vb.allowlist_verified = true
end
end
### Nginx VM ###
config.vm.define "web01" do |web01|
web01.vm.box = "spox/ubuntu-arm"
web01.vm.hostname = "web01"
web01.vm.network "private_network", ip: "192.168.56.21"
web01.vm.provider "vmware_desktop" do |vmware|
vmware.gui = true
vmware.allowlist_verified = true
end
end
end
모든 VM이 192.168.56.x 대역을 사용하는 이유는, 같은 private_network 안에서 서로 통신하게 하기 위해서다.
각 VM이 서로 다른 IP를 가져야 하는 이유는 다음과 같다.
즉 같은 사설망에 두되, 각 머신은 별도의 주소를 가져야 한다.
강의에서는 다음 순서로 준비되어야 한다고 설명한다.
이유는 의존성 순서이기 때문이다.
Tomcat은 단독으로 존재하는 것이 아니라, 뒤쪽의 MySQL, Memcache, RabbitMQ 같은 서비스에 의존한다. 이 서비스들이 먼저 떠 있어야 애플리케이션이 안정적으로 시작할 수 있다.
반대로 Nginx는 최종적으로 준비된 애플리케이션 서버로 요청을 전달하는 진입점이므로 가장 마지막에 뜨는 것이 자연스럽다.
정리하면 다음 흐름이다.
vagrant up 이후 web01에 접속해 /etc/hosts를 확인하면, Vagrantfile에 정의한 hostname과 IP가 매핑되어 있는 것을 볼 수 있다.
vagrant ssh web01
cat /etc/hosts
ping app01 -c 4
ping db01 -c 4
강의에서는 web01에서 확인하지만, vagrant-hostmanager의 성격상 다른 VM들의 /etc/hosts에도 공통 매핑이 들어갈 가능성이 높다.
이론적으로는 모든 VM이 모든 hostname을 꼭 알아야 하는 것은 아니다. 다만 자동화와 일관성 관점에서는 전체 머신 정보를 공통으로 반영하는 편이 더 단순하고 실습에도 유리하다.
로드밸런싱, reverse proxy, 요청 진입점 역할에 강점이 있기 때문이다.
Apache httpd는 Nginx와 같은 웹서버 계열이고, Tomcat은 Java 웹 애플리케이션 실행 서버다. 즉 Apache httpd와 Tomcat은 같은 종류가 아니다.
역할 분리, 장애 격리, 고가용성, 확장성을 확보하기 위해서다.
애플리케이션은 뒤의 의존 서비스가 먼저 준비되어 있어야 정상적으로 시작할 수 있기 때문이다.
이번 단계는 로컬 멀티 VM 환경을 구성하고 계층 간 관계를 이해하는 단계였다. 다음에는 이 구조 위에서 실제 Local Setup을 진행하면서 각 서비스가 어떻게 연결되고, 어떤 부분을 자동화 포인트로 가져갈 수 있는지 이어서 정리할 예정이다.