Getting started

In this tutorial, we will deploy and run an SD-Core 5G core network using Juju and Terraform. As part of this tutorial, we will also deploy additional components:

  • gNB Simulator: a 5G radio and a cellphone simulator,

  • SD-Core Router: a software router facilitating communication between the core and the Radio Access Network (RAN) to simulate usage of this network.

Both gNB Simulator and SD-Core Router serve only demonstration purposes and shouldn’t be part of production deployments.

To complete this tutorial, you will need a machine which meets the following requirements:

  • A recent x86_64 CPU (Intel 4ᵗʰ generation or newer, or AMD Ryzen or newer)

  • At least 4 cores

  • 8GB of RAM

  • 50GB of free disk space

1. Install MicroK8s

From your terminal, install MicroK8s:

sudo snap install microk8s --channel=1.27-strict/stable

Add your user to the snap_microk8s group:

sudo usermod -a -G snap_microk8s $USER
newgrp snap_microk8s

Add the community repository MicroK8s addon:

sudo microk8s addons repo add community https://github.com/canonical/microk8s-community-addons --reference feat/strict-fix-multus

Enable the following MicroK8s addons. We must give MetalLB an address range that has at least 3 IP addresses for Charmed Aether SD-Core.

sudo microk8s enable hostpath-storage
sudo microk8s enable multus
sudo microk8s enable metallb:10.0.0.2-10.0.0.4

2. Bootstrap a Juju controller

From your terminal, install Juju.

sudo snap install juju --channel=3.4/stable

Bootstrap a Juju controller

juju bootstrap microk8s

Note

There is a bug in Juju that occurs when bootstrapping a controller on a new machine. If you encounter it, create the following directory: mkdir -p /home/ubuntu/.local/share

3. Install Terraform

From your terminal, install Terraform.

sudo snap install terraform --classic

4. Create Terraform module

On the host machine create a new directory called terraform:

mkdir terraform

Inside newly created terraform directory create a terraform.tf file:

cd terraform
cat << EOF > terraform.tf
terraform {
  required_providers {
    juju = {
      source  = "juju/juju"
      version = ">= 0.11.0"
    }
  }
}
EOF

Create a Terraform module containing the SD-Core 5G core network, 5G radio and a cellphone simulator and a router:

cat << EOF > main.tf
resource "juju_model" "sdcore" {
  name = "sdcore"
}

module "sdcore-router" {
  source = "git::https://github.com/canonical/sdcore-router-k8s-operator//terraform"

  model_name = juju_model.sdcore.name
  depends_on = [juju_model.sdcore]
}

module "sdcore" {
  source = "git::https://github.com/canonical/terraform-juju-sdcore//modules/sdcore-k8s"

  model_name = juju_model.sdcore.name
  create_model = false

  traefik_config = {
    routing_mode = "subdomain"
  }

  depends_on = [module.sdcore-router]
}

module "gnbsim" {
  source = "git::https://github.com/canonical/sdcore-gnbsim-k8s-operator//terraform"

  model_name = juju_model.sdcore.name
  depends_on = [module.sdcore-router]
}

resource "juju_integration" "gnbsim-amf" {
  model = juju_model.sdcore.name

  application {
    name     = module.gnbsim.app_name
    endpoint = module.gnbsim.fiveg_n2_endpoint
  }

  application {
    name     = module.sdcore.amf_app_name
    endpoint = module.sdcore.fiveg_n2_endpoint
  }
}

resource "juju_integration" "gnbsim-nms" {
  model = juju_model.sdcore.name

  application {
    name     = module.gnbsim.app_name
    endpoint = module.gnbsim.fiveg_gnb_identity_endpoint
  }

  application {
    name     = module.sdcore.nms_app_name
    endpoint = module.sdcore.fiveg_gnb_identity_endpoint
  }
}
EOF

Note

You can get a ready example by cloning this Git repository. All necessary files are in the examples/terraform/getting_started directory.

5. Deploy SD-Core

Initialize Juju Terraform provider:

terraform init

Deploy SD-Core by applying your Terraform configuration:

terraform apply -auto-approve

The deployment process should take approximately 15-20 minutes.

Monitor the status of the deployment:

juju switch sdcore
watch -n 1 -c juju status --color --relations

The deployment is ready when all the charms are in the Active/Idle state. It is normal for grafana-agent to remain in waiting state. Example:

ubuntu@host:~$ juju status
Model    Controller          Cloud/Region        Version  SLA          Timestamp
sdcore   microk8s-localhost  microk8s/localhost  3.4.0    unsupported  13:40:12+01:00

App                       Version  Status   Scale  Charm                         Channel             Rev  Address          Exposed  Message
amf                                active       1  sdcore-amf-k8s                1.5/edge            57   10.152.183.208   no
ausf                               active       1  sdcore-ausf-k8s               1.5/edge            40   10.152.183.237   no
gnbsim                             active       1  sdcore-gnbsim-k8s             1.5/edge            43   10.152.183.167   no
grafana-agent             0.32.1   waiting      1  grafana-agent-k8s             latest/stable       44   10.152.183.245   no       installing agent
mongodb                            active       1  mongodb-k8s                   6/beta              36   10.152.183.156   no       Primary
nms                                active       1  sdcore-nms-k8s                1.5/edge            26   10.152.183.121   no
nrf                                active       1  sdcore-nrf-k8s                1.5/edge            62   10.152.183.123   no
nssf                               active       1  sdcore-nssf-k8s               1.5/edge            37   10.152.183.165   no
pcf                                active       1  sdcore-pcf-k8s                1.5/edge            32   10.152.183.205   no
router                             active       1  sdcore-router-k8s             1.5/edge            33   10.152.183.49    no
self-signed-certificates           active       1  self-signed-certificates      1.5/edge            33   10.152.183.153   no
smf                                active       1  sdcore-smf-k8s                1.5/edge            37   10.152.183.147   no
traefik                   2.10.4   active       1  traefik-k8s                   latest/stable      148   10.0.0.4         no
udm                                active       1  sdcore-udm-k8s                1.5/edge            35   10.152.183.168   no
udr                                active       1  sdcore-udr-k8s                1.5/edge            31   10.152.183.96    no
upf                                active       1  sdcore-upf-k8s                1.5/edge            64   10.152.183.126   no
webui                              active       1  sdcore-webui-k8s              1.5/edge            23   10.152.183.128   no

Unit                         Workload  Agent  Address      Ports  Message
amf/0*                       active    idle   10.1.182.23
ausf/0*                      active    idle   10.1.182.18
gnbsim/0*                    active    idle   10.1.182.50
grafana-agent/0*             blocked   idle   10.1.182.51         logging-consumer: off, grafana-cloud-config: off
mongodb/0*                   active    idle   10.1.182.35         Primary
nms/0*                       active    idle   10.1.182.2
nrf/0*                       active    idle   10.1.182.53
nssf/0*                      active    idle   10.1.182.48
pcf/0*                       active    idle   10.1.182.46
router/0*                    active    idle   10.1.182.57
self-signed-certificates/0*  active    idle   10.1.182.56
smf/0*                       active    idle   10.1.182.27
traefik/0*                   active    idle   10.1.182.40
udm/0*                       active    idle   10.1.182.52
udr/0*                       active    idle   10.1.182.39
upf/0*                       active    idle   10.1.182.60
webui/0*                     active    idle   10.1.182.33

6. Configure the ingress

Get the IP address of the Traefik application:

juju status traefik

In this tutorial, the IP is 10.0.0.4. Please note it, as we will need it in the next step.

Configure Traefik to use an external hostname. To do that, edit traefik_config in the main.tf file:

:caption: main.tf
(...)
module "sdcore" {
  (...)
  traefik_config = {
    routing_mode      = "subdomain"
    external_hostname = "10.0.0.4.nip.io"
  }
  (...)
}
(...)

Apply new configuration:

terraform apply -auto-approve

Retrieve the NMS address:

juju run traefik/0 show-proxied-endpoints

The output should be http://sdcore-nms.10.0.0.4.nip.io/. Navigate to this address in your browser.

7. Configure the 5G core network through the Network Management System

In the Network Management System (NMS), create a network slice with the following attributes:

  • Name: default

  • MCC: 208

  • MNC: 93

  • UPF: upf-external.sdcore.svc.cluster.local:8805

  • gNodeB: sdcore-gnbsim-gnbsim

You should see the following network slice created:

NMS Network Slice

Create a subscriber with the following attributes:

  • IMSI: 208930100007487

  • OPC: 981d464c7c52eb6e5036234984ad0bcf

  • Key: 5122250214c33e723a5dd523fc145fc0

  • Sequence Number: 16f3b3f70fc2

  • Network Slice: default

  • Device Group: default-default

You should see the following subscriber created:

NMS Subscriber

8. Run the 5G simulation

Run the simulation:

juju run gnbsim/leader start-simulation

The simulation executed successfully if you see success: "true" as one of the output messages:

ubuntu@host:~$ juju run gnbsim/leader start-simulation
Running operation 1 with 1 task
  - task 2 on unit-gnbsim-0

Waiting for task 2...
info: run juju debug-log to get more information.
success: "true"

9. Destroy the environment

Destroy Terraform deployment:

terraform destroy -auto-approve

Note

Terraform does not remove anything from the working directory. If needed, please clean up the terraform directory manually by removing everything except for the main.tf and terraform.tf files.

Destroy the Juju controller and all its models:

juju kill-controller microk8s-localhost