ansible-galaxy collection install openstack.cloud
인증 정보 설정 (clouds.yaml)
~/.config/openstack/clouds.yaml/etc/kolla/admin-openrc.sh 파일의 내용을 참고해서 작성# clouds.yaml
clouds:
my-openstack:
auth:
auth_url: "http://<admin-openrc.sh의 OS_AUTH_URL>/v3"
username: "admin"
password: "<비밀번호>"
project_name: "admin"
project_domain_name: "Default"
user_domain_name: "Default"
region_name: "RegionOne"
interface: "public"
identity_api_version: 3
http://IP:5000/v3라는 특정 경로에서 인증 토큰 발행 요청을 받는다. # 해당 코드는 에러가 발생함. 이유는 아래에서 설명
---
- name: OpenStack Resource Provisioning
hosts: localhost
connection: local
gather_facts: false
vars:
cloud_name: "my-openstack" # clouds.yaml에 정의한 이름
vm_name: "ansible-test-vm"
image_name: "cirros"
flavor_name: "m1.tiny"
key_name: "my-key"
net_name: "private_net_ansible"
subnet_name: "private_subnet_ansible"
router_name: "router_ansible"
ext_net_name: "ext_net" # 대시보드를 통해 만든 외부 네트워크 이름
cidr: "10.0.1.0/24"
dns_servers: ["8.8.8.8"]
tasks:
- name: 1. Create Private Network (VXLAN)
openstack.cloud.network:
cloud: "{{ cloud_name }}"
name: "{{ net_name }}"
state: present
external: false
- name: 2. Create Subnet
openstack.cloud.subnet:
cloud: "{{ cloud_name }}"
name: "{{ subnet_name }}"
network_name: "{{ net_name }}"
cidr: "{{ cidr }}"
dns_nameservers: "{{ dns_servers }}"
state: present
- name: 3. Create Router and Connect to External Network
openstack.cloud.router:
cloud: "{{ cloud_name }}"
name: "{{ router_name }}"
state: present
network: "{{ ext_net_name }}" # Gateway 설정
interfaces:
- "{{ subnet_name }}"
- name: 4. Create Keypair
openstack.cloud.keypair:
cloud: "{{ cloud_name }}"
name: "{{ key_name }}"
state: present
public_key_file: "<본인 SSH 키 경로>"
- name: 5. Allow ICMP (Ping) in Security Group
openstack.cloud.security_group_rule:
cloud: "{{ cloud_name }}"
security_group: default
protocol: icmp
remote_ip_prefix: 0.0.0.0/0
state: present
- name: 6. Allow SSH in Security Group
openstack.cloud.security_group_rule:
cloud: "{{ cloud_name }}"
security_group: default
protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
state: present
- name: 7. Create VM Instance
openstack.cloud.server:
cloud: "{{ cloud_name }}"
name: "{{ vm_name }}"
state: present
image: "{{ image_name }}"
flavor: "{{ flavor_name }}"
key_name: "{{ key_name }}"
network: "{{ net_name }}"
wait: yes
auto_ip: yes # Floating IP 자동 할당 옵션
register: server_info
- name: 8. Print VM IP Address
debug:
msg: "VM Created! IP: {{ server_info.server.accessIPv4 }}"
public_key_file에서 SSH 키 경로 확인 방법
# .pub로 끝나는 파일이 있다면 그 파일의 경로가 SSH 키 경로 $ ls -al ~/.ssh/*.pub # 파일이 없다면 다음의 명령어로 생성 $ ssh-keygen -t rsa -b 4096
vars:
sec_group_name: "ansible-secgroup" # 새로 만들 보안 그룹 이름
tasks:
# 보안 그룹 생성
- name: 5. Create Security Group
openstack.cloud.security_group:
cloud: "{{ cloud_name }}"
name: "{{ sec_group_name }}"
description: "Security group for Ansible test"
state: present
# 새로 만든 그룹에 ICMP/SSH 규칙 추가
- name: 6. Allow ICMP and SSH
openstack.cloud.security_group_rule:
cloud: "{{ cloud_name }}"
security_group: "{{ sec_group_name }}" # default가 아니라 위에서 만든 그룹 지정
protocol: "{{ item.protocol }}"
port_range_min: "{{ item.port | default(omit) }}"
port_range_max: "{{ item.port | default(omit) }}"
remote_ip_prefix: 0.0.0.0/0
state: present
loop:
- { protocol: icmp }
- { protocol: tcp, port: 22 }
# 보안 그룹 연결 부분 수정
- name: 7. Create VM Instance
openstack.cloud.server:
cloud: "{{ cloud_name }}"
name: "{{ vm_name }}"
state: present
image: "{{ image_name }}"
flavor: "{{ flavor_name }}"
key_name: "{{ key_name }}"
network: "{{ net_name }}"
security_groups:
- "{{ sec_group_name }}"
wait: yes
auto_ip: yes
register: server_info
- name: 8. Print VM IP Address
debug:
var: server_info
server_info.server.addresses.private_net_ansible[0].addr

$ ansible-playbook provision_vm.yml
# common_vars.yml
cloud_name: "my-openstack"
vm_name: "ansible-test-vm"
key_name: "my-key"
net_name: "private_net_ansible"
subnet_name: "private_subnet_ansible"
router_name: "router_ansible"
sec_group_name: "ansible-secgroup"
image_name: "cirros"
flavor_name: "m1.tiny"
ext_net_name: "ext_net"
cidr: "10.0.1.0/24"
dns_servers: ["8.8.8.8"]
# delete_resources.yml
---
- name: OpenStack Resource Clean-up
hosts: localhost
connection: local
gather_facts: false
vars_files:
- common_vars.yml
tasks:
- name: 1. Delete VM Instance
openstack.cloud.server:
cloud: "{{ cloud_name }}"
name: "{{ vm_name }}"
state: absent
wait: yes # VM이 완전히 사라질 때까지 대기
- name: 2. Delete Security Group
openstack.cloud.security_group:
cloud: "{{ cloud_name }}"
name: "{{ sec_group_name }}"
state: absent
- name: 3. Delete Keypair
openstack.cloud.keypair:
cloud: "{{ cloud_name }}"
name: "{{ key_name }}"
state: absent
- name: 4. Detach Subnet from Router (Interface 제거)
openstack.cloud.router:
cloud: "{{ cloud_name }}"
name: "{{ router_name }}"
state: present
interfaces: [] # 인터페이스 목록을 비워서 강제로 분리
- name: 5. Delete Router
openstack.cloud.router:
cloud: "{{ cloud_name }}"
name: "{{ router_name }}"
state: absent
- name: 6. Delete Subnet
openstack.cloud.subnet:
cloud: "{{ cloud_name }}"
name: "{{ subnet_name }}"
state: absent
- name: 7. Delete Network
openstack.cloud.network:
cloud: "{{ cloud_name }}"
name: "{{ net_name }}"
state: absent
모듈별 동작 분석
POST /v2.0/networks)cloud: my-openstack 정보를 이용해 인증 토큰을 발급받는다. (Keystone)state: present를 확인하고, private_net_ansible이라는 이름의 네트워크가 이미 존재하는지 조회(GET)한다. (멱등성)external: false 옵션에 의해 이 네트워크는 Tenant Network로 설정된다. Kolla-Ansible의 기본 설정에 따라 VXLAN 타입으로 생성되며, VNI(VXLAN ID)가 자동으로 할당된다.network_name 변수를 참조하여, 앞서 만든 네트워크의 UUID를 조회한다. (API는 이름 대신 UUID를 요구하기 때문)wait: yes) : VM 상태가 BUILD에서 ACTIVE로 변할 때까지 API를 주기적으로 Polling한다.auto_ip: yes)state: absentwait: yes (VM 삭제 시 필수)interfaces: []를 주면, Ansible은 이 라우터에는 아무 인터페이스도 없어야 한다고 판단하고 기존에 연결된 서브넷을 Detach 한다. (IaC의 선언적 특징 활용)