# Week5: 5GC Deployment
## 課程目標
- 了解容器化技術的基本概念
- 學習 Docker 的基本操作與管理
- 掌握 Docker Compose 的使用方法
- 將 5G 核心網路元件容器化部署
- 理解容器化部署的優勢與挑戰
## 為什麼需要容器化?
在前面的課程中,我們學習了 5G 核心網路的各種網路元件以及它們之間的協作關係。當我們要在實際環境中部署這些網路元件時,會面臨許多挑戰:
### 傳統部署方式的問題
- **環境依賴複雜**:每個網路元件可能需要不同版本的執行環境、函式庫
- **部署一致性**:開發環境與正式環境的差異可能導致「在我的機器上可以跑」的問題
- **擴展困難**:當需要增加 UPF 實例以支援更多流量時,傳統方式需要手動配置多台機器
- **資源利用率低**:每個服務獨佔一台實體機器,造成資源浪費
- **維護成本高**:系統更新、安全修補需要逐台處理
### 容器化技術的優勢
正如我們在[認識核心網路](https://hackmd.io/@cndi2025/B1CuTo0Gll)中提到的,營運商需要核心網路提供:
- **承載大量 UE 的能力**
- **動態擴展的能力**
- **部署在分散式架構的能力**
容器化技術完美地解決了這些需求:
1. **環境一致性**:「Build once, run anywhere」
2. **快速部署**:秒級啟動,相比虛擬機器的分鐘級啟動
3. **資源效率**:共享主機核心,比虛擬機器更輕量
4. **易於擴展**:可以快速啟動多個相同的容器實例
5. **微服務架構支援**:每個網路元件可以獨立部署和更新
## Docker 基礎概念
### 什麼是 Docker?
[Moby](https://www.ithome.com.tw/news/113899)(Docker)是一個開源的容器化平台,它使用 Linux 核心功能(如 cgroups 和 namespaces)來實現應用程式的隔離執行。
```
傳統虛擬機器 vs 容器
┌─────────────────────┐ ┌─────────────────────┐
│ Application A │ │ Application A │
├─────────────────────┤ ├─────────────────────┤
│ Guest OS │ │ Container │
├─────────────────────┤ ├─────────────────────┤
│ Hypervisor │ │ Docker Engine │
├─────────────────────┤ ├─────────────────────┤
│ Host OS │ │ Host OS │
└─────────────────────┘ └─────────────────────┘
```
### 核心概念
#### Image(映像檔)
- **定義**:容器的模板,包含了應用程式執行所需的所有內容
- **特性**:唯讀、分層儲存、可版本控制
- **類比**:就像是 VM 的 ISO 檔案,但更輕量
#### Container(容器)
- **定義**:Image 的執行實例
- **特性**:可讀寫、隔離執行、可以啟動/停止/刪除
- **類比**:就像是從 ISO 檔案安裝並執行的虛擬機器
#### Dockerfile
- **定義**:定義如何建置 Image 的文字檔案
- **用途**:自動化建置過程,確保環境一致性
### Docker 基本操作
#### 1. 映像檔管理
```bash
# 拉取映像檔
docker pull ubuntu:20.04
# 列出本地映像檔
docker images
# 刪除映像檔
docker rmi ubuntu:20.04
# 建置映像檔
docker build -t my-app:latest .
```
#### 2. 容器管理
```bash
# 執行容器
docker run -it ubuntu:20.04 /bin/bash
# 在背景執行容器
docker run -d --name my-container nginx
# 列出執行中的容器
docker ps
# 列出所有容器(包含已停止的)
docker ps -a
# 停止容器
docker stop my-container
# 啟動已停止的容器
docker start my-container
# 進入執行中的容器
docker exec -it my-container /bin/bash
# 刪除容器
docker rm my-container
```
#### 3. 網路與儲存
```bash
# 建立自定義網路
docker network create my-network
# 使用自定義網路執行容器
docker run -d --name app --network my-network my-app
# 掛載本地目錄到容器
docker run -v /host/path:/container/path my-app
# 建立 Volume
docker volume create my-volume
docker run -v my-volume:/data my-app
```
### 撰寫 Dockerfile
以 free5GC 的 AMF 為例,一個基本的 Dockerfile 可能長這樣:
```dockerfile
# 使用官方 Golang 映像檔作為建置環境
FROM golang:1.21-alpine AS builder
# 設定工作目錄
WORKDIR /app
# 複製 go.mod 和 go.sum
COPY go.mod go.sum ./
# 下載依賴套件
RUN go mod download
# 複製原始碼
COPY . .
# 建置應用程式
RUN go build -o amf ./cmd/amf
# 使用輕量的 Alpine Linux 作為執行環境
FROM alpine:latest
# 安裝必要的工具
RUN apk --no-cache add ca-certificates
# 建立應用程式使用者
RUN adduser -D -s /bin/sh amf
# 複製建置好的執行檔
COPY --from=builder /app/amf /usr/local/bin/amf
# 複製配置檔案
COPY --from=builder /app/config /etc/free5gc/
# 切換到應用程式使用者
USER amf
# 暴露埠號
EXPOSE 8000
# 設定啟動命令
CMD ["amf", "-config", "/etc/free5gc/amfcfg.yaml"]
```
## Docker Compose 簡介
### 為什麼需要 Docker Compose?
當我們要部署完整的 5G 核心網路時,需要同時執行多個容器:
- AMF
- SMF
- UPF
- AUSF
- UDM
- UDR
- NRF
- CHF
- NEF
- MongoDB(作為資料庫)
手動使用 `docker run` 命令來啟動這麼多容器會很麻煩,而且容器之間的網路配置和依賴關係也很複雜。Docker Compose 就是為了解決這個問題而生的。
### Docker Compose 的優勢
1. **宣告式配置**:使用 YAML 檔案定義整個應用程式的架構
2. **一鍵部署**:`docker-compose up` 就能啟動整個系統
3. **依賴管理**:自動處理容器間的啟動順序
4. **網路管理**:自動建立專用網路,容器間可以用服務名稱互相通訊
5. **環境隔離**:不同的專案可以有獨立的環境
### Docker Compose 基本操作
```bash
# 啟動所有服務
docker-compose up
# 在背景啟動所有服務
docker-compose up -d
# 檢視服務狀態
docker-compose ps
# 檢視服務日誌
docker-compose logs
# 檢視特定服務的日誌
docker-compose logs amf
# 停止所有服務
docker-compose stop
# 停止並刪除所有容器
docker-compose down
# 重新建置並啟動服務
docker-compose up --build
# 執行一次性命令
docker-compose exec amf /bin/sh
```
### 撰寫 docker-compose.yml
以下是一個簡化的 free5GC 部署範例:
```yaml
version: '3.8'
services:
# 資料庫服務
mongodb:
image: mongo:5.0
container_name: mongodb
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
- mongodb_data:/data/db
networks:
- free5gc-net
ports:
- "27017:27017"
# NRF - 服務註冊與發現
nrf:
build:
context: ./nf_repository
dockerfile: Dockerfile
container_name: nrf
environment:
- DB_URI=mongodb://admin:password@mongodb:27017/free5gc?authSource=admin
depends_on:
- mongodb
networks:
- free5gc-net
ports:
- "8000:8000"
# AMF - 存取與行動管理
amf:
build:
context: ./access_mobility_mgmt
dockerfile: Dockerfile
container_name: amf
environment:
- NRF_URI=http://nrf:8000
depends_on:
- nrf
networks:
- free5gc-net
ports:
- "8001:8000"
# SMF - 會話管理
smf:
build:
context: ./session_mgmt
dockerfile: Dockerfile
container_name: smf
environment:
- NRF_URI=http://nrf:8000
depends_on:
- nrf
networks:
- free5gc-net
ports:
- "8002:8000"
# UPF - 用戶平面
upf:
build:
context: ./user_plane
dockerfile: Dockerfile
container_name: upf
environment:
- SMF_URI=http://smf:8000
depends_on:
- smf
networks:
- free5gc-net
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
ports:
- "8805:8805/udp"
networks:
free5gc-net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
mongodb_data:
```
### 重要配置說明
#### 1. 網路配置
```yaml
networks:
free5gc-net:
driver: bridge
```
- 建立專用網路,容器間可以使用服務名稱互相通訊
- 例如:AMF 可以透過 `http://nrf:8000` 存取 NRF 服務
#### 2. 依賴關係
```yaml
depends_on:
- nrf
```
- 確保 NRF 先啟動,再啟動依賴它的服務
#### 3. 環境變數
```yaml
environment:
- NRF_URI=http://nrf:8000
```
- 設定容器內的環境變數,應用程式可以讀取這些變數進行配置
#### 4. 持久化儲存
```yaml
volumes:
- mongodb_data:/data/db
```
- 確保資料庫資料不會因為容器重啟而遺失
#### 5. 特殊權限
```yaml
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
```
- UPF 需要網路管理權限來建立 TUN/TAP 介面
## 實際部署 free5GC
### 1. 準備工作
首先確保系統已安裝 Docker 和 Docker Compose:
```bash
# 檢查 Docker 版本
docker --version
# 檢查 Docker Compose 版本
docker-compose --version
# 確保 Docker 服務正在執行
sudo systemctl status docker
```
### 2. 設定組態檔案
每個網路元件都需要相應的配置檔案,以 AMF 為例:
```yaml
# amfcfg.yaml
info:
version: 1.0.9
description: AMF initial local configuration
configuration:
amfName: AMF
ngapIpList:
- 172.20.0.10 # AMF 在容器網路中的 IP
ngapPort: 38412
sbi:
scheme: http
registerIPv4: amf # 使用服務名稱註冊到 NRF
bindingIPv4: 0.0.0.0 # 綁定到所有網路介面
port: 8000
serviceNameList:
- namf-comm
- namf-evts
- namf-mt
- namf-loc
- namf-oam
nrfUri: http://nrf:8000 # NRF 服務位址
```
### 3. 啟動核心網路
```bash
# 啟動所有服務
docker-compose up -d
# 檢查服務狀態
docker-compose ps
# 檢視 AMF 日誌
docker-compose logs -f amf
```
### 4. 驗證部署
```bash
# 檢查 NRF 中註冊的服務
curl http://localhost:8000/nnrf-nfm/v1/nf-instances
# 檢查 AMF 狀態
curl http://localhost:8001/namf-comm/v1/status
```
## 容器化部署的優勢
### 1. 開發與正式環境一致性
```bash
# 開發環境
docker-compose -f docker-compose.dev.yml up
# 正式環境
docker-compose -f docker-compose.prod.yml up
```
### 2. 輕鬆的水平擴展
```yaml
# 擴展 UPF 實例
upf:
# ... 其他配置
deploy:
replicas: 3 # 啟動 3 個 UPF 實例
```
### 3. 版本管理與回滾
```bash
# 更新到新版本
docker-compose pull
docker-compose up -d
# 回滾到舊版本
docker tag myapp:latest myapp:backup
docker-compose down
docker-compose up -d
```
### 4. 監控與日誌集中化
```yaml
# 整合監控工具
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
```
#
## 課堂/課後練習
最新版本的 free5gc-compose 會部署 [grafana 與 prometheus](https://github.com/free5gc/free5gc-compose/blob/master/docker-compose-prometheus.yaml),請參考網路資源練習擴充核心網路的可觀測性:
1. 參考 [Configure logging drivers](https://docs.docker.com/engine/logging/configure/) 使用 [loki](https://grafana.com/docs/loki/latest/) 替換預設的 log driver。
2. 設置 Grafana Dashboard,使用 Loki 作為 Data Source 以顯示網路元件的日誌。
繳交答案時,請提供 Grafana Dashboard(帶有顯示網路元件的日誌)的畫面截圖。
範例(顯示的方式有很多,這個只是其中一個):
