3. 아키텍처적 사고#
이 장은 이 책의 기초를 소개한다. 이 마인드셋을 채택해야 하는 이유를 설명하고, Network Automation Forum (NAF)이 제안하는 참조 프레임워크를 소개하며, 프로젝트에서 이를 어떻게 활용하는지 보여준다.
2부에서 이러한 주제들을 깊이 다룬다. 이 장에서는 세부 사항에 들어가기 전에 전체적인 그림을 제공하기 위해 간략하게 소개한다. 각 구성 요소를 설명한 후에 전체 그림을 갖는 것이 점들을 연결하는 데 도움이 되기 때문에 이것이 중요하다.
하지만 나는 무엇을 하기 전에 왜를 이해하는 것을 강하게 믿는다. 먼저 아키텍처를 활용해야 하는 이유를 이해해보자.
3.1. 참조 아키텍처가 왜 중요한가#
“교육받은 자만이 자유롭다.” - 에픽테토스
네트워크 자동화 솔루션은 여러 조각들의 조합이며, 각각은 역할을 담당한다. 네트워킹에서 우리는 모든 문제를 해결하는 올인원 박스처럼 동작하려는 단순하거나 모놀리식 솔루션에 익숙하다. 어느 정도 그것이 사실일 수 있지만, 혼자서 다양한 모든 도전과 유스케이스를 해결할 수 있는 것은 없다. 따라서 유스케이스가 가장 인기 있는 것들 중 하나가 아니라면, 커스터마이즈하거나 확장할 필요가 있을 수 있다.
명확한 참조 아키텍처 없이 팀들은 종종 예측 가능한 일련의 문제들에 직면한다:
- 중복 노력: 여러 팀이 독립적으로 유사한 도구(데이터 소스, 중복된 스크립트, 중복된 모니터링 시스템)를 구축하여 자원을 낭비하고 일관성 없는 인터페이스를 만든다.
- 통합 갭: 도구들이 깔끔하게 서로 통신하지 못해 비싼 커스텀 통합 작업을 강제한다.
- 불명확한 책임: 어떤 도구가 옵저버빌리티, 오케스트레이션, 또는 상태 관리를 처리해야 하는지 불명확하여 혼란과 책임 회피를 야기한다.
- 확장 어려움: 새로운 기능이나 도구를 추가하려면 전체 시스템을 다시 생각해야 한다.
- 지식 사일로: 다른 팀들이 다른 멘탈 모델을 사용하여 새 사람을 온보딩하거나 솔루션을 유지 보수하기 어렵게 만든다.
참조 아키텍처는 자동화 시스템이 어떻게 구성되어야 하는지에 대한 단일 명확한 멘탈 모델을 제공함으로써 이러한 문제들을 해결한다. 다음을 정의한다:
- 각 구성 요소가 무엇을 해야 하는지 -> 그것의 책임
- 구성 요소들이 어떻게 상호 작용하는지 -> 인터페이스와 데이터 흐름
- 어디서 선택을 할 수 있는지 -> 어떤 도구를 사용할지
- 어디서 일관성이 필요한지 -> 구성 요소들이 어떻게 서로 통신하는지
참조 아키텍처는 네트워크 엔지니어들에게 새롭지 않다. 우리 모두 사랑하는 OSI 모델과 함께 자라왔다. OSI 모델을 사용하면 각 레이어가 다른 책임과 관심사를 갖기 때문에 네트워크 문제를 진단하고 이해하기 위한 단계별 계층적 접근 방식을 제공한다. 네트워크 전문가들은 이 관심사 분리가 복잡한 시스템을 관리 가능하게 만든다는 것을 직관적으로 이해한다.
네트워크 자동화에서는 함께 작동하는 솔루션을 개발하고 상호 연결하는 방법을 안내할 수 있는 유사한 것이 필요하다. 팀들이 일관된 결정을 내리고, 프로젝트 간에 구성 요소를 재사용하며, 매번 바퀴를 재발명하지 않고 자동화 역량을 발전시키는 데 도움이 된다.
3.2. 네트워크 자동화 아키텍처#
따라서 아키텍처가 필요하다. 하지만 섹션 제목의 ‘A’에 주목하라: 단 하나의 아키텍처가 있는 것이 아니라 많다. 아키텍처는 단순히 참조 프레임워크다: 사고를 구조화하고 일관된 결정을 안내하는 방법. 나는 세 가지 이니셔티브에 기여했다:
- Network to Code 참조 아키텍처, NTC 아키텍처 팀(내가 4년 동안 속해 있었던)이 주도하는 집단적 노력으로, 광범위한 유스케이스에 걸쳐 효율적이고 이해 가능한 네트워크 자동화를 지원하도록 설계됨.
- O’Reilly의 Network Automation and Programmability 2nd Edition, 공동 저자들인 Matt Oswalt, Scott S. Lowe, Jason Edelman과 함께 책의 모든 내용의 점들을 연결하는 노력.
- NAF 프레임워크는 Wim Henderickx, Dinesh Dutt, Claudia de Luna, Ryan Shaw, Damien Garros와 함께 이끈 NAF 산하 커뮤니티 프로젝트로, 신규 입문자와 숙련된 실무자 모두가 구조화되고 반복 가능한 방식으로 자동화 솔루션을 구축하는 데 도움을 주는 것을 목표로 함.
이러한 반복들을 거치면서 일관성을 유지하고 각 발전에서 배우는 데 집중했다. 세 가지 접근 방식 모두 유용하다. 하지만 나는 현재 모범 사례로 NAF Framework를 사용할 것을 제안한다: 커뮤니티 주도이고, 벤더 중립적이며, 광범위하게 적용 가능하다. 수년간의 집단적 학습을 통합하며 참여적이고 성장하는 커뮤니티에 의해 적극적으로 유지 관리된다.
세 가지는 경쟁하기보다는 상호 보완적이다. 간략한 비교가 각각이 가장 관련성이 있는 때를 명확하게 하는 데 도움이 된다:
| 아키텍처 | 주요 초점 | 거버넌스 | 가장 도움이 될 때 |
|---|---|---|---|
| NTC 참조 아키텍처 | 독자적인 도구 선택 및 통합 패턴 | NTC 내부, 적극적으로 발전 | NTC 도구를 사용하며 규범적인 구현 지침을 원하는 팀 |
| O’Reilly 14장 | 프로그래밍 가능성 주제를 연결하는 개념적 프레임워크 | 출판됨, 정적 | 자동화 개념들이 어떻게 연결되는지 보고 싶은 독자 |
| NAF 프레임워크 | 모듈당 MUST/SHOULD/MAY를 갖는 상호 운용성 표준 | 커뮤니티 유지 관리, 벤더 중립 | 다중 도구, 다중 벤더 환경의 공유 레퍼런스를 원하는 모든 팀 |
NAF 프레임워크는 블록 간의 계약을 정의하고 구현 선택은 열어둔다. NTC 아키텍처는 특정 도구 권장 사항으로 그 선택들을 채운다. 팀이 NTC 도구를 사용한다면, 둘 다 충돌 없이 동시에 적용된다.
NAF Framework는 다음 아키텍처를 제안한다:
block-beta
columns 7
space:1
block:layer1:5
Presentation["프레젠테이션"]
end
space:1
space:7
block:Observability:2
columns 2
ObservedState[("관찰된 상태")]:1
ObservedLogic["관찰 로직"]:1
end
space
block:Orchestration:1
columns 1
OrchLabel["오케스트레이션"]:1
end
space
block:Intent:2
columns 2
IntendedState[("의도된 상태")]:1
IntendedLogic["의도 로직"]:1
end
space:7
space
Collector["수집기"]:2
space
Executor["실행기"]:2
space
space:7
space:1
block:layer4:5
NetworkInfra["네트워크 인프라"]
end
Presentation <--> Observability
Presentation <--> Orchestration
Presentation <--> Intent
Observability <--> Orchestration
Orchestration <--> Intent
Collector --> Observability
Collector <--> Orchestration
NetworkInfra --> Collector
Orchestration --> Executor
Intent --> Executor
Executor --> NetworkInfra
classDef darkStyle fill:#5a4149,stroke:#4a9eff,stroke-width:2px,color:#e8e8e8,font-size:20px,font-weight:bold
class Presentation,NetworkInfra,ObsLabel,IntLabel,Collector,Executor,ObservedState,ObservedLogic,IntendedState,IntendedLogic,OrchLabel darkStyle
이 아키텍처는 문서의 정의를 사용하여 다음 블록들을 포함한다:
- Intent (Architectural Block): 설정과 운영 기대 사항 모두를 포함한 네트워크의 Desired State를 저장하는 영속성 레이어와 처리하는 로직을 정의한다.
- Executor: 의도된 상태에 의해 안내되는 변경을 구동하기 위해 네트워크에 적용되는 실제 작업(설정 업데이트)을 포함한다.
- Collector: Executor와 달리, 이 구성 요소는 네트워크의 Actual State를 검색(읽기)하는 데 초점을 맞춘다.
- Observability: 네트워크의 Actual State를 영속시키고, 그것을 처리하는 로직을 정의한다.
- Orchestrator: 자동화 작업이 이벤트에 대응하여 어떻게 조율되고 실행되는지 정의한다.
- Presentation (Layer): 대시보드, 그래픽 사용자 인터페이스 (ITSM), Command Line Interface (CLI) 도구를 포함한 사용자가 시스템과 상호 작용하는 인터페이스를 제공한다.
이 아키텍처는 자의적이지 않다; 소프트웨어 엔지니어링 원칙을 네트워크 운영에 적용한 자연스러운 결과다.
NAF 프레임워크는 네트워크 자동화 아키텍트들이 각 모듈의 기능을 참조하고 MUST, SHOULD, MAY(RFC 스타일 사용)를 정의함으로써 솔루션을 구성하는 데 도움을 주는 것을 목표로 한다. 그런 다음 자신의 유스케이스를 해결하기 위해 어떻게 구현할지 결정할 수 있다.
여러 구성 요소를 갖는다는 것이 구성 요소당 하나의 도구를 선택해야 한다는 의미가 아니다. 많은 경우, 다양한 기능을 구현하는 도구를 사용할 수 있지만, 이것은 이해하고 (인정해야 하는) 타협이 수반된다.
이제 다른 블록들을 소개하기 위해 살펴볼 것이다.
3.2.1. 인텐트 또는 진실의 원천#
인텐트는 네트워크를 아무것도 없는 상태에서 완전히 운영 가능한 상태로 만드는 데 필요한 모든 정보를 정의하는 모든 데이터이며, 프리프로비저닝부터 부트스트랩, 완전히 운영 가능한 상태, 그리고 모든 종류의 네트워크 서비스의 최종 폐기에 이르는 모든 다양한 라이프사이클 상태를 포함한다.
아키텍처는 그것을 인텐트라고 부르지만, 나는 또 다른 인기 있는 용어인 진실의 원천 (SoT)과 일치시킨다. SoT 용어는 때로 오해되며, SoT 또는 인텐트가 무엇인지 명확히 하는 것으로 시작하고 싶다 (책 전반에 걸쳐 그것들을 상호 교환적으로 사용할 것이다).
상상할 수 있듯이 이것은 장비, IP 주소 지정, 데이터 센터 인프라 (랙, 케이블), 라우팅 프로토콜, 가상화된 서비스, 비밀, 운영 한계, 설정 템플릿, 서비스 또는 정책 추상화를 포함한 매우 다양한 데이터를 나타낼 수 있다. 한 가지 핵심 측면은 이 데이터가 기계가 이해할 수 있도록 구조화되어야 한다는 것이다. 그런 다음 생성, 읽기, 업데이트, 삭제 작업을 지원하고 Representational State Transfer (REST) 또는 GraphQL과 같은 표준화되고 잘 문서화된 Application Programming Interface (API)를 통해 접근 가능해야 한다.
수동 네트워크 관리와의 유사점으로, 이것은 설계를 정의하는 네트워크 아키텍트나 새 네트워크 배포를 위한 BOM을 정의하는 네트워크 플래너의 역할과 대부분 일치한다.
이상적으로, 이 구성 요소는 데이터가 여러 데이터 소스에 분산되어 있더라도 원하는 상태의 일관되고 통합된 뷰를 제공해야 한다. 내가 기록 시스템 (SoR)이라고 부르는 이러한 데이터 소스들은 데이터의 실제 소유자다. 따라서 이것이 명확히 해야 할 첫 번째 사항 중 하나다: 하나의 데이터 소스만 갖는 것은 극히 드물지만 통합될 때 데이터는 일관성이 있어야 한다. 데이터 관리는 타임스탬프, 데이터 원천, 데이터 소유권, 유효 기간 같은 메타데이터 형태를 포함한 데이터 거버넌스 기능을 필요로 하는 복잡한 주제다.
또한, 신뢰할 수 있는 네트워크 자동화를 가능하게 하는 기능에 연결하여, 이 블록은 예측 가능하고 신뢰할 수 있는 네트워크 자동화 프로세스를 가능하게 하는 트랜잭셔널 및 버전 관리된 데이터 접근을 제공해야 한다.
이 카테고리에 맞는 실제 도구들이 무엇인지 이해하려 한다면, 몇 가지 예시가 있다: CSV/YAML/JavaScript Object Notation (JSON) 파일, Git, NetBox, Nautobot, Infrahub, Infoblox, 또는 범용 데이터베이스.
진실의 원천 구축 및 관리에 대한 심층 분석은 4장을 참조하라.
3.2.2. 실행기#
실행기는 인텐트에서 오는 원하는 상태를 SSH, NETCONF, gNMI/gNOI, REST APIs 같은 다양한 인터페이스를 통해 네트워크와 상호 작용하면서 실제 네트워크 상태에 구현(쓰기)하는 역할을 맡는다.
수동 네트워크 관리와의 유사점을 계속하면, 실행기는 최종 네트워크 설정을 준비하고 설정 명령을 입력하기 위해 CLI를 통해 네트워크 장비에 연결하는 네트워크 엔지니어가 될 것이다.
하지만 이것은 한 곳(인텐트)에서 다른 곳(네트워크)으로 데이터를 복사하는 것만큼 단순하지 않다. 네트워크 변경부터 시스템 재부팅이나 업그레이드까지 고려해야 할 많은 작업이 있다. 또한 대부분의 시간에 참조 데이터는 인텐트 블록에서 오지만, 일부 경우에는 옵저버빌리티에서 오는 관찰된 데이터가 이 구성 요소에 영향을 줄 수 있으므로 둘 다 결합되어야 한다.
예를 들어, 실행기는 변경을 시도하기 전에 장비 도달 가능성을 검증하거나, 현재 네트워크 상태를 기반으로 페일오버 로직을 적응시키거나, 옵저버빌리티가 중요한 의존성 서비스가 다운됐음을 보여주면 실행을 건너뛸 수 있다. 옵저버빌리티에서 오는 이 피드백은 자동화 결정이 인텐트만이 아닌 실시간 네트워크 조건에 의해 정보화되도록 보장한다.
인텐트와 유사하게, 이 구성 요소는 드라이런, 트랜잭셔널 변경, 멱등성 (선언적 또는 명령적 접근 방식을 통해)과 같은 기능을 제공해야 한다. 이러한 기능들은 네트워크 엔지니어들이 신뢰할 수 있는 자동화 시스템을 구축하는 데 도움이 된다. 이것은 보통 네트워크 엔지니어들이 (초기에) 가장 관심을 갖는 구성 요소다. 실제로 네트워크를 “변경"하는 구성 요소이기 때문이다.
이 카테고리에 대부분 맞는 도구들은 Ansible, Terraform/OpenTofu, 또는 Netmiko, Scrapli, Napalm과 같은 라이브러리를 활용하는 모든 종류의 스크립트, 심지어 Kubernetes CRD (Custom Resource)다.
실행 프레임워크, 멱등성 패턴, 구현 전략을 탐구하려면 5장으로 가라.
3.2.3. 수집기#
실행기와 유사하게, 수집기는 동일한 인터페이스와 프로토콜(실행기와 동일한 인터페이스에 SNMP, Syslogs, 또는 다른 플로우 기반 텔레메트리 같은 추가 인터페이스)을 통해 네트워크에서 실제 운영 데이터를 검색하는 역할을 맡는다.
이 모든 데이터의 목적지는 데이터가 자동화 결정을 지원하는 데 사용되는 옵저버빌리티 블록이다.
여기서 보통 고려되지 않는 중요한 주제 중 하나는 비교 가능하도록 정규화된 데이터의 필요성이다. 따라서 모든 벤더에 대해 일관된 메트릭 이름을 얻는 것(system_version이 플랫폼에 관계없이 OS 버전을 정의)과 고급 데이터 처리를 허용하는 일관된 메타데이터가 중요하다.
이 카테고리에 맞는 도구의 예시로는 Telegraf, Vector, gNMIc, PMACCT, goFlow, Akvorado, 또는 네트워크에서 데이터를 가져오기 위해 라이브러리를 활용하는 모든 종류의 스크립트가 있다.
친화성 때문에, 수집기를 다음 구성 요소인 옵저버빌리티와 함께 6장에서 다룰 것이다. 수집기와 옵저버빌리티는 아키텍처적으로 구별되지만 운영상 불가분하다: 데이터를 어떻게 수집할지에 대한 모든 설계 결정은 옵저버빌리티 레이어가 처리해야 하는 것에 의해 이끌린다. 함께 다루는 것이 그 의존성을 보존한다.
3.2.4. 옵저버빌리티#
수집기와 밀접하게 관련된 (많은 경우 함께 보이는) 옵저버빌리티는 수집된 데이터를 받고, 그것의 영속성을 지원하며, 이상적으로는 PromQL과 같은 유능한 쿼리 언어를 사용하여 고급 분석, 보고, 트러블슈팅 워크플로를 지원하는 프로그래밍 방식 접근을 제공한다.
이 블록의 데이터는 네트워크의 Desired State와 Actual State 사이의 관련 불일치를 노출해야 하며, 완화 시스템을 트리거할 수 있는 이벤트(또는 경보)를 생성한다.
수동 네트워크 관리 유사점을 계속하면, 이것은 네트워크의 실제 상태를 확인하고 그에 따라 반응하는 네트워크 운영 센터의 역할에 맞는다.
또한, 관찰된 데이터는 다른 서드파티 소스(예: EoL 정보, CVE, 유지 보수 알림 등)를 포함한 의도된 상태의 맥락 정보로 풍부화될 수 있어 분석을 강화하고 더 정확한 데이터 상관을 가능하게 한다.
전통적인 네트워크 모니터링에서는 옵저버빌리티 (및 수집)의 모든 기능이 하나의 큰 박스에 통합되었다 (Nagios, LibreNMS, Spectrum 같은 도구들).
현재, 통합되는 더 다양한 시스템들이 인기를 얻고 있다. Prometheus와 InfluxDB가 인기 있는 Time Series Database (TSDB)이거나 Elasticsearch, 그리고 경보를 관리하는 (Alertmanager) 다른 관련 시스템들과 시각화하는 (Grafana, Kibana) 시스템들이 있다. 이것은 일부 인기 있는 스택으로 이어졌다: ELK, TIG, 또는 TPG.
모니터링 아키텍처, 경보 전략, 옵저버빌리티 모범 사례에 대한 자세한 내용은 6장을 참조하라.
3.2.5. 오케스트레이터#
지금까지 많은 다른 구성 요소들을 보았고, 그것들을 조율해야 할 필요가 있다: 다양한 구성 요소들의 프로세스를 통합하고 정교한 엔드-투-엔드 자동화 워크플로를 만드는 것. 이 때문에 오케스트레이터는 수동 트리거에서 완전히 이벤트 기반 워크플로까지, 동기적으로와 비동기적으로 모두, 다양한 상호 작용 방법을 지원해야 한다.
오케스트레이터가 구현하는 워크플로는 여러 단계를 정의하는 방법을 제공해야 하며, (예를 들어 인텐트 블록의 버전 관리된 스냅샷을 사용하여) 다른 구성 요소에 의존하면서 롤백과 드라이런 기능도 지원해야 한다.
수동 운영에서 이것은 보통 따라야 할 프로세스에 대한 체크리스트에 느슨하게 정의되어 있다.
이 구성 요소는 사용자에게 전체 네트워크 자동화에서 무슨 일이 일어나고 있는지에 대한 포괄적인 시각화를 제공하며, 명확한 로깅과 추적성을 통해 다양한 프로세스들이 어떻게 함께 모이는지 보여준다.
여기 예시로는 AAP 또는 AWX (Ansible Automation Platform), Windmill, 또는 Prefect가 있다.
AI와 에이전트가 아키텍처에서 어디에 맞는지: AI 보조 의사 결정은 주로 오케스트레이터와 옵저버빌리티 블록의 교차점에 위치한다. AI 에이전트는 감지-로직-행동 루프를 따른다: 옵저버빌리티 블록을 통해 네트워크 상태를 관찰하고, 어떤 조치가 필요한지 결정하기 위해 추론을 적용하며, 오케스트레이터를 통해 실행기를 트리거한다. 이것은 오케스트레이터의 전통적인 역할(사전 정의된 워크플로 따르기)과 다르지만 동일한 인프라를 사용한다. 7장(오케스트레이션, 7.2.7절)은 조율 패턴으로서 에이전트 접근 방식을 다루고; 15-17장은 자율 네트워크의 기반으로 그것을 탐구한다. 지금은, 에이전트 자동화를 정적 워크플로 정의를 동적이고 모델 기반 의사 결정으로 대체하는 조율 접근 방식으로 생각하라.
워크플로 설계, 이벤트 기반 자동화, 오케스트레이션 플랫폼에 대한 내용은 7장을 참조하라.
3.2.6. 프레젠테이션#
때로는 네트워크 자동화 사용자에게 적절한 인터페이스를 노출하는 것이 얼마나 중요한지 잊는다. 이것은 보통 흐릿한 영역이다. 우리가 이미 소개한 모든 도구들이 CLI, API, 또는 웹 기반의 어떤 종류의 인터페이스를 갖고 있기 때문이다. 일부 경우에 충분하다고 결정할 수 있다. 다른 경우에는 모든 세계의 최고를 얻고 사용자 경험을 단순화하기 위해 자체 사용자 인터페이스를 만들 수 있다. 상황에 따라 다르다.
전통적으로, 외부 사용자에게는 전화 통화나 이메일로, 네트워크 팀에게는 CLI로 제한되어 있었다.
어떤 방식으로든, 이 레이어는 유연한 인증과 권한 부여를 허용해야 하며 (시스템의 진입점이다), 그런 다음 실제 필요에 맞게 조정해야 한다. 때로는 네트워크 특정 플랫폼일 수 있고, 때로는 회사 전체 시스템 (ServiceNow, Slack 등)과 통합될 수 있다.
역할에 따라 쓰기 또는 읽기 작업을 커버할 수 있지만, 최상의 결과를 얻기 위해 항상 다양한 유형의 사용자 필요를 고려하라.
사용자 경험, 인터페이스 설계, 통합 패턴을 탐구하려면 8장을 참조하라.
3.2.7. 네트워크#
마지막으로 중요하지 않은 것은 아니지만, 자동화를 지원하기 위한 네트워크의 기능을 이해해야 한다. 그리고 네트워크는 더 이상 연결된 장비와 케이블만이 아니다. 2020년대에는 가상화와 클라우드 기반 네트워킹 솔루션이 엔드-투-엔드 도달 가능성(네트워크)을 하이브리드하고 다양한 환경으로 만든다.
네트워크 자체는 전체 자동화 아키텍처의 제약이자 가능하게 하는 요소다. 제어권을 갖는 이전 여섯 가지 블록들과 달리, 네트워크 인프라 (장비, 플랫폼, 서비스, 연결성)는 무엇이 가능한지에 영향을 미치는 제한이 있을 수 있다.
네트워크 기능은 여러 카테고리로 나뉜다:
- 인터페이스 & 프로토콜: 네트워크가 지원하는 관리 인터페이스는 무엇인가? SSH CLI? NETCONF? gNMI? REST APIs? SNMP? 일부 플랫폼은 많이 지원하고, 일부는 적게 지원한다. 이러한 선택들은 수집기와 실행기가 할 수 있는 것을 직접 제약한다.
- 데이터 모델: 장비가 gNMI를 지원하더라도 노출하는 YANG 모델이 불완전할 수 있다. 예를 들어, 장비가 gNMI 지원을 주장하지만 관리해야 하는 특정 설정을 노출하지 않을 수 있다. 이러한 갭을 이해하는 것이 계획 중에 중요하다.
- 운영 성숙도: 최신 플랫폼은 현대적인 API를 가질 수 있지만 문서화되지 않은 동작이 있을 수 있다. 오래된 플랫폼은 안정적이지만 API가 전혀 없을 수 있다. 마케팅된 기능이 아닌 실제 성숙도를 평가해야 한다.
자동화를 효과적으로 지원하기 위해, 네트워크 인프라는 이상적으로 다음을 제공해야 한다:
- 개발 & 테스팅 환경: 소프트웨어 개발처럼, 자동화는 안전하게 테스트할 장소가 필요하다. 이것은 랩 네트워크 (종종 비싸고 제한적), 가상 네트워크 환경 (Containerlab, GNS3), 또는 벤더 제공 시뮬레이터 (Cisco DevNet, Arista EOS-lite)를 의미할 수 있다.
- 일관된 인터페이스: 장비의 90%가 NETCONF를 지원하지만 10%는 SSH만 지원한다면, 표준화하거나 여러 실행기를 구축해야 할 것이다. 모든 불일치는 복잡성을 증가시킨다.
- 적절한 텔레메트리: 장비에서 필요한 데이터를 얻을 수 없다면, 옵저버빌리티는 의미가 없어진다. 장비가 필요한 세분화도와 정보로 텔레메트리(스트리밍 텔레메트리, SNMP, syslog)를 스트리밍할 수 있는지 확인하라.
네트워크는 변경하기 가장 어려운 아키텍처 부분이다. 라우터를 쉽게 교체할 수 없다. 따라서 초기에 제약을 이해하고, 그 안에서 자동화를 설계하라. 이것이 네트워크 블록이 아키텍처 계획 중에 신중한 주의를 받을 가치가 있는 이유다.
네트워크 기능, 장비 APIs, 테스트 환경을 이해하려면 9장을 참조하라.
이 섹션을 요약하기 위해, 매우 단순한 유스케이스와 아키텍처가 어떻게 그것에 매핑되는지 살펴보자.
3.2.8. 실용적인 예시#
각 블록을 깊이 다루기 전에, 아키텍처가 어떻게 함께 작동하는지 보여주는 구체적인 시나리오를 살펴보자.
문제: 애플리케이션 팀이 새 애플리케이션 세그먼트 요청을 제출했다: Cisco, Arista, HPE의 약 800개의 액세스 및 배포 스위치를 실행하는 이기종 캠퍼스 네트워크 전반에 걸쳐 새 VLAN, IP 서브넷, 라우팅 정책, 접근 제어 영역. 운영 팀은 수백 개의 장비에 수동 CLI 작업 없이 엔드-투-엔드로 이를 처리해야 한다.
아키텍처가 어떻게 해결할 수 있는가:
- 인텐트 (진실의 원천): 네트워크 엔지니어가 Nautobot에 새 서비스 정의를 입력한다: VLAN ID, 서브넷, 라우팅 정책, 벤더별 설정 템플릿, 적용되는 스위치 그룹. 이것은 800개 장비의 단일 진실의 장소인 Desired State로 저장된다.
- Orchestrator: AWX가 변경에 대한 Nautobot의 웹훅을 받고 실행 워크플로를 트리거하여 올바른 순서로 단계를 조율하고 장비별 실패를 처리한다.
- Executor: Ansible 플레이북이 Nautobot Application Programming Interface (API)에서 읽고, 벤더별 장비 특정 설정을 렌더링하며 (Cisco, Arista, HPE 각각 다른 구문이 필요), NETCONF를 통해 변경을 푸시한다. 각 실행은 멱등적이다: 이미 설정된 스위치에 다시 실행해도 변경이 없다.
- Collector: 배포 후, gNMIc 수집기가 각 스위치에 연결하고 실제 VLAN 멤버십, 인터페이스 상태, 라우팅 엔트리를 검색한다.
- Observability: 수집된 데이터가 Prometheus Time Series Database (TSDB)로 흐른다. 쿼리가 Desired State (인텐트에서)를 Actual State (Collector에서)와 비교한다. VLAN이 없는 스위치들은 메트릭으로 노출되고 경보를 트리거한다.
- Orchestrator: 경보가 발화되면 (“VLAN 210이 access-switch-b3-07에 없음”), AWX 워크플로가 자동으로 해당 스위치에 Executor를 다시 실행하고, 데이터를 재수집하고, 수정을 검증한다.
- Presentation (Layer): 대시보드가 건물과 벤더별로 그룹화된 800개 스위치를 표시하며, 어떤 것이 준수 (✅)하고 어떤 것이 드리프트됐는지 (❌) 강조한다. 애플리케이션 팀은 CLI 접근 없이 롤아웃을 추적할 수 있다. IT 운영은 코드 작성 없이 수동 수정을 트리거할 수 있다.
- 네트워크: 이 흐름의 성공은 장비가 실제로 지원하는 것에 달려 있다. Cisco와 Arista에서 NETCONF는 깔끔하게 작동한다. 일부 HPE 스위치는 SSH CLI만 지원하므로 별도의 실행기 경로가 그것들을 처리한다. 덜 우아하지만 필요하다. 어떤 아키텍처도 벤더 제약을 제거하지 않는다; 단지 그것들을 명시적으로 만들 뿐이다.
핵심 통찰: 단일 도구가 이것을 하지 않았다. Nautobot (인텐트), Ansible (실행기), gNMIc (수집기), Prometheus (옵저버빌리티), AWX (오케스트레이터), Grafana 대시보드 (프레젠테이션) 모두 함께 작동했다. 아키텍처는 그것들을 통합하는 방법에 대한 멘탈 모델을 제공했다.
이것이 아키텍처적 사고가 가능하게 하는 것이다: 체계적이고 합성 가능한 자동화.
2부 (4-9장) 전반에 걸쳐 동일한 캠퍼스 네트워크로 돌아와 각 구성 요소를 깊이 탐구한다: SoT는 VLAN 서비스 정의를 저장하고 (4장), 실행기는 그것을 배포하고 (5장), 옵저버빌리티는 그것을 모니터링하며 (6장), 오케스트레이터는 전체 라이프사이클을 조율하고 (7장), 프레젠테이션 레이어는 그것을 다양한 청중에게 노출하며 (8장), 네트워크 장은 시뮬레이션 기반 프리프로덕션 게이트로 마무리된다 (9장). 진실의 원천 도구를 참조하는 예시에서 Nautobot과 NetBox는 상호 교환적으로 사용된다; 아키텍처 패턴은 어느 것을 선택하든 동일하다.
3.3. 아키텍처 사용 방법#
이제 NAF 네트워크 자동화 아키텍처의 다양한 구성 요소들을 이해했으니, 이렇게 물을 수 있다: “실제로 내 프로젝트에서 어떻게 시작하나요?”
3.3.1. 채택을 위한 순차적 접근 방식#
참조 아키텍처는 처방이 아니다. 자동화 솔루션에 대한 사고와 구성을 위한 프레임워크다. 그것을 적용하기 위한 실용적이고 순차적인 접근 방식이 있다:
flowchart LR
A[현재 상태 이해]:::phase1 --> B[자동화 여정 계획]:::phase2
B --> C[더 나은 도구 & 설계 결정]:::phase3
C --> D[통합을 위한 설계]:::phase4
D --> E[이해관계자와 소통]:::phase5
E --> F[점진적 발전]:::phase6
classDef phase1 fill:#e0f7fa,stroke:#333,stroke-width:2px;
classDef phase2 fill:#b2ebf2,stroke:#333,stroke-width:2px;
classDef phase3 fill:#80deea,stroke:#333,stroke-width:2px;
classDef phase4 fill:#4dd0e1,stroke:#333,stroke-width:2px;
classDef phase5 fill:#26c6da,stroke:#333,stroke-width:2px;
classDef phase6 fill:#00bcd4,stroke:#333,stroke-width:2px;
단계 1: 현재 상태 이해
기존 도구와 프로세스를 아키텍처 블록에 매핑하는 것으로 시작하라. 이 평가 연습은 갭, 중복, 잠재적인 개선 영역을 식별하는 데 도움이 된다:
- 데이터가 여러 시스템에 흩어져 있는가?
- 네트워크 상태를 효과적으로 수집하고 있는가, 아니면 눈을 감고 비행하고 있는가?
- 현재 변경을 어떻게 실행하는가? 수동으로? 임시 스크립트로? 구성된 프레임워크로?
뛰어난 실행 기능을 발견했지만 옵저버빌리티가 빈약하다면, 다음에 해결할 높은 영향의 문제를 식별한 것이다.
단계 2: 자동화 여정 계획
아키텍처를 사용하여 자동화 로드맵을 안내하라. 모든 블록을 한 번에 구현할 필요가 없다. 가장 중요한 고통 지점을 해결하는 구성 요소로 시작하라:
- 설정 드리프트로 어려움을 겪고 있다면, 인텐트/진실의 원천과 실행에 집중하라.
- 문제를 빠르게 감지할 수 없다면, 수집기와 옵저버빌리티를 우선시하라.
- 자동화가 분산되어 있고 신뢰할 수 없다면, 오케스트레이션에 투자하라.
- 사용자들이 변경 요청 방법에 대해 혼란스럽다면, 프레젠테이션을 개선하라.
아키텍처 완전성이 아닌 비즈니스 영향으로 우선순위를 정하라.
단계 3: 더 나은 도구 & 설계 결정
새로운 도구를 평가하거나 커스텀 솔루션을 구축할 때 스스로에게 물어라:
- 이것이 어떤 아키텍처 블록을 담당하는가?
- 다른 구성 요소들과 잘 통합되는가?
- 블록 간에 어떤 데이터 흐름이 필요한가?
이것은 도구 난립을 방지하고 자동화 생태계가 일관성 있게 유지되도록 한다. 또한 구매해야 하는지 구축해야 하는지를 명확히 한다. 도구가 하나의 블록에 깔끔하게 맞고 잘 정의된 인터페이스를 가지고 있다면, 보통 구축보다 구매하는 것이 더 낫다.
단계 4: 통합을 위한 설계
구성 요소 간의 경계를 이해하면 더 나은 인터페이스를 설계하는 데 도움이 된다. 핵심 원칙: 구성 요소들은 서로의 내부를 알 필요가 없다.
- 실행기는 인텐트가 데이터를 어떻게 저장하는지 알 필요가 없다: 원하는 상태를 쿼리하기 위한 잘 정의된 API만 필요하다.
- 오케스트레이터는 Ansible 또는 Terraform을 사용하는지 신경 쓸 필요가 없다: 실행을 트리거하고 결과를 모니터링하기만 하면 된다.
- 옵저버빌리티 시스템은 수집기 내부에 대해 알 필요가 없다: 명확한 메트릭과 이벤트만 필요하다.
이 결합 해제가 각 구성 요소를 독립적으로 발전시킬 수 있게 하는 것이다.
단계 5: 이해관계자와 소통
아키텍처는 다양한 청중과 자동화에 대해 논의하기 위한 공통 언어를 제공한다:
- 경영진에게: “MTTR 감소를 위해 옵저버빌리티 태세를 강화하고 있습니다.”
- 팀에게: “수집기가 옵저버빌리티로 데이터를 보내는 방법을 표준화합시다.”
- 다른 부서에게: “우리의 프레젠테이션 레이어가 귀하의 ITSM 인스턴스와 통합될 것입니다.”
명확한 아키텍처 언어는 혼란을 줄이고 동의를 확보하는 데 도움이 된다.
단계 6: 점진적 발전
아키텍처는 필요에 따라 구성 요소를 교체할 수 있게 한다:
- 오늘은 Git을 진실의 원천으로 사용할 수 있지만, 내일은 명확한 인터페이스를 유지하는 한 자동화 워크플로를 완전히 재설계하지 않고 NetBox나 Infrahub를 채택할 수 있다.
- 단순한 스크립트를 오케스트레이터로 시작하고, 나중에 AAP 또는 Windmill로 교체할 수 있다.
- 수집기가 데이터를 검색하는 방식을 방해하지 않고 옵저버빌리티에서 하나의 TSDB에서 다른 것으로 마이그레이션할 수 있다.
이 진화적 접근 방식은 위험을 최소화하고 진행하면서 배울 수 있게 한다.
과도한 엔지니어링의 함정에 빠지지 말라. 목표는 아키텍처 순수성이 아니라 실제 문제를 해결하는 실용적인 자동화다. 때로는 최선의 솔루션이 여러 아키텍처 블록에 걸쳐 있는 단순한 스크립트다. 아키텍처는 안내이지, 구속복이 아니다.
핵심 시사점: 아키텍처를 사고를 구성하고, 갭을 식별하며, 의도적인 설계 결정을 내리기 위한 멘탈 모델로 사용하라. 모든 구현 세부 사항을 지시하는 경직된 템플릿으로 사용하지 말라.
3.3.2. 피해야 할 일반적인 함정들#
솔직히 말하자: 실수를 할 것이다. 하지만 다른 사람들로부터 배우면 많은 고통을 줄일 수 있다. 다음은 일반적인 함정들이다:
한 번에 모든 것을 구현하려는 시도
유혹적인 생각이 있다: “이 아키텍처가 좋다면, 일곱 블록 모두를 완벽하게 구축해야 한다.” 그것은 완성되기 전에 구식이 되는 대규모, 다년간 프로젝트로 이어진다.
더 나은 접근 방식: 가장 긴급한 문제를 해결하는 하나 또는 두 개의 블록으로 시작하라. 점진적으로 구축하라. 초기 성공은 모멘텀과 동의를 구축한다.
“모든 것을 지배하는 하나의 도구” 믿기
일부 벤더들은 그들의 플랫폼이 모든 것을 한다고 주장한다. 그것이 사실일 수 있지만, 종종 다음을 의미한다:
- 그들의 방식에 잠긴다
- 나중에 구성 요소를 교체할 수 없다
- 필요하지 않은 기능에 비용을 지불한다
더 나은 접근 방식: 각 블록에 대해 최고 수준의 도구를 선택하되, 명확한 APIs와 통합 지점이 있는지 확인하라. 3-5개의 도구를 통합해야 할 수 있다는 것을 받아들이지만, 유연성을 갖게 된다.
네트워크 제약 무시
gNMI를 사용하는 아름다운 실행기를 설계하지만 장비의 30%가 SSH CLI만 지원한다. 또는 스트리밍 텔레메트리를 원하지만 구형 플랫폼은 SNMP만 지원한다.
더 나은 접근 방식: 먼저 네트워크 인프라의 기능을 이해하라. 이러한 제약들이 아키텍처를 형성한다. 물리학을 무시할 수 없고, 장비가 실제로 할 수 있는 것을 무시할 수도 없다.
인터페이스가 단순할 것이라고 가정하기
“실행기가 인텐트의 API에서 원하는 상태를 가져올 것"이라고 말한다. 하지만 인텐트는 커스텀 확장이 있는 NetBox를 사용하고, 실행기는 플랫 YAML을 기대한다. 갑자기 번역 레이어를 작성하게 된다.
더 나은 접근 방식: 명확하고 잘 문서화된 인터페이스에 미리 투자하라. 가능한 곳에서 표준을 사용하라 (REST APIs, gRPC, 명확한 스키마 정의). 좋은 인터페이스는 지금 비용이 덜 들고 번역 레이어는 나중에 더 많은 비용이 든다.
좋은 도구가 있을 때 커스텀 도구 구축
팀이 “어떤 도구도 정확히 우리의 필요에 맞지 않기 때문에” 커스텀 수집기를 구축하기로 결정한다. 6개월 후, 독점 텔레메트리 파이프라인을 유지 관리하는 3,000줄의 코드가 생겼다.
더 나은 접근 방식: 기존 도구를 먼저 평가하라 (Telegraf, Vector, gNMIc). 유스케이스의 80%를 처리하고 실전에서 검증됐다. 필요하다면 커스터마이즈하거나 어댑터를 구축하되, 처음부터 구축하지 말라.
옵저버빌리티를 나중에 생각하기
많은 팀들이 인텐트와 실행기에 집중하다가, 네트워크에서 실제로 무슨 일이 일어나고 있는지 볼 수 없다는 것을 너무 늦게 깨닫는다. 옵저버빌리티가 마지막에 추가된다.
더 나은 접근 방식: 첫날부터 옵저버빌리티를 계획하라. 어떤 메트릭을 수집할 것인가? 드리프트를 어떻게 감지할 것인가? 어떤 경보가 중요한가? 실행기를 구축하기 전에 이것들에 답하라.
사용자 잊기
엔지니어들이 강력한 오케스트레이터를 구축하지만, 사용자들이 그것과 상호 작용하는 유일한 방법은 CLI 명령을 통해서다. 비기술적 사용자들은 혼란스러워하고; 채택이 저조하다.
더 나은 접근 방식: 사용자들에 대해 일찍 생각하라. 어떤 인터페이스가 필요한가? APIs? 웹 UI? ServiceNow 통합? 때로는 프레젠테이션 레이어가 채택을 좌우한다.
이러한 함정들은 이론적이지 않다. 실제 자동화 프로젝트에서 나온 패턴들이다. 지금 그것들로부터 배우면 아키텍처가 더 강해진다.
3.3.3. 어디서 시작할 것인가#
아키텍처는 일곱 개의 블록을 정의한다. 아무도 일곱 개를 모두 한 번에 구현하지 않는다. 실제로 두 가지 시작 패턴이 실제 배포의 대부분을 차지한다.
패턴 A: 설정 기반 시작 (가장 일반적)
이미 수동으로 설정을 관리하고 그 프로세스를 일관성 있고 자동화된 방식으로 만들고 싶은 팀. 인텐트와 실행기로 시작하라: 진실의 원천을 마련하고 그것에서 배포하는 플레이북을 구축하라. 실행이 안정적이고 실제로 배포된 것에 대한 피드백이 필요할 때 옵저버빌리티를 추가하라.
flowchart LR
A[인텐트 / SoT] --> B[실행기] --> C[옵저버빌리티] --> D[오케스트레이터] --> E[프레젠테이션]
style A fill:#4a9eff,color:#fff
style B fill:#4a9eff,color:#fff
style C fill:#7db8f7,color:#fff
style D fill:#b8d4f5,color:#333
style E fill:#ddeeff,color:#333
패턴 B: 가시성 기반 시작
주요 고통이 네트워크의 현재 상태를 모르는 것인 팀. 수집기와 옵저버빌리티로 시작하라: 먼저 데이터 파이프라인을 구축하고, 실제로 배포된 것을 이해한 다음, 대응할 신뢰할 수 있는 그림을 갖추면 인텐트와 실행기를 추가하라.
flowchart LR
A[수집기] --> B[옵저버빌리티] --> C[인텐트 / SoT] --> D[실행기] --> E[오케스트레이터]
style A fill:#4a9eff,color:#fff
style B fill:#4a9eff,color:#fff
style C fill:#7db8f7,color:#fff
style D fill:#b8d4f5,color:#333
style E fill:#ddeeff,color:#333
두 패턴 모두에서, 오케스트레이터와 프레젠테이션은 핵심 데이터 흐름이 안정적인 후에 온다. 신뢰할 수 있는 인텐트나 실행 전에 오케스트레이터로 시작하는 것은 시기상조다: 아직 조율할 의미 있는 것이 없다. 내부 팀들이 자동화를 사용하고 직접 API 또는 CLI 접근 대신 적절한 인터페이스가 필요할 때 프레젠테이션이 중요해진다.
이것들은 시작점이지, 청사진이 아니다. 제약 (기존 도구, 팀 기술, 가장 긴급한 고통)이 순서를 결정해야 한다. 핵심은 모든 것을 병렬로 구축하고 아무것도 완성하지 못하려 하기보다 의도적으로 시작점을 선택하는 것이다.
3.3.4. 팀 간 블록 소유#
일곱 개의 블록은 아키텍처 질문만큼이나 조직적 질문을 만든다: 누가 무엇을 소유하며, 여러 팀이 서로 방해하지 않고 동일한 플랫폼을 어떻게 공유하는가?
중소규모 및 대규모 조직에서 가장 일반적인 모델은 두 그룹으로 나뉜다. 플랫폼 팀은 자동화 인프라 자체를 소유한다: SoT 스키마와 APIs, 오케스트레이터 런타임, 옵저버빌리티 파이프라인, 프레젠테이션 레이어, 공유 수집기 인프라. 이것들이 나머지 조직이 의존하는 구성 요소다. 플랫폼 팀의 역할은 그것들을 신뢰할 수 있고, 버전 관리되며, 사용 가능하게 유지하는 것이다. 네트워크 운영 팀 (또는 기술 영역당 하나씩 여러 도메인 팀)은 자동화 콘텐츠를 소유한다: 플랫폼 위에서 실행되는 플레이북, 워크플로 정의, 의도된 데이터, 비즈니스 로직. 그들은 플랫폼을 소비한다; 유지 관리하지 않는다.
이 분할은 블록 경계가 팀 경계로 어떻게 번역되는지에 영향을 미친다. SoT는 공유 플랫폼 리소스지만 다른 팀들은 그것에 대해 다른 쓰기 권한을 갖는다: IP 주소 지정 팀은 IPAM 데이터를 소유할 수 있고; 캠퍼스 팀은 스위치 인벤토리를 소유할 수 있으며; 보안 팀은 방화벽 정책 데이터를 소유할 수 있다. SoT의 Term "rbac" not found 모델은 이러한 소유권 경계에 매핑되어야 한다. 잘못된 도메인에 대한 쓰기는 운영 인시던트를 기다리고 있는 것이다.
오케스트레이터도 유사하다: 플랫폼 팀은 런타임과 워크플로 실행 프레임워크를 소유하고; 운영 팀은 워크플로 정의를 소유한다. 워크플로 정의는 오케스트레이터의 UI에서 직접 편집하기보다 배포 시 오케스트레이터가 가져오는 운영 팀 소유권 하의 버전 제어에 있어야 한다. 이것은 플랫폼 팀과 운영 팀이 서로의 작업을 방해하지 않게 유지한다.
프레젠테이션은 소유권 질문을 더 나눈다. 다른 자동화 도구들이 사용하는 내부 API는 플랫폼 관심사다. 애플리케이션 팀을 위한 셀프서비스 포털은 전담 도구 팀이나 공유 서비스 그룹에 속할 수 있는 제품 관심사다. 이러한 경계를 일찍 정의하면 모든 팀이 동일한 기본 플랫폼에 대한 자체 임시 인터페이스를 구축하는 상황을 방지한다.
자동화 플랫폼 운영의 조직적 차원, 팀들이 그것 주변에 어떻게 구성되는지, 내부 도구에 제품 사고가 어떻게 적용되는지, 플랫폼 팀들이 내부 소비자와의 계약을 어떻게 관리하는지는 10장 (플랫폼 엔지니어링)과 13장 (문화와 협업)에서 깊이 다룬다. 여기서 이루어진 아키텍처 선택들, 특히 SoT RBAC 범위와 오케스트레이터 워크플로 소유권은 해당 장들이 설명하는 조직 모델을 직접 제약한다.
3.4. 요약#
아키텍처적 사고는 실제로 작동하는 네트워크 자동화를 구축하는 데 필수적이다. OSI 모델이 네트워크 이해를 위한 계층적 프레임워크를 제공하는 것처럼, 참조 아키텍처는 유지 보수 가능하고, 확장 가능하며, 신뢰할 수 있는 자동화 시스템을 구성하고 설계하는 데 도움이 된다.
이 장은 일곱 가지 핵심 구성 요소를 정의하는 NAF 프레임워크를 소개했다. 아키텍처는 경직된 처방이 아니다. 유연한 프레임워크다. 현재 상태를 평가하고, 자동화 여정을 계획하며, 정보에 입각한 도구 결정을 내리고, 이해관계자와 소통하며, 통합을 위해 설계하고, 점진적으로 발전하기 위해 사용하라. 기억하라: 목표는 실제 문제를 해결하는 실용적인 자동화이지, 아키텍처 순수성이 아니다.
이 책의 2부에서는 이러한 각 구성 요소들을 깊이 다루며, 자신의 자동화 프로젝트에 적용할 수 있는 구현 패턴, 모범 사례, 실제 예시를 탐구할 것이다.
💬 Found something to improve? Send feedback for this chapter