修士の研究でfree 5GCをKubernetes上で動かす必要があったが、どちらも全く触ったことがなかったので備忘録として手順を残しておく。
ポートとかファイアウォールとかセキュリティに関してはザルなので(とにかく動くこと優先)、その辺は参考にしないように。
2台のPCを使って同一LAN内で環境構築することを前提とする。
マシンの準備
何はともあれマシンを準備する。
研究室でおねだりした結果、ノートPCとデスクトップの2台のPCを借りられたのでノートPCをMaster Node, デスクトップをWorker Nodeとして使う。
-
Master Node(DELL XPS-13-9305)
CPU: 第11世代 インテル® Core™ i7-1165G7
メモリ: 16GB 4267MHz LPDDR4x メモリー -
Worker Node(研究室で余ってたやつ)
CPU: インテル® Core™ i7-11700
メモリ: 32GB 8GB*4枚
OSのセッティング
ubuntuをインストールしてカーネルのバージョンを下げる。
Ubuntuのインストール
今回はUbuntu 20.04 LTSをインストールする。Worker Nodeには何のOSも入っていなかったので、何の工夫もなくインストールできたが、Master Nodeには元々windowsがインストールされているのでデュアルブートする必要がある。
https://www.pc-koubou.jp/magazine/35542 などを参考にデュアルブートしてください。(ミスるとwindowsごとぶっ壊す可能性があるので自己責任で)
カーネルのダウングレード
5GCのパケット処理に使われるカーネルモジュールgtp5gはlinuxのカーネルバージョンが5.4以下でないと動作しないので、カーネルをダウングレードする。
https://kazuhira-r.hatenablog.com/entry/2020/03/08/141730
https://level69.net/archives/31142
この辺の記事を参考にカーネルバージョンを下げる。
各種モジュールのインストール
free5gcのパケット処理に使われるgtp5g、kubernetesのコンテナランタイムとなるdocker、kubernetes環境を構築するためのツールkubeadmをインストールする。
gtp5gのインストール
リポジトリを参考にインストール
git clone https://github.com/free5gc/gtp5g.git
cd gtp5g
make clean && make
sudo make install
dockerのインストール
kubernetesのコンテナランタイム(CRI)にはdocker, containerd, CRI-Oの三つがあるが、今回はdockerを採用する。理由としてはcadvisorでコンテナメトリクスを収集するのにdockerである必要があるから。
ちなみにkubernetesではdockerが非推奨になっているっぽい。dockerの内部にはcontainerdがあるため、dockerとcontainerdがどちらも入っているとdockerが優先される。
こちらを参考にインストール
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
sudo apt update
apt-cache policy docker-ce
今回インストールしたdockerのバージョンは23.0.1。サーバーとクライアントのバージョンは揃えているが、揃わないと動かないかは知らん。
最後にこのコマンドでインストールできる。
sudo apt install docker-ce=23.0.1
dockerがインストールできているか確認する。
sudo docker version
ちゃんとインストールされていれば次のように出力される。
Client: Docker Engine - Community
Version: 23.0.1
API version: 1.42
Go version: go1.19.5
Git commit: a5ee5b1
Built: Thu Feb 9 19:46:56 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 23.0.1
API version: 1.42 (minimum version 1.12)
Go version: go1.19.5
Git commit: bc3805a
Built: Thu Feb 9 19:46:56 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.16
GitCommit: 31aa4358a36870b21a992d3ad2bef29e1d693bec
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
kubeadm, kubelet, kubectlのインストール
kubeadmはkubernetesクラスターの構築をめちゃめちゃ簡単にできるツールで、kubeadm init
とkubeadm join
の二つのコマンドを提供する。
kubeadm init
は最初にクラスターを作成する時に使い、(今回のように2台構成なら)Master Nodeで打つ。
kubeadm join
はクラスターにノードを追加する時に使い、Worker Nodeや2つ目以降のMaster Nodeで打つ。
kubeletはクラスター内の全てのマシンで実行され、podの起動などを請け負っている。(ユーザーがこのコマンドを使うことはあんまりない)
kubectlはクラスターを操作するコマンド。 デプロイや削除など基本的にはこのコマンドで全てを行う。
kubeadmをインストールする前にいくつか準備が必要。
MACアドレスとproduct_uuidが全てのノードでユニークであることの検証
ip link
もしくはifconfig -a
でMACアドレスを確認。
また、sudo cat /sys/class/dmi/id/product_uuid
でproduct_uuidを確認。
今回はハードウェアが異なるので、どちらもユニークだったが、VMの場合はこれらが同じになる場合がある。
iptablesがブリッジを通過するトラフィックを処理できるようにする
何してるかはよくわからんが、公式ページに書いてあったのでやっておく。(通信についての設定かな?)
modprobe br_netfilter
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
必須ポートの確認
このサイトの通りにポートを開いておく。
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
開いているポートの確認はsudo ufw status
でできる。
ポートの解放はsudo ufw allow <開きたいポート番号>
でできる。
スワップをオフにする
kubernetesではメモリのスワップがあると動作しないのでMasterもWorkerもどちらもswapoff -a
でスワップをオフにする。
kubeadm, kubelet, kubectlのインストール
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
kubeadmでクラスター作成
kubernetesクラスターの作成にはkubeadmを使う。
kubeadm init
Master Nodeでkubeadm init
をしてクラスターを作成する。
kubeadm init --apiserver-advertise-address=172.19.109.201 --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/cri-dockerd.sock
apiserver-advertise-addressはクラスター内で使うipアドレスを指定している。Master Nodeのipアドレスを指定しておく。
pod-network-cidrはpod間通信をするためのCNIが利用するipアドレス。
cri-socketはdockerdのソケットのパスを渡す。
成功すると、次のコマンドを打つよう指示されるのでコマンドを打つ。
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
CNI(flannel)の導入
pod間通信を可能にする仮想ネットワークのアドオンであるflannelを導入する。
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
動いたか確認
kubectl get nodes
kubeadm joinでWorker Nodeを追加
kubeadm init
した際にWorker Nodeを追加する用のコマンドが出力されるので、それをWorker Nodeで打つ。
kubeadm join 172.19.109.201:6443 --token <表示されるtoken> --discovery-token-ca-cert-hash sha256:...
追加されたら、Master Nodeで確認
kubectl get nodes
二つのノードが表示されたらOK
クラスターのリセット
色々試しててクラスターがぐちゃぐちゃになってしまった時はクラスターをリセットする。(マジで役に立った)
Master NodeでWorker Nodeを削除する
kubectl delete node <worker nodeの名前>
Worker NodeとMaster Nodeからreset
kubeadm reset --force
systemctl stop kubelet
rm -rf /etc/kubernetes/
rm -rf ~/.kube/
rm -rf /var/lib/kubelet/
rm -rf /var/lib/cni/
rm -rf /etc/cni/
rm -rf /var/lib/etcd/
iptables -F && iptables -X
注) 最後のiptablesは実行するとwifiや有線LANが繋がらなくなるかもしれないので、繋がらなくなったら再起動しましょう。
ノードを再起動したら、
これで完全にリセットされるので、再度クラスターを作成する。
デプロイ
free5gcやらcadvisorやらprometheusやら色々デプロイしていく。
free5gcのデプロイ
ここにfree5gcのマニフェストファイルがあるので、これを利用する。(stage-3.1.1を利用するが、確認すると無くなってる)
マニフェストファイルの詳しい説明は省略するが、podの様式をyamlで書いておいて簡単にデプロイできるようにしたもの。
このfree5gcのcnfをクラスター上にデプロイしていく。
以降のコマンドは全てMaster Nodeで実行する。
まず、namespaceを作成する。
kubectl create namespace free5gc
namespaceはクラスター上の仮想環境みたいなもの。
free5gcは次の順番でデプロイしていく。
NRF > UDR > UDM > AUSF > NSSF > AMF > PCF > UPF > SMF
必ず、前のpodがrunningになったことを確認してから次のNFをデプロイする。
kubectl apply -f 03-free5gc-nrf.yaml -n free5gc
kubectl apply -f 06-free5gc-udr.yaml -n free5gc
kubectl apply -f 08-free5gc-udm.yaml -n free5gc
kubectl apply -f 10-free5gc-ausf.yaml -n free5gc
kubectl apply -f 09-free5gc-nssf.yaml -n free5gc
kubectl apply -f 04-free5gc-amf.yaml -n free5gc
kubectl apply -f 07-free5gc-pcf.yaml -n free5gc
kubectl apply -f 02-free5gc-upf.yaml -n free5gc
kubectl apply -f 05-free5gc-smf.yaml -n free5gc
kubectl apply -f 01-free5gc-mongodb.yaml -n free5gc
kubectl apply -f 11-free5gc-webui.yaml -n free5gc
正常に動作しているか確認。
>> kubectl get pods -n free5gc
NAME READY STATUS RESTARTS AGE
free5gc-amf-deployment-5b94ff96d-f5vjh 1/1 Running 0 3m7s
free5gc-ausf-deployment-5548b989-nvc9f 1/1 Running 0 3m39s
free5gc-mongodb-7d954666d4-mvmnz 1/1 Running 0 62s
free5gc-nrf-deployment-5f9666c4f4-8l9m7 1/1 Running 0 4m42s
free5gc-nssf-deployment-586cb84fcd-zfzzn 1/1 Running 0 3m23s
free5gc-pcf-deployment-6f99976745-pp9tq 1/1 Running 0 2m48s
free5gc-smf-deployment-7647c6787-hm9c8 1/1 Running 0 2m17s
free5gc-udm-deployment-6f5f499c5f-pkktr 1/1 Running 0 3m58s
free5gc-udr-deployment-5749586f77-dqnrl 1/1 Running 0 4m13s
free5gc-upf-deployment-5f575485fc-tkwrh 1/1 Running 0 2m32s
free5gc-webui-deployment-57cc7b5498-gpdfr 1/1 Running 0 27s
web uiの確認
クラスターのPCから確認する場合は、http://<web uiのpodのipアドレス>:5000
podのipアドレスは次のコマンドで確認できる。
>> kubectl get pods -n free5gc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
free5gc-amf-deployment-5b94ff96d-f5vjh 1/1 Running 0 9m20s 10.244.1.7 system-product-name <none> <none>
free5gc-ausf-deployment-5548b989-nvc9f 1/1 Running 0 9m52s 10.244.1.5 system-product-name <none> <none>
free5gc-mongodb-7d954666d4-mvmnz 1/1 Running 0 7m15s 10.244.1.11 system-product-name <none> <none>
free5gc-nrf-deployment-5f9666c4f4-8l9m7 1/1 Running 0 10m 10.244.1.2 system-product-name <none> <none>
free5gc-nssf-deployment-586cb84fcd-zfzzn 1/1 Running 0 9m36s 10.244.1.6 system-product-name <none> <none>
free5gc-pcf-deployment-6f99976745-pp9tq 1/1 Running 0 9m1s 10.244.1.8 system-product-name <none> <none>
free5gc-smf-deployment-7647c6787-hm9c8 1/1 Running 0 8m30s 10.244.1.10 system-product-name <none> <none>
free5gc-udm-deployment-6f5f499c5f-pkktr 1/1 Running 0 10m 10.244.1.4 system-product-name <none> <none>
free5gc-udr-deployment-5749586f77-dqnrl 1/1 Running 0 10m 10.244.1.3 system-product-name <none> <none>
free5gc-upf-deployment-5f575485fc-tkwrh 1/1 Running 0 8m45s 10.244.1.9 system-product-name <none> <none>
free5gc-webui-deployment-57cc7b5498-gpdfr 1/1 Running 0 6m40s 10.244.1.12 system-product-name <none> <none>
クラスター外(同一LAN内)から確認する場合
http://<Worker Nodeのローカルipアドレス>:31111
web uiはID/pass:admin/free5gc でログインできる。
UERANSIMのデプロイ
UERANSIMはその名の通りUEと基地局のシミュレータで、いろんなシミュレーションができる。
まず、UERANSIMのマニフェストファイルを書き換える。
gnbのマニフェストファイルを以下の部分を書き換える。
name: ueransim-gnb-configmap
data:
free5gc-gnb.yaml: |
mcc: '208' # Mobile Country Code value
mnc: '93' # Mobile Network Code value (2 or 3 digits)
nci: '0x000000010' # NR Cell Identity (36-bit)
idLength: 32 # NR gNB ID length in bits [22...32]
tac: 1 # Tracking Area Code
- linkIp: 10.244.3.31 # gNB's local IP address for Radio Link Simulation (Usually same with local IP)
- ngapIp: 10.244.3.31 # gNB's local IP address for N2 Interface (Usually same with local IP)
- gtpIp: 10.244.3.31 # gNB's local IP address for N3 Interface (Usually same with local IP)
+ linkIp: 10.244.1.13 # gnbのpodのipアドレス
+ ngapIp: 10.244.1.13 # gnbのpodのipアドレス
+ gtpIp: 10.244.1.13 # gnbのpodのipアドレス
# List of AMF address information
amfConfigs:
- - address: 10.244.3.22
- port: 38412
+ - address: 10.244.1.7 # AMFのpodのipアドレス
+ port: 38412 # AMFのSCTPプロトコルのポート
kubernetesのpodのipアドレスは一つずつインクリメントされるため、最後にデプロイされたpodのipアドレス(ここではweb ui)に1足したものを入力する。
変更したらデプロイする。
kubectl apply -f ueransim/ueransim-gnb.yaml -n free5gc
podの中に入って、is-ngap-up: trueになることを確認。
kubectl -n free5gc exec -it ueransim-gnb-deployment-7cf855fc85-z998r -- bash
/UERANSIM# cd build
/UERANSIM/build# ./nr-cli UERANSIM-gnb-208-93-1
-------------------------------------------------------------------------------------
$ status
is-ngap-up: true
-------------------------------------------------------------------------------------
次にueransim-ue.yamlの次の部分を書き換える。
data:
free5gc-ue.yaml: |
# IMSI number of the UE. IMSI = [MCC|MNC|MSISDN] (In total 15 digits)
supi: 'imsi-208930000000003'
# Mobile Country Code value of HPLMN
mcc: '208'
# Mobile Network Code value of HPLMN (2 or 3 digits)
mnc: '93'
# Permanent subscription key
key: '8baf473f2f8fd09487cccbd7097c6862'
# Operator code (OP or OPC) of the UE
op: '8e27b6af0e692e750f32667a3b14605d'
# This value specifies the OP type and it can be either 'OP' or 'OPC'
opType: 'OP'
# Authentication Management Field (AMF) value
amf: '8000'
# IMEI number of the device. It is used if no SUPI is provided
imei: '356938035643803'
# IMEISV number of the device. It is used if no SUPI and IMEI is provided
imeiSv: '4370816125816151'
# List of gNB IP addresses for Radio Link Simulation
gnbSearchList:
- - 10.244.3.31
+ - 10.244.1.13 # gnbのpodのipアドレス
書き換えたらデプロイ
kubectl apply -f ueransim/ueransim-ue.yaml -n free5gc
podの中に入って確認
kubectl -n free5gc exec -it ueransim-ue-deployment-dd445b88d-wcmm9 -- bash
/UERANSIM# cd build
/UERANSIM/build# ./nr-cli -d imsi-208930000000003
imsi-208930000000003
/UERANSIM/build# ./nr-cli imsi-208930000000003
-------------------------------------------------------------------------------------
$ status
cm-state: CM-CONNECTED
rm-state: RM-REGISTERED
mm-state: MM-REGISTERED/NORMAL-SERVICE
5u-state: 5U1-UPDATED
sim-inserted: true
selected-plmn: 208/93
current-cell: 1
current-plmn: 208/93
current-tac: 1
last-tai: PLMN[208/93] TAC[1]
stored-suci: no-identity
stored-guti:
plmn: 208/93
amf-region-id: 0xca
amf-set-id: 1016
amf-pointer: 0
tmsi: 0x00000001
has-emergency: false
-------------------------------------------------------------------------------------
cm-state: CM-CONNECTEDになっていることを確認
cAdvisorのデプロイ
dockerのコンテナメトリクスを収集できるcAdvisorを導入する。
まずはnamespaceの作成。
kubectl create namespace cadvisor
cadvisorのgithubにkubernetes用のマニフェストファイルがあるので、これを利用。
daemonset.yamlの最後に次のコードを追加
---
apiVersion: v1
kind: Service
metadata:
name: cadvisor
namespace: cadvisor
spec:
selector:
app: cadvisor
ports:
- protocol: TCP
port: 8080
nodePort: 30080
type: NodePort
これによってサービスとして外部に公開できる。
kustomizeによってデプロイする。
kubectl apply -k cadvisor/ -n cadvisor
デプロイできたか確認
>> kubectl get pod -n cadvisor
NAME READY STATUS RESTARTS AGE
cadvisor-z6v7l 1/1 Running 0 21s
>> kubectl get service -n cadvisor
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cadvisor NodePort 10.102.196.48 <none> 8080:30080/TCP 33s
>> kubectl get daemonset -n cadvisor
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
cadvisor 1 1 1 1 1 <none> 42s
uiにはfree5gcのweb uiと同様にアクセスできる。
prometheusのデプロイ
httpプル方式でメトリクスを蓄積、監視するprometheusを導入して、cadvisorのメトリクスをこちらに流す。
https://uzimihsr.github.io/post/2022-11-28-kubernetes-prometheus-kube-state-metrics-cadvisor-ja/
こちらを参考にprometheusのマニフェストファイルとコンフィグファイルをgistにしたので、これを使えばできるはず。
kubectl -n prometheus create serviceaccount prometheus
kubectl create clusterrole prometheus --verb=get,list,watch --resource=pods,services,endpoints
kubectl create clusterrolebinding prometheus --clusterrole=prometheus --serviceaccount=prometheus:prometheus
kubectl apply -f configmap.yaml -n prometheus
kubectl apply -f deployment.yaml -n prometheus
service discoveryにcadvisorがあることを確認。
デプロイメントの削除
デプロイしたものを削除したいときは次のコードで削除できる。
kubectl delete -f 01-free5gc-mongodb.yaml -n free5gc