Getting started¶
In this tutorial, we will deploy and run Charmed OAI RAN (Radio Access Network) using Juju and Terraform. The Charmed OAI RAN consists of two Juju charms representing the CU (Central Unit) and the DU (Distributed Unit).
As part of this tutorial, we will also deploy additional components:
Charmed Aether SD-Core: A 5G core network which will manage our RAN network
SD-Core Router: a software router facilitating communication between the 5G Core and the RAN
User Equipment (UE) simulator: A simulated cellphone which will allow us to validate the correctness of the entire deployment
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 (8 recommended)
At least 8 GB of RAM (16 GB recommended)
50GB of free disk space
1. Deploy Charmed Aether SD-Core¶
Install MicroK8s¶
From your terminal, install MicroK8s:
sudo snap install microk8s --channel=1.29/stable --classic
Add your user to the microk8s
group:
sudo usermod -a -G microk8s $USER
newgrp microk8s
Add the community repository MicroK8s addon:
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.
microk8s enable hostpath-storage
microk8s enable multus
microk8s enable metallb:10.0.0.2-10.0.0.4
Export MicroK8s cluster’s configuration:
microk8s config > ~/.kube/config
Bootstrap a Juju controller¶
From your terminal, install Juju:
sudo snap install juju --channel=3.4/stable
Add MicroK8s cluster to Juju:
juju add-k8s microk8s-classic
Bootstrap a Juju controller:
juju bootstrap microk8s-classic
Install Terraform¶
From your terminal, install Terraform:
sudo snap install terraform --classic
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 > versions.tf
terraform {
required_providers {
juju = {
source = "juju/juju"
version = ">= 0.12.0"
}
}
}
EOF
Create a Terraform module containing the Charmed Aether SD-Core 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 = juju_model.sdcore.name
depends_on = [juju_model.sdcore]
}
module "sdcore" {
source = "git::https://github.com/canonical/terraform-juju-sdcore//modules/sdcore-k8s"
model = juju_model.sdcore.name
depends_on = [module.sdcore-router]
traefik_config = {
routing_mode = "subdomain"
}
}
EOF
Note
You can get a ready example by cloning this Git repository.
All necessary files are in the examples/terraform/getting_started
directory.
Deploy 5G Core network¶
Initialize Juju Terraform provider:
terraform init
Deploy SD-Core by applying your Terraform configuration:
terraform apply -auto-approve
The deployment process should take approximately 10-15 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.
It is also expected that traefik
goes to the error state (related Traefik bug).
Example:
ubuntu@host:~$ juju status
Model Controller Cloud/Region Version SLA Timestamp
sdcore microk8s-classic-localhost microk8s-classic/localhost 3.4.5 unsupported 08:08:50Z
App Version Status Scale Charm Channel Rev Address Exposed Message
amf 1.4.4 active 1 sdcore-amf-k8s 1.5/edge 707 10.152.183.176 no
ausf 1.4.2 active 1 sdcore-ausf-k8s 1.5/edge 520 10.152.183.65 no
grafana-agent 0.32.1 waiting 1 grafana-agent-k8s latest/stable 45 10.152.183.221 no installing agent
mongodb active 1 mongodb-k8s 6/beta 38 10.152.183.92 no Primary
nms 1.0.0 active 1 sdcore-nms-k8s 1.5/edge 580 10.152.183.141 no
nrf 1.4.1 active 1 sdcore-nrf-k8s 1.5/edge 580 10.152.183.130 no
nssf 1.4.1 active 1 sdcore-nssf-k8s 1.5/edge 462 10.152.183.62 no
pcf 1.4.3 active 1 sdcore-pcf-k8s 1.5/edge 512 10.152.183.144 no
router active 1 sdcore-router-k8s 1.5/edge 341 10.152.183.218 no
self-signed-certificates active 1 self-signed-certificates latest/stable 155 10.152.183.33 no
smf 1.5.2 active 1 sdcore-smf-k8s 1.5/edge 590 10.152.183.64 no
traefik v2.11.0 waiting 1 traefik-k8s latest/stable 194 10.152.183.198 no installing agent
udm 1.4.3 active 1 sdcore-udm-k8s 1.5/edge 489 10.152.183.31 no
udr 1.4.1 active 1 sdcore-udr-k8s 1.5/edge 486 10.152.183.82 no
upf 1.4.0 active 1 sdcore-upf-k8s 1.5/edge 591 10.152.183.164 no
Unit Workload Agent Address Ports Message
amf/0* active idle 10.1.10.181
ausf/0* active idle 10.1.10.186
grafana-agent/0* blocked idle 10.1.10.133 grafana-cloud-config: off, logging-consumer: off
mongodb/0* active idle 10.1.10.155 Primary
nms/0* active idle 10.1.10.174
nrf/0* active idle 10.1.10.151
nssf/0* active idle 10.1.10.136
pcf/0* active idle 10.1.10.146
router/0* active idle 10.1.10.145
self-signed-certificates/0* active idle 10.1.10.141
smf/0* active idle 10.1.10.154
traefik/0* error idle 10.1.10.160 hook failed: "ingress-relation-changed"
udm/0* active idle 10.1.10.187
udr/0* active idle 10.1.10.176
upf/0* active idle 10.1.10.169
Configure the ingress¶
Get the external IP address of Traefik’s traefik-lb
LoadBalancer service:
microk8s.kubectl -n sdcore get svc | grep "traefik-lb"
The output should look similar to below:
ubuntu@host:~/terraform$ microk8s.kubectl -n sdcore get svc | grep "traefik-lb"
traefik-lb LoadBalancer 10.152.183.142 10.0.0.2 80:32435/TCP,443:32483/TCP 11m
In this tutorial, the IP is 10.0.0.2
. 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.2.nip.io"
}
(...)
}
(...)
Apply new configuration:
terraform apply -auto-approve
Resolve Traefik error in Juju:
juju resolve traefik/0
2. Deploy Charmed OAI RAN CU¶
Create a Terraform module for the Radio Access Network and add Charmed OAI RAN CU to it:
cat << EOF > ran.tf
resource "juju_model" "oai-ran" {
name = "ran"
}
module "cu" {
source = "git::https://github.com/canonical/oai-ran-cu-k8s-operator//terraform"
model_name = juju_model.oai-ran.name
config = {
"n3-interface-name": "ran"
}
}
resource "juju_offer" "cu-fiveg-gnb-identity" {
model = juju_model.oai-ran.name
application_name = module.cu.app_name
endpoint = module.cu.fiveg_gnb_identity_endpoint
}
resource "juju_integration" "cu-amf" {
model = juju_model.oai-ran.name
application {
name = module.cu.app_name
endpoint = module.cu.fiveg_n2_endpoint
}
application {
offer_url = module.sdcore.amf_fiveg_n2_offer_url
}
}
resource "juju_integration" "cu-nms" {
model = juju_model.sdcore.name
application {
name = module.sdcore.nms_app_name
endpoint = module.sdcore.fiveg_gnb_identity_endpoint
}
application {
offer_url = juju_offer.cu-fiveg-gnb-identity.url
}
}
EOF
Update Juju Terraform provider:
terraform init
Deploy CU:
terraform apply -auto-approve
Monitor the status of the deployment:
juju switch ran
juju status --watch 1s --relations
The deployment is ready when the cu
application is in the active/idle
state.
3. Configure the 5G core network through the Network Management System¶
Retrieve the NMS address:
juju switch sdcore
juju run traefik/0 show-proxied-endpoints
The output should be http://sdcore-nms.10.0.0.2.nip.io/
.
Navigate to this address in your browser.
In the Network Management System (NMS), create a network slice with the following attributes:
Name:
Tutorial
MCC:
001
MNC:
01
UPF:
upf-external.private5g.svc.cluster.local:8805
gNodeB:
private5g-cu-cu (tac:1)
You should see the following network slice created:
Navigate to Subscribers and create a new subscriber with the following attributes:
IMSI:
001010100007487
OPC:
981d464c7c52eb6e5036234984ad0bcf
Key:
5122250214c33e723a5dd523fc145fc0
Sequence Number:
16f3b3f70fc2
Network Slice:
Tutorial
Device Group:
Tutorial-default
You should see the following subscriber created:
Note
Due to current limitations in the network configuration procedure, it is required to restart the CU Pod after configuring the network.
This limitation will be addressed in the future.
To restart the CU Pod execute:
microk8s.kubectl -n ran delete pod cu-0
4. Deploy Charmed OAI RAN DU¶
Add Charmed OAI RAN DU Terraform module to ran.tf
:
cat << EOF >> ran.tf
module "du" {
source = "git::https://github.com/canonical/oai-ran-du-k8s-operator//terraform"
model_name = juju_model.oai-ran.name
config = {
"simulation-mode": true
}
}
resource "juju_integration" "du-cu" {
model = juju_model.oai-ran.name
application {
name = module.du.app_name
endpoint = module.du.fiveg_f1_endpoint
}
application {
name = module.cu.app_name
endpoint = module.cu.fiveg_f1_endpoint
}
}
EOF
Update Juju Terraform provider:
terraform init
Deploy DU:
terraform apply -auto-approve
Monitor the status of the deployment:
juju switch ran
juju status --watch 1s --relations
The deployment is ready when the du
application is in the active/idle
state.
5. Deploy Charmed OAI RAN UE Simulator¶
Add Charmed OAI RAN UE Terraform module to ran.tf
:
cat << EOF >> ran.tf
module "ue" {
source = "git::https://github.com/canonical/oai-ran-ue-k8s-operator//terraform"
model_name = juju_model.oai-ran.name
}
resource "juju_integration" "ue-du" {
model = juju_model.oai-ran.name
application {
name = module.ue.app_name
endpoint = module.ue.fiveg_rfsim_endpoint
}
application {
name = module.du.app_name
endpoint = module.du.fiveg_rfsim_endpoint
}
}
EOF
Update Juju Terraform provider:
terraform init
Deploy the UE simulator:
terraform apply -auto-approve
Monitor the status of the deployment:
juju status --watch 1s --relations
The deployment is ready when the ue
application is in the active/idle
state.
6. Run 5G network traffic simulation¶
Run the simulation:
juju run ue/leader start-simulation
The simulation executed successfully if you see success: "true"
as one of the output messages:
ubuntu@host:~$ juju run ue/leader start-simulation
Running operation 1 with 1 task
- task 2 on unit-ue-0
Waiting for task 2...
result: |
PING 8.8.8.8 (8.8.8.8) from 172.250.0.2 oaitun_ue1: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=13.2 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=15.3 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=13.8 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=116 time=12.6 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=116 time=14.1 ms
64 bytes from 8.8.8.8: icmp_seq=6 ttl=116 time=14.8 ms
64 bytes from 8.8.8.8: icmp_seq=7 ttl=116 time=14.6 ms
64 bytes from 8.8.8.8: icmp_seq=8 ttl=116 time=14.6 ms
64 bytes from 8.8.8.8: icmp_seq=9 ttl=116 time=14.6 ms
64 bytes from 8.8.8.8: icmp_seq=10 ttl=116 time=14.5 ms
--- 8.8.8.8 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9010ms
rtt min/avg/max/mdev = 12.561/14.217/15.294/0.772 ms
success: "true"
7. 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-classic-localhost