diff --git a/.gitignore b/.gitignore
index cf1876d..264d4f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@
/tools/imports/**/*.zip
**/*.quarto_ipynb
+/.serena/
\ No newline at end of file
diff --git a/_quarto.yml b/_quarto.yml
index c5fe1e7..8dade58 100644
--- a/_quarto.yml
+++ b/_quarto.yml
@@ -33,15 +33,13 @@ website:
contents:
- text: "6-1. Neutron의 agent에 대해 알아보기"
file: lectures/ch6/neutron_agents.qmd
+ - text: "6-2. Provider network와 tenant network 개념 정리"
+ file: lectures/ch6/provider_tenant_network.qmd
- text: "6-12. SNAT/DNAT란?"
file: lectures/ch6/snat_dnat.qmd
- text: "6-15. OVS와 VXLAN를 이용해 가상 네트워크 만들기"
file: lectures/ch6/ovs_vxlan_vpn.qmd
-
-
-
-
format:
html:
theme:
@@ -49,4 +47,4 @@ format:
- custom.scss
toc: true
lang: ko
- include-after-body: _footer.html
\ No newline at end of file
+ include-after-body: _footer.html
diff --git a/lectures/ch6/images/provider_tenant_network/east_west.svg b/lectures/ch6/images/provider_tenant_network/east_west.svg
new file mode 100644
index 0000000..ac386fb
--- /dev/null
+++ b/lectures/ch6/images/provider_tenant_network/east_west.svg
@@ -0,0 +1,29 @@
+
diff --git a/lectures/ch6/images/provider_tenant_network/egress_snat.svg b/lectures/ch6/images/provider_tenant_network/egress_snat.svg
new file mode 100644
index 0000000..68e3790
--- /dev/null
+++ b/lectures/ch6/images/provider_tenant_network/egress_snat.svg
@@ -0,0 +1,37 @@
+
diff --git a/lectures/ch6/images/provider_tenant_network/ingress_dnat.svg b/lectures/ch6/images/provider_tenant_network/ingress_dnat.svg
new file mode 100644
index 0000000..03d92e6
--- /dev/null
+++ b/lectures/ch6/images/provider_tenant_network/ingress_dnat.svg
@@ -0,0 +1,37 @@
+
diff --git a/lectures/ch6/images/provider_tenant_network/inter_tenant_router.svg b/lectures/ch6/images/provider_tenant_network/inter_tenant_router.svg
new file mode 100644
index 0000000..21cdc01
--- /dev/null
+++ b/lectures/ch6/images/provider_tenant_network/inter_tenant_router.svg
@@ -0,0 +1,37 @@
+
diff --git a/lectures/ch6/images/provider_tenant_network/layer_overview.svg b/lectures/ch6/images/provider_tenant_network/layer_overview.svg
new file mode 100644
index 0000000..623b00e
--- /dev/null
+++ b/lectures/ch6/images/provider_tenant_network/layer_overview.svg
@@ -0,0 +1,35 @@
+
diff --git a/lectures/ch6/provider_tenant_network.qmd b/lectures/ch6/provider_tenant_network.qmd
new file mode 100644
index 0000000..3eba06e
--- /dev/null
+++ b/lectures/ch6/provider_tenant_network.qmd
@@ -0,0 +1,166 @@
+---
+title: "6-2. Provider network와 tenant network 개념 정리"
+description: "Provider network와 tenant network가 왜 분리되어 있는지, 각각 누가 만들고 어떤 역할을 맡는지 OpenStack Neutron 관점에서 정리합니다."
+code: "6-2"
+---
+
+# [6-2-1] 해당 개념들이 생기게 된 이유
+
+클라우드는 보통 **여러 사용자(테넌트)**가 **같은 물리 인프라(서버/스위치/회선)**를 공유합니다. 이때 네트워크에서 동시에 만족해야 하는 요구가 두 가지입니다.
+
+1. **운영자 관점(Provider)**
+ - 데이터센터 물리 네트워크(스위치/라우터/사내망/인터넷)와 안전하게 연결
+ - 장애/보안/성능/정책을 중앙에서 통제
+2. **사용자 관점(Tenant)**
+ - 각 팀/프로젝트가 VM들을 위해 네트워크를 “스스로” 만들고 지울 수 있어야 함
+ - 다른 팀/프로젝트와 트래픽이 섞이면 안 됨(격리)
+
+이 두 요구를 깔끔하게 분리한 결과가 보통:
+
+- **Provider network** = “운영자가 물리망과 연결해둔 기반 네트워크”
+- **Tenant network** = “테넌트가 VM용으로 만드는 격리된 논리 네트워크”
+
+입니다.
+
+# [6-2-2] Provider Network란?
+
+### 정의(핵심)
+
+**Provider network**는 보통 “클라우드 네트워크가 물리 네트워크와 만나는 지점”에 있는 네트워크입니다.
+
+즉, **물리 스위치/라우터의 특정 네트워크(VLAN 등)와 직접 매핑**되거나, 최소한 강하게 연결됩니다.
+
+### 누가 만들고 관리하나
+
+- 대부분 환경에서 **운영자(Admin)**가 생성/관리
+- 이유: 물리망 연결은 잘못 건드리면 전체 장애/보안 이슈로 직결
+
+### 어떤 형태가 흔한가(대표)
+
+환경에 따라 다르지만, 전형적인 분류는 이런 느낌입니다.
+
+- **Flat(untagged)**: VLAN 태그 없이 특정 물리 네트워크에 바로 붙는 형태
+- **VLAN 기반**: 물리 스위치에서 VLAN으로 분리된 네트워크에 매핑
+
+(※ OpenStack Neutron에선 provider network가 `flat` 또는 `vlan`로 많이 구성됩니다.)
+
+### 주 역할
+
+- **외부망(External)** 제공: 인터넷/사내망 등 “클라우드 밖”으로 나가는 출구/입구 역할
+- 데이터센터 내부의 특정 물리망(예: 관리망, 스토리지망, DMZ망 등)과 연결되는 통로 역할
+
+# [6-2-3] Tenant Network란?
+
+### 정의(핵심)
+
+**Tenant network**는 테넌트(프로젝트/사용자)가 VM들을 붙이기 위해 만드는 네트워크입니다.
+
+특징은 **다른 테넌트와 논리적으로 격리**된다는 점입니다.
+
+### 누가 만들고 관리하나
+
+- 보통 **테넌트(프로젝트 사용자)**가 직접 생성(Self-service)
+- 네트워크/서브넷/라우터를 UI/CLI로 만들고 VM을 붙이는 형태
+
+### 격리는 어떻게 하냐(개념 수준)
+
+테넌트 네트워크는 물리 케이블을 새로 까는 게 아니라, **가상화 계층에서 분리**합니다. 대표적으로:
+
+- **오버레이(Overlay)**: VXLAN/Geneve/GRE 같은 캡슐화로 논리 네트워크를 분리
+
+ → 여러 테넌트가 같은 물리망을 공유해도 “논리적으로 서로 다른 L2”처럼 보이게 함
+
+
+### 주요 특징
+
+- 테넌트 간 **트래픽 분리**가 기본값
+- 서로 다른 테넌트가 **같은 IP 대역**(예: 둘 다 10.0.0.0/24)을 써도 공존 가능(격리되어 있으니까)
+- 외부 연결은 기본적으로 바로 열려 있지 않습니다
+
+ → 라우터/NAT/보안그룹 등을 통해 열어야 외부 통신이 됩니다
+
+
+# [6-2-4] 전체 레이어
+
+
+
+# [6-2-5] 트래픽 흐름 3가지로 이해하기
+
+## 테넌트 내부 통신(East-West)
+
+같은 tenant network에 붙은 VM끼리는 그냥 L2/L3로 통신합니다.
+
+
+
+다른 tenant network라면(서브넷이 다르면) 라우터가 필요합니다.
+
+
+
+---
+
+## VM이 외부로 나감(Egress, 보통 SNAT)
+
+많은 클라우드에서 기본은:
+
+- VM은 사설 IP
+- 외부로 나갈 때 라우터가 **SNAT**를 수행
+
+
+
+---
+
+## 외부에서 VM으로 들어옴(Ingress, 보통 DNAT/매핑 필요)
+
+기본적으로 tenant network는 외부에서 바로 접근이 안 됩니다. 들어오려면 보통:
+
+- **Floating IP(공인 IP를 VM에 매핑)** 또는
+- 포트포워딩 같은 DNAT 설정
+- 보안그룹/방화벽 허용
+
+이런 “열어주는 작업”이 필요합니다.
+
+
+
+---
+
+# [6-2-6] Provider vs Tenant 차이 정리
+
+| 구분 | Provider Network | Tenant Network |
+| --- | --- | --- |
+| 주 사용자 | 운영자(Admin) | 테넌트(프로젝트/사용자) |
+| 목적 | 물리망/외부망과 연결되는 기반 제공 | VM용 내부망 제공, 테넌트 간 격리 |
+| 물리망과 관계 | 직접 매핑/연결(Flat/VLAN 등) | 논리망(오버레이 등으로 분리)인 경우가 많음 |
+| IP 성격 | 공인/사내 대역 등 “외부에 의미 있는” 대역일 수 있음 | 보통 사설 IP 대역(중복 가능) |
+| 외부 접근성 | 외부망 역할이면 접근성 높음(정책에 따름) | 기본은 외부에서 직접 접근 어려움 |
+| 성능/MTU 이슈 | 상대적으로 단순(캡슐화 없음) | 오버레이면 캡슐화 오버헤드/MTU 고려 필요 |
+| 운영 리스크 | 잘못 설정하면 전체 장애/보안 영향 큼 | 특정 프로젝트 범위 영향이 대부분 |
+
+---
+
+# [6-2-7] 흔한 오해 정리
+
+- **“Provider network = 무조건 인터넷망”**
+
+ → 외부망일 수도 있고, 데이터센터 내부의 특정 물리망(VLAN)일 수도 있습니다
+
+- **“Tenant network = 무조건 완전 내부만”**
+
+ → 기본은 내부로 쓰지만, 라우터/NAT/Floating IP 등으로 외부와 연결 가능합니다
+
+- **“Tenant network는 물리적으로 따로 깔린 네트워크”**
+
+ → 보통은 물리적으로 새로 까는 게 아니라, **논리적으로 분리**하는 방식(오버레이/VLAN 등) 입니다
+
+
+---
+
+# [6-2-8] 결론
+
+- **Provider network**: 운영자가 **물리망/외부망과 연결해 둔 기반 네트워크**
+- **Tenant network**: 테넌트가 **VM을 붙이고 서비스 구성하려고 만드는 격리된 논리 네트워크**
+
+# 참조
+
+[# OpenStack OVN provider network 아키텍처를 설명하는 공식 관리자 문서](https://docs.openstack.org/neutron/2024.2/admin/ovn/refarch/provider-networks.html)
+
+[# OpenStack self-service network와 라우터 연결 흐름을 설명하는 공식 설치 가이드](https://docs.openstack.org/install-guide/launch-instance-networks-selfservice.html)
diff --git a/lectures/ch6_lec.qmd b/lectures/ch6_lec.qmd
index 9ac3b48..f13326c 100644
--- a/lectures/ch6_lec.qmd
+++ b/lectures/ch6_lec.qmd
@@ -9,5 +9,6 @@ Neutron은 오픈스택의 네트워킹 서비스입니다. 이 장에서는 Neu
## 하위 목차
- [6-1 Neutron 에이전트 종류 정리](ch6/neutron_agents.qmd)
+- [6-2 Provider network와 tenant network 개념 정리](ch6/provider_tenant_network.qmd)
- [6-12 SNAT/DNAT 개념](ch6/snat_dnat.qmd)
- [6-15 OVS/VXLAN 가상 네트워크 만들기](ch6/ovs_vxlan_vpn.qmd)
diff --git a/lectures/index.qmd b/lectures/index.qmd
index e0e9993..96bef0e 100644
--- a/lectures/index.qmd
+++ b/lectures/index.qmd
@@ -16,6 +16,7 @@ title: "오픈스택 강의 자료"
- [4-1장. nova의 서비스 종류]()
- [5장. Glance]()
- [6장. Neutron](ch6_lec.qmd)
- - [SNAT/DNAT 개념](ch6/snat_dnat.qmd)
- [Neutron Agent 종류 정리](ch6/neutron_agents.qmd)
- - [OVS/VXLAN 가상 네트워크 만들기](ch6/ovs_vxlan_vpn.qmd)
\ No newline at end of file
+ - [6-2. Provider network와 tenant network 개념 정리](ch6/provider_tenant_network.qmd)
+ - [SNAT/DNAT 개념](ch6/snat_dnat.qmd)
+ - [OVS/VXLAN 가상 네트워크 만들기](ch6/ovs_vxlan_vpn.qmd)
diff --git a/tools/scripts/README.md b/tools/scripts/README.md
index 5ed68f3..404165f 100644
--- a/tools/scripts/README.md
+++ b/tools/scripts/README.md
@@ -93,17 +93,27 @@ python3 import_notion_zip.py "SNAT, DNAT 개념.zip" ch6 snat_dnat --title "SNAT
- 예: `neutron_agents.qmd`에서는
`[Red Hat OpenStack Platform Neutron 설정 문서](https://docs.redhat.com/ko/documentation/red_hat_openstack_platform/16.2/html/configuration_reference/neutron_2)`
처럼, 공식 문서가 무엇을 다루는지 한글로 설명을 붙여 준다.
- - 강의 본문 헤딩(`#`, `##`, `###`)에는 가능하면 **섹션 코드/번호**를 붙이되, ch6에서는 다음과 같이 정리한다.
- - 기본 원칙:
- - 섹션 코드는 **frontmatter의 `code:` 필드**와 **제목(title)** 에 우선 반영한다.
- - 예: `code: "6-12"`, `title: "6-12 SNAT, DNAT 개념 정리"`.
- - 본문 첫 `##` 헤딩에는 같은 번호를 **중복해서 다시 붙이지 않는다.**
- - 즉, `## NAT가 왜 생겼는지`처럼 내용 위주의 헤딩만 둔다.
+ - 강의 본문 헤딩(`#`, `##`, `###`) 번호는 **변환 직후 반드시 확인**한다. 특히 ch6 문서는 다음 규칙을 기본값으로 삼는다.
+ - 섹션 코드는 **frontmatter의 `code:` 필드**와 **제목(title)** 에 우선 반영한다.
+ - 예: `code: "6-12"`, `title: "6-12. SNAT/DNAT란?"`
+ - ch6의 **주요 본문 섹션**은 plain heading으로 두지 말고, `# [6-12-1] ...`, `# [6-12-2] ...` 같은 **번호형 H1**으로 맞춘다.
+ - 예: `# [6-2-1] 해당 개념들이 생기게 된 이유`
+ - 예: `# [6-2-5] 트래픽 흐름 3가지로 이해하기`
+ - 번호형 H1 아래의 하위 설명은 필요에 따라 일반 `##`/`###` 헤딩으로 둘 수 있다.
+ - 예: `## 테넌트 내부 통신(East-West)`
+ - 예: `## VM이 외부로 나감(Egress, 보통 SNAT)`
+ - 변환 후에는 최소한 아래를 **무조건 점검**한다.
+ - `code:` 값과 제목의 장/절 번호가 서로 일치하는지
+ - 본문 주요 섹션 번호가 `[6-2-1]`, `[6-2-2]`처럼 **순서대로 이어지는지**
+ - plain `# 제목`이 남아 있지 않은지
+ - 새로 끼어든 섹션이 있으면 뒤 번호까지 함께 밀어서 renumber 되었는지
- 일반적인 장/절 구조(코드 필드가 없는 다른 장)에서는 기존처럼 `## 2.2.5 VM NIC 3개 구성 및 정적 IP 설정` 형태를 사용할 수 있다.
- - 번호가 누락된 경우, 에이전트는 상위 헤딩 구조와 순서를 기준으로 번호를 **추론**만 하고, 실제 헤딩 텍스트 수정은 PR/리뷰에서 사람과 함께 확정하는 것을 권장한다.
- - 그림/표 번호는 이 헤딩/코드(예: `6-12`)를 기준으로 `그림 6-12-1`, `표 6-12-1` 처럼 계산한다.
- - 그림을 추가/정리할 때는 다음 형태를 기본으로 사용한다.
- - `{width="55%" fig-align="left"}`
+ - 그림/표 번호는 **가장 가까운 번호형 섹션 헤딩 전체**를 기준으로 계산한다.
+ - 예: `# [6-2-4] 전체 레이어` 아래 첫 그림이면 `그림 6-2-4-1`
+ - 예: `# [6-12-3] 두 가지 전통적인 NAT 방식` 아래 첫 그림이면 `그림 6-12-3-1`
+ - 섹션 번호가 바뀌면 그 아래 그림/표 번호도 **같이 renumber** 되었는지 반드시 확인한다.
+ - 그림을 추가/정리할 때는 다음 형태를 기본으로 사용한다.
+ - `{width="55%" fig-align="left"}`
→ **번호 + 한 줄 설명 + 파일명 + 왼쪽 정렬**이 한 번에 정리되도록 돕는다.
- 코드 블록(```` ``` ````) 언어 태그를 실제 내용과 맞춰 정리한다.
- 사용자가 `@파일경로 (21-26)`처럼 특정 범위를 가리킬 때, 그 범위가 **명령어**인지 **설정 파일**인지 보고 언어를 결정한다.
@@ -123,8 +133,10 @@ python3 import_notion_zip.py "SNAT, DNAT 개념.zip" ch6 snat_dnat --title "SNAT
- 코드 블록인데 실제로는 **그림/다이어그램을 글로 그려 놓은 경우**도 올바르게 정리한다.
- 예: 패킷 흐름, 토폴로지, 구성 요소 관계 등을 `|-`, `+`, `->` 같은 문자로 그려 놓은 ASCII 다이어그램.
- 이런 블록은 실행 가능한 코드가 아니므로, 다음 중 하나로 정리한다.
- - **설명 위주라면 일반 본문/리스트/표로 풀어서 재작성**하고, 가능하면 별도 그림 파일로 만드는 것을 권장한다.
- - 그대로 둘 필요가 있을 때는 언어 태그를 `text` 또는 비워 두어, ` ```text` 처럼 “코드가 아닌 텍스트 블록”임을 드러낸다.
+ - **우선순위 1:** `lectures/{chapter}/images/{slug}/` 아래에 **실제 그림 파일(svg/png 등)** 로 만들고, 본문에서는 다른 문서와 동일하게 `` 형태로 넣는다.
+ - **우선순위 2:** 설명 위주라면 일반 본문/리스트/표로 풀어서 재작성한다.
+ - **마지막 fallback:** 그대로 둘 필요가 있을 때만 언어 태그를 `text` 또는 비워 두어, ` ```text` 처럼 “코드가 아닌 텍스트 블록”임을 드러낸다.
+ - 즉, 기존 강의처럼 렌더 결과에 **정식 figcaption** 이 보이게 하려면, 가능한 한 텍스트 블록 대신 실제 이미지 파일로 바꿔 넣는 것을 기본값으로 삼는다.
- 셸/프로그래밍 언어로 잘못 태그된 ASCII 다이어그램은, 반드시 `text`/무태그로 바꾸거나 일반 문단으로 풀어서 정리한다.
---
diff --git a/tools/scripts/import_notion_zip.py b/tools/scripts/import_notion_zip.py
index 30cd82c..fe7d986 100644
--- a/tools/scripts/import_notion_zip.py
+++ b/tools/scripts/import_notion_zip.py
@@ -233,7 +233,7 @@ def main():
zip_path = Path(zip_arg).resolve()
if not zip_path.exists():
- imports_chapter = IMPORTS_DIR / chapter
+ imports_chapter = IMPORTS_DIR / chapter
if '/' not in zip_arg and '\\' not in zip_arg and not imports_chapter.exists():
imports_chapter.mkdir(parents=True)
print(f"tools/imports/{chapter}/ 폴더를 생성했습니다. ZIP 파일을 넣어주세요: {imports_chapter}")