Rocky Linux 운영 실습망 구축 가이드 — 온라인망과 폐쇄망을 같은 기준으로
AI_Manager
같은 서버를 인터넷이 있는 곳과 없는 곳에서 다시 만들 수 있는가. 이 글은 Oracle VirtualBox와 Rocky Linux 10.2를 기반으로, 기본 VM에서 자산 관리·자동화·모니터링까지 확장하는 구축 절차를 정리한다.
이 글의 순서글의 범위와 실행 상태
2026년 9월 20일 기준, 실제 완료한 범위는 설치 원본 검증과 Rocky 기본 VM의 설치·복구·기본 점검이다. 역할별 VM과 서비스 설치, 폐쇄망 재현은 미실행이다. 아래 서비스 부분은 공식 문서와 프로젝트 설계를 바탕으로 작성한 구축 가이드이며 실행 완료 보고서가 아니다. 예제 명령의 실행 위치와 전제를 각 단계에 적었다.
- 1. 구축 순서와 준비물
- 2. ISO 검증과 기본 VM 만들기
- 3. 역할별 VM과 네트워크 배치
- 4. 접근 정책·DNS·시간·인증서
- 5. RPM과 반입 묶음 준비
- 6. NetBox와 의존성 구성
- 7. K3s와 AWX 구축
- 8. Bastion과 Zabbix 수집 경로 구성
- 9. 표준 구성과 연동 Worker 연결
- 10. 백업·복원과 업데이트
- 11. 설치 후 기본 확인
- 12. 오류 기록과 구축 종료 기준
1. 구축 순서와 준비물
호스트 자원 확인 → 버전·원본 고정 → 기본 VM → 네트워크·이름·시간
→ DB와 저장소 → NetBox → K3s·AWX → Bastion·Zabbix
→ 연동 Worker → 온라인 검증 → 반입 묶음 → 폐쇄망 새 설치 → 복원 검증
첫 번째 목표는 대상 Linux 한 대에 표준 설정을 적용하고 실제 모니터링 값까지 수신하는 것이다. HA와 PXE를 처음부터 동시에 구현하지 않는다. 기본 경로가 동작한 뒤 실패·재실행·장애 전환을 추가하면 원인 범위를 줄일 수 있다.
| 구분 | 사용하거나 준비할 내용 |
|---|---|
| 실제 호스트 | Core Ultra 9 185H, 32GB RAM, Windows 11 Pro, 2TB NVMe |
| 실제 기본 환경 | VirtualBox 7.2.18r175117, Rocky Linux 10.2 Minimal x86_64 |
| 확인된 템플릿 | fml-template-rocky10.2 / UEFI / 1 vCPU / 3072MiB / 64GiB 동적 디스크 |
| 계획된 망 | fml-core: 10.77.10.0/24, fml-remote: 10.77.20.0/24 |
| 내부 이름 | fullmoon.test 하위 이름, 외부 DNS에 게시하지 않는 실습용 이름 |
| 보관할 자료 | 공식 원본·체크섬, RPM 목록, 소스 버전, 이미지 digest, 설정, 시험 로그 |
| 별도 보관 | SSH 개인키, DB 암호, API 토큰, AWX 비밀키, 내부 CA 개인키 |
Rocky Linux는 작성 시점의 최신 정식 계열인 10.2를 사용한다. 재현할 때는 ‘최신’이라는 표현 대신 ISO 파일명과 SHA256을 남긴다. 다른 솔루션의 버전은 Rocky 최신 버전과 별개로 호환성을 확인해 선택해야 한다. Rocky Linux 10.2 릴리스 노트
온라인망에서 구성 시
공식 저장소에 접근할 수 있는 준비 환경을 사용한다. 설치 전에 선택한 릴리스, 아키텍처, 다운로드 주소, 서명 키를 기록한다. 실행 중인 업무 프로그램의 메모리를 고려해 전체 VM 시작 전 여유 메모리를 확인한다. 최초 13.5GiB VM 메모리 예산은 성능 보장값이 아니며 필요하면 서비스를 순차 실행한다.
폐쇄망에서 구성 시
인터넷이 되는 준비 환경과 격리된 설치 환경을 구분한다. 준비 환경은 대상과 같은 OS 계열·아키텍처로 만들고 설치에 필요한 모든 의존성을 모은다. 반입 성공의 기준은 파일 개수가 아니라 외부 연결과 기존 캐시가 없는 새 VM에서 재설치되는지다.
2. ISO 검증과 기본 VM 만들기
사용한 ISO는 Rocky-10.2-x86_64-minimal.iso, 크기는 2,072,444,928바이트다. 실제 내려받은 파일의 SHA256을 공식 CHECKSUM과 대조했다.
aac6ac3ce781b91a91ce78463405f66c611a5dca4b3840c79e5e01d97302f6c8
Windows PowerShell에서 해시를 확인한다. 아래 경로는 이 실습의 전용 디렉터리이며 OneDrive 동기화 폴더 밖이다. 동일한 ISO인지 확인한 다음 사용한다.
$labRoot = Join-Path $env:USERPROFILE 'VirtualBox VMs\FullMoon-Lab'
$iso = Join-Path $labRoot 'media\Rocky-10.2-x86_64-minimal.iso'
$expected = 'aac6ac3ce781b91a91ce78463405f66c611a5dca4b3840c79e5e01d97302f6c8'
$actual = (Get-FileHash -LiteralPath $iso -Algorithm SHA256).Hash
if ($actual -ne $expected) { throw 'ISO hash mismatch' }
Get-Item -LiteralPath $iso | Select-Object Name,Length
VirtualBox에서 새 Linux VM을 만들고 UEFI, SATA 동적 64GiB 디스크, RAM 3GiB, virtio NIC를 지정한다. 현재 기준선은 1 vCPU다. 설치 시 2 vCPU 부팅 정체가 관찰됐기 때문에 역할별 다중 vCPU 배치는 별도로 재시험한다. 이 관찰을 Rocky Linux의 다중 CPU 미지원으로 해석하지 않는다.
초기 설치는 NAT 한 개와 호스트 loopback에만 바인딩한 SSH 전달을 사용했다. 전달 규칙은 127.0.0.1:22022 → 게스트 TCP 22다. 이는 기본 OS 점검용 임시 경로다. 대상 서버를 최종 망에 배치한 후에는 이 규칙으로 접근 통제를 우회하지 않도록 제거한다.
| 설치 항목 | 이 실습의 기준 |
|---|---|
| 설치 방식 | Minimal, 텍스트 설치, 명시적인 Kickstart 경로 |
| EFI 파티션 | 600MiB |
| /boot | 2048MiB, XFS |
| swap | 1024MiB |
| / | 남은 공간, XFS |
| 운영 계정 | 실습 관리 계정, SSH 공개키 인증 |
| 기본 보호 | SELinux Enforcing, firewalld 활성, root 직접 SSH 금지 |
| 시간 | Asia/Seoul, chronyd |
파티션 자동화는 새로 생성한 빈 실습 디스크에만 적용한다. 기존 VM의 디스크를 재사용해 자동 파티션 명령을 실행하지 않는다. 이 프로젝트의 생성 스크립트는 같은 이름의 VM이나 디렉터리가 이미 있으면 중단하도록 만들었다.
Kickstart 후처리에서 SSH 설정을 검사하기 전에는 서버 호스트 키가 준비되어야 한다. 아래는 순서 설명을 위한 핵심 부분이다. 개인키나 실제 암호는 본문에 포함하지 않는다.
# Kickstart %post 내부: 계정과 공개키 배치 후 실행
restorecon -RF /home/labadmin/.ssh
ssh-keygen -A
sshd -t
visudo -c
systemctl enable sshd chronyd firewalld
현재 VM은 최초 설치 후 문제를 복구해 검증했다. 위 순서를 반영한 Kickstart의 빈 디스크 재설치는 아직 실행하지 않았다. 문법 수정과 새 설치 재현은 다른 검증이다. Rocky Kickstart 가이드
온라인망에서 구성 시
공식 ISO와 CHECKSUM을 내려받아 대조한다. 설치 후 활성 저장소와 패키지 버전을 기록하고 패치를 적용한다. 어떤 시점의 저장소로 업데이트했는지 남겨야 이후 결과 차이를 설명할 수 있다.
폐쇄망에서 구성 시
준비 환경에서 검증한 ISO와 CHECKSUM을 함께 반입하고 반입 후 해시를 다시 계산한다. Minimal ISO만으로 추가 솔루션 설치가 모두 가능하다고 가정하지 않는다. OS 설치 성공 뒤에 필요한 RPM과 이미지 공급 단계를 따로 둔다.
3. 역할별 VM과 네트워크 배치
| VM | 주소 | 자원 계획 | 역할 |
|---|---|---|---|
| fml-router | Core .1 / Remote .1 | 1 vCPU, 1GiB | 라우팅·ACL, DNS·NTP 제공 검토 |
| fml-core01 | 10.77.10.11 | 4 vCPU, 6GiB | NetBox, AWX/K3s, Zabbix Server 1 |
| fml-core02 | 10.77.10.12 | 2 vCPU, 2GiB | Worker, Ansible CLI, Zabbix Server 2 |
| fml-monitor | 10.77.10.20 | 2 vCPU, 2GiB | Zabbix PostgreSQL·Web/API |
| fml-remote | 10.77.20.10 | 1 vCPU, 1.5GiB | Bastion·Proxy·Proxy DB |
| fml-target01 | 10.77.20.101 | 2 vCPU, 1GiB | 관리 대상·Agent 2 |
VirtualBox 어댑터는 아래처럼 고정한다. Host-only 관리망은 실제 호스트·VPN 경로와 겹치지 않는 대역을 선택해 라우터에만 연결한다. 그 관리망의 인터넷 공유·브리징을 사용하지 않는다. 내부 서버는 자신의 대역에 해당하는 Internal Network 한 개를 사용한다.
라우터 NIC 1 = NAT (온라인에서만 사용)
라우터 NIC 2 = Internal Network: fml-core
라우터 NIC 3 = Internal Network: fml-remote
라우터 NIC 4 = 필요할 때만 제한된 Host-only 관리 경로
Core 1·Core 2·Monitor = fml-core
Remote·Target = fml-remote
운영 계정과 패키지만 준비된 기본 이미지를 복제할 경우 MAC 주소, machine-id, DHCP 식별 정보, 호스트명, SSH 호스트 키가 중복되지 않는지 확인한다. 원본 템플릿이 아닌 새 복제본에서 고유값을 준비한 뒤 망에 연결한다. 복구한 템플릿은 아직 이 일반화 절차를 통과하지 않았으므로 즉시 배포 가능한 골든 이미지로 부르지 않는다.
대상 VM의 NetworkManager 설정 예시다. 먼저 장치명과 연결 이름을 확인하고, VirtualBox 콘솔에서 새 프로필을 만든다. 아래 enp0s3는 실제로 확인한 뒤 쓰는 값이며 게스트마다 다를 수 있다. DNS·라우터가 준비된 이후에 활성화한다.
nmcli device status
nmcli connection show
sudo nmcli connection add type ethernet ifname enp0s3 con-name fml-static \
ipv4.method manual ipv4.addresses 10.77.20.101/24 \
ipv4.gateway 10.77.20.1 ipv4.dns 10.77.20.1
sudo nmcli connection up fml-static
ip -brief address
ip route
이후 기존 DHCP 프로필의 자동 연결을 끄고 재부팅 후에도 올바른 프로필이 선택되는지 확인한다. IPv6도 점검 대상이다. 이 실습의 경계에서 IPv6 외부 포워딩은 허용하지 않는 정책으로 관리하고, IPv4 경로만 검사한 뒤 폐쇄망이라고 판정하지 않는다.
온라인망에서 구성 시
외부 NAT는 라우터에만 둔다. 라우터의 IP forwarding, 출발 대역별 ACL, 외부 NAT, 반환 트래픽 정책을 함께 구성한다. 게스트가 내부 라우터를 기본 경로로 갖고, 라우터가 허용한 트래픽만 외부로 보낼 수 있게 한다. 실습망 내부 라우팅까지 NAT로 숨기지 않아 로그에서 출발지를 확인할 수 있도록 한다.
폐쇄망에서 구성 시
전환 전에 VM을 정상 종료하고 라우터의 외부 NAT 연결을 제거한다. 각 VM의 NAT·NAT Network·브리지 어댑터와 호스트 프록시·ICS 경로를 검사한다. 게스트의 내부 기본 경로까지 없앨 필요는 없다. Core와 Remote 간 라우팅, K3s 노드의 경로 선택을 위해 내부 라우터는 유지하고 라우터의 외부 전달만 차단한다. VirtualBox 네트워크, K3s 격리 환경의 경로 조건
4. 접근 정책·DNS·시간·인증서
아래는 서비스 구축을 위한 통신 계약이다. 실제 방화벽 적용 결과는 아직 없으며, Kubernetes 내부 통신 전체를 나열한 표도 아니다. 방화벽은 라우터에서 관리하는 정책과 각 서버의 firewalld 정책이 같은 의도를 가져야 한다.
| 출발지 → 목적지 | 허용 목적 | 포트·조건 |
|---|---|---|
| AWX 실행 환경 → Bastion | SSH 중계 | TCP 22, 승인 계정·키 |
| Bastion → Target | 표준 설정 | TCP 22, 지정 대상만 |
| Core → Target 직접 | 우회 관리 금지 | TCP 22 차단 시험 |
| Worker → NetBox·AWX·Zabbix API | 승인·실행·등록 | 내부 HTTPS 443 계획 |
| Target Agent → Proxy | Active Agent | TCP 10051, Hostname·TLS 일치 |
| Proxy → Server 1·2 | Active Proxy | TCP 10051, HA 서버 목록 |
| Server 1·2·Web → Monitor DB | Zabbix DB | TCP 5432, 지정 계정·출발지 |
| VM → 내부 DNS·NTP | 이름·시간 | UDP/TCP 53, UDP 123 |
AWX 컨테이너의 실제 출발지 주소는 CNI와 SNAT 설정에 따라 달라질 수 있다. VM 주소만 허용 목록에 넣고 끝내지 않고 Bastion에서 관찰되는 출발지를 확인한다. PostgreSQL 계정은 애플리케이션별로 분리하며 외부 대역 전체를 허용하지 않는다.
내부 DNS에는 각 VM 이름과 서비스 이름을 등록한다. 서비스 이름은 NetBox·AWX·Zabbix Web·DB가 실제 제공되는 주소를 가리키게 한다. 내부 CA를 사용할 경우 호스트뿐 아니라 AWX 실행 환경, Python, 컨테이너 런타임에도 신뢰를 배포한다. 인증서 이름과 DNS 이름이 일치해야 하며 TLS 확인을 끄지 않는다.
# 게스트에서 이름·시간·현재 경로 확인
getent hosts fml-remote.fullmoon.test
chronyc tracking
chronyc sources -v
timedatectl show -p Timezone -p NTPSynchronized
ip route
ip -6 route
온라인망에서 구성 시
승인된 DNS·NTP 상위 서버를 사용하고 내부 VM은 내부 서비스를 참조한다. 외부 저장소 허용과 관리 화면 공개는 별개의 문제다. 내부 관리 UI를 공인 인터넷에 노출하지 않는다.
폐쇄망에서 구성 시
DNS의 외부 질의와 시간 서버의 외부 참조를 정리한다. 내부 시간 원천을 정의하고 VM 간 오차를 측정한다. 외부 기준시각 없이 동기화 상태만 맞춘 것을 절대시각 정확도 확보로 표현하지 않는다. TLS 인증서 유효기간, 로그 시각, Zabbix 수집 시각을 함께 점검한다.
5. RPM과 반입 묶음 준비
반입 묶음은 OS와 서비스의 버전을 하나로 고정하는 단위다. 실제 서비스 버전은 설치 전 호환성 점검에서 확정하고 매니페스트에 기록한다. 아직 설치하지 않은 버전에 임의의 검증 완료 표식을 붙이지 않는다.
| 자료 종류 | 반드시 함께 기록할 값 |
|---|---|
| ISO·RPM | 파일명, SHA256, OS·아키텍처, NEVRA, 서명 키 지문 |
| Python | Python 버전, 직접·전이 의존성, wheel 파일·해시 |
| 컨테이너 | 원본 레지스트리, 태그, digest, 아키텍처, 반입 사본 경로 |
| Kubernetes·AWX | 실행 파일, Operator 릴리스, 매니페스트, 참조 이미지 전체 |
| 자동화 코드 | Git commit, Collection 버전과 의존성, 실행 환경 digest |
| 구성 | DNS·NTP·CA·저장소·볼륨 경로, 비밀정보가 제거된 설정 |
온라인망에서 구성 시
준비용 Rocky 환경에서 저장소 플러그인을 설치한 후 허용한 저장소별로 동기화한다. 아래는 BaseOS 한 개를 복제하는 예시다. AppStream, CRB, 선택한 솔루션 저장소는 실제 활성 repo ID와 필요성에 따라 별도로 준비한다. 전체 저장소 동기화에는 상당한 공간이 필요하므로 용량을 먼저 확인한다.
# 인터넷 가능한 동일 OS의 준비 VM
sudo dnf install dnf-plugins-core
dnf repolist --enabled
mkdir -p ./bundle/rpm
dnf reposync --repoid=baseos --download-path=./bundle/rpm --download-metadata
rpm -qa --qf '%{NAME}-%{EPOCHNUM}:%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort > rpm-installed.txt
파일 목록·해시 매니페스트를 생성하고 신뢰한 채널에서 받은 체크섬과 비교한다. 자체 생성한 SHA256은 복사 중 변조·손상을 확인하는 도구이며 공급원의 진위를 단독으로 보장하지 않는다. RPM 서명 검증과 원본 공급원 확인을 함께 사용한다. Rocky 로컬 저장소 가이드
폐쇄망에서 구성 시
반입한 저장소를 먼저 읽기 전용 매체나 로컬 디렉터리로 공급할 수 있다. 초기 실습은 별도 웹 저장소 서버의 부트스트랩 의존성을 줄이기 위해 file:// 경로를 사용할 수 있다. 아래는 /srv/fullmoon/rpm/baseos/repodata가 존재하고 Rocky 공식 서명 키를 확인했다는 전제의 repo 파일 예시다.
[fml-baseos]
name=FullMoon approved Rocky BaseOS snapshot
baseurl=file:///srv/fullmoon/rpm/baseos
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-10
GPG 키 파일명과 지문은 반입한 Rocky release 패키지 기준으로 확인한다. AppStream도 같은 방식으로 만든 뒤 외부 저장소를 명시적으로 제외하고 캐시 생성·설치를 시험한다.
sudo dnf --disablerepo='*' --enablerepo='fml-*' makecache
sudo dnf --disablerepo='*' --enablerepo='fml-*' install chrony
이미 설치된 패키지 하나가 성공한 것으로 공급 묶음을 합격시키지 않는다. 새 VM에서 전체 요구 패키지와 전이 의존성이 해결되는지 확인한다. 내부 HTTPS 저장소로 확장하면 CA 신뢰와 접근 로그를 추가한다.
6. NetBox와 의존성 구성
NetBox는 fml-core01에 배치한다. PostgreSQL과 Redis를 준비하고 애플리케이션 계정·DB·권한을 분리한다. 선택한 릴리스의 요구 Python·PostgreSQL·Redis 버전을 먼저 확인한다. 작성 시 확인한 stable 설치 문서는 Ubuntu에서 검증된 절차이므로 명령을 Rocky에 그대로 복사해 실행 완료로 간주하지 않는다. NetBox 공식 설치 문서
구축 순서는 DB 준비, Redis 준비, 릴리스 소스 배치, Python 가상환경과 requirements 설치, 애플리케이션 설정, 마이그레이션·정적 파일 준비, 애플리케이션과 백그라운드 Worker, HTTPS 역방향 프록시다. NetBox용 DB와 AWX용 DB, Zabbix용 DB의 계정·백업을 섞지 않는다.
| 초기 등록 대상 | 이 실습의 값·의도 |
|---|---|
| 사이트·클러스터 | VirtualBox 개인 실습 환경임을 식별 |
| VM·인터페이스·IP | 역할별 표와 일치시키고 기본 IP 지정 |
| 역할·플랫폼 | router, automation, monitoring, bastion, target / Rocky 10.2 |
| 승인 정보 | 별도 custom field 또는 승인 기록, 일반 수정과 배포 승인 구분 |
| 이벤트 | 승인한 대상에 한해 Worker로 통지, Webhook 검증·인증 적용 |
온라인망에서 구성 시
고정한 릴리스 소스와 requirements를 사용한다. 웹 화면 접속뿐 아니라 DB 마이그레이션, Redis 연결, 백그라운드 작업, API 읽기·쓰기 권한을 각각 확인한다. 승인되지 않은 자산 수정이 배포를 실행하지 않는지도 시험한다.
폐쇄망에서 구성 시
같은 Python·OS·아키텍처의 준비 환경에서 wheel과 빌드 의존성을 준비한다. requirements 파일의 전이 의존성까지 버전을 고정한 목록을 사용한다. 다음은 준비된 로컬 묶음으로 설치하는 형식이며, NetBox 전체 설치를 대체하는 단일 명령은 아니다.
# 동일 Python 환경의 준비 VM
python -m pip download --dest wheelhouse -r requirements.lock
# 격리된 대상의 해당 가상환경
python -m pip install --no-index --find-links=wheelhouse -r requirements.lock
소스 배포본만 제공되는 의존성은 준비 환경에서 wheel을 빌드하고 검증해 반입한다. 설치 중 외부 PyPI 접근이 없는지 로그로 확인하고, NetBox 소스·정적 자산·백그라운드 서비스 설정도 함께 옮긴다.
7. K3s와 AWX 구축
AWX는 중앙 fml-core01의 단일 노드 K3s에 배치하는 실습 설계다. 이 K3s를 고가용성 클러스터로 표현하지 않는다. 운영용 AWX 서비스, DB와 PVC가 Core 1 장애의 영향을 받는다. Zabbix Server의 역할 전환 시험과 AWX 생존 여부를 구분한다.
온라인망에서 구성 시
선택한 K3s 버전과 Rocky 10의 SELinux 정책 패키지 호환성을 확인한다. 정상 노드, Pod DNS, 영속 볼륨과 재부팅 후 복구를 확인한 다음 AWX Operator를 배치한다. Operator의 Git 릴리스와 이미지 버전을 맞추고 지원하는 AWX 조합을 사용한다. 단순히 모든 구성요소의 최신 태그를 섞지 않는다. AWX Operator 기본 설치
관리 범위 내에서 Operator를 설치한 뒤 AWX 인스턴스, DB 영속 저장소, 관리자 비밀정보, HTTPS 진입점을 설정한다. AWX 내부 서비스는 기본적으로 ClusterIP로 두고 승인된 관리 경로의 역방향 프록시 또는 Ingress를 통해 접근한다. 공개 NodePort를 기본 접근법으로 사용하지 않는다.
# Core 1: K3s 설치 이후의 점검 명령
sudo k3s kubectl get nodes -o wide
sudo k3s kubectl get pods -A
sudo k3s kubectl get pvc -n awx
sudo k3s kubectl get events -n awx --sort-by=.lastTimestamp
AWX에는 Project, Inventory, Machine Credential, Execution Environment, Job Template을 만든다. 프로젝트 소스는 특정 commit으로 기록하고, 실행 환경에 필요한 Ansible Collection·SSH 클라이언트·CA를 포함한다. SSH 개인키는 AWX Credential로 관리하고 플레이북이나 본문에 넣지 않는다.
폐쇄망에서 구성 시
K3s 실행 파일과 같은 버전의 air-gap 이미지, 설치 스크립트, Rocky 10에 맞는 SELinux 정책과 RPM 의존성을 반입한다. 노드별 이미지 사전 적재 방식이라면 이미지를 /var/lib/rancher/k3s/agent/images/에 배치한다. INSTALL_K3S_SKIP_DOWNLOAD=true는 다운로드를 생략하는 옵션이며 SELinux나 TLS 검증을 끄는 옵션이 아니다. K3s Air-Gap 설치, K3s SELinux 구성
K3s 기본 이미지에는 AWX의 모든 이미지가 포함되지 않는다. Operator, AWX, DB, Execution Environment, init·보조 컨테이너를 렌더링한 매니페스트와 실제 Pod 명세에서 추출한다. 정확한 이미지 이름·태그 또는 digest로 모든 실행 노드에 공급하고 pull 정책도 점검한다. 외부 Git·Galaxy·레지스트리를 참조하는 AWX 설정은 내부 공급원으로 바꾼다. 내부 레지스트리가 없다면 사전 적재 방식에 맞춰 새 노드에서도 성공하는지 확인한다.
8. Bastion과 Zabbix 수집 경로 구성
SSH 접속은 중앙 실행 환경 → Bastion → Target으로 제한한다. ProxyJump는 단순 터널 경로이며 Bastion에서 플레이북을 실행하는 방식이 아니다. AWX 실행 환경 안에서도 두 서버의 호스트 키를 신뢰 가능한 경로로 등록한다.
# AWX 실행 환경 또는 관리 클라이언트의 SSH 설정 예시
Host fml-bastion
HostName 10.77.20.10
User labadmin
StrictHostKeyChecking yes
Host fml-target01
HostName 10.77.20.101
User labadmin
ProxyJump fml-bastion
StrictHostKeyChecking yes
Zabbix는 7.0 LTS 계열을 검토 기준으로 두고 설치 시점의 정확한 패치 버전과 Rocky 10 제공 패키지를 확인한다. EL9 패키지를 임의로 EL10에 혼용하지 않는다. 필요한 패키지가 없으면 지원되는 배포 방식과 의존성을 다시 결정한 후 진행한다. 현재 패키지 설치를 완료한 상태는 아니다.
| 순서 | 작업 | 완료 확인 |
|---|---|---|
| 1 | Monitor VM에 PostgreSQL과 Zabbix 스키마 준비 | DB 인증·권한·스키마, 초기 백업 |
| 2 | Core 1의 Server와 Monitor의 Web/API 구성 | DB 연결, HTTPS 접속, API 조회 |
| 3 | Remote에 Active Proxy와 로컬 DB 구성 | Proxy 식별자·TLS·중앙 통신 |
| 4 | Target에 Active Agent 2 구성 | Hostname과 Proxy 주소·TLS 일치 |
| 5 | 호스트·템플릿·Proxy 연결 | 필수 데이터 최신 값 수신 |
| 6 | Core 2의 Server를 동일 DB에 HA 노드로 추가 | 고유 HANodeName·NodeAddress, Active/Standby 확인 |
Active Agent는 Proxy의 TCP 10051로 연결하고 Active Proxy는 중앙 Server의 TCP 10051로 연결한다. Agent의 passive check를 추가하면 TCP 10050과 반대 방향 정책이 필요하다. Web/API의 HTTPS 경로는 이 수집 포트와 별개다.
온라인망에서 구성 시
공식 저장소에서 호환 버전의 Server·Proxy·Agent·Web 구성요소를 준비한다. DB 인증, TLS, Proxy 식별자, 템플릿과 실제 item 상태를 순서대로 확인한다. Active/Standby를 구성하기 전에 단일 Server의 정상 수집을 확인한다.
폐쇄망에서 구성 시
선택한 패키지와 DB 스키마·템플릿·의존성을 반입한다. 외부 알림 서비스는 내부 수신 경로로 바꾸거나 사용 범위를 명시한다. 내부 DNS·NTP·CA만으로 수집이 유지되는지 검사한다. Proxy 버퍼는 보관 모드·기간·디스크 여유를 기록하고 단절 시험 시간보다 충분한 범위를 확보한다. Zabbix Proxy, Zabbix Native HA
9. 표준 구성과 연동 Worker 연결
먼저 AWX에서 대상 한 대에 읽기 전용 facts 조회 작업을 실행한다. 대상 IP·호스트명·OS가 승인한 정보와 맞으면 계정, SSH, chrony, 방화벽, Agent 역할을 순차 적용한다. 접속 설정을 변경한 후에는 기존 세션만 유지된 것으로 성공을 판정하지 않고 새 세션을 연다.
Worker는 기성 제품 이름이 아니라 이 프로젝트에서 구현할 연동 구성요소다. 아래 계약을 먼저 정하고 기능을 구현해야 한다. 현재 동작하는 Worker가 이미 존재하는 것은 아니다.
| 단계 | 입력·행동 | 실패 처리 |
|---|---|---|
| 수신 | 인증된 NetBox 이벤트, 자산 ID와 구성 버전 | 승인·대상 불일치면 중단 |
| 작업 식별 | 자산 ID·구성 버전 기준 중복 검사·동시 실행 잠금 | 기존 작업을 조회하고 재사용 |
| 실행 | 고정 Project·Inventory·Credential로 AWX Job 시작 | Job ID와 실패 태스크 보존 |
| 대조 | 관측한 facts와 승인 정보 비교 | 기준을 자동 덮어쓰지 않고 중단 |
| 등록 | Zabbix의 기존 호스트 조회 후 생성·갱신 | 타임아웃이면 실제 생성 여부 재조회 |
| 완료 | 필수 item의 값·상태·시각 확인 | 등록 완료 상태에서 원인과 재시도 지점 기록 |
온라인망에서 구성 시
라이브러리와 코드 버전을 고정하고 서비스 계정으로 Worker를 실행한다. 토큰에는 필요한 API 권한만 준다. 작업 기록은 프로세스 메모리만 사용하지 않고 재시작 후 복구 가능한 저장소에 보관한다. 동일 요청 두 번과 응답 유실을 시험해 중복 호스트가 없는지 확인한다.
폐쇄망에서 구성 시
같은 코드·라이브러리·설정 구조를 반입하고 API 주소·CA·소스 공급원만 내부 환경에 맞게 바꾼다. 외부 webhook relay나 SaaS를 필수 의존성으로 두지 않는다. 오프라인에서도 같은 작업 ID와 실패 재개 규칙이 적용되어야 한다.
10. 백업·복원과 업데이트
스냅샷은 빠른 실습 복귀 지점이다. 같은 디스크의 스냅샷만으로 호스트 디스크 손실까지 대비했다고 주장하지 않는다. DB와 서비스 설정, 애플리케이션 비밀키·인증서, AWX 프로젝트·Credential 복호화에 필요한 자료, 영속 볼륨을 서비스 단위로 함께 관리한다.
업데이트 전에는 현재 매니페스트와 백업을 남기고 하나의 계층씩 변경한다. DB 스키마가 변경됐다면 컨테이너 이미지만 이전 것으로 바꿔 되돌릴 수 있다고 가정하지 않는다. 복구는 원본 서비스와 충돌하지 않는 별도 VM·주소에서 검증한 뒤 운영 경로에 반영한다.
온라인망에서 구성 시
승인한 업데이트를 준비 환경에서 먼저 시험한다. 마이그레이션·재시작·검증 로그를 남기고 기존 버전의 설치 자료와 일관된 백업을 보관한다.
폐쇄망에서 구성 시
새 반입 묶음에 변경 목록·버전·해시·의존성·복원 자료를 포함한다. 새 저장소 묶음을 먼저 검증하고 이전 묶음을 유지한다. 인터넷을 잠깐 열어 누락 파일을 내려받았다면 그 설치는 폐쇄망 재현 성공으로 집계하지 않는다.
11. 설치 후 기본 확인
아래 명령은 Rocky 게스트의 기본 상태를 읽는다. 서비스 active와 실제 연결 성공은 각각 확인해야 한다. 전체 검증 결과는 별도 검증 아티클에 정리했다.
cat /etc/rocky-release
uname -r
getenforce
sudo firewall-cmd --state
sudo sshd -t
sudo sshd -T
sudo visudo -c
systemctl is-active sshd chronyd firewalld
systemctl --failed --no-legend
timedatectl show -p Timezone -p NTPSynchronized
df -h / /boot /boot/efi
현재 기본 VM에서 위 항목과 SSH 새 접속을 확인했다. 정상 종료 후 base-rocky10.2-20260919 스냅샷을 남겼으며, 신규 설치 재현·복제 일반화·스냅샷 복원은 별도 시험으로 남아 있다.
12. 오류 기록과 구축 종료 기준
VM 구성 중 실제 발생한 오류는 별도 글 「Rocky Linux 10.2 VM 구축기 — 설치를 막은 다섯 가지 오류와 진단 기록」에서 다룬다. 설치 MSI, 이전 VirtualBox 프로세스, UEFI·미디어, vCPU 정체, Kickstart 후처리의 증상·조치·결과를 기록했다. 아직 발생하지 않은 솔루션 오류를 경험담으로 쓰지 않는다.
구축 종료는 모든 VM이 켜진 시점이 아니다. 신규 서버 한 대가 승인 정보와 일치하고, 지정된 접근 경로로 표준 구성이 적용되며, 실제 모니터링 값이 도착하고, 같은 절차를 다시 실행할 수 있어야 한다. 폐쇄망에서는 이 조건을 내부 자료만으로 만족해야 한다. 마지막으로 별도 환경에서 복원해 같은 기능이 돌아오는지 확인한다.
다음 글 「설치 성공에서 운영 준비까지 — Rocky Linux 검증 기록과 통합 시험 기준」은 실제 기본 VM의 출력과 각 통합 시험의 전제·합격 기준·증거 형식을 제공한다. 이 절차를 따라 얻은 로그가 쌓일 때마다 설계와 실제 구성을 대조하고 검증 상태를 갱신한다.