목차
Ansible로 멀티 클라우드 인프라 자동화: AWS, Azure, GCP 통합 관리 가이드
안녕하세요, 13년차 서버실 지킴이입니다. 요즘 인프라 환경을 보면 단순히 한 클라우드에만 갇혀 있지 않죠? 멀티 클라우드(Multi-Cloud)는 이제 선택이 아니라 필수가 되어가는 시대인 것 같습니다. 저도 처음엔 AWS만 주력으로 썼었는데, 프로젝트가 커지고 요구사항이 다양해지면서 Azure나 GCP도 함께 다루게 되더라고요. 근데 이게 여러 클라우드를 동시에 관리하려니 여간 복잡한 게 아니었습니다. 각 클라우드마다 CLI도 다르고, API도 다르고… 수동으로 관리하다가는 퇴근은커녕 야근만 늘겠다 싶었죠. 😭
이런 고민을 하던 중에 저의 든든한 동반자, Ansible(앤서블)을 떠올렸습니다. Ansible은 이미 온프레미스 환경에서 서버 자동화에 요긴하게 써왔던 도구거든요. '이걸로 멀티 클라우드도 통합 관리할 수 있지 않을까?' 하는 생각에 홈랩에서 이것저것 실험해봤습니다. 결과는 대만족이었습니다! 오늘은 제가 직접 경험하며 삽질했던 내용과 함께, Ansible로 AWS, Azure, GCP 인프라를 한 번에 자동화하는 방법을 여러분께 알려드리려고 합니다. 이 글을 통해 멀티 클라우드 관리의 복잡성을 확 줄여보시길 바랍니다. 자, 그럼 시작해볼까요? 🎉
Ansible을 활용한 멀티 클라우드 통합 관리 아키텍처 다이어그램.
Ansible, 왜 멀티 클라우드 자동화에 최적일까요?
먼저 Ansible이 어떤 녀석인지, 그리고 왜 멀티 클라우드 환경에 딱 맞는지 간단히 짚고 넘어가죠. 쉽게 말해 Ansible(앤서블)은 에이전트리스(Agentless) 기반의 자동화 도구(Automation Tool)입니다. 관리 대상 서버에 별도의 에이전트를 설치할 필요 없이 SSH(Secure Shell)나 WinRM(Windows Remote Management) 프로토콜을 이용해 명령을 실행하죠. 이게 멀티 클라우드 환경에서 엄청난 강점입니다.
- 단일 제어 플레인(Single Control Plane): 각 클라우드 콘솔이나 CLI를 오갈 필요 없이, Ansible 컨트롤러 노드(Control Node) 하나에서 모든 클라우드 인프라를 관리할 수 있습니다.
- 모듈(Modules) 기반의 추상화: Ansible은 각 클라우드 프로바이더(Cloud Provider)별로 수많은 모듈을 제공합니다. 예를 들어, AWS EC2 인스턴스를 만들 때는
amazon.aws.ec2_instance모듈을, Azure VM을 만들 때는azure.azcollection.azure_rm_virtualmachine모듈을 사용하죠. 각 클라우드 API의 복잡성을 몰라도 모듈만 잘 사용하면 됩니다. - 멱등성(Idempotency): 플레이북(Playbook)을 여러 번 실행해도 항상 동일한 최종 상태(Desired State)를 보장합니다. 이미 생성된 리소스는 건드리지 않고, 필요한 변경사항만 적용되니 안심하고 재실행할 수 있습니다.
- YAML(YAML Ain't Markup Language) 기반의 쉬운 학습 곡선: 복잡한 프로그래밍 언어 대신 사람이 읽고 쓰기 쉬운 YAML 문법으로 플레이북을 작성합니다. 인프라 엔지니어에게는 정말 친숙한 방식이죠.
결론적으로 Ansible은 코드로서의 인프라(Infrastructure as Code, IaC)를 구현하기에 아주 적합하며, 특히 이종 클라우드 환경을 통합 관리하는 데 강력한 성능을 발휘합니다.
실전 구현: AWS, Azure, GCP 인프라 자동화
자, 이제 직접 Ansible로 멀티 클라우드 인프라를 구축해볼 차례입니다. 목표는 각 클라우드에 웹 서버 역할을 할 가상 머신(Virtual Machine)을 하나씩 생성하고, 간단한 웹 서비스(Nginx)를 설치하는 것입니다.
1. Ansible 및 클라우드 연동 환경 설정
먼저 Ansible 컨트롤러 노드에 필요한 도구들을 설치해야 합니다. 저는 Ubuntu 환경에서 진행했습니다.
#!/bin/bash
# Ansible 설치
sudo apt update && sudo apt install -y ansible python3-pip
# AWS 연동을 위한 boto3 라이브러리 설치
pip3 install boto3 botocore
# Azure 연동을 위한 Azure CLI 및 모듈 설치
sudo apt install -y azure-cli
ansible-galaxy collection install azure.azcollection
# GCP 연동을 위한 Google Cloud SDK 및 모듈 설치
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt update && sudo apt install -y google-cloud-sdk
ansible-galaxy collection install google.cloud
각 클라우드 인증 정보 설정도 중요합니다:
- AWS:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY환경 변수 설정 또는~/.aws/credentials파일 설정 - Azure:
az login명령으로 로그인 또는 서비스 주체(Service Principal) 생성 후 환경 변수 설정 - GCP: 서비스 계정(Service Account) 키 파일 다운로드 후
GOOGLE_APPLICATION_CREDENTIALS환경 변수 설정
⚠️ 인증 정보 관리 중요: 실제 운영 환경에서는 AWS Secrets Manager, Azure Key Vault, GCP Secret Manager 같은 비밀 관리 서비스(Secret Management Service)를 활용하거나 Ansible Vault를 사용하여 인증 정보를 안전하게 보관해야 합니다. 절대 민감한 정보를 플레이북에 직접 넣지 마세요!
2. 동적 인벤토리(Dynamic Inventory) 설정
클라우드 환경은 리소스가 수시로 생성/삭제되기 때문에 고정된 인벤토리 파일보다는 동적 인벤토리를 사용하는 것이 효율적입니다. Ansible은 각 클라우드 프로바이더를 위한 동적 인벤토리 플러그인을 제공하거든요.
# aws_ec2.yml (AWS EC2 인스턴스 동적 인벤토리)
plugin: amazon.aws.ec2
regions:
- ap-northeast-2
keyed_groups:
- key: tags.env
prefix: env_
# azure_rm.yml (Azure VM 동적 인벤토리)
plugin: azure.azcollection.azure_rm
include_vm_resource_groups:
- my-ansible-rg
# gcp_compute.yml (GCP Compute Engine 동적 인벤토리)
plugin: google.cloud.gcp_compute
projects:
- your-gcp-project-id
zones:
- asia-northeast3-a
이제 ansible-inventory -i aws_ec2.yml --list 등으로 각 클라우드의 인벤토리를 확인할 수 있습니다.
Ansible으로 생성된 각 클라우드 가상 머신 목록.
3. 클라우드 리소스 생성 플레이북 작성
각 클라우드에 가상 머신을 생성하고 Nginx를 설치하는 플레이북입니다. 하나의 플레이북에서 여러 클라우드를 대상으로 할 수 있다는 점이 핵심입니다.
---
# multi_cloud_infra.yml
# AWS, Azure, GCP에 동시에 웹 서버를 배포하는 플레이북
- name: AWS 인프라 준비
hosts: localhost
connection: local
gather_facts: no
vars:
aws_region: ap-northeast-2
ssh_key_path: ~/.ssh/id_rsa.pub
tasks:
# AWS Security Group 먼저 생성
- name: AWS 보안 그룹 생성
amazon.aws.ec2_security_group:
name: ansible-sg-aws
description: "Ansible managed AWS webserver security group"
region: "{{ aws_region }}"
rules:
- proto: tcp
ports: 22
cidr_ip: 0.0.0.0/0
- proto: tcp
ports: 80
cidr_ip: 0.0.0.0/0
rules_egress:
- proto: all
cidr_ip: 0.0.0.0/0
register: aws_sg_output
# AWS EC2 인스턴스 생성
- name: AWS EC2 인스턴스 생성
amazon.aws.ec2_instance:
name: ansible-aws-webserver
image_id: ami-0c802847a7dd848c0 # Ubuntu 22.04 LTS (ap-northeast-2)
instance_type: t2.micro
region: "{{ aws_region }}"
security_group: ansible-sg-aws
key_name: your_aws_keypair
tags:
env: dev
project: ansible-multi-cloud
state: running
wait: yes
register: aws_ec2_output
- name: Azure 인프라 준비
hosts: localhost
connection: local
gather_facts: no
vars:
azure_resource_group: my-ansible-rg
azure_location: koreacentral
ssh_key_path: ~/.ssh/id_rsa.pub
tasks:
# Azure Virtual Network 생성 (필수 선행 작업)
- name: Azure Virtual Network 생성
azure.azcollection.azure_rm_virtualnetwork:
resource_group: "{{ azure_resource_group }}"
name: ansible-vnet
location: "{{ azure_location }}"
address_prefixes:
- "10.0.0.0/16"
register: azure_vnet_output
# Azure Subnet 생성
- name: Azure Subnet 생성
azure.azcollection.azure_rm_subnet:
resource_group: "{{ azure_resource_group }}"
name: default
address_prefix: "10.0.0.0/24"
virtual_network: ansible-vnet
register: azure_subnet_output
# Azure NSG 생성
- name: Azure 네트워크 보안 그룹 생성
azure.azcollection.azure_rm_networksecuritygroup:
resource_group: "{{ azure_resource_group }}"
name: ansible-azure-nsg
location: "{{ azure_location }}"
rules:
- name: AllowSSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 100
direction: Inbound
- name: AllowHTTP
protocol: Tcp
destination_port_range: 80
access: Allow
priority: 110
direction: Inbound
register: azure_nsg_output
# Azure VM 생성
- name: Azure VM 생성
azure.azcollection.azure_rm_virtualmachine:
resource_group: "{{ azure_resource_group }}"
name: ansible-azure-webserver
vm_size: Standard_B1s
admin_username: azureuser
ssh_password_enabled: false
ssh_public_keys:
- path: /home/azureuser/.ssh/authorized_keys
key_data: "{{ lookup('file', ssh_key_path) }}"
image:
offer: 0001-com-ubuntu-server-jammy
publisher: Canonical
sku: 22_04-lts-gen2
version: latest
location: "{{ azure_location }}"
register: azure_vm_output
- name: GCP 인프라 준비
hosts: localhost
connection: local
gather_facts: no
vars:
gcp_project: your-gcp-project-id
gcp_zone: asia-northeast3-a
gcp_network: default
ssh_key_path: ~/.ssh/id_rsa.pub
gcp_user: ansible
tasks:
# GCP Firewall 규칙 생성
- name: GCP 방화벽 규칙 생성
google.cloud.gcp_compute_firewall:
name: ansible-gcp-allow-http-ssh
project: "{{ gcp_project }}"
allowed:
- IPProtocol: tcp
ports: [ '22', '80' ]
source_ranges: [ '0.0.0.0/0' ]
target_tags: [ 'http-server' ]
state: present
register: gcp_fw_output
# GCP Compute Engine 인스턴스 생성
- name: GCP Compute Engine 인스턴스 생성
google.cloud.gcp_compute_instance:
name: ansible-gcp-webserver
project: "{{ gcp_project }}"
zone: "{{ gcp_zone }}"
machine_type: e2-micro
disks:
- auto_delete: 'true'
boot: 'true'
initialize_params:
source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts
disk_size_gb: 20
network_interfaces:
- name: "{{ gcp_network }}"
access_configs:
- name: "External NAT"
type: "ONE_TO_ONE_NAT"
metadata:
ssh-keys: "{{ gcp_user }}:{{ lookup('file', ssh_key_path) }}"
tags:
items:
- http-server
state: present
register: gcp_instance_output
- name: 모든 클라우드 웹서버에 Nginx 설치
hosts: all
gather_facts: yes
pre_tasks:
- name: SSH 연결 대기
ansible.builtin.wait_for_connection:
timeout: 300
tasks:
- name: Nginx 설치
ansible.builtin.apt:
name: nginx
state: present
update_cache: yes
become: yes
- name: Nginx 서비스 시작
ansible.builtin.service:
name: nginx
state: started
enabled: yes
become: yes
위 플레이북은 각 클라우드별로 분리된 구조로 작성되어 있습니다. 첫 번째부터 세 번째까지는 각각 AWS, Azure, GCP 인프라를 생성하는 hosts: localhost 플레이북입니다. 마지막 플레이북은 동적 인벤토리에서 수집된 모든 호스트에 Nginx를 설치합니다.
플레이북 실행은 간단합니다:
ansible-playbook -i aws_ec2.yml -i azure_rm.yml -i gcp_compute.yml multi_cloud_infra.yml
⚠️ 삽질 경험 및 트러블슈팅
제가 이 과정을 진행하면서 겪었던 몇 가지 삽질 경험과 해결 방법을 공유합니다. 여러분은 저처럼 헤매지 마시길 바랍니다. ㅎㅎ
1. 클라우드 인증 실패
문제: 플레이북 실행 시 Unauthorized, Access Denied, Credential Error 같은 메시지가 뜨면서 클라우드 리소스 생성이 안 되는 경우가 많았습니다.
해결:
- AWS:
~/.aws/credentials파일의 내용이 정확한지, 또는 환경 변수(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY)가 올바르게 설정되었는지 확인했습니다. 그리고 해당 IAM 사용자에게 EC2 생성, Security Group 관리 등 필요한 권한이 제대로 부여되었는지 IAM 정책을 검토했습니다. - Azure:
az login으로 로그인 세션이 유효한지 확인하거나, 서비스 주체(Service Principal)를 사용한다면AZURE_CLIENT_ID,AZURE_SECRET,AZURE_TENANT,AZURE_SUBSCRIPTION_ID환경 변수가 정확한지 확인했습니다. 해당 서비스 주체에 기여자(Contributor) 또는 그에 준하는 역할이 할당되어야 합니다. - GCP: 서비스 계정 키 파일(JSON)의 경로가
GOOGLE_APPLICATION_CREDENTIALS환경 변수에 올바르게 지정되었는지 확인했습니다. 또한, 서비스 계정에 Compute Engine Instance Admin (v1), Service Account User 등 필요한 역할이 부여되어 있는지 GCP IAM 콘솔에서 확인했습니다.
2. SSH 접속 문제 (Nginx 설치 단계)
문제: 인스턴스는 잘 생성됐는데, Nginx 설치 단계에서 SSH Connection refused 또는 Timeout 에러가 발생했습니다.
해결:
- 보안 그룹/방화벽 규칙: 각 클라우드에서 생성된 가상 머신의 보안 그룹(AWS), 네트워크 보안 그룹(Azure), 방화벽 규칙(GCP)에 Ansible 컨트롤러 노드의 IP 주소 또는
0.0.0.0/0(테스트용)에서 22번 포트(SSH) 접속을 허용하는 규칙이 있는지 확인했습니다. - SSH 키페어: 플레이북에서 지정한
ssh_key_path의 퍼블릭 키가 각 클라우드 인스턴스에 올바르게 등록되었는지 확인했습니다. AWS는 키페어 이름을, Azure/GCP는 직접 퍼블릭 키 내용을 전달하는 방식이므로 차이에 유의했습니다. - 사용자 이름: 각 클라우드 인스턴스의 기본 사용자 이름이 다릅니다. AWS Ubuntu는
ubuntu, Azure Ubuntu는azureuser, GCP Ubuntu는ubuntu로 설정했습니다. 플레이북에ansible_user: 사용자명으로 명시하면 더 안전합니다. - 인스턴스 부팅 시간: 가끔 인스턴스가 완전히 부팅되기 전에 Ansible이 SSH 접속을 시도하여 실패하는 경우가 있습니다.
ansible.builtin.wait_for_connection모듈을 사용해 SSH 포트가 열릴 때까지 기다리도록 플레이북에 추가했습니다. 이건 정말 중요해요!
3. Azure 네트워크 구성 누락
문제: Azure VM을 생성하려니 Virtual Network와 Subnet이 없다고 에러가 나왔습니다.
해결: Azure는 AWS나 GCP와 달리 기본 네트워크 구조가 없으므로, VM 생성 전에 Virtual Network와 Subnet을 명시적으로 생성해야 합니다. 위의 플레이북에서 이를 추가했으니 참고하세요.
검증 및 결과 확인 ✅
플레이북 실행이 성공적으로 완료되었다면, 이제 각 클라우드 콘솔에 접속하여 리소스가 잘 생성되었는지 확인해볼 차례입니다. AWS EC2, Azure VM, GCP Compute Engine 목록에서 ansible-aws-webserver, ansible-azure-webserver, ansible-gcp-webserver라는 이름의 인스턴스가 실행 중인 것을 볼 수 있을 겁니다.
각 인스턴스의 퍼블릭 IP 주소로 웹 브라우저에서 접속해보세요. Nginx 기본 페이지가 보인다면 성공입니다! 드디어 됐다! 🎉
이 과정에서 여러분이 직접 각 클라우드의 콘솔을 열어 인스턴스를 생성하고, 보안 그룹을 설정하고, SSH로 접속해서 Nginx를 설치하는 수고를 덜 수 있었다는 것을 체감할 수 있을 겁니다. 자동화의 힘은 정말 대단하죠.
성공적으로 배포된 Nginx 웹 서버 페이지.
마무리하며: 클라우드 여정의 다음 단계
오늘은 Ansible을 활용해서 AWS, Azure, GCP 멀티 클라우드 환경에 인프라를 자동화하고 웹 서버를 배포하는 과정을 함께 해봤습니다. 제가 직접 해보니, 처음엔 각 클라우드 모듈과 인증 방식에 적응하는 데 시간이 좀 걸렸지만, 한 번 체계를 잡아두니 그 이후부터는 정말 편하더라고요. 삽질 끝에 얻은 귀한 경험이었습니다. 💡
이 글이 여러분의 멀티 클라우드 여정에 작은 등대가 되었기를 바랍니다. 여기서 멈추지 않고, 더 나아가 다음과 같은 내용들을 탐구해보시면 좋을 것 같습니다:
- Ansible Vault: 민감한 정보를 안전하게 관리하는 방법.
- CI/CD 파이프라인 통합: GitOps 워크플로우를 통해 변경 사항이 자동으로 배포되도록 구성.
- Terraform과의 연동: Terraform으로 인프라를 프로비저닝하고, Ansible로 프로비저닝된 인스턴스에 소프트웨어를 구성하는 하이브리드 접근 방식.
- 삭제 플레이북: 생성된 리소스를 깔끔하게 정리하는 삭제 플레이북 작성 (
state: absent활용).
저도 홈랩에서 이런저런 실험을 계속하면서 새로운 인사이트를 얻고 있습니다. 다음번에는 더 재미있고 유익한 경험담으로 찾아뵙겠습니다. 혹시 이 글을 읽으시면서 궁금한 점이나 공유하고 싶은 삽질 경험이 있으시다면 언제든지 댓글로 남겨주세요! 감사합니다!
Ansible을 통한 멀티 클라우드 자동화 요약.
'IT > Cloud' 카테고리의 다른 글
| [Cloud] Terraform vs Pulumi: IaC 도구 비교 및 선택 가이드 (0) | 2026.05.19 |
|---|---|
| [Cloud] Docker Compose 실전 가이드: 로컬 개발 환경 구축 및 관리 (1) | 2026.05.19 |
| [Cloud] Pulumi vs Terraform: 멀티 클라우드 IaC 선택 가이드 및 실전 활용 (0) | 2026.05.18 |
| [Cloud] GitHub Actions OIDC로 AWS 인증하기: 보안 강화 및 자격 증명 관리 (0) | 2026.05.15 |
| [Cloud] Terraform State 관리 완벽 가이드: S3, DynamoDB 활용 모범 사례 (0) | 2026.05.14 |
| [Cloud] GitHub Actions 모노레포: 매트릭스 빌드로 CI/CD 최적화하기 (0) | 2026.05.12 |