MeetBack 2026.08.25 6 min read

VyOS로 MySQL DB망을 분리하며 Route와 NAT를 구분한 과정

VyOS로 DB망을 분리하다 외부 통신이 막혔다. Live ISO, 버전별 NAT 문법, commit 실패를 확인하고 라우팅·NAT·재부팅을 나눠 검증한 과정을 기록했다.

프로젝트 기간: 2026-08-18 ~ 2026-09-02
글 범위: VyOS Routing·NAT 기반 MySQL DB망 분리

MySQL Primary와 Replica를 서비스망에서 분리하려고 VyOS 라우터를 추가했다. DB 서버는 전용망에 연결하고 Swarm Worker와 모니터링 서버가 필요한 통신만 VyOS를 거쳐 접근하도록 했다.

구성한 연결은 아래와 같다.

Service network
  → VyOS eth0
  → VyOS eth1
  → DB private network
       ├─ MySQL Primary
       └─ MySQL Replica

작업 중에는 라우팅과 NAT 외에도 버전별 설정 문법과 영구 설치 여부를 확인해야 했다.

VMware network를 두 개로 나눴다

VyOS VM에 네트워크 어댑터 두 개를 연결했다.

  • WAN 역할: 기존 서비스망
  • LAN 역할: VMware Host-only DB망

DB1과 DB2에도 두 번째 어댑터를 추가해 DB망에 연결했다. 전환을 확인한 뒤 기존 서비스망 어댑터의 Connected를 해제했다. MySQL이 두 망에서 동시에 접속을 받지 않도록 연결 자체를 정리했다.

DB의 기본 게이트웨이는 VyOS의 DB망 주소로 바꿨다. 모니터링 서버에는 DB 서브넷으로 가는 정적 경로를 추가했다. App Worker도 서비스망에서 VyOS를 거쳐 DB에 접근하도록 했다.

첫 번째 문제: 설정이 재부팅 후 사라질 수 있었다

인터페이스와 경로를 설정하다 아래 경고를 확인했다.

WARNING: You are currently configuring a live-ISO environment,
changes will not persist until installed

ISO로 부팅한 Live 환경에서 작업하고 있었다. 여기서 commit한 설정은 현재 실행에만 반영되고, 디스크에 설치된 시스템의 설정으로 유지되는 상태가 아니었다.

install image로 로컬 디스크에 설치하고 현재 config.boot를 복사했다. VM을 종료한 뒤 ISO 연결을 해제하고 디스크 부팅을 우선하도록 바꿨다. 재부팅 후 show version과 인터페이스, 경로, 설정을 다시 확인했다.

이후에는 네트워크 장비의 연결 시험과 재부팅 후 설정 유지 여부를 각각 확인했다.

두 번째 문제: VyOS 버전별 NAT 문법이 달랐다

출발지 NAT 규칙을 작성할 때 아래 문법이 거부됐다.

set nat source rule 100 outbound-interface name 'eth0'
Configuration path ... is not valid

사용 중인 VyOS 1.3.5에서는 outbound-interface name eth0 대신 outbound-interface eth0를 사용해야 했다. 참고한 예제와 설치 버전의 문법이 달랐다.

문법을 고친 다음에도 commit에서 다른 오류가 발생했다.

Source NAT configuration error in rule 10:
outbound-interface not specified

Masquerade 규칙에는 인터페이스를 넣었지만 NO-NAT exclude 규칙에는 빠져 있었다. 이 버전에서는 제외 규칙에도 출구 인터페이스를 지정해야 했다.

최종 설정은 내부 통신과 외부 통신을 아래처럼 나눴다.

Rule 10
  source: DB private network
  destination: internal service network
  outbound: service interface
  action: exclude

Rule 100
  source: DB private network
  outbound: service interface
  translation: masquerade

내부 서비스망에는 DB의 원래 출발지 주소를 유지하고, 인터넷으로 나갈 때만 VyOS 주소로 변환하도록 했다.

Route가 정상인데 internet ping은 실패했다

DB2의 ip route get은 VyOS를 게이트웨이로 선택했다. DB에서 VyOS의 LAN 인터페이스까지 ping도 성공했다. 그런데 출발지를 지정한 외부 ping에는 응답이 없었다.

상위 게이트웨이나 Host-only 연결을 먼저 의심했지만 NAT 규칙의 commit이 실패한 상태였다. 기본 경로는 있어도 내부 출발지 주소를 외부에서 응답할 수 있는 주소로 바꾸는 NAT가 적용되지 않았다.

이때 두 설정이 맡는 일을 구분해서 확인했다.

  • 라우팅: 패킷을 보낼 다음 경로 선택
  • 출발지 NAT: 응답이 돌아올 수 있는 출발지 주소로 변환

commit이 실패하면 뒤에 save를 실행해도 실패한 변경이 저장되지는 않는다. 규칙을 수정하고 commit 성공을 확인한 다음 저장했다. 이후 아래 순서로 다시 점검했다.

1. DB interface와 address
2. DB default route
3. DB → VyOS LAN reachability
4. VyOS interface와 default route
5. VyOS ARP
6. source NAT rules와 counters
7. 외부 IP 통신
8. DNS name resolution

내부 traffic에 NO-NAT를 둔 이유

DB 통신을 모두 masquerade하면 MySQL에서 연결의 출발지를 VyOS로만 볼 수 있다. Worker별 계정 Host 제한이나 모니터링 출발지 구분이 어려워질 수 있었다.

내부 서비스망 목적지는 NAT 없이 라우팅해 실제 클라이언트 주소를 유지했다. 패키지 업데이트처럼 인터넷으로 나가는 요청에만 masquerade를 적용했다.

DB network 전환 뒤 listener를 하나로 줄였다

전환 직후에는 관리 편의를 위해 예전 서비스망 주소도 남길지 고민했다. 최종적으로 MySQL은 DB 전용 주소 하나에서만 접속을 받도록 정리했다.

MySQL listener → DB private address only
Replication source → DB private address
Exporter → DB private address
Backup NFS access → DB private route
Administrator → Tailscale or controlled jump path

호스트 방화벽은 전체 구성이 끝난 뒤 적용할 예정이었다. 그 전에 수신 주소와 MySQL 계정 Host 조건부터 제한해 접근 범위를 줄였다.

이 작업에서 얻은 교훈

같은 ping 실패라도 인터페이스, 경로, NAT와 응답 경로, 수신 서비스, 접근 정책을 나눠 봐야 했다. 이번에는 경로가 있다는 사실만 확인하고 NAT의 적용 여부를 놓쳤다.

버전에 맞는 문법과 Live ISO 여부를 확인한 뒤 설정을 반영하고 재부팅까지 시험했다. 최종적으로 DB 서버를 서비스망에서 분리하면서도 복제, 모니터링, 백업, 패키지 업데이트 경로를 유지했다.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동