English {#english}
After Pulumi has created Hetzner servers and Cloudflare resources, pass outputs (server_ip, db_server_ip, management_dns, etc.) to Ansible inventory and run playbooks. Ref: pulumi-ansible-step1-step2-plan §1.3·§2, provision-tenant-pipeline. Full details: see Korean section below.
한국어 {#korean}
Runbook: Pulumi 완료 후 Ansible 실행 연결 방법
전제: Pulumi로 Hetzner 서버 생성 및 Cloudflare 설정이 이미 완료된 상태.
목적: 이 정보를 Ansible에 넘겨 Ansible을 실행하는 방법 정리. (코드 생성 없음 — 방법만 안내)
Ref: pulumi-ansible-step1-step2-plan §1.3·§2, provision-tenant-pipeline.
1. Pulumi에서 Ansible로 넘겨야 할 정보
| Pulumi 출력 | Ansible에서의 용도 |
|---|---|
server_ip (또는 app_server_ip) | App 서버 IP → 인벤토리 prego_nodes의 ansible_host |
db_server_ip | DB 서버 IP → 인벤토리 prego_db_servers의 ansible_host, prego_nodes의 db_host |
management_dns | 참고용(SSH 시 node-01.pregoi.com 등). 인벤토리는 IP 사용 권장 |
값 얻는 방법 (Pulumi가 이미 완료된 경우):
스택이 passphrase로 암호화되어 있으면 먼저 패스프레이즈를 사용할 수 있게 해야 합니다. prego-pulumi/.env.local에 PULUMI_CONFIG_PASSPHRASE가 있으면 해당 파일을 로드한 뒤 stack output을 실행하세요.
cd /Users/marco/prego-pulumi# .env.local에 PULUMI_CONFIG_PASSPHRASE가 있으면 로드 (set -a로 export까지 적용)set -a && source .env.local && set +a
pulumi stack select sg # 또는 us, eu — 사용 중인 스택pulumi stack output server_ippulumi stack output db_server_ip2. 자동 연동: GitHub Actions 워크플로
서버가 이미 있고, 같은 파이프라인 안에서 Pulumi 출력을 받아 Ansible까지 이어서 실행하려면 Provision Tenant 워크플로를 사용하면 됩니다.
2.1 “서버는 이미 있음” 시나리오 (Pulumi 스킵)
- 이미 Pulumi로 서버 생성·Cloudflare 설정이 끝났다면, 워크플로에서는 새 서버를 만들지 않고 기존 서버 IP만 사용해 Ansible을 돌리면 됩니다.
provision-tenant.yml에서:- target_server_id 에 기존 노드 ID를 넣으면, Control Plane API로 해당 노드의
host(IP)를 가져와서 그 IP로 인벤토리를 만들고 Ansible을 실행합니다. - 즉, “Pulumi는 이미 끝났고, IP는 Control Plane에 등록된 노드로 쓰는” 자동 연동입니다.
- target_server_id 에 기존 노드 ID를 넣으면, Control Plane API로 해당 노드의
2.2 “이번에 Pulumi up 한 뒤 바로 Ansible” 시나리오
- create_new_server: true 로 워크플로를 띄우면:
resolve-serverjob에서 Pulumi up 실행 후pulumi stack output server_ip,db_server_ip로 IP를 읽고- 그 값을 job output으로 내보내고
- ansible-provision job이
needs.resolve-server로 그 출력을 받아 - 인벤토리 파일을 동적으로 생성 (
inventory/inventory.yml에SERVER_IP,DB_SERVER_IP치환) - ansible-playbook 실행
즉, “Pulumi에서 서버 생성이 완료되고 Cloudflare 설정이 다 됐다”는 정보는, 워크플로에서는 resolve-server의 outputs (server_ip, db_server_ip) 로 전달되고, Ansible은 그 IP로 생성된 인벤토리를 사용해 실행됩니다.
2.3 자동 연동 요약
| 방식 | 입력 | 결과 |
|---|---|---|
| 기존 노드 사용 | target_server_id = 노드 ID | Control Plane에서 host 조회 → 해당 IP로 인벤토리 생성 → Ansible 실행 |
| 이번에 Pulumi up | create_new_server: true, region | Pulumi up → stack output으로 server_ip, db_server_ip 획득 → 인벤토리 생성 → Ansible 실행 |
둘 다 “Pulumi(또는 기존 노드)에서 나온 IP”를 Ansible에 넘기는 구조라, 정보 연결은 워크플로가 job output과 인벤토리 생성으로 처리합니다.
3. 테스트 모드: 커맨드에서 Ansible 수동 실행
Pulumi와 Cloudflare는 이미 끝났고, 로컬/테스트에서 명령어로만 Ansible을 실행하는 방법입니다.
3.1 사전 확인
- Pulumi 스택에서 IP 확인 가능:
pulumi stack output server_ip,db_server_ip - prego-ansible 레포 클론 또는 로컬 경로:
/Users/marco/prego-ansible(또는 해당 경로) - SSH 키: Hetzner에 등록한 키와 동일한 키(예:
~/.ssh/prego-admin)로root@<server_ip>접속 가능해야 함
3.2 Step 1 — Pulumi에서 IP 가져오기
.env.local에 PULUMI_CONFIG_PASSPHRASE가 있으면 먼저 로드한 뒤 실행하세요.
cd /Users/marco/prego-pulumiset -a && source .env.local && set +a
pulumi stack select sg # 사용 중인 스택 (sg / us / eu)export APP_IP=$(pulumi stack output server_ip)export DB_IP=$(pulumi stack output db_server_ip)echo "App: $APP_IP DB: $DB_IP"3.3 Step 2 — 인벤토리 파일 준비
방법 A: 예제 복사 후 수동 치환
cd /Users/marco/prego-ansiblecp inventory/inventory.example.yml inventory/inventory.yml# inventory/inventory.yml 을 열어# REPLACE_WITH_APP_SERVER_IP → 위에서 확인한 App IP (또는 $APP_IP)# REPLACE_WITH_DB_SERVER_IP → 위에서 확인한 DB IP (또는 $DB_IP)# 로 치환방법 B: 한 번에 셸로 생성 (테스트용)
cd /Users/marco/prego-ansibleAPP_IP="여기에_App_서버_IP"DB_IP="여기에_DB_서버_IP"TENANT_ID="test-tenant-01"
mkdir -p inventorycat > inventory/inventory.yml << EOFall: children: prego_db_servers: hosts: db_01: ansible_host: ${DB_IP} vars: ansible_user: root ansible_ssh_private_key_file: ~/.ssh/prego-admin prego_nodes: hosts: node_01: ansible_host: ${APP_IP} tenant_id: "${TENANT_ID}" vars: ansible_user: root ansible_ssh_private_key_file: ~/.ssh/prego-admin db_host: ${DB_IP} db_port: 3306EOFAPP_IP, DB_IP, TENANT_ID만 Pulumi 출력과 테넌트에 맞게 바꿔서 실행하면 됩니다.
3.4 Step 3 — Ansible 실행
필수 extra vars: tenant_id, db_root_password. (선택) canonical_hostname.
cd /Users/marco/prego-ansibleansible-playbook -i inventory/inventory.yml playbook.yml \ -e tenant_id=YOUR_TENANT_ID \ -e db_root_password=YOUR_DB_ROOT_PASSWORD예 (테스트용 tenant_id, 비밀번호는 안전한 값으로 교체):
ansible-playbook -i inventory/inventory.yml playbook.yml \ -e tenant_id=test-tenant-01 \ -e db_root_password=YourSecureDbRootPassword- API 키는 실행 후
artifacts/tenant_api_key.txt에 기록됩니다 (디렉터리 없으면 생성, git 무시).
3.5 SSH 키 세팅 — 어디서 하나
Ansible이 서버에 접속하려면 Pulumi로 서버에 주입된 것과 같은 SSH 키를 로컬에서 써야 합니다. 세팅은 두 곳에서 합니다.
| 단계 | 어디서 | 할 일 |
|---|---|---|
| 1. 키 쌍 생성 (로컬) | 사용하는 PC | ssh-keygen -t ed25519 -f ~/.ssh/prego-admin (또는 -t rsa -b 4096). 비밀키는 ~/.ssh/prego-admin, 공개키는 ~/.ssh/prego-admin.pub. |
| 2. Hetzner에 공개키 등록 | Hetzner Cloud 콘솔 → 프로젝트 선택 → Security → SSH Keys → Add SSH Key | Name에 prego-admin 입력(Pulumi __main__.py의 ssh_key_name과 동일해야 함). Public key에 ~/.ssh/prego-admin.pub 내용 붙여넣기. |
| 3. Pulumi로 서버 생성 | 이미 완료했다면 생략 | 서버 생성 시 Pulumi가 Hetzner에서 이름 prego-admin인 키를 조회해 해당 서버에 주입함. |
| 4. Ansible에서 사용 | 인벤토리 / 실행 환경 | 인벤토리 ansible_ssh_private_key_file: ~/.ssh/prego-admin 이 로컬의 비밀키 파일 경로를 가리키면 됨. 즉, 로컬에 ~/.ssh/prego-admin 파일이 있으면 Ansible이 그걸 씀. |
정리:
- Hetzner: 공개키를 이름
prego-admin으로 등록해 두는 것(1단계 Pulumi 전에 해두면 서버 생성 시 자동 주입). - 로컬: 비밀키를
~/.ssh/prego-admin에 두는 것. 인벤토리가 그 경로를 참조하므로 별도 “Ansible용 설정”은 없고, 그 경로에 파일만 있으면 됨.
다른 경로에 비밀키를 두었다면 inventory.yml의 ansible_ssh_private_key_file 값을 해당 경로로 바꾸면 됩니다.
3.6 테스트 모드 요약 (커맨드만)
- Pulumi에서 IP 확인:
pulumi stack output server_ip,db_server_ip - 인벤토리 작성:
inventory/inventory.yml에 위 IP와 tenant_id 반영 (예제 복사 후 치환 또는 셸로 생성) - Ansible 실행:
ansible-playbook -i inventory/inventory.yml playbook.yml -e tenant_id=... -e db_root_password=...
4. 정리
| 목적 | 방법 |
|---|---|
| 자동 연동 | GitHub Actions provision-tenant.yml 사용. 서버는 기존 노드(target_server_id) 또는 이번에 Pulumi up(create_new_server: true). resolve-server 출력(server_ip, db_server_ip)이 Ansible job으로 전달되어 인벤토리 생성 후 playbook 실행. |
| 테스트(커맨드) | Pulumi stack output으로 IP 확인 → prego-ansible에서 inventory.yml에 해당 IP와 tenant_id 설정 → ansible-playbook -i inventory/inventory.yml playbook.yml -e tenant_id=... -e db_root_password=... 로 실행. |
Pulumi에서 “서버 생성이 완료되고 Cloudflare 설정이 다 됐다”는 정보는 server_ip / db_server_ip 두 값이면 Ansible과 연결할 수 있고, 자동화는 워크플로의 job output과 인벤토리 생성으로, 테스트는 위 커맨드 순서로 처리하면 됩니다.