개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 잘못된 부분은 말씀주시면 감사하겠습니다
본 내용은 아래 자료를 기반으로 학습하면서 작성했습니다.
- https://docs.openstack.org/heat/latest/
- https://wikidocs.net/230737
- https://somaz.tistory.com/383
- https://docs.redhat.com/ko/documentation/red_hat_openstack_platform/16.1/html/advanced_overcloud_customization/assembly_understanding-heat-templates
Heat Concept


Heat는 결국 Orchestrtation as a Service를 위한 Openstack Component!
이를 위해 Template 을 통해 정의하고,Stack 이라는 실제 Instance를 생성해서 구성 및 관리하는 것으로 보인다.
"HOT" (Heat Orchestration Template)
YAMLorJSON으로 작성이 가능한데, 대부분YAML으로 작성 하는 것으로 보임- 특징으로
AWS CloudFormation호환이 됨 - Template 구성 시 조건부/조건문, 중첩구조 등이 가능함
| (참고) AWS CloudFormation 호환 관련해서는, 공식 Component Docs 내 아래와 같은 문구도 볼 수 있음 현재 OpenStack에는 CloudFormation을 구현한 다른 프로젝트가 존재하지 않습니다. 개발자들은 클라우드 개발자들이 AWS에서 OpenStack 배포 환경으로 워크로드를 이전하고자 하는 강한 요구가 있다고 믿고 있습니다. OpenStack에서 잘 구현되고 통합된 CloudFormation API가 부재한 상황에서, 우리는 이 공백을 메우는 고품질 구현을 제공함으로써 OpenStack의 보편성을 향상시키고자 합니다. |
"Stack"
- 위
HOTTemplate에 정의된대로 생성된 실제 Infrastructure (Server, Network, Port...)들을 의미 - 단, 위
HOT통해서 일관되고 반복적으로 여러Stack생성 등이 가능하다. (쓰는 이유 중 가장 중요한 점일듯..)
또한 중요한 기능으로 Stack 리소스 기반으로 Auto Scaling 기능을 지원함.
- 단, Auto Scaling을 위해서는 Metrics 등이 수집되고 관리되어야 하는데 이를 위해서
Ceilometer,Aodh등과 같은 요소들이 함께 필요한 것으로 보임.
Heat 사용에 대한 장점
대부분의 Application은, 단일 Layer가 아닌 Mutli Layer 기반으로 구성됨.
이를 위해서는(Application 의) Infrastructure 관점에서도 복잡한 구조를 가지게 됨.
하지만 WEB - WAS - DB 와 같은 (이제는.. Classiscal 하지만...) 3 Layer 구조를 Openstack 에서 형성하기 위해서는... (짧게 생각해도) 아래와 같이 Openstack 관점에서는 많은 구성 작업들이 필요함.
예시
- Layer 별로
Network혹은Subnet을 분리하고, - 서로 통신이 가능하도로
Router를 생성한 뒤 각각의Subnet을 연결하고, Port를 생성하는데, 추가로Security Group등으로 ACL을 제어하고,- 이후 각각
Server,Volume을 생성하고, - 또한 Ocatavia 기반의
LB를 연결하고... - 등등등 ........
하지만 Heat 를 통해서, 위와 같은 복잡한 구조의 인프라 배포 및 구성을 (Openstack 관점에서) 쉽게 할 수 있음
거기에 Template 구조를 통해서 Auto Scaling 뿐만아니라, 장애 등의 상황에서 자동으로 리소스 복구가 가능한 구조임.
즉, 관리의 단순화 + 인프라스트럭처 배포 및 운영의 자동화 등의 장점이 있음
Heat Architecture
Heat Services
ref. https://docs.openstack.org/heat/latest/developing_guides/architecture.html
Heat 를 구성하기 위해서 어떠한 Service 들이 구성되어 있는가?
heat
- Heat 서비스들에 대한 CLI 도구
heat-api- Openstack Natvie 한 Heat API 제공의 역할 (즉, api-server)
- API 요청을 수신할 경우 RPC 통신을 통해,
heat-engineService를 호출하는 구조
heat-api-cfn
- (참고)
cfn-> "CloudFormation" - AWS CloudFormation과 호환되는 AWS Query API를 제공하는 목적
- 역시 동일하게 API 요청 수신 시, RPC 통신으로 Heat Engine 으로 전송
heat-engine
- Orchestrate (template 실행 등)에 대한 Main 책임을 가지는 서비스임.
- 오케스트레이션 관련해서 API Consumer에게 Event 제공도 해주고 있음
Heat Agent를 활용한 Configuration
주 목적은 배포 된 Server 내에 (Agent 기반으로) 필요한 "Software Configuration" 을 실행하기 위함.
즉, Heat를 통해서 Infrastrucutre의 배포 뿐만 아니라, Software Config 까지 수행이 가능하다.
(간단한 예시로 특정 패키지 설치, 설정파일 배포, 특정 커맨드 실행)
단, 이를 위해서 생성한 Server 내 아래와 같은 Agent 설치 및 구성이 필요하다.
Server 내에서 Agent 설치를 위해선, Agent 설치는 Cloud-Init을 사용하거나 사전 설치 후 전용 Image 를 구성하는 등의 방식이 필요해보임
Heat Agent
Template->Stack으로 생성된Server내부에서 동작하는 Agent.- Agent 종류
os-collect-config- 설정 데이터 수집
os-refresh-config- 변경 설정 감지 ->
os-apply-config실행 트리거
- 변경 설정 감지 ->
os-apply-config- 수집된 설정데이터 기반으로 실제 파일 생성, 명령 실행 등 수행
Agent 구성 이후 사용 가능한,Template 리소스
- Agent 구성 이후,
Template내에서 아래와 같은 리소스 타입 구성들을 통해서 필요한 작업을 구성할 수 있다.type: OS::Heat::SoftwareConfigtype: OS::Heat::SoftwareDeployment
예시 Template
# 생략....
resources:
my_config:
type: OS::Heat::SoftwareConfig
properties:
config: |
#!/bin/bash
echo "Hello from Heat" > /tmp/hello.txt
my_deployment:
type: OS::Heat::SoftwareDeployment
properties:
config: { get_resource: my_config }
server: { get_resource: my_server }
# 생략....
Template -> Agent 기반의 실행 절차 요약
Heat Stack 생성 시
↓
heat-engine 이 SoftwareDeployment 리소스 생성
↓
heat-agent (예: os-collect-config) 가 주기적으로 설정 요청 확인
↓
설정 감지 시 os-apply-config 등을 통해 내부 명령 실행
↓
결과를 Heat API에 보고 (성공/실패 등)
Hands On
HOT (Heat Orchestration Template) 작성
Template 기본 구조
공식 Docs를 참고하면서 작성하면 된다.
Template 기본 구조
heat_template_version: 2016-10-14
description:
# a description of the template
parameter_groups:
# a declaration of input parameter groups and order
parameters:
# declaration of input parameters
resources:
# declaration of template resources
outputs:
# declaration of output parameters
conditions:
# declaration of conditions
heat_template_version
- Template 규격에 대한 Version 을 정의
- 현재 작성 시점 기준으로는
2021-04-16가 마지막 최신 Version 인 것 같다. - 다만, 버전 별로 지원되는 템플릿 렌더링 메서드나 구조에서 차이가 있을 수 있으니 이 부분은 미리 확인이 필요해보인다.
resources
- 해당 Template 을 통해서 생성할 실제 Resource들을 정의
- ref. https://docs.openstack.org/heat/2025.1/template_guide/hot_spec.html#wallaby
- resource 정의 시 위 문서를 참고해서, resource 별로 요구되는 properties 를 '직접' 혹은 '전달구조'로 전달해주면 된다.
- 아래는 Network와 Subnet 에 대한 Resource 생성을 정의한 예시
# 생략 ...
# Network
test01_network:
type: OS::Neutron::Net
properties:
name: test01_network
# Subnet
test01_subnet:
type: OS::Neutron::Subnet
properties:
name: test01_subnet
network: { get_resource: test01_network }
cidr: { get_param: my_net_cidr }
ip_version: 4
# 생략 ...
Network 생성 한 이후, 해당 Network 하위에 Subnet 을 생성한다.
- Subnet 생성 시점에, 상위 Network 리소스 정보를 얻기 위해서 { get_resource: test01_network } 와 같이 구성.
cidr는 CLI를 통해 Template 에서stack리소스 생성 시 직접 파라미터로 입력 받게 함. ({ get_param: my_net_cidr })- 이외에
properties중name과 같은 부분은 상수 하드코딩(?) 하였음.
직접 해본 예시 Template :: nginx 서버 구성하기
시나리오
Tenant(self-service, overlay) Network내 Web Server 역할을 수행할Server(VM)를 생성하고,- 사전에 정의한 외부 네트워크와 연결된 네트워크에서
Floating IP를 할당해서, 최종적으로는 외부에서 접근 가능한 Web Server를 배포하는 예시

각 Resource 별로 Properites (필수, optional ...) 등은 역시 공식 문서 참고하면서 작성
OpenStack Resource Types — openstack-heat 24.0.1.dev3 documentation
use_request_body_as_input Available since 6.0.0 (Mitaka) Defines the method in which the request body for signaling a workflow would be parsed. In case this property is set to True, the body would be parsed as a simple json where each key is a workflow inp
docs.openstack.org
샘플 Template
heat_template_version: 2018-08-31
description: "Simple Heat Test1"
parameters:
# NW
my_external_nw_name:
type: string
description: External Network ID for Router
my_net_cidr:
type: string
description: Tenant Network cidr
# Volume
my_image_id:
type: string
description: Image ID for Instance
my_volume_type:
type: string
description: Root Volume Type
# Server
my_public_key:
type: string
description: PublicKey
my_flavor_id:
type: string
description: Flavor for Instance
resources:
# Router
test01_router:
type: OS::Neutron::Router
properties:
name: test01_router
external_gateway_info: {
enable_snat: true,
network: { get_param: my_external_nw_name }
}
# Network
test01_network:
type: OS::Neutron::Net
properties:
name: test01_network
# Subnet
test01_subnet:
type: OS::Neutron::Subnet
properties:
name: test01_subnet
network: { get_resource: test01_network }
cidr: { get_param: my_net_cidr }
ip_version: 4
# Connect Subnet to Router
router_interface:
type: OS::Neutron::RouterInterface
properties:
router_id: { get_resource: test01_router }
subnet_id: { get_resource: test01_subnet }
# Security Group
test01_sg:
type: OS::Neutron::SecurityGroup
properties:
name: test01_sg
rules: [
{
direction: "ingress",
ethertype: "IPv4",
port_range_max: "80",
port_range_min: "80",
protocol: "tcp",
remote_ip_prefix: "0.0.0.0/0",
remote_mode: "remote_ip_prefix"
},
{
direction: "egress",
ethertype: "IPv4",
port_range_min: "1",
port_range_max: "65535",
protocol: "tcp",
remote_ip_prefix: "0.0.0.0/0",
remote_mode: "remote_ip_prefix"
},
{
direction: "egress",
ethertype: "IPv4",
port_range_min: "1",
port_range_max: "65535",
protocol: "udp",
remote_ip_prefix: "0.0.0.0/0",
remote_mode: "remote_ip_prefix"
}
]
# Port
test01_port:
type: OS::Neutron::Port
properties:
name: test01_port1
network: { get_resource: test01_network }
fixed_ips: [{ "subnet": { get_resource: test01_subnet } }]
security_groups: [{ get_resource: test01_sg }]
# Floating IP
test01_fip:
type: OS::Neutron::FloatingIP
properties:
floating_network: { get_param: my_external_nw_name }
# ---
# Keypair
test01_keypair:
type: OS::Nova::KeyPair
properties:
name: test01_keypair
public_key: { get_param: my_public_key }
# Root Volume
test01_root_volume:
type: OS::Cinder::Volume
properties:
name: test01_root_volume
image: { get_param: my_image_id }
size: 40
volume_type: { get_param: my_volume_type }
# Server
test01_server:
type: OS::Nova::Server
properties:
name: test01_server
key_name: { get_resource: test01_keypair }
flavor: { get_param: my_flavor_id }
block_device_mapping_v2: [
{
delete_on_termination: True,
volume_id: { get_resource: test01_root_volume }
}
]
networks: [{ port: { get_resource: test01_port }} ]
user_data:
str_replace:
template: |
#!/bin/bash
apt update
apt install -y nginx
systemctl enable nginx
systemctl start nginx
params: {}
# Associate Floating IP
test01_fip_associate:
type: OS::Neutron::FloatingIPAssociation
properties:
floatingip_id: { get_resource: test01_fip }
port_id: { get_resource: test01_port }
outputs:
test01_server:
value: { get_attr: [ test01_server, name, networks ]}
floating_ip:
value: { get_attr: [ test01_fip, floating_ip_address ]}
- VM 내 Nginx 구성은, 간단히 Cloud-Init 스크립트 기반으로 구성!
Heat CLI
Template 에서 Stack 생성하기
우선, 작성한 Template에 오류가 없는지 검증하기 위해, Template 에서 정의한 parameter 들을 같이 전달해서 validate 를 수행해보자.
openstack orchestration template validate -t /heat01.yaml \
--parameter my_external_nw_name='provider-nw' \
--parameter my_net_cidr='192.168.100.0/24' \
--parameter my_image_id='c2ffc3d6-b84e-4fb6-a708-7e8562eeee10' \
--parameter my_volume_type='rbd1' \
--parameter my_flavor_id='29eb198c-e2ae-44e6-bce2-6f1b3fdb987b' \
--parameter my_public_key="$(cat /test.pub)"
- Heat 템플릿 문법 및 리소스 검증을 수행
- 별도의 오류가 없다면, 정상적으로 템플릿 구조 요약 출력
위에서 정의한 Template 파일를 통해서 실제로 stack 리소스를 생성하자.
openstack stack create -t /heat01.yaml \
--parameter my_external_nw_name='provider-nw' \
--parameter my_net_cidr='192.168.100.0/24' \
--parameter my_image_id='c2ffc3d6-b84e-4fb6-a708-7e8562eeee10' \
--parameter my_volume_type='rbd1' \
--parameter my_flavor_id='29eb198c-e2ae-44e6-bce2-6f1b3fdb987b' \
--parameter my_public_key="$(cat /test.pub)" \
my-stack-01 --wait
CLI 실행 결과

생성된 리소스 구성

Stack 조회, 삭제 등..!
이후 필요에 따라 생성한 stack 리소스에 대해서 조회, 삭제 등을 수행이 가능
# Stack 리스트 조회
openstack stack list
# Stack 상세 조회
openstack stack show <stack-name>
# 특정 Stack Event 조회
openstack stack evnet list <stack-name>
# 특정 Stack 삭제
openstack stack delete <stack-name>
# 그외 등...
Next🤨 ...
다음 편에 이어서 해보거나, 아직은 궁금한 것들!
- Ceilometer 와 연계해서, Auto Scaling 등 해보기!
- Heat engine 은 어떤 내부 구조로 리소스들이 생성되는 것을 감지하고 넘어가는 것일까?
- 템플릿에서 -> 리소스 생성을 위한 Graph 구성은 어떤 방식으로 하는 것일까?
'Cloud > Openstack' 카테고리의 다른 글
| Openstack :: Nova Cell 이란? (0) | 2025.10.18 |
|---|---|
| Openstack :: Nova의 Service 목록과 Status & State (0) | 2025.09.23 |
| Openstack :: Keystone System Role (0) | 2025.02.16 |
| Openstack :: barbican 이란? (1) | 2025.02.08 |