[ACI-IaC] Terraform vs Ansible 개요 ← 현재 글
[ACI-IaC] Terraform으로 Basic Tenant 프로비저닝하기
[ACI-IaC] Terraform으로 3계층 앱 구성하기
[ACI-IaC] Ansible로 Basic Tenant 프로비저닝하기
[ACI-IaC] Terraform vs Ansible 실전 비교
GitHub: github.com/MinYongUm/aci-as-code
개요
ACI를 Terraform(초기 프로비저닝)과 Ansible(운영/변경) 두 가지 IaC 도구로 구현하고 비교하는 시리즈입니다. Cisco DevNet Always-On Sandbox를 대상으로 Tenant, VRF, Bridge Domain, EPG, Contract를 코드로 관리합니다. 이 글은 시리즈 전체의 배경과 도구 선택 이유를 설명하는 개요 편입니다.
WHY — GUI 클릭으로는 뭐가 부족한가?
ACI APIC GUI는 직관적입니다. Tenant 만들고, BD 연결하고, EPG에 Contract 바인딩하는 작업을 빠르게 할 수 있습니다. 그런데 운영을 하다 보면 반드시 마주치는 상황이 있습니다.
문제 1 — 변경 이력이 없다
APIC GUI에서 설정을 바꿔도 별도 Change Log를 관리하지 않는 이상 누가, 언제, 무엇을 바꿨는지 추적할 방법이 없습니다. 장애가 발생했을 때 "어제 이 설정 건드린 사람 있어요?"라는 질문이 나오는 이유입니다.
문제 2 — 같은 구성을 반복 적용하기 어렵다
새로운 Tenant에 기존과 동일한 EPG/Contract 구조를 적용해야 할 때, 처음부터 다시 클릭해야 합니다. 실수가 발생하기 쉽고, 일관성을 보장하기 어렵습니다.
IaC가 이 문제를 어떻게 해결하는가?
인프라 구성을 코드 파일로 정의하면, Git으로 모든 변경 이력이 자동으로 기록됩니다. 누가, 언제, 어떤 이유로 바꿨는지 commit 메시지와 diff로 확인할 수 있습니다. 그리고 같은 코드를 다른 환경에 그대로 실행하면 동일한 구성이 만들어집니다.
HOW — Terraform과 Ansible은 어떻게 ACI를 다루는가?
Terraform — "이 상태로 만들어줘" (선언형)
Terraform은 원하는 최종 상태를 HCL(HashiCorp Configuration Language)로 정의합니다.
"이 Tenant가 있어야 한다"고 선언하면, 없으면 만들고 이미 있으면 건드리지 않습니다.
terraform plan으로 실제 적용 전에 변경 사항을 미리 확인할 수 있습니다.
# Terraform HCL — Tenant를 정의하는 코드
resource "aci_tenant" "this" {
name = "demo-tenant"
description = "Scenario 01 - Basic Tenant"
}
resource "aci_vrf" "this" {
tenant_dn = aci_tenant.this.id # Tenant가 먼저 생성된 뒤 VRF 생성
name = "prod-vrf"
}
# terraform plan 출력 — 적용 전 변경 계획서
Terraform will perform the following actions:
# module.tenant.aci_tenant.this will be created
+ resource "aci_tenant" "this" {
+ name = "demo-tenant"
+ description = "Scenario 01 - Basic Tenant"
}
# module.tenant.aci_vrf.this will be created
+ resource "aci_vrf" "this" {
+ name = "prod-vrf"
+ tenant_dn = (known after apply)
}
Plan: 13 to add, 0 to change, 0 to destroy.
+ 생성 / ~ 변경 / - 삭제. apply 전에 반드시 plan 결과를 확인하는 것이 핵심입니다.
Ansible — "이 순서대로 실행해줘" (절차형)
Ansible은 작업 순서를 YAML Playbook으로 정의합니다. "1번: Tenant 생성, 2번: VRF 생성, 3번: BD 생성" 순서로 Task를 나열합니다. 오브젝트가 이미 존재해도 멱등성 덕분에 오류 없이 "변경 없음"으로 처리됩니다.
# Ansible Playbook — Tenant와 VRF를 생성하는 Task
- name: Tenant 생성
cisco.aci.aci_tenant:
host: "{{ aci_host }}"
username: "{{ aci_username }}"
password: "{{ aci_password }}"
tenant: "demo-tenant"
state: present
- name: VRF 생성
cisco.aci.aci_vrf:
host: "{{ aci_host }}"
tenant: "demo-tenant"
vrf: "prod-vrf"
state: present
두 도구의 역할 분담 — Day 0 / Day 1-2
| 단계 | 설명 | ACI 작업 예시 | 적합한 도구 |
|---|---|---|---|
| Day 0 | 초기 프로비저닝 | Tenant/VRF/BD/EPG/Contract 전체 생성 | Terraform |
| Day 1 | 초기 운영 변경 | 새 EPG 추가, Contract 정책 수정 | Ansible |
| Day 2 | 지속적 운영 | 정기 감사(Audit), 대량 변경, 드리프트 감지 | Ansible |
ACI 오브젝트 계층과 코드의 1:1 대응
IaC로 ACI를 다룰 때 핵심은 GUI에서 클릭하던 계층 구조 그대로 코드가 작성된다는 점입니다. Tenant를 만들고, 그 아래에 VRF, BD, EPG를 만들던 순서가 코드 순서와 동일합니다.
Tenant (fvTenant) ← aci_tenant 리소스
└── VRF (fvCtx) ← aci_vrf 리소스
└── Bridge Domain (fvBD) ← aci_bridge_domain 리소스
├── Subnet (fvSubnet) ← aci_subnet 리소스
└── App Profile (fvAp) ← aci_application_profile 리소스
└── EPG (fvAEPg) ← aci_application_epg 리소스
└── Contract (vzBrCP) ← aci_contract 리소스
└── Subject (vzSubj) ← aci_contract_subject 리소스
└── Filter (vzFilter) ← aci_filter 리소스
└── Entry (vzEntry) ← aci_filter_entry 리소스
uni/tn-demo-tenant, 그 아래 VRF는 uni/tn-demo-tenant/ctx-prod-vrf 형태입니다.
Terraform에서는 리소스의 .id 속성이 이 DN에 해당하며, 하위 오브젝트 생성 시 상위 DN을 전달해야 합니다.
실습 환경 및 시나리오 구성
이 시리즈는 실제 ACI 장비 없이 Cisco DevNet의 무료 Sandbox로 실습합니다.
| 항목 | 값 |
|---|---|
| APIC URL | https://sandboxapicdc.cisco.com |
| 계정 | admin / !v3G@!4@Y (공용 환경 — 테스트용) |
| Terraform | v1.14.8 / CiscoDevNet/aci Provider v2.18.0 |
| Ansible | core 2.16.3 / cisco.aci 컬렉션 2.8.0 |
| GitHub | github.com/MinYongUm/aci-as-code |
시나리오 01 — Basic Tenant
Tenant → VRF → BD → EPG → Contract의 기본 흐름을 처음부터 끝까지 구현합니다. 단일 EPG가 HTTP/HTTPS 트래픽을 허용하는 가장 단순한 구성입니다.
Tenant: demo-tenant / VRF: prod-vrf BD: web-bd (10.10.1.1/24) AP: demo-ap → EPG: web-epg [Provider + Consumer] Contract: allow-http → Filter: filter-http (tcp/80, tcp/443)
시나리오 02 — Three-Tier App
Web / App / DB 3계층 앱 구조를 구현합니다. EPG 간 Contract 방향(Provider/Consumer)과 세그멘테이션 개념을 실습합니다.
[외부]
→ web-epg [Consumer: web-to-app]
→ app-epg [Provider: web-to-app, Consumer: app-to-db]
→ db-epg [Provider: app-to-db]
디렉토리 구조
aci-as-code/
├── terraform/modules/ # 재사용 가능한 Terraform 모듈
│ ├── tenant/ # Tenant + VRF
│ ├── networking/ # BD + Subnet
│ ├── policy/ # Contract + Filter
│ └── epg/ # AP + EPG + Contract 바인딩
├── scenarios/ # 시나리오별 실행 진입점
│ ├── 01_basic_tenant/
│ └── 02_three_tier_app/
├── ansible/
│ ├── roles/ # 재사용 가능한 Ansible Role
│ └── scenarios/ # 시나리오별 Playbook
└── .github/workflows/ # GitHub Actions CI
├── terraform-ci.yml # PR 시 terraform plan 자동 실행
└── ansible-ci.yml # ansible-lint 자동 실행
면접 포인트
Terraform은
terraform.tfstate 파일로 현재 인프라 상태를 추적합니다.
"지금 APIC에 무엇이 있는지"를 알고 있기 때문에, 다음 실행 시 변경이 필요한 부분만 계산해서 적용합니다.
이를 통해 드리프트 감지(실제 상태와 코드 상태의 차이 확인)가 가능합니다.Ansible은 State가 없습니다. 실행할 때마다 APIC에 직접 현재 상태를 확인하고, Task를 실행합니다. 멱등성 덕분에 이미 올바른 상태라면 "변경 없음"으로 넘어갑니다. 이 방식은 구조가 단순하지만, "지금 뭐가 배포되어 있는지"를 코드 레벨에서 추적하기 어렵습니다.
첫째, 변경 이력 관리입니다. 모든 설정 변경이 Git commit으로 기록되므로 누가, 언제, 왜 바꿨는지 추적할 수 있습니다. 장애 원인 분석과 감사(Audit)에 직접적으로 도움됩니다.
둘째, 재현성과 일관성입니다. 같은 코드를 실행하면 동일한 구성이 만들어집니다. 개발/스테이징/운영 환경을 동일하게 유지하거나, 새 Tenant에 표준 구성을 빠르게 적용할 수 있습니다.
셋째, 코드 리뷰를 통한 협업입니다. GitHub Pull Request로 변경 사항을 팀이 검토한 뒤 APIC에 반영하는 프로세스를 만들 수 있습니다.
tenant_dn = aci_tenant.this.id처럼 Tenant의 DN을 전달해야 합니다.이 구조가 중요한 이유는 Terraform이 이 DN 참조를 분석해서 오브젝트 생성 순서를 자동으로 결정하기 때문입니다. Tenant가 완전히 생성된 뒤에 VRF를 만들어야 한다는 것을 코드에서 명시하지 않아도 Terraform이 의존성 그래프를 통해 자동으로 순서를 보장합니다.
'Network > ACI' 카테고리의 다른 글
| [ACI-IaC] Terraform vs Ansible 실전 비교 (0) | 2026.04.07 |
|---|---|
| [ACI-IaC] Ansible로 Basic Tenant 프로비저닝하기 (0) | 2026.04.07 |
| [ACI-IaC] Terraform으로 3계층 앱 구성하기 (0) | 2026.04.07 |
| [ACI-IaC] Terraform으로 Basic Tenant 프로비저닝하기 (2) | 2026.04.07 |