Skip to content

Deploy a Standalone 5G Core in 15 Minutes

This tutorial brings up a complete Standalone (SA) 5G Core on Kubernetes using chart-based packaging, then verifies the two things that prove the SBA is alive: NRF-based NF discovery and a PDU session. It uses an open SA SBA core deployed via community-published charts. The same flow applies to any compliant SA core implementation with its own charts.

  1. A Kubernetes cluster (single-node or multi-node) with at least 4 vCPU / 8 GB RAM free and a kernel that supports the GTP-U kernel datapath your UPF requires.

  2. A Kubernetes CLI and a chart-based packaging CLI (v3) installed and pointed at the cluster:

    Terminal window
    kubectl version --short
    <chart-cli> version --short
  3. The GTP-U kernel module your chosen UPF expects, loaded on the node that will host the UPF - many kernel-mode UPFs use a GTP-U module for N3:

    Terminal window
    # Build/install the GTP-U kernel module per your UPF's documentation
    make && sudo make install
    sudo modprobe <gtp_module>
    lsmod | grep <gtp_module>
  1. Add and update the chart repo for your chosen core:

    Terminal window
    <chart-cli> repo add <repo-name> <chart-repo-url>
    <chart-cli> repo update
    <chart-cli> search repo <repo-name>
  2. Create a dedicated namespace so the core is easy to manage and tear down:

    Terminal window
    kubectl create namespace fivegc

The chart deploys every control-plane NF plus the UPF. Pin the UPF to the node where you loaded the GTP-U module.

  1. Find the node name and label it:

    Terminal window
    kubectl get nodes
    kubectl label node <your-node> nodetype=upf-host
  2. Create a minimal values.yaml to keep the lab simple:

    # values.yaml - lab profile
    global:
    n2network: { enabled: true }
    n3network: { enabled: true }
    n4network: { enabled: true }
    upf:
    nodeSelector:
    nodetype: upf-host
  3. Install the core:

    Terminal window
    <chart-cli> install fivegc-core <repo-name>/<core-chart> \
    --namespace fivegc \
    --values values.yaml
  4. Watch the NFs come up. Every pod should reach Running / Ready:

    Terminal window
    kubectl get pods -n fivegc -w

This is the SBA acid test: each NF should have registered with the NRF, and the NRF should be able to enumerate them.

  1. Port-forward the NRF’s SBI port:

    Terminal window
    kubectl -n fivegc port-forward svc/<nrf-service> 8000:8000
  2. Query the NRF’s NF management service for all registered instances:

    Terminal window
    curl -s http://127.0.0.1:8000/nnrf-nfm/v1/nf-instances \
    -H 'Accept: application/json' | jq '.["_links"].item[].href'

    You should see one entry per NF (AMF, SMF, AUSF, UDM, UDR, PCF, NSSF, UPF). If an NF is missing here, it failed to register - fix that before going further.

  3. Confirm the NRF tracks an AMF specifically (the NF the RAN will discover via N2 attach):

    Terminal window
    curl -s "http://127.0.0.1:8000/nnrf-nfm/v1/nf-instances?nf-type=AMF" \
    -H 'Accept: application/json' | jq '.nfInstances[].nfStatus'

    Expect "REGISTERED".

The core needs a subscriber provisioned in the UDR before the UE can authenticate.

  1. Open the core’s provisioning UI (web console):

    Terminal window
    kubectl -n fivegc port-forward svc/<webui-service> 5000:5000
  2. Browse to http://127.0.0.1:5000 and log in with your core’s default credentials. Add a subscriber whose IMSI, key (K), OPc, and S-NSSAI match what your UE simulator will present. Keep these values - the simulator must use the same.

Step 5 - Drive a PDU session with a UE/gNB simulator

Section titled “Step 5 - Drive a PDU session with a UE/gNB simulator”

A UE/gNB simulator emulates the gNB (N2/N3) and the UE (N1), letting you exercise registration and a PDU session end to end.

Terminal window
<chart-cli> install ue-sim <repo-name>/<ue-sim-chart> \
--namespace fivegc
kubectl get pods -n fivegc -l app=ue-sim -w
  1. Watch the UE pod logs for a successful registration and PDU session:

    Terminal window
    kubectl -n fivegc logs -l component=ue -f

    Look for Registration is successful followed by PDU Session establishment is successful and an assigned IP.

  2. Exec into the UE pod and send traffic through the tunnel interface (uesimtun0) - this proves the full N1→N2→N4→N3→N6 path:

    Terminal window
    kubectl -n fivegc exec -it <ue-pod> -- \
    ping -I uesimtun0 -c 4 8.8.8.8

    Replies confirm the UPF is forwarding subscriber packets out N6.

Terminal window
<chart-cli> uninstall ue-sim -n fivegc
<chart-cli> uninstall fivegc-core -n fivegc
kubectl delete namespace fivegc