서울 리전에 필요한 VCN과 VM 인스턴스를 생성합니다. Public IP와 Private IP는 동적으로 할당되므로 다르게 여기서의 구성과 다를 수 있습니다. VCN과 VM 인스턴스 생성 가이드는 다음 포스트를 참고 합니다.
OCI에서 VCN Wizard를 활용하여 빠르게 VCN 생성하기
Virtual Cloud Network (VCN)
Name | CIDR | Subnet |
---|---|---|
VCN-SEOUL-HUB | 172.16.0.0/16 | 172.16.0.0/24 (Public), 172.16.1.0/24 (Private) |
VCN-SEOUL-SPOKE-1 | 172.17.0.0/16 | 172.17.0.0/24 (Public), 172.17.1.0/24 (Private) |
VM 인스턴스
HAProxy 인스턴스를 Public Subnet에 생성한 이유는 HAProxy 구성 및 백엔드 WebServer 구성을 위한 Bastion 용도로도 사용하기 위함입니다.
Name | VCN | Subnet | Public IP | Private IP |
---|---|---|---|---|
HAProxy | VCN-SEOUL-HUB | 172.17.0.0/24(Public) | 129.154.215.53 | 172.17.0.237 |
webserver-1 | VCN-SEOUL-SPOKE-1 | 172.17.1.0/24(Private) | 172.17.1.82 | |
webserver-2 | VCN-SEOUL-SPOKE-1 | 172.17.1.0/24(Private) | 172.17.1.210 |
이제 두 VCN을 DRG로 연결합니다. OCI Console 메뉴 > Networking > Customer connectivity > Dynamic routing gateways로 이동한 후 Create dynamic routing gateway 버튼을 클릭하고 DRG-SEOUL-1 이라는 이름으로 생성합니다.
DRG에 앞서 생성한 두 개의 VCN을 붙입니다. 생성한 DRG를 클릭하면 왼쪽 VCN attachments라는 Resources를 볼 수 있습니다. VCN attachments를 선택한 후 Create virtual cloud network attachment 버튼을 클릭한 후 다음과 같이 두 개의 VCN Attachment를 생성합니다.
Attachment name | Virtual cloud network |
---|---|
VCN-SEOUL-HUB-DRG-ATT | VCN-SEOUL-HUB |
VCN-SEOUL-SPOKE-1-DRG-ATT | VCN-SEOUL-SPOKE-1 |
두 개의 VCN Attachment가 추가되었습니다.
이제 각 VCN에서 사용하는 Route Table에서 Target을 DRG로 지정합니다. 우선 VCN-SEOUL-HUB VCN을 선택한 후 Route Table에서 Default Route Table for VCN-SEOUL-HUB을 선택합니다. VCN-SEOUL-SPOKE-1으로 Routing을 위한 Rule을 추가합니다.
본 구성에서는 DRG를 직접 사용하는 Subnet은 Network Load Balancer가 위치한 VCN-SEOUL-HUB의 Public Subnet과 HAProxy가 위치한 VCN-SEOUL-SPOKE-1의 Public Subnet입니다. 따라서 두 Subnet에 대해서만 Target Type을 DRG로 지정합니다.
마찬가지로 VCN-SEOUL-SPOKE-1 VCN을 선택한 후 Route Table에서 default route table for VCN-SEOUL-SPOKE-1을 선택합니다. VCN-SEOUL-HUB로 Routing을 위한 Rule을 추가합니다.
마지막으로 각 VCN의 Subnet에 대한 Security List 구성을 합니다. VCN-SEOUL-HUB VCN을 선택한 후 Security Lists에서 Default Security List for VCN-SEOUL-HUB를 선택합니다. Ingress Rules에 다음과 같이 Rule을 추가합니다. VCN-SEOUL-HUB에는 Network Load Balancer만 구성할 것이고, 80 포트만 Listening 합니다.
마찬가지로 VCN-SEOUL-SPOKE-1 VCN을 선택한 후 Security Lists에서 Default Security List for VCN-SEOUL-SPOKE-1를 선택합니다. HAProxy가 Network Load Balancer로 부터 트래픽이 들어오므로, Ingress Rules에 다음과 같이 Rule을 추가합니다.
마지막으로 백엔드 WebServer가 위치한 Subnet에 대한 Security List를 설정합니다. Security Lists에서 security list for private subnet-VCN-SEOUL-SPOKE-1을 선택합니다. VCN-SEOUL-SPOKE-1 VCN의 Public Subnet으로 부터 트래픽이 들어오므로, Ingress Rules에 다음과 같이 Rule을 추가합니다.
두 대의 백엔드 WebServer를 설치합니다. 먼저 HAProxy서버에 접속한 후 각 WebServer로 다시 접속하여 설치를 진행합니다.
HAProxy 서버에 접속합니다.
$ ssh -i ~/.ssh/id_rsa opc@129.154.215.53
Private ssh키는 HAProxy서버에 복사한 후 각 백엔드 WebServer 접속을 위해 사용합니다.
HAProxy서버에서 webserver-1 서버로 접속합니다.
$ [opc@haproxy ~] ssh -i ~/.ssh/id_rsa opc@172.17.1.82
httpd 서버를 설치합니다.
$ [opc@webserver-1 ~] sudo yum install httpd -y
httpd 서버를 시작합니다.
$ [opc@webserver-1 ~] sudo systemctl start httpd
OS 방화벽에 80 포트를 추가합니다.
$ [opc@webserver-1 ~] sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
$ [opc@webserver-1 ~] sudo firewall-cmd --reload
동일하게 webserver-2도 설치 및 구성합니다.
다시 HAProxy 서버에 접속합니다.
$ ssh -i ~/.ssh/id_rsa opc@129.154.215.53
HAProxy를 설치합니다.
$ [opc@haproxy ~] sudo dnf install -y haproxy
HAProxy 설정을 합니다.
$ [opc@haproxy ~] sudo vi /etc/haproxy/haproxy.cfg
주요 설정 내용은 다음과 같습니다.
log 127.0.0.1 local0
frontend main
bind *:5000 accept-proxy
bind *:80 accept-proxy
backend app
balance roundrobin
server app1 172.17.1.82:80 check
server app2 172.17.1.210:80 check
로그 설정을 위해 syslog facility로 local0를 사용합니다. 5000포트(기본)와 80포트(추가)를 바인드하고, 각각 accept-proxy를 추가하여 Proxy Protocol V2 프로토콜을 허용합니다. Backend App으로 앞서 설치한 백엔드 WebServer를 추가합니다.
이제 rsyslog를 haproxy로 전달하기 위해 다음과 같이 설정합니다.
$ [opc@haproxy ~] sudo vi /etc/rsyslog.d/haproxy.conf
haproxy.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
$template Haproxy, "%msg%\n"
local0.* /var/log/haproxy.log
rsyslog과 haproxy를 재시작합니다. (중지된 상태면 시작(start)합니다.)
$ [opc@haproxy ~] sudo systemctl restart rsyslog
$ [opc@haproxy ~] sudo systemctl restart haproxy
이제 haproxy.log파일이 정상적으로 생성되었는지 확인합니다.
$ [opc@haproxy ~] ls -l /var/log/haproxy.log
-rw-------. 1 root root 228189 Mar 31 12:20 /var/log/haproxy.log
마지막으로 HAProxy서버에서 OS 방화벽에 80 포트를 추가합니다.
$ [opc@webserver-1 ~] sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
$ [opc@webserver-1 ~] sudo firewall-cmd --reload
Network Load Balancer 생성을 위해 OCI Console 메뉴 > Networking > Load balancers > Network load balancer로 이동합니다. Create network load balancer 버튼을 클릭한 후 다음과 같이 설정합니다.
Add details
Configure Listener
Choose backends
Specify health check policy
마지막으로 Create network load balancer버튼을 클릭하여 Network Load Balancer를 생성합니다.
두 가지 시나리오로 테스트를 해보겠습니다.
현재 Network Load Balancer Listner에 PPv2가 Enable된 상태입니다. 바로 Network Load Balancer Public IP로 접속해봅니다.
http://132.226.175.83/
HAProxy 로그를 확인합니다.
$ [opc@haproxy ~] sudo tail -f /var/log/haproxy.log
Mar 31 12:48:13 localhost haproxy[102136]: 211.207.67.71:41366 [31/Mar/2025:12:48:13.965] main app/app1 0/0/0/1/1 403 3823 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Mar 31 12:48:13 localhost haproxy[102136]: 211.207.67.71:41366 [31/Mar/2025:12:48:13.965] main app/app1 0/0/0/1/1 403 3823 - - ---- 2/2/0/0/0 0/0 "GET / HTTP/1.1"
Mar 31 12:48:13 localhost haproxy[102136]: 211.207.67.71:41366 [31/Mar/2025:12:48:13.984] main static/<NOSRV> 0/-1/-1/-1/0 503 212 - - SC-- 2/2/0/0/0 0/0 "GET /icons/apache_pb2.gif HTTP/1.1"
Mar 31 12:48:13 localhost haproxy[102136]: 211.207.67.71:41366 [31/Mar/2025:12:48:13.984] main static/<NOSRV> 0/-1/-1/-1/0 503 212 - - SC-- 2/2/0/0/0 0/0 "GET /icons/apache_pb2.gif HTTP/1.1"
Client 실제 IP (211.207.67.71)가 확인됩니다.
이제 Network Load Balancer Listner에서 PPv2를 Diable 합니다. 생성한 NLB_FOR_PPv2를 클릭한 후 Listeners에서 생성한 Listner를 Edit합니다. 그리고 Enable proxy protocol V2은 체크해제한 후 저장합니다.
haproxy.cfg에서 accept-proxy를 제거하여 HAProxy에서 PPv2를 다시 허용하지 않도록 합니다.
HAProxy에서 80 포트에 대해 PPv2가 Enable(accept-proxy)되어 있을 경우, HAProxy에서 Proxy Protocol을 기대하는 상황에서 실제로 받은 데이터가 Proxy Protocol 헤더 형식이 아니므로, “Received something which does not look like a PROXY protocol header” 메시지와 함께 정상적으로 접속이 안됩니다.
$ [opc@haproxy ~] sudo vi /etc/haproxy/haproxy.cfg
frontend main
bind *:5000
bind *:80
HAProxy를 다시 시작합니다.
$ [opc@haproxy ~] sudo systemctl restart haproxy
다시 Network Load Balancer Public IP로 접속해봅니다. HAProxy 로그를 확인합니다.
$ [opc@haproxy ~] sudo tail -f /var/log/haproxy.log
Mar 31 13:04:16 localhost haproxy[118722]: 172.16.0.230:21411 [31/Mar/2025:13:04:16.698] main app/app1 0/0/0/1/1 403 3823 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
Mar 31 13:04:16 localhost haproxy[118722]: 172.16.0.230:21411 [31/Mar/2025:13:04:16.698] main app/app1 0/0/0/1/1 403 3823 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
Mar 31 13:04:16 localhost haproxy[118722]: 172.16.0.230:21411 [31/Mar/2025:13:04:16.726] main static/<NOSRV> 0/-1/-1/-1/0 503 212 - - SC-- 2/2/0/0/0 0/0 "GET /icons/apache_pb2.gif HTTP/1.1"
Mar 31 13:04:16 localhost haproxy[118722]: 172.16.0.230:21411 [31/Mar/2025:13:04:16.726] main static/<NOSRV> 0/-1/-1/-1/0 503 212 - - SC-- 2/2/0/0/0 0/0 "GET /icons/apache_pb2.gif HTTP/1.1"
Client 실제 IP (211.207.67.71)가 아닌 Network Load Balancer의 Private IP(172.16.0.230)가 출력되는 것을 확인할 수 있습니다.
이번에는 PPv2를 사용하지 않고 Network Load Balancer의 Backend sets에서 Preserve source IP옵션을 활성화 해보도록 하겠습니다. 생성한 NLB_FOR_PPv2를 클릭한 후 Listeners에서 생성한 Backend sets를 Edit합니다. 그리고 Preserve source IP은 체크한 후 저장합니다.
다시 Network Load Balancer Public IP로 접속해봅니다. 연결이 안되는 것을 확인할 수 있고, HAProxy에도 어떤 Access 로그도 남지 않는 것을 확인할 수 있습니다. Local Peering Gateway를 사용하는 환경이라면 전달이 되겠지만, DRG를 사용할 경우 패킷이 DRG를 거쳐 Backend까지 도달되지 않는 문제가 생기게 되며, 이로 인해 HAProxy에 연결이 되지 않는 현상이 발생합니다.
다른 리전과 Remote Peering으로 구성한 경우에도 PPv2 Header가 다른 리전의 HAProxy로 전달이 되는지도 확인해보았습니다. 구성도는 다음과 같습니다.
마찬가지로 Network Load Balancer Public IP로 접속해보고, 도쿄 리전에 있는 HAProxy 로그를 확인합니다.
$ [opc@haproxy ~] sudo tail -f /var/log/haproxy.log
Apr 1 06:23:30 localhost haproxy[75798]: 211.207.67.71:5442 [01/Apr/2025:06:23:30.809] main app/app2 0/0/0/1/1 403 3823 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
Apr 1 06:23:30 localhost haproxy[75798]: 211.207.67.71:5442 [01/Apr/2025:06:23:30.866] main static/<NOSRV> 0/-1/-1/-1/0 503 212 - - SC-- 2/2/0/0/0 0/0 "GET /icons/apache_pb2.gif HTTP/1.1"
Apr 1 06:23:30 localhost haproxy[75798]: 211.207.67.71:6083 [01/Apr/2025:06:23:30.950] main app/app2 0/0/0/1/1 404 389 - - ---- 1/1/0/0/0 0/0 "GET /favicon.ico HTTP/1.1"
Apr 1 06:31:17 localhost haproxy[75798]: 80.82.77.202:60000 [01/Apr/2025:06:31:15.084] main/2: Received something which does not look like a PROXY protocol header
Remote Peering을 통해서 다른 리전에 있는 HAProxy 서버에서도 Client 실제 IP (211.207.67.71)가 출력되는 것을 확인할 수 있습니다.
이 글은 개인적으로 얻은 지식과 경험을 작성한 글로 내용에 오류가 있을 수 있습니다. 또한 글 속의 의견은 개인적인 의견으로 특정 회사를 대변하지 않습니다.
Donghu Kim INFRASTRUCTURE
oci nlb ppv2