⚙️

Incus VM上のMicroK8s環境にfree5GCを構築してみた

に公開

改訂リリースノート

2025年8月: jammy VM上で構築するように改訂

最近IncusのImage serverからubuntu/focal/desktopイメージを取得できなくなりました。そのため改定前の手順ではfree5gc・UERANSIMを構築できなくなりました。対策として、現在取得できるubuntu/jammy/desktopイメージを使ってfree5gc・UERANSIMを構築し1call確認できましたので、手順を改訂しました。

手順の変更箇所
指定パラメータの変更のみで、手順の流れは変更ありません。

改定前 改訂後
1 incus launch images:ubuntu/focal/desktop images:ubuntu/jammy/desktop
2 apt -y install linux-headers-5.4.0-216-generic linux-headers-5.15.0-151-generic
3 snap install microk8s --channel=1.28/stable --channel=1.32/stable

はじめに

free5GC公式サイトにHelm chartを使ってfree5GCを構築する手順らしきものがあります。

https://free5gc.org/guide/7-free5gc-helm/

本記事は、これをお手本に、まずIncus VMインスタンスを立ててその上にMicroK8s環境を構築し、そのMicroK8s環境上にHelm chartを使ってfree5GCを構築してみた手順メモです。

構築Before:
本記事では、以下の状態から構築手順を開始します。

  1. Incus導入済のIncusホストマシンを自宅ホームルータ配下に設置してある。
  2. Tailscale導入済で、クライアントPCからIncusホストマシンのincusbr0ブリッジネットワークにアクセスできる。

構築After:
本記事の構築手順により、以下の構築が完了した状態となります。

  1. VMインスタンス間をL2接続するlocalbr0ブリッジ
  2. free5gc on microk8s用のVMインスタンスfree5gc-k8s1-vm
  3. UERANSIM用のVMインスタンスl2ueransim1-vm

なお本記事では、構築完了後の、UERANSIMからfree5gcへの接続テストの手順も記述します。
※UEは、n6(DataNetwork)から多段NAT(NAT3とNAT1を経由)でInternetにIP疎通できます。

1 Incusホストマシンの設定

1.1 localbr0ブリッジを作成する

手順:
自作のsystemdサービスrclocal.serviceを用意し、IncusホストマシンのOS起動時にlocalbr0ブリッジが自動作成(永続化)されるようにします。

Incusホストマシン
sudo bash -c 'cat > /etc/systemd/system/rclocal.service' <<'_EOS_'
[Unit]
Description=rc.local
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ip link add localbr0 type bridge
ExecStart=/usr/sbin/ip link set dev localbr0 up
TimeoutStartSec=0
RemainAfterExit=yes
[Install]
WantedBy=default.target
_EOS_

systemctl startlocalbr0ブリッジを作成し、今後のためにsystemctl enableします。

Incusホストマシン
sudo systemctl daemon-reload
sudo systemctl start rclocal.service
sudo systemctl enable rclocal.service

1.2 free5gc VMインスタンスを作成する

手順:
defaultのプロファイルを流用し、free5gc VM用のプロファイルを用意します。

Incusホストマシン
incus profile copy default prof-free5gc
incus profile edit prof-free5gc

defaultプロファイルからの変更点:
 - description: for free5gcを下記のとおり追記
 - devices: eth1eth2を下記のとおり追加

Incusホストマシン
incus profile show prof-free5gc
config: {}
description: Default Incus profile for free5gc
devices:
  eth0:
    name: eth0
    network: incusbr0
    type: nic
  eth1:
    name: eth1
    nictype: bridged
    parent: localbr0
    type: nic
  eth2:
    name: eth2
    nictype: macvlan
    parent: enlan0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: prof-free5gc
used_by:

プロファイルを用いてfree5gc VMを作成(起動)します。

Incusホストマシン
incus launch images:ubuntu/jammy/desktop free5gc-k8s1-vm --vm -p prof-free5gc -c limits.cpu=4 -c limits.memory=8GiB

作成(起動)したVMをいったん停止し、セキュアブート無効化と/(root)ディスクサイズをVMに指定します。起動すると、それらの指定が反映されて起動します。

Incusホストマシン
incus stop free5gc-k8s1-vm
incus config set free5gc-k8s1-vm security.secureboot=false
incus config device override free5gc-k8s1-vm root size=16GiB
incus start free5gc-k8s1-vm

2 free5gc VMインスタンスの設定

手順:
まずfree5gc VMに入ります。

Incusホストマシン
incus exec free5gc-k8s1-vm -- bash

VM内の時刻表示の形式をデフォルトのUTCからJSTに変更します。

free5gc VM
timedatectl set-timezone Asia/Tokyo

2.1 VMのNICインタフェース名を変更する

概要:
free5gcのHelm chart内で、free5gcのn2/n4/n3/n9/n6の各インタフェース(ネットワーク)へマッピングするNICインタフェースがデフォルトでは下表のように設定されています。n6 (DataNetwork)のみeth1で、それ以外はeth0です。

free5gc Config parameter Default value
1 global.n2network.masterIf eth0
2 global.n4network.masterIf eth0
3 global.n3network.masterIf eth0
4 global.n9network.masterIf eth0
5 global.n6network.masterIf eth1

上記の設定を上書き修正してもよいのですが、free5gc側のデフォルト設定にあまり変更を加えたくないため、以下のようにVMのNICインタフェース設定をfree5gc側のデフォルト設定に合わせて変更します。
また、enp5s0のIPアドレスはmicrok8sノードのNodeIPとして扱うため、固定IPに変更します。

VMのNICインタフェース設定の変更点:
 - 名前の変更
  - enp6s0 -> eth0
  - enp7s0 -> eth1
 - enp5s0のIPアドレス: DHCP動的IP -> 固定IP

手順:
名前を変更するためのudev設定ファイル70-persistent-net.rulesを新規作成します。

free5gc VM
bash -c 'cat > /etc/udev/rules.d/70-persistent-net.rules' <<'_EOS_'
# Execute: sudo udevadm control --reload-rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="virtio_net", SUBSYSTEMS=="virtio", KERNELS=="virtio10", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="virtio_net", SUBSYSTEMS=="virtio", KERNELS=="virtio11", NAME="eth1"
_EOS_

enp5s0を固定IPにするためのnetplan設定ファイル95-free5gc.yamlを新規作成します。
・enp5s0を10.57.140.220/24に固定
・NameserverとDefault GWをincusbr0ブリッジのIPアドレス10.57.140.1に指定

free5gc VM
bash -c 'cat > /etc/netplan/95-free5gc.yaml' <<'_EOS_'
network:
  version: 2
  renderer: networkd
  ethernets:
    enp5s0:
      dhcp4: false
      addresses:
        - 10.57.140.220/24
      nameservers:
        addresses:
          - 10.57.140.1
      routes:
        - to: default
          via: 10.57.140.1
      dhcp6: false
      accept-ra: no
    eth0:
      dhcp4: false
      dhcp6: false
      accept-ra: no
    eth1:
      dhcp4: false
      dhcp6: false
      accept-ra: no
_EOS_

udevとnetplanの設定を反映するため、いったんVMからexitしてVMを再起動します。
再起動後に再度VMに入ります。

free5gc VM
exit
Incusホストマシン
incus restart free5gc-k8s1-vm
incus exec free5gc-k8s1-vm -- bash

ip aping 8.8.8.8で、udevとnetplanの設定が反映されたことを確認します。
※今回の設定変更ではInternetへのIP疎通性は変化せず、IP疎通できるままです。

free5gc VM
ip a
ping 8.8.8.8

2.2 gtp5g kernel moduleをインストールする

概要:
free5gcの通常インストール手順を参考にしてgtp5gをインストールします。
※参考箇所1 A.4. User-plane Supporting Packages
※参考箇所2 C.2. Retrieve the 5G GTP-U kernel module using git and build it

https://free5gc.org/guide/3-install-free5gc/

手順:
まず、gtp5gのビルドに必要なパッケージをapt installします。

free5gc VM
apt -y update
apt -y install git gcc g++ cmake autoconf libtool pkg-config libmnl-dev libyaml-dev
uname -r
apt -y install linux-headers-5.15.0-151-generic

ビルド、インストールします。

free5gc VM
git clone -b v0.9.14 https://github.com/free5gc/gtp5g.git
cd gtp5g
make
make install

lsmodでgtp5gが表示されることを確認します。

free5gc VM
lsmod | grep gtp5g
cd ~

2.3 microk8sをインストールする

手順:
snapでインストールします。
なお、インストールによる新たなパスを通すためsu - $USERします。

free5gc VM
snap info microk8s
snap install microk8s --classic --channel=1.32/stable
su - $USER

microk8sが起動してreadyであることを確認します。

free5gc VM
microk8s status --wait-ready
///
microk8s is running
high-availability: no
  datastore master nodes: 127.0.0.1:19001
  datastore standby nodes: none
addons:
  enabled:
    dns                  # (core) CoreDNS
    ha-cluster           # (core) Configure high availability on the current node
    helm                 # (core) Helm - the package manager for Kubernetes
    helm3                # (core) Helm 3 - the package manager for Kubernetes
  disabled:
(...)

2.4 kubectlとhelmをインストールする

手順:
kubectlhelmを使えるようにします。
なお、インストールによる新たなパスを通すためsu - $USERします。

free5gc VM
snap install kubectl --classic
snap install helm --classic
microk8s config > ~/.kube/config
su - $USER

2.5 free5gc用のk8sネームスペースを作成する

手順:

free5gc VM
kubectl create ns free5gc

2.6 kube-ovnプラグインを有効化する

手順:
UPFのIPフォワーディングを許容するために有効化します。

free5gc VM
microk8s enable kube-ovn --force
microk8s status --wait-ready

2.7 communityとmultusプラグインを有効化する

手順:

free5gc VM
microk8s enable community
microk8s enable multus
microk8s status --wait-ready

2.8 PersistentVolumeを作成する

手順:

1) persistent-vol-for-mongodb.yaml

mongodb PVデータ格納用フォルダを作成します。

free5gc VM
cd ~
mkdir -p localpv/mongodb

mongodb PV作成用のyamlファイルを用意します。

筆者によるパラメータ指定:
</path/to/storage> /root/localpv/mongodb
<work-node-name> free5gc-k8s0-vm

free5gc VM
bash -c 'cat > /root/localpv/persistent-vol-for-mongodb.yaml' <<'_EOS_'
apiVersion: v1
kind: PersistentVolume
metadata:
  name: free5gc-pv-mongo
  labels:
    project: free5gc
spec:
  capacity:
    storage: 8Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: microk8s-hostpath
  local:
    path: /root/localpv/mongodb
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - free5gc-k8s0-vm
_EOS_

2) persistent-vol-for-cert.yaml

cert PVデータ格納用フォルダを作成します。

free5gc VM
mkdir localpv/cert

cert PV作成用のyamlファイルを用意します。

筆者によるパラメータ指定:
</path/to/storage> /root/localpv/cert
<work-node-name> free5gc-k8s0-vm

free5gc VM
bash -c 'cat > /root/localpv/persistent-vol-for-cert.yaml' <<'_EOS_'
apiVersion: v1
kind: PersistentVolume
metadata:
  name: free5gc-pv-cert
  labels:
    project: free5gc
spec:
  capacity:
    storage: 2Mi
  accessModes:
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: microk8s-hostpath
  local:
    path: /root/localpv/cert
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - free5gc-k8s0-vm
_EOS_

3) PV作成実行と事後確認

free5gc VM
kubectl apply -f /root/localpv/persistent-vol-for-mongodb.yaml
kubectl apply -f /root/localpv/persistent-vol-for-cert.yaml

Availableであることを確認します。

free5gc VM
kubectl get persistentvolume
NAME               CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS        VOLUMEATTRIBUTESCLASS   REASON   AGE
free5gc-pv-cert    2Mi        ROX            Retain           Available           microk8s-hostpath   <unset>                          8s
free5gc-pv-mongo   8Gi        RWO            Retain           Available           microk8s-hostpath   <unset>                          18s

4) hostpath-storageプラグインを有効化する

マシン上のディレクトリでPVを扱えるようにするプラグインを有効化します。

free5gc VM
microk8s enable hostpath-storage
microk8s status --wait-ready

2.9 Helm chartでfree5gcをデプロイする

手順:

1) リポジトリをcloneする

free5gc VM
git clone https://github.com/free5gc/free5gc-helm.git

2) free5gc-smf/values.yamlを修正する (重要)

概要:
free5gc公式サイトに紹介されているように、singleulclの2モードがあります。

https://free5gc.org/guide/SMF-Config/

singleモード - SMFは、PDU SessionごとにUPF1台を選択:
UPFを使用
ulclモード - SMFは、PDU SessionごとにUPF2台を選択:
BranchingUPFAnchorUPF1を使用; または
BranchingUPFAnchorUPF2を使用

Helm chartのデフォルトではulclが指定されています。

free5gc Config parameter Default value
1 global.userPlaneArchitecture ulcl

今回、シンプルにfree5gcを使用したいためsingleモードを指定してhelm installを進めますが、singleモードを指定する場合のワークアラウンドとして、helm installで読み込むyamlファイルの1つであるfree5gc-smf/values.yamlを修正する必要があります。

手順:

修正対象ファイルを念のためバックアップした上で、修正します。

free5gc VM
cp -p free5gc-helm/charts/free5gc/charts/free5gc-smf/values.yaml free5gc-helm/charts/free5gc/charts/free5gc-smf/values.yaml.org
vi free5gc-helm/charts/free5gc/charts/free5gc-smf/values.yaml

修正箇所(1of4) dnnInfos:
・ulcl特有のdnaiList設定を削除
・ipv6 DNSサーバアドレスを削除

          dnnInfos: # DNN information list
            - dnn: internet # Data Network Name
-              dnaiList:
-                - mec
              dns: # the IP address of DNS
                ipv4: 8.8.8.8
-                ipv6: 2001:4860:4860::8888

修正箇所(2of4) upNodes:
・singleモード用のUPF定義を追加
・ulclモード用のBranchingUPF,AnchorUPF1, AnchorUPF2定義を削除

        upNodes: # information of userplane node (AN or UPF)
          gNB1: # the name of the node
            type: AN # the type of the node (AN or UPF)
+          UPF:
+            type: UPF
+            nodeID: 10.100.50.241 # PFCP address
+            sNssaiUpfInfos:
+              - sNssai:
+                  sst: 1
+                  sd: 010203
+                dnnUpfInfoList:
+                  - dnn: internet
+                    pools:
+                    - cidr: 10.1.0.0/17
+            interfaces:
+              - interfaceType: N3
+                endpoints:
+                  - 10.100.50.233
+                networkInstances:
+                  - internet
-          BranchingUPF:
-            type: UPF
-            nodeID: 10.100.50.241 # PFCP address
-            sNssaiUpfInfos:
-              - sNssai:
-                  sst: 1
-                  sd: 010203
-                dnnUpfInfoList:
-                  - dnn: internet
-                    dnaiList:
-                      - mec
-            interfaces:
-              - interfaceType: N3
-                endpoints:
-                  - 10.100.50.233
-                networkInstances:
-                  - internet
-              - interfaceType: N9
-                endpoints:
-                  - 10.100.50.225
-                networkInstances:
-                  - internet
-          AnchorUPF1:
-            type: UPF
-            nodeID: 10.100.50.242 # PFCP address
-            sNssaiUpfInfos:
-              - sNssai:
-                  sst: 1
-                  sd: 010203
-                dnnUpfInfoList:
-                  - dnn: internet
-                    pools:
-                    - cidr: 10.1.0.0/17
-            interfaces:
-              - interfaceType: N9
-                endpoints:
-                  - 10.100.50.226 # AnchorUPF1 N9 address
-                networkInstances:
-                  - internet
-          AnchorUPF2:
-            type: UPF
-            nodeID: 10.100.50.243 # PFCP address
-            sNssaiUpfInfos:
-              - sNssai:
-                  sst: 1
-                  sd: 010203
-                dnnUpfInfoList:
-                  - dnn: internet
-                    pools:
-                    - cidr: 10.1.128.0/17
-            interfaces:
-              - interfaceType: N9
-                endpoints:
-                  - 10.100.50.227 # AnchorUPF2 N9 address
-                networkInstances:
-                  - internet

修正箇所(3of4) links:
・singleモード用のUPFのトポロジ定義を追加
・ulclモード用のBranchingUPF,AnchorUPF1,AnchorUPF2のトポロジ定義を削除

        links:
+          - A: gNB1
+            B: UPF
-          - A: gNB1
-            B: BranchingUPF
-          - A: BranchingUPF
-            B: AnchorUPF1
-          - A: BranchingUPF
-            B: AnchorUPF2

修正箇所(4of4) ueRoutingInfo:
・ulclモード用のBranchingUPF,AnchorUPF1,AnchorUPF2に関するグループ定義を削除

    ueRoutingInfo: |-
-      UE1: # Group Name
-        members:
-        - imsi-208930000000001 # Subscription Permanent Identifier of the UE
-        topology: # Network topology for this group (Uplink: A->B, Downlink: B->A)
-        # default path derived from this topology
-        # node name should be consistent with smfcfg.yaml
-          - A: gNB1
-            B: BranchingUPF
-          - A: BranchingUPF
-            B: AnchorUPF1
-        specificPath:
-          - dest: 1.0.0.1/32
-            path: [BranchingUPF, AnchorUPF2]
-
-      UE2: # Group Name
-        members:
-        - imsi-208930000000004 # Subscription Permanent Identifier of the UE
-        topology: # Network topology for this group (Uplink: A->B, Downlink: B->A)
-        # default path derived from this topology
-        # node name should be consistent with smfcfg.yaml
-          - A: gNB1
-            B: BranchingUPF
-          - A: BranchingUPF
-            B: AnchorUPF1
-        specificPath:
-          - dest: 10.100.100.16/32 # the destination IP address on Data Network (DN)
-            # the order of UPF nodes in this path. We use the UPF's name to represent each UPF node.
-            # The UPF's name should be consistent with smfcfg.yaml
-            path: [BranchingUPF, AnchorUPF2]

3) helm install

singleモード指定でデプロイを実行します。
なお、指定しているn6のgatewayIP (192.168.0.1)は自宅ホームルータです。

free5gc VM
cd free5gc-helm/charts/
helm install -n free5gc free5gc-helm ./free5gc/ \
--set global.n6network.subnetIP="192.168.0.0" \
--set global.n6network.gatewayIP="192.168.0.1" \
--set global.n6network.excludeIP="192.168.0.254" \
--set global.userPlaneArchitecture="single" \
--set free5gc-upf.upf.n6if.ipAddress="192.168.0.221"

参考: helm installに成功すると以下のようなリターン表示があります。

free5gc VM
NAME: free5gc-helm
LAST DEPLOYED: Sat Jul  5 22:17:55 2025
NAMESPACE: free5gc
STATUS: deployed
REVISION: 1
NOTES:
#
# Software Name : towards5gs-helm
# SPDX-FileCopyrightText: Copyright (c) 2021 Orange
# SPDX-License-Identifier: Apache-2.0
#
# This software is distributed under the Apache License 2.0,
# the text of which is available at https://github.com/Orange-OpenSource/towards5gs-helm/blob/main/LICENSE
# or see the "LICENSE" file for more details.
#
# Author: Abderaouf KHICHANE, Ilhem FAJJARI
# Software description: An open-source project providing Helm charts to deploy 5G components (Core + RAN) on top of Kubernetes
#
#
# Visit the project at https://github.com/Orange-OpenSource/towards5gs-helm
#

1. Get the list of created Pods by running:
  kubectl get pods --namespace free5gc -l "project="

Release notes (What's changed in this version):
- Fix TLS configuration for SBI communications

helm ls -Aで、デプロイされたことを確認します。

free5gc VM
helm ls -A
///
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
free5gc-helm    free5gc         1               2025-07-05 22:17:55.080876313 +0900 JST deployed        free5gc-1.1.7   latest

kubectl get all -n free5gcでデプロイの進捗を確認します。

  1. upfとmongdbがRunningステータスに、その他がInit:0/1ステータスになったことを確認します。
free5gc VM
kubectl get all -n free5gc | grep pod
(...)
pod/free5gc-helm-free5gc-upf-upf-5b7bf98f5b-mqxg4             1/1     Running   0          2m28s
pod/mongodb-0                                                 1/1     Running   0          2m28s
  1. その他がInit:0/1ステータスから進まない状態になったら、ワークアラウンドとしてcorednsのrestartを実行します。
free5gc VM
kubectl -n kube-system rollout restart deployment coredns
  1. さらに数分待って、すべてがRunningステータスになったことを確認します。
free5gc VM
kubectl get all -n free5gc
NAME                                                          READY   STATUS    RESTARTS   AGE
pod/free5gc-helm-free5gc-amf-amf-6967fd4b94-899pc             1/1     Running   0          2m29s
pod/free5gc-helm-free5gc-ausf-ausf-57855479f9-pzglr           1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-chf-chf-564944ddb6-rl6hx             1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-dbpython-dbpython-6fcc8ff5f6-lr2xp   1/1     Running   0          2m29s
pod/free5gc-helm-free5gc-nef-nef-65654bb7ff-vf79k             1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-nrf-nrf-64b64f5564-mftgx             1/1     Running   0          2m29s
pod/free5gc-helm-free5gc-nssf-nssf-fd4f4994d-252jg            1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-pcf-pcf-55f76945ff-g7rrf             1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-smf-smf-7556dc9f88-klz7p             1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-udm-udm-b589558bb-f2488              1/1     Running   0          2m29s
pod/free5gc-helm-free5gc-udr-udr-89b6d9fdc-jnltd              1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-upf-upf-5b7bf98f5b-mqxg4             1/1     Running   0          2m28s
pod/free5gc-helm-free5gc-webui-webui-667c475cbb-r89rh         1/1     Running   0          2m29s
pod/mongodb-0                                                 1/1     Running   0          2m28s

NAME                                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/free5gc-helm-free5gc-amf-service    ClusterIP   10.152.183.39    <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-ausf-service   ClusterIP   10.152.183.252   <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-chf-service    ClusterIP   10.152.183.158   <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-nef-service    ClusterIP   10.152.183.194   <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-nssf-service   ClusterIP   10.152.183.69    <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-pcf-service    ClusterIP   10.152.183.56    <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-smf-service    ClusterIP   10.152.183.85    <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-udm-service    ClusterIP   10.152.183.19    <none>        80/TCP           2m29s
service/free5gc-helm-free5gc-udr-service    ClusterIP   10.152.183.246   <none>        80/TCP           2m29s
service/mongodb                             ClusterIP   10.152.183.74    <none>        27017/TCP        2m29s
service/nrf-nnrf                            ClusterIP   10.152.183.35    <none>        8000/TCP         2m29s
service/webui-nbiling                       ClusterIP   10.152.183.136   <none>        2122/TCP         2m29s
service/webui-ncgf                          ClusterIP   10.152.183.144   <none>        2121/TCP         2m29s
service/webui-service                       NodePort    10.152.183.157   <none>        5000:30500/TCP   2m29s

NAME                                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/free5gc-helm-free5gc-amf-amf             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-ausf-ausf           1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-chf-chf             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-dbpython-dbpython   1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-nef-nef             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-nrf-nrf             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-nssf-nssf           1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-pcf-pcf             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-smf-smf             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-udm-udm             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-udr-udr             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-upf-upf             1/1     1            1           2m29s
deployment.apps/free5gc-helm-free5gc-webui-webui         1/1     1            1           2m29s

NAME                                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/free5gc-helm-free5gc-amf-amf-6967fd4b94             1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-ausf-ausf-57855479f9           1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-chf-chf-564944ddb6             1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-dbpython-dbpython-6fcc8ff5f6   1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-nef-nef-65654bb7ff             1         1         1       2m28s
replicaset.apps/free5gc-helm-free5gc-nrf-nrf-64b64f5564             1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-nssf-nssf-fd4f4994d            1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-pcf-pcf-55f76945ff             1         1         1       2m28s
replicaset.apps/free5gc-helm-free5gc-smf-smf-7556dc9f88             1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-udm-udm-b589558bb              1         1         1       2m29s
replicaset.apps/free5gc-helm-free5gc-udr-udr-89b6d9fdc              1         1         1       2m28s
replicaset.apps/free5gc-helm-free5gc-upf-upf-5b7bf98f5b             1         1         1       2m28s
replicaset.apps/free5gc-helm-free5gc-webui-webui-667c475cbb         1         1         1       2m29s

NAME                       READY   AGE
statefulset.apps/mongodb   1/1     2m29s

4) UPF IPフォワーディング設定の正常性確認

下記コマンドのリターンが1であることを確認します。
なお、UPFでIPフォワーディングが有効であればリターン1です。

free5gc VM
kubectl exec -it -n free5gc deployment/free5gc-helm-free5gc-upf-upf \
-- cat /proc/sys/net/ipv4/ip_forward

3 free5GC WebUI上での設定

3.1 WebUIにアクセスする

手順:
クライアントPCのブラウザからwebui-serviceにアクセスします。
webui-serviceはtype: NodePortで、<NodeIP>:<NodePort>でアクセスできます。

※筆者の環境ではhttp://10.57.140.220:30500
 <NodeIP>: 1.57.140.220 ※free5gc VMのenp5s0の固定IPアドレス
 <NodePort>: 30500 ※kubectl get all -n free5gcで確認可

UsernameとPasswerdを入力してログインします。
・Username=admin
・Password=******* ※free5gc公式サイトを参照

3.2 テスト用の加入者データを作成する

手順:
WebUI上でテスト用の加入者データ(1件)を作成します。

  1. SUBSCRIBERS > CREATEボタンを押下する。
  2. SUPI (IMSI)を変更し、画面最下部のCREATEボタンを押下する。
     -変更前: imsi-208930000000001
     -変更後: imsi-208930000000003
     ※SUPI (IMSI)以外のフィールド値は初期値のまま変更不要

上記で作成完了です。
SUBSCRIBERS画面に作成した加入者データがリスト表示されるようになります。

4 UERANSIMによるfree5gc接続テスト

概要:
free5gc側の構築で、n2のネットワークとn3のネットワークがそれぞれ出来ました。
UERANSIMのn2(NGAP)とn3(GTP-U)のインタフェースを、それらのネットワークに所属させる形でUERANSIMを構築します。つまり、free5gcとUERANSIMの間にL3ルータを置かず、UERANSIMをL2ブリッジでfree5gcに接続します。

4.1 UERANSIM VMインスタンスを作成する

手順:
defaultのプロファイルを流用し、UERANSIM VM用のプロファイルを用意します。

Incusホストマシン
incus profile copy default prof-l2ueransim
incus profile edit prof-l2ueransim

defaultプロファイルからの変更点:
 - description: for l2ueransimを下記のとおり追記
 - devices: eth1eth2を下記のとおり追加

Incusホストマシン
incus profile show prof-l2ueransim
config: {}
description: Default Incus profile for l2ueransim
devices:
  eth0:
    name: eth0
    network: incusbr0
    type: nic
  eth1:
    name: eth1
    nictype: bridged
    parent: localbr0
    type: nic
  eth2:
    name: eth2
    nictype: bridged
    parent: localbr0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: prof-l2ueransim
used_by:

プロファイルを用いてUERANSIM VMを作成(起動)します。

Incusホストマシン
incus launch images:ubuntu/jammy/desktop l2ueransim1-vm --vm -p prof-l2ueransim -c limits.cpu=2 -c limits.memory=2GiB

UERANSIM VMに入り、VM内の時刻表示の形式をデフォルトのUTCからJSTに変更します。

Incusホストマシン
incus exec l2ueransim1-vm -- bash
UERANSIM VM
timedatectl set-timezone Asia/Tokyo

4.2 VMのNICインタフェースにIPアドレスを設定する

概要:
Helm chart版のUERANSIMの設定と同じIPアドレスを設定します。

subnet gatewayIP free5GC IP UERANSIM IP
n2 10.100.50.248/29 10.100.50.254 (AMF) 10.100.50.249 (enp6s0) 10.100.50.250
n3 10.100.50.232/29 10.100.50.238 (UPF) 10.100.50.233 (enp7s0) 10.100.50.236

・enp6s0 -> n2ネットワーク free5gc-amf接続用 (NGAP)
・enp7s0 -> n3ネットワーク free5gc-upf接続用 (GTP-U)

手順:
enp6s0とenp7s0にIPアドレスを設定するためのnetplan設定ファイル95-l2ueransim.yamlを新規作成します。

UERANSIM VM
bash -c 'cat > /etc/netplan/95-l2ueransim.yaml' <<'_EOS_'
network:
  version: 2
  renderer: networkd
  ethernets:
    enp6s0:
      dhcp4: false
      addresses:
        - 10.100.50.250/29
      dhcp6: false
      accept-ra: no
    enp7s0:
      dhcp4: false
      addresses:
        - 10.100.50.236/29
      dhcp6: false
      accept-ra: no
_EOS_

設定を反映します。

UERANSIM VM
netplan try

VM上からfree5gc側へping疎通確認をします。

UERANSIM VM
 ip a | grep enp
2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.57.140.180/24 metric 100 brd 10.57.140.255 scope global dynamic enp5s0
3: enp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.100.50.250/29 brd 10.100.50.255 scope global enp6s0
4: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 10.100.50.236/29 brd 10.100.50.239 scope global enp7s0

ping 10.100.50.249
PING 10.100.50.249 (10.100.50.249) 56(84) bytes of data.
64 bytes from 10.100.50.249: icmp_seq=1 ttl=64 time=0.557 ms
64 bytes from 10.100.50.249: icmp_seq=2 ttl=64 time=1.19 ms
64 bytes from 10.100.50.249: icmp_seq=3 ttl=64 time=1.10 ms

ping 10.100.50.233
PING 10.100.50.233 (10.100.50.233) 56(84) bytes of data.
64 bytes from 10.100.50.233: icmp_seq=1 ttl=64 time=0.542 ms
64 bytes from 10.100.50.233: icmp_seq=2 ttl=64 time=0.795 ms
64 bytes from 10.100.50.233: icmp_seq=3 ttl=64 time=1.32 ms

4.3 UERANSIMをインストールする

概要:
free5gc公式を参考にしてUERANSIMをインストールします。
※参考箇所 2. Install UERANSIM
https://free5gc.org/guide/5-install-ueransim/

手順:

UERANSIM VM
apt -y install git
git clone https://github.com/aligungr/UERANSIM
cd UERANSIM/
git checkout 85a0fbf

apt -y install make g++ libsctp-dev lksctp-tools iproute2
snap install cmake --classic
su - $USER

cd ~/UERANSIM
make

4.4 UERANSIMを設定する

概要:
free5gc公式を参考にしてUERANSIMを設定します。
※参考箇所 6. Setting UERANSIM
https://free5gc.org/guide/5-install-ueransim/

手順:
free5gc側の設定値に合わせてUERANSIMを設定します。

UERANSIM VM
cd ~/UERANSIM
cp -p config/free5gc-gnb.yaml config/free5gc-gnb.yaml.org
cp -p config/free5gc-ue.yaml config/free5gc-ue.yaml.org

free5gc-gnb.yaml設定:

UERANSIM VM
sed -i 's/ngapIp: 127.0.0.1/ngapIp: 10.100.50.250/' ~/UERANSIM/config/free5gc-gnb.yaml
sed -i 's/gtpIp: 127.0.0.1/gtpIp: 10.100.50.236/' ~/UERANSIM/config/free5gc-gnb.yaml
sed -i 's/address: 127.0.0.1/address: 10.100.50.249/' ~/UERANSIM/config/free5gc-gnb.yaml

free5gc-ue.yaml設定:

UERANSIM VM
sed -i s/imsi-208930000000001/imsi-208930000000003/ ~/UERANSIM/config/free5gc-ue.yaml

4.5 free5gc接続テストを実行する

ターミナル画面を3つ用意します。(画面#1,#2,#3)

手順:
gnbシミュレータを起動します。

(画面#1)Incusホストマシン
incus exec l2ueransim1-vm -- bash
(画面#1)UERANSIM VM
cd ~/UERANSIM
build/nr-gnb -c config/free5gc-gnb.yaml

期待結果:
・[ngap] [info] NG Setup procedure is successful

(画面#1)UERANSIM VM
build/nr-gnb -c config/free5gc-gnb.yaml
UERANSIM v3.2.6
[2025-07-07 17:34:55.709] [sctp] [info] Trying to establish SCTP connection... (10.100.50.249:38412)
[2025-07-07 17:34:55.714] [sctp] [info] SCTP connection established (10.100.50.249:38412)
[2025-07-07 17:34:55.714] [sctp] [debug] SCTP association setup ascId[7]
[2025-07-07 17:34:55.714] [ngap] [debug] Sending NG Setup Request
[2025-07-07 17:34:55.715] [ngap] [debug] NG Setup Response received
[2025-07-07 17:34:55.715] [ngap] [info] NG Setup procedure is successful

上記gNBシミュレータ画面#1の状態を維持したまま、
別のターミナル画面#2で、ueシミュレータを起動します。

(画面#2)Incusホストマシン
incus exec l2ueransim1-vm -- bash
(画面#2)UERANSIM VM
cd ~/UERANSIM
build/nr-ue -c config/free5gc-ue.yaml

期待結果:
・[nas] [info] Initial Registration is successful
・[nas] [info] PDU Session establishment is successful PSI[1]
・[app] [info] Connection setup for PDU session[1] is successful,
  TUN interface[uesimtun0, 10.1.0.2] is up. ←IPプールから払い出されたIPアドレス

(画面#2)UERANSIM VM
build/nr-ue -c config/free5gc-ue.yaml
UERANSIM v3.2.6
[2025-07-07 17:38:02.412] [nas] [info] UE switches to state [MM-DEREGISTERED/PLMN-SEARCH]
[2025-07-07 17:38:02.414] [rrc] [debug] New signal detected for cell[1], total [1] cells in coverage
[2025-07-07 17:38:02.414] [nas] [info] Selected plmn[208/93]
[2025-07-07 17:38:02.414] [rrc] [info] Selected cell plmn[208/93] tac[1] category[SUITABLE]
[2025-07-07 17:38:02.415] [nas] [info] UE switches to state [MM-DEREGISTERED/PS]
[2025-07-07 17:38:02.415] [nas] [info] UE switches to state [MM-DEREGISTERED/NORMAL-SERVICE]
[2025-07-07 17:38:02.415] [nas] [debug] Initial registration required due to [MM-DEREG-NORMAL-SERVICE]
[2025-07-07 17:38:02.415] [nas] [debug] UAC access attempt is allowed for identity[0], category[MO_sig]
[2025-07-07 17:38:02.415] [nas] [debug] Sending Initial Registration
[2025-07-07 17:38:02.415] [nas] [info] UE switches to state [MM-REGISTER-INITIATED]
[2025-07-07 17:38:02.415] [rrc] [debug] Sending RRC Setup Request
[2025-07-07 17:38:02.417] [rrc] [info] RRC connection established
[2025-07-07 17:38:02.417] [rrc] [info] UE switches to state [RRC-CONNECTED]
[2025-07-07 17:38:02.417] [nas] [info] UE switches to state [CM-CONNECTED]
[2025-07-07 17:38:02.450] [nas] [debug] Authentication Request received
[2025-07-07 17:38:02.450] [nas] [debug] Received SQN [000000000024]
[2025-07-07 17:38:02.450] [nas] [debug] SQN-MS [000000000000]
[2025-07-07 17:38:02.454] [nas] [debug] Security Mode Command received
[2025-07-07 17:38:02.454] [nas] [debug] Selected integrity[2] ciphering[0]
[2025-07-07 17:38:02.460] [nas] [debug] Registration accept received
[2025-07-07 17:38:02.460] [nas] [info] UE switches to state [MM-REGISTERED/NORMAL-SERVICE]
[2025-07-07 17:38:02.460] [nas] [debug] Sending Registration Complete
[2025-07-07 17:38:02.460] [nas] [info] Initial Registration is successful
[2025-07-07 17:38:02.460] [nas] [debug] Sending PDU Session Establishment Request
[2025-07-07 17:38:02.460] [nas] [debug] UAC access attempt is allowed for identity[0], category[MO_sig]
[2025-07-07 17:38:02.706] [nas] [debug] Configuration Update Command received
[2025-07-07 17:38:04.752] [nas] [debug] PDU Session Establishment Accept received
[2025-07-07 17:38:04.752] [nas] [info] PDU Session establishment is successful PSI[1]
[2025-07-07 17:38:04.773] [app] [info] Connection setup for PDU session[1] is successful, TUN interface[uesimtun0, 10.1.0.2] is up.

gNBシミュレータ画面#1およびUEシミュレータ画面#2を維持したまま、
別のターミナル画面#3で、uesimtun0が生成されていることを確認します。

(画面#3)Incusホストマシン
incus exec l2ueransim1-vm -- bash
(画面#3)UERANSIM VM
ip a show uesimtun0
6: uesimtun0: <POINTOPOINT,PROMISC,NOTRAILERS,UP,LOWER_UP> mtu 1400 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none
    inet 10.1.0.2/32 scope global uesimtun0
       valid_lft forever preferred_lft forever
    inet6 fe80::f6e5:610f:8bcd:fd61/64 scope link stable-privacy
       valid_lft forever preferred_lft forever

uesimtun0指定で8.8.8.8へping疎通確認をします。

(画面#3)UERANSIM VM
ping -I uesimtun0 8.8.8.8
PING 8.8.8.8 (8.8.8.8) from 10.1.0.1 uesimtun0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=15.6 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=118 time=8.06 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=118 time=11.5 ms

テストが終わったら、

  1. UEシミュレータ画面#2でCTRL+cを押下し、UERANSIM(UE)を終了します。
  2. gNBシミュレータ画面#1でCTRL+cを押下し、UERANSIM(gNB)を終了します。

付録

free5gc接続テストNGの場合のfree5gcログ確認方法

コールフローのどのあたりで止まっているかアタリがつきます。

free5gc VM
(例)
kubectl -n free5gc logs free5gc-helm-free5gc-amf-amf-6967fd4b94-899pc 
kubectl -n free5gc logs free5gc-helm-free5gc-smf-smf-7556dc9f88-klz7p

Incusホストマシンをシャットダウンする場合の対応方法

Incusホストマシンの電源を落とす場合は、とりあえず以下の手順で運用しています。
・Incusホストマシンをシャットダウンする前にVMを停止(incus stop free5gc-k8s1-vm)
・Incusホストマシンを電源投入した後にVMを再起動(incus start free5gc-k8s1-vm)

VMを再起動すると、microk8sも自律でrunning状態に戻ります。

free5gc VM
microk8s status --wait-ready
///
microk8s is running
high-availability: no
  datastore master nodes: 127.0.0.1:19001
  datastore standby nodes: none
(...)

VMを再起動すると、free5gcも自律でrunning状態に戻ります。(RESTARTSの値が1つ上がります。)

free5gc VM
kubectl get all -n free5gc
///
NAME                                                         READY   STATUS    RESTARTS        AGE
pod/free5gc-helm-free5gc-amf-amf-d7c7757f8-vqtnq             1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-ausf-ausf-857bdcb84-7cnzk           1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-chf-chf-5b778755f5-wcsbc            1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-dbpython-dbpython-59684d749-75dwc   1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-nef-nef-6cbcd74fd8-66r8g            1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-nrf-nrf-56cf4bdd95-xgls5            1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-nssf-nssf-64c575f955-4c9ng          1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-pcf-pcf-77894cd7d8-k8h2c            1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-smf-smf-858747d674-5bnpr            1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-udm-udm-6cdf97cc-w4vpb              1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-udr-udr-5f5c45dccb-74h4g            1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-upf-upf-8f7445d7b-cm5dj             1/1     Running   1 (2m40s ago)   17h
pod/free5gc-helm-free5gc-webui-webui-b8dfd4c67-xxkbn         1/1     Running   1 (2m40s ago)   17h
pod/mongodb-0                                                1/1     Running   1 (2m40s ago)   17h
(...)

参考文献

下記リンクは、本記事を書く上で特に参考にしたものです。

https://qiita.com/wzm/items/0dbe928ed891d82380d6

https://free5gc.org/blog/20250306/20250306/

https://free5gc.org/blog/20250416/20250416/

https://github.com/zanattabruno/5G-all-in-one-helm/blob/main/charts/free5gc/charts/free5gc-smf/values.yaml

以上

Discussion