Metonymical Deflection

ゆるく日々のコト・たまにITインフラ

CentOS8 KubernetesのSR-IOV設定方法

Kubernetes(以下、k8s)のSR-IOV設定方法を記載します。
PodとVMI(Virtual Machine Instance)の両方でそれぞれSR-IOVを設定していきます。

1.構成

1-1.環境
1.Master
VMWare              : VMware(R) Workstation 15 Pro 15.5.1 build-15018445 

2.Worker
筐体                             : ProLiant DL360p Gen8
System ROM                       : P71 05/24/2019
NIC                              : Intel X520-SR2(82599ES), X540-AT2

3.Master&Worker共通
OS                               : CentOS8.0(1905)
Kernel                           : 4.18.0-80.el8.x86_64
Installed Environment Groups     : 
  @^graphical-server-environment
  @container-management
  @development
  @virtualization-client
  @virtualization-hypervisor
  @virtualization-tools 

Kubernetes                       : 1.17.0
Docker                           : 19.03.5
flannel                          : latest
KubeVirt                         : 0.24.0
Multus                           : latest
sriov-cni                        : latest
sriov-network-device-plugin      : latest
1-2.全体の構成

f:id:metonymical:20191215102800p:plain

1-3.全体の流れ
  1. 事前準備
  2. k8s Cluster & flannelの構築
  3. KubeVirtの構築
  4. SR-IOV関連のビルド
  5. SR-IOV関連の設定
  6. VMIとPodのデプロイ

1~3までは比較的多くのドキュメントが存在しますので、重要な箇所以外はある程度割愛します。*1

2.事前準備

2-1.諸々の準備
SELinuxの無効化 : Master&Worker*2
sed -i -e "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

FW無効化 : Master&Worker
systemctl stop firewalld
systemctl disable firewalld

パススルー設定 : Master&Worker*3
sed -i -e "s/#options kvm_intel nested=1/options kvm_intel nested=1/g" /etc/modprobe.d/kvm.conf

swap無効化 : Master&Worker
vi /etc/fstab

#/dev/mapper/cl-swap     swap                    swap    defaults        0 0

hostsファイル設定 : Master&Worker*4
vi /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 c80g105.md.jp c80g105
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.11.105 c80g105 c80g105.md.jp
192.168.11.106 c80g106 c80g106.md.jp
2-2.HugePageとIOMMUの有効化 : Worker
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ default_hugepagesz=1G hugepagesz=1G hugepages=16\"/g" /etc/default/grub
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub
grub2-mkconfig -o /etc/grub2.cfg

vi /etc/fstab

最終行に以下を追記
nodev  /mnt/huge_1GB hugetlbfs pagesize=1GB    0 0

hugepageの有効化
iommuの有効化
grubに設定反映
マウント

2-3.SR-IOVのVF設定 : Worker
vi /etc/rc.local

echo 8 > /sys/class/net/ens1f0/device/sriov_numvfs
echo 8 > /sys/class/net/ens1f1/device/sriov_numvfs
echo 8 > /sys/class/net/ens2f0/device/sriov_numvfs
echo 8 > /sys/class/net/ens2f1/device/sriov_numvfs
sleep 1
exit 0

chmod +x /etc/rc.d/rc.local

2枚のNICの各ポートにVFをそれぞれ8つづつ設定
実行権限付与

<補足>
過去記事では、Blacklistに追加していますが、今回は不要です。

2-4.vfio-pciの設定 : Worker
vi /etc/modprobe.d/vfio_pci.conf

options vfio_pci ids=8086:10ed

echo "vfio-pci" > /etc/modules-load.d/vfio-pci.conf
echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modules-load.d/iommu.conf

vfio-pciを有効化するデバイス(NIC)のDeviceID設定
vfio-pciの永続化設定
vfio-pciのiommu利用の永続化

<補足(重要)>
DeviceIDはそれぞれ以下の通りとなります。

8086:10ed X520 VMI用 vfio-pci
8086:1515 X540 Pod用 ixgbevf

今回は2枚のNICでそれぞれVMI用とPod用として分けているため、vfio-pciを有効化するのは、X520のみとしています。*5
というのも、以下2点を確認したからです。*6

  • VMIでixgbevfを使用すると、kubectl get vmi上ではscheduledのまま固まります。flannelのIPはアサインされますがPingは通りません。*7
  • Podでvfio-pciNICを掴むことができませんでした。ip link showなどで確認しても追加されていません。

ここまでの準備が整ったらMaster&Workerを一旦再起動してください。

3.k8s Cluster & flannelの構築

3-1.Dockerのインストール : Master&Worker
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
dnf -y install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.10-3.2.el7.x86_64.rpm && \
dnf -y install docker-ce && \
systemctl start docker && \
systemctl enable docker
3-3.k8sのインストール : Master&Worker
Master
dnf -y install kubeadm kubectl

Worker
dnf -y install kubeadm

Master&Worker
systemctl start kubelet.service && \
systemctl enable kubelet.service
3-4.Dockerの設定 : Master&Worker
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF

mkdir -p /etc/systemd/system/docker.service.d

systemctl daemon-reload && \
systemctl restart docker
3-5.k8sClusterの構築 : Master
kubeadm init --apiserver-advertise-address=192.168.11.105 --pod-network-cidr=10.244.0.0/16

<出力例>
最後に以下の出力が表示されますので、赤文字部分をコピーしておいてください。
WorkerがMasterへJoinする際に使用します。

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.11.105:6443 --token 0gfh5j.vgu76alcycb2tc2e \
    --discovery-token-ca-cert-hash sha256:edcb1a3856838586a6ea7c99200daafa4fbb639e822838f4df81ce09d2faaac3 
3-6.k8s Cluster構築後の設定 : Master
コンフィグファイルのコピー
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

コマンド補完設定
echo "source <(kubectl completion bash)" >> ~/.bashrc
3-7.flannelのインストール : Master
mkdir /root/tmp && \
cd /root/tmp/ && \
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml && \
kubectl apply -f kube-flannel.yml

kubectl get nodes

<出力例>
以下のようにReadyとなるまで待ってください。

[root@c80g105 ~]# kubectl get nodes
NAME            STATUS   ROLES    AGE   VERSION
c80g105.md.jp   Ready    master   48m   v1.17.0
3-8.WorkerのJoin : Worker
kubeadm join 192.168.11.105:6443 --token 0gfh5j.vgu76alcycb2tc2e \
    --discovery-token-ca-cert-hash sha256:edcb1a3856838586a6ea7c99200daafa4fbb639e822838f4df81ce09d2faaac3

<出力例>
以下のようにWorkerもReadyとなるまで待ってください。

[root@c80g105 ~]# kubectl get nodes
NAME            STATUS   ROLES    AGE   VERSION
c80g105.md.jp   Ready    master   48m   v1.17.0
c80g106.md.jp   Ready    <none>   19s   v1.17.0

ここまでの準備が整ったらMaster&Workerをもう一度再起動してください。

4.KubeVirtの構築

4-1.KubeVirtインストール : Master
export RELEASE=v0.24.0
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml
kubectl apply -f https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml

<出力例>
Podの状態が以下のようにすべてRunningになるまでには、2分程度掛かります。

kubectl get pods -n kubevirt

[root@c80g116 ~]# kubectl -n kubevirt get pods
NAME                               READY   STATUS    RESTARTS   AGE
virt-api-64f59f44dd-prkj4          1/1     Running   3          70m
virt-api-64f59f44dd-w9984          1/1     Running   3          71m
virt-controller-79cc7fb59d-6bz7d   1/1     Running   3          70m
virt-controller-79cc7fb59d-wt8g4   1/1     Running   3          70m
virt-handler-ljfqg                 1/1     Running   5          88m
virt-operator-54db765c7d-4xkq5     1/1     Running   3          70m
virt-operator-54db765c7d-5bgw4     1/1     Running   3          64m

全てRunningになったら、以下のコマンドを実行

kubectl -n kubevirt wait kv kubevirt --for condition=Available

<出力例>
以下の出力が表示されればOKです。

[root@c80g105 ~]# kubectl -n kubevirt wait kv kubevirt --for condition=Available
kubevirt.kubevirt.io/kubevirt condition met
4-2.virtctlのインストール : Master : オプション

必須ではありませんが、vmiを操作する際に便利です。*8

export RELEASE=v0.24.0
curl -L -o virtctl \
    https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/virtctl-${RELEASE}-linux-amd64

chmod +x virtctl
chown root:root virtctl
mv virtctl /usr/bin
4-3.virtctlのインストール : Master : オプション

必須ではありませんが、virtctlはKrewを使ってもインストールできます。*9

export RELEASE=v0.3.3

set -x; cd "$(mktemp -d)" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/download/v0.3.3/krew.{tar.gz,yaml}" &&
tar zxvf krew.tar.gz &&
KREW=./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" &&
"$KREW" install --manifest=krew.yaml --archive=krew.tar.gz &&
"$KREW" update

export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

kubectl krew install virt

echo 'PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"' >> ~/.bashrc

5.SR-IOV関連のビルド

5-1.Golangのインストール : Master
dnf -y install epel-release golang
5-2.SR-IOV CNIのビルド : Master
git clone https://github.com/intel/sriov-cni.git && \
cd sriov-cni && \
make && \
cp build/sriov /opt/cni/bin

SRIOV CNIの実行ファイルをWorkerへコピー
scp /opt/cni/bin/sriov root@192.168.11.106:/opt/cni/bin/
5-3.SR-IOV Network Deviceのビルド : Master
cd ~/ && \
git clone https://github.com/intel/sriov-network-device-plugin.git && \
cd sriov-network-device-plugin && \
make

docker build -t nfvpe/sriov-device-plugin -f ./images/Dockerfile .

<出力例>

docker images

[root@c80g105 sriov-network-device-plugin]# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
nfvpe/sriov-device-plugin            latest              a45310aae832        13 seconds ago      25.3MB
<none>                               <none>              b65d412dee59        19 seconds ago      905MB
k8s.gcr.io/kube-proxy                v1.17.0             7d54289267dc        6 days ago          116MB
k8s.gcr.io/kube-apiserver            v1.17.0             0cae8d5cc64c        6 days ago          171MB
k8s.gcr.io/kube-controller-manager   v1.17.0             5eb3b7486872        6 days ago          161MB
k8s.gcr.io/kube-scheduler            v1.17.0             78c190f736b1        6 days ago          94.4MB
golang                               alpine              69cf534c966a        8 days ago          359MB
k8s.gcr.io/coredns                   1.6.5               70f311871ae1        5 weeks ago         41.6MB
k8s.gcr.io/etcd                      3.4.3-0             303ce5db0e90        7 weeks ago         288MB
alpine                               latest              965ea09ff2eb        7 weeks ago         5.55MB
quay.io/coreos/flannel               v0.11.0-amd64       ff281650a721        10 months ago       52.6MB
k8s.gcr.io/pause                     3.1                 da86e6ba6ca1        24 months ago       742kB
5-4.SR-IOV Network Deviceのビルド : Worker
cd ~/ && \
git clone https://github.com/intel/sriov-network-device-plugin.git && \
cd sriov-network-device-plugin && \
docker build -t nfvpe/sriov-device-plugin -f ./images/Dockerfile .

<出力例>

docker images

[root@c80g106 sriov-network-device-plugin]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
nfvpe/sriov-device-plugin   latest              8c508ab37c1c        28 seconds ago      25.3MB
<none>                      <none>              571b3587b90d        34 seconds ago      855MB
k8s.gcr.io/kube-proxy       v1.17.0             7d54289267dc        6 days ago          116MB
golang                      alpine              69cf534c966a        8 days ago          359MB
alpine                      latest              965ea09ff2eb        7 weeks ago         5.55MB
quay.io/coreos/flannel      v0.11.0-amd64       ff281650a721        10 months ago       52.6MB
k8s.gcr.io/pause            3.1                 da86e6ba6ca1        24 months ago       742kB
kubevirt/virt-api           <none>              1a3697b92f09        49 years ago        293MB
kubevirt/virt-controller    <none>              ab9c8cce9c60        49 years ago        291MB
kubevirt/virt-handler       <none>              c5919b95ca31        49 years ago        313MB
kubevirt/virt-operator      <none>              45c6d543afb1        49 years ago        326MB

<補足>
この後の工程で、sriovdp-daemonset.yaml をデプロイするのですが、元から以下のように書かれているため、WorkerにおいてもDockerイメージをビルドしています。

      containers:
      - name: kube-sriovdp
        image: nfvpe/sriov-device-plugin
        imagePullPolicy: Never

6.SR-IOV関連の設定

以下のQuick Startに記載された順番に従い設定を行っていきます。
GitHub - k8snetworkplumbingwg/sriov-network-device-plugin: SRIOV network device plugin for Kubernetes

流れは以下の通りです。*10

  1. configMapの設定&デプロイ
  2. sriovdp-daemonsetのデプロイ
  3. Master:Multusのインストール
  4. sriov-crdの設定&デプロイ
  5. リソースの確認
6-1.ConfigMapの設定 : Master

ポイントは

"resourceName": "intel_sriov_netdevice1",
"resourceName": "intel_sriov_netdevice2",

として別けて記載している点です。
CRDやVMI&Podのyamlファイルにも一連の流れとして記載していくため、に別けて書いておきます。

既存ファイルを以下のように書き換えてください。

vi /root/sriov-network-device-plugin/deployments/configMap.yaml

[root@c80g105 ~]# vi /root/sriov-network-device-plugin/deployments/configMap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [{
apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
                "resourceName": "intel_sriov_netdevice1",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["154c", "10ed"],
                    "drivers": ["i40evf", "vfio-pci"]
                }
            },
            {
                "resourceName": "intel_sriov_netdevice2",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["154c", "1515"],
                    "drivers": ["i40evf", "ixgbevf"]
                }
            },
            {
                "resourceName": "intel_sriov_dpdk",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["154c", "10ed"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["enp0s0f0","enp2s2f1"]
                }
            },
            {
                "resourceName": "mlnx_sriov_rdma",
                "isRdma": true,
                "selectors": {
                    "vendors": ["15b3"],
                    "devices": ["1018"],
                    "drivers": ["mlx5_ib"]
                }
            }
        ]
    }

kubectl create -f /root/sriov-network-device-plugin/deployments/configMap.yaml

<出力例>

kubectl get configmaps -n kube-system

[root@c80g105 ~]# kubectl get configmaps -n kube-system
NAME                                 DATA   AGE
coredns                              1      4h32m
extension-apiserver-authentication   6      4h33m
kube-flannel-cfg                     2      4h32m
kube-proxy                           2      4h32m
kubeadm-config                       2      4h32m
kubelet-config-1.17                  1      4h32m
multus-cni-config                    1      3h16m
sriovdp-config                       1      3h16m

<補足>
先ほど記載した表の通りに別けて書いてあることが確認できると思います。

8086:10ed X520 VMI用 vfio-pci
8086:1515 X540 Pod用 ixgbevf
6-2.SRIOVDP DaemonSetのデプロイ : Master

特に修正する箇所はありませんので、yamlファイルの中身を確認せず、以下のコマンドを入力しても構いません。

kubectl create -f /root/sriov-network-device-plugin/deployments/k8s-v1.16/sriovdp-daemonset.yaml
vi /root/sriov-network-device-plugin/deployments/k8s-v1.16/sriovdp-daemonset.yaml

[root@c80g105 ~]# vi /root/sriov-network-device-plugin/deployments/k8s-v1.16/sriovdp-daemonset.yaml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sriov-device-plugin
  namespace: kube-system

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-sriov-device-plugin-amd64
  namespace: kube-system
  labels:
    tier: node
    app: sriovdp
spec:
  selector:
    matchLabels:
      name: sriov-device-plugin
  template:
    metadata:
      labels:
        name: sriov-device-plugin
        tier: node
        app: sriovdp
    spec:
      hostNetwork: true
      hostPID: true
      nodeSelector:
        beta.kubernetes.io/arch: amd64
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: sriov-device-plugin
      containers:
      - name: kube-sriovdp
        image: nfvpe/sriov-device-plugin
        imagePullPolicy: Never
        args:
        - --log-dir=sriovdp
        - --log-level=10
        securityContext:
          privileged: true
        volumeMounts:
        - name: devicesock
          mountPath: /var/lib/kubelet/
          readOnly: false
        - name: log
          mountPath: /var/log
        - name: config-volume
          mountPath: /etc/pcidp
      volumes:
        - name: devicesock
          hostPath:
            path: /var/lib/kubelet/
        - name: log
          hostPath:
            path: /var/log
        - name: config-volume
          configMap:
            name: sriovdp-config
            items:
            - key: config.json
              path: config.json

kubectl create -f /root/sriov-network-device-plugin/deployments/k8s-v1.16/sriovdp-daemonset.yaml

<出力例>*11

kubectl get pods -n kube-system

[root@c80g105 ~]# kubectl get pods -n kube-system
NAME                                    READY   STATUS    RESTARTS   AGE
coredns-6955765f44-cn2xp                1/1     Running   1          4h35m
coredns-6955765f44-z9dj6                1/1     Running   1          4h35m
etcd-c80g105.md.jp                      1/1     Running   1          4h35m
kube-apiserver-c80g105.md.jp            1/1     Running   1          4h35m
kube-controller-manager-c80g105.md.jp   1/1     Running   1          4h35m
kube-flannel-ds-amd64-7ltvr             1/1     Running   1          4h35m
kube-flannel-ds-amd64-rfr4f             1/1     Running   1          4h35m
kube-multus-ds-amd64-475wf              1/1     Running   0          3h19m
kube-multus-ds-amd64-9zz5d              1/1     Running   0          3h19m
kube-proxy-dmqvr                        1/1     Running   1          4h35m
kube-proxy-pwmx2                        1/1     Running   0          4h35m
kube-scheduler-c80g105.md.jp            1/1     Running   1          4h35m
kube-sriov-device-plugin-amd64-c2szn    1/1     Running   0          3h19m
kube-sriov-device-plugin-amd64-ttwj5    1/1     Running   0          3h19m
6-3.Multusのインストール : Master

ここも特に設定変更などは不要です。

cd /root && \
git clone https://github.com/intel/multus-cni.git && \
cd multus-cni && \
cat ./images/multus-daemonset.yml | kubectl apply -f -

<出力例>
デプロイ後、以下のような出力が表示されればOKです。

kubectl get pods --all-namespaces | grep -i multus

[root@c80g105 multus-cni]# kubectl get pods --all-namespaces | grep -i multus
kube-system   kube-multus-ds-amd64-7kc44              1/1     Running   0          51s
kube-system   kube-multus-ds-amd64-8ds8r              1/1     Running   0          51s
6-4.SRIOV CRDの設定 : Master
8086:10ed X520 VMI用 vfio-pci

上記VMI用のCRD(Custom Resource Definitions)の設定を行っていきます。
ポイントはannotationsのresourceNameがconfigMap.yamlと一致している点です。
加えて、この後に設定するVMI用yamlにsriov-net1を記載します。

vi /root/sriov-network-device-plugin/deployments/sriov-crd1.yaml

[root@c80g105 ~]# vi /root/sriov-network-device-plugin/deployments/sriov-crd1.yaml

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: sriov-net1
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_netdevice1
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov300_1",
  "vlan": 300,
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.30.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }],
    "gateway": "192.168.30.254"
  }
}'

kubectl create -f /root/sriov-network-device-plugin/deployments/sriov-crd1.yaml


続いて、Pod用のCRD設定を行っていきます。

8086:1515 X540 Pod用 ixgbevf
vi /root/sriov-network-device-plugin/deployments/sriov-crd2.yaml

[root@c80g105 ~]# vi /root/sriov-network-device-plugin/deployments/sriov-crd2.yaml

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: sriov-net2
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_netdevice2
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov300_2",
  "vlan": 300,
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.30.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }],
    "gateway": "192.168.30.254"
  }
}'

kubectl create -f /root/sriov-network-device-plugin/deployments/sriov-crd2.yaml

<出力例>
以下のように表示されればOKです。

[root@c80g105 ~]# kubectl get network-attachment-definitions
NAME         AGE
sriov-net1  3h29m
sriov-net2  3h29m
6-5.リソースの確認 : Master

SR-IOVのVFがWorkerのリソースとしてk8sに認識されていることを確認します。

dnf -y install jq
kubectl get node c80g106.md.jp -o json | jq '.status.allocatable'

<出力例>
以下のような出力が表示されればOKです。

[root@c80g105 ~]# kubectl get node c80g106.md.jp -o json | jq '.status.allocatable'
{
  "cpu": "40",
  "devices.kubevirt.io/kvm": "110",
  "devices.kubevirt.io/tun": "110",
  "devices.kubevirt.io/vhost-net": "110",
  "ephemeral-storage": "400024062519",
  "hugepages-1Gi": "16Gi",
  "intel.com/intel_sriov_dpdk": "0",
  "intel.com/intel_sriov_netdevice": "0",
  "intel.com/intel_sriov_netdevice1": "16",
  "intel.com/intel_sriov_netdevice2": "16",
  "intel.com/mlnx_sriov_rdma": "0",
  "memory": "313085984Ki",
  "pods": "110"
}

7.VMIとPodのデプロイ

VMI用として事前にqcow2イメージファイルを作成しておきます。*12
以下の過去記事などを参照の上、適当な仮想マシンを作成してください。
CentOS7 kickstartによるインストール - Metonymical Deflection
CentOS8 kickstartによるインストール - Metonymical Deflection

ここでは、CentOS7.7をインストールしたqcow2ファイルが、/root直下に既に存在する前提として話を進めます。

7-1.VMI用のイメージ登録 : Worker
イメージファイルのコピー
mkdir /root/docker
cd /root/docker
cp /root/c771.qcow2 ./

ビルド用のDockerfile作成
cat << END > Dockerfile
FROM scratch
ADD c771.qcow2 /disk/
END

イメージのビルド
docker build -t vmidisks/centos:7.7 .

<出力例>

[root@c80g106 docker]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
vmidisks/centos             7.7                 f5a39b56e448        21 seconds ago      1.64GB
nfvpe/sriov-device-plugin   latest              8c508ab37c1c        6 minutes ago       25.3MB
<none>                      <none>              571b3587b90d        7 minutes ago       855MB
k8s.gcr.io/kube-proxy       v1.17.0             7d54289267dc        6 days ago          116MB
golang                      alpine              69cf534c966a        8 days ago          359MB
nfvpe/multus                v3.4                7cf8e2d1b733        10 days ago         312MB
alpine                      latest              965ea09ff2eb        7 weeks ago         5.55MB
quay.io/coreos/flannel      v0.11.0-amd64       ff281650a721        10 months ago       52.6MB
k8s.gcr.io/pause            3.1                 da86e6ba6ca1        24 months ago       742kB
kubevirt/virt-handler       <none>              c5919b95ca31        49 years ago        313MB
kubevirt/virt-controller    <none>              ab9c8cce9c60        49 years ago        291MB
kubevirt/virt-api           <none>              1a3697b92f09        49 years ago        293MB
kubevirt/virt-operator      <none>              45c6d543afb1        49 years ago        326MB
7-2.VMIのデプロイ : Master
vi /root/sriov-network-device-plugin/deployments/c771.yaml

[root@c80g105 deployments]# vi /root/sriov-network-device-plugin/deployments/c771.yaml

apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachineInstance
metadata:
  name: c771
spec:
  domain:
    resources:
      requests:
        memory: "2048Mi"
        cpu: "1"
    devices:
      disks:
      - name: containerdisk
        disk:
          bus: virtio
      interfaces:
      - name: pod
        bridge: {}
      - name: net1
        sriov: {}
      - name: net2
        sriov: {}
  volumes:
  - name: containerdisk
    containerDisk:
      image: vmidisks/centos:7.7
      imagePullPolicy: Never
  networks:
  - name: pod
    pod: {}
  - name: net1
    multus:
      networkName: sriov-net1
  - name: net2
    multus:
      networkName: sriov-net1


kubectl create-f /root/sriov-network-device-plugin/deployments/c771.yaml

<出力例>

kubectl get pods
kubectl get vmi

[root@c80g105 ~]# kubectl get pods
kubectl get vmi
NAME                       READY   STATUS    RESTARTS   AGE
virt-launcher-c771-5kdr2   2/2     Running   0          3h29m

[root@c80g105 ~]# kubectl get vmi
NAME   AGE     PHASE     IP               NODENAME
c771   3h29m   Running   10.244.1.14/24   c80g106.md.jp

<補足>
ポイントを5点ほど。

  1. multus: > networkName: に先ほど作成したCRDの名前sriov-net1を指定している点です。これにより、明示的にX520を使用する設定*13となっています。
  2. spec: > domain: > resources: には、requests:のみを記載している点です。ここでlimits: を追記すると起動後に高確率でOOM Killerが発動しVMIが瞬殺されます。*14
  3. kubectl get podsにて、READYが2/2になっています。これはVMIに加えて、virt-launcherが起動しているためです。
  4. kubectl get vmiにて、IPが10.244.1.14/24*15となっています。IPアドレス自体「10.244.1.14」は、PHASEがRunningになると、すぐに表示されます。しかし、私の環境ではプリフィックス「 /24 」が表示されるまでに90秒程度かかりました。また、プリフィックスが表示されなくてもログインできる場合があります。*16
  5. SR-IOVにてアサインされたNICが保持するIPアドレスを確認するためには、VMIへのログインが必要なので、virtctl console コマンドやsshなどでVMIにログインしてください。ログイン後、ip add showすると、以下のように見えると思います。eth1とeth2のMACアドレスがWorkerのVFのMACアドレスと一致していることを確認してください。加えて、外部NW機器にPingが通ることを確認できれば構築完了です。
[root@c771 ~]# ip add show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1450 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 8e:29:cb:fc:87:4a brd ff:ff:ff:ff:ff:ff
    inet 10.244.1.14/24 brd 10.244.1.255 scope global noprefixroute dynamic eth0
       valid_lft 86312966sec preferred_lft 86312966sec
    inet6 fe80::f6a2:e021:e183:9852/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: eth1:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 96:e5:96:36:1c:90 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.139/24 brd 192.168.30.255 scope global noprefixroute dynamic eth1
       valid_lft 2966sec preferred_lft 2966sec
    inet6 fe80::409f:ff:fe56:8741/64 scope link 
       valid_lft forever preferred_lft forever
4: eth2:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 9e:46:96:a2:4b:4e brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.138/24 brd 192.168.30.255 scope global noprefixroute dynamic eth2
       valid_lft 2966sec preferred_lft 2966sec
    inet6 fe80::6c:5eff:fee0:56ca/64 scope link 
       valid_lft forever preferred_lft forever

Worker上では以下のように認識されます。

[root@c80g106 ~]# ip link show
  一部省略
6: ens1f0:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 90:e2:ba:0b:37:b8 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 96:e5:96:36:1c:90, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 4 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 5 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 6 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 7 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
7: ens1f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 90:e2:ba:0b:37:b9 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 9e:46:96:a2:4b:4e, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
    vf 4 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 5 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 6 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 7 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off

7-3.Podのデプロイ
vi /root/sriov-network-device-plugin/deployments/pod2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod2
  annotations:
    k8s.v1.cni.cncf.io/networks: sriov-net2
spec:
  containers:
  - name: pod2
    image: docker.io/centos/tools:latest
    command:
    - /sbin/init
    resources:
      requests:
        intel.com/intel_sriov_netdevice2: '1'
      limits:
        intel.com/intel_sriov_netdevice2: '1'

kubectl create -f /root/sriov-network-device-plugin/deployments/pod2.yaml

<出力例>

[root@c80g105 ~]# kubectl get pods -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES
pod2                       1/1     Running   1          11h   10.244.1.19   c80g106.md.jp              
virt-launcher-c771-cp2nk   2/2     Running   0          23m   10.244.1.27   c80g106.md.jp              

<補足>
ポイントを3点ほど。

  1. annotations: > k8s.v1.cni.cncf.io/networks: に先ほど作成したCRDの名前sriov-net2を指定している点です。これにより、明示的にX540を使用する設定*17となっています。
  2. resources: > requests: に intel.com/intel_sriov_netdevice2を指定している点です。また「'1'」はVFの数を示していますが、2や3と増やしても、VFは1つしかアサインされませんでした。*18
  3. SR-IOVにてアサインされたNICが保持するIPアドレスは、以下のコマンドで確認できます。net1のMACアドレスがWorkerのVFのMACアドレスと一致していることを確認してください。加えて、外部NW機器にPingが通ることを確認できれば構築完了です。
kubectl exec -it pod2 -- ip addr show

[root@c80g105 ~]# kubectl exec -it pod2 -- ip addr show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
3: eth0@if31:  mtu 1450 qdisc noqueue state UP group default
    link/ether 0a:56:43:b8:ad:f5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.244.1.19/24 scope global eth0
       valid_lft forever preferred_lft forever
24: net1:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 2e:f2:70:b7:e9:ca brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.6/24 brd 192.168.30.255 scope global net1
       valid_lft forever preferred_lft forever

Worker上では以下のように認識されます。

[root@c80g106 ~]# ip link show
  一部省略
8: ens2f0:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:70:d4 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 4e:bc:dc:62:a8:7e, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC ee:c9:15:96:2d:5d, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC c2:82:b1:0f:ca:2e, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 86:e2:0a:d6:96:ff, spoof checking on, link-state auto, trust off, query_rss off
    vf 4 MAC 6e:5e:70:e8:da:48, spoof checking on, link-state auto, trust off, query_rss off
    vf 5 MAC f2:2f:55:d8:b3:40, spoof checking on, link-state auto, trust off, query_rss off
    vf 6 MAC ae:a8:e8:48:25:2c, spoof checking on, link-state auto, trust off, query_rss off
    vf 7 MAC da:d8:2a:7d:2f:5b, spoof checking on, link-state auto, trust off, query_rss off
9: ens2f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:70:d6 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC ba:73:6f:81:ea:31, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 0a:24:c7:34:26:ec, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC d6:62:b0:f5:01:fc, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC a2:05:32:03:eb:d4, spoof checking on, link-state auto, trust off, query_rss off
    vf 4 MAC b2:46:0e:e4:93:90, spoof checking on, link-state auto, trust off, query_rss off
    vf 5 MAC 76:d6:8a:9f:1a:84, spoof checking on, link-state auto, trust off, query_rss off
    vf 6 MAC 2e:f2:70:b7:e9:ca, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
    vf 7 MAC 8e:c0:94:c2:98:f9, spoof checking on, link-state auto, trust off, query_rss off
7-4.VMIとPodの差異について

以下にまとめます。

8086:10ed X520 VMI用 vfio-pci
8086:1515 X540 Pod用 ixgbevf

VMI用vfio-pciについて

  • worker上でip add showを打っても、vfio-pci上で動作しているため、blacklist登録時と同様にVFのNICは表示されません。このためip link showでMACアドレスを確認します。
  • VMIによってVFが掴まれていないとき、MACアドレスは00:00:00:00:00:00が正常です。
  • 今回の構成では、IPアドレスは外部NW機器*19にてDHCPサーバを立ててIPアドレスアサインしています。

Pod用ixgbevfについて

  • ixgbevfにて動作しているため、ip add showにてVFのNICが表示されます。
  • PodによってVFが掴まれているか否かに関わらず、任意のMACアドレスアサインされます。そのMACアドレスはそのままPodが継承します。
  • IPアドレスは(恐らく)MultusからDHCPのように自動でアサインされています。
  • アドレスレンジを指定する場合は以下のようにCRDに追記してください。
vi /root/sriov-network-device-plugin/deployments/sriov-crd2.yaml

[root@c80g105 ~]# vi /root/sriov-network-device-plugin/deployments/sriov-crd2.yaml

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: sriov-net2
  annotations:
    k8s.v1.cni.cncf.io/resourceName: intel.com/intel_sriov_netdevice2
spec:
  config: '{
  "type": "sriov",
  "cniVersion": "0.3.1",
  "name": "sriov300_2",
  "vlan": 300,
  "ipam": {
    "type": "host-local",
    "subnet": "192.168.30.0/24",
    "rangeStart": "192.168.30.64",
    "rangeEnd": "192.168.30.127",
    "routes": [{
      "dst": "0.0.0.0/0"
    }],
    "gateway": "192.168.30.254"
  }
}'
7-5.VMIとPodのdescribe情報*20

VMIのdescribe
以下のコマンドで確認できます。実際の出力はここにアップしておきます。

kubectl describe pods virt-launcher-c771-cp2nk

Podのdescribe
以下のコマンドで確認できます。実際の出力はここにアップしておきます。

kubectl describe pods pod2

VMIのlog
VMIが正常起動しないときやログインできないときは、以下のログを確認してみてください。
膨大な量のログが出力されるので、ここにアップしておきます。

kubectl logs virt-launcher-c771-cp2nk compute

以上です。

8.最後に

以下のサイトを参考にさせて頂きました。
GitHub - k8snetworkplumbingwg/multus-cni
GitHub - k8snetworkplumbingwg/sriov-cni: DPDK & SR-IOV CNI plugin
GitHub - k8snetworkplumbingwg/sriov-network-device-plugin: SRIOV network device plugin for Kubernetes
https://kubevirt.io/user-guide/docs/latest/creating-virtual-machines/interfaces-and-networks.html
Kubernetes: Multus + SRIOV quickstart – Zenghui Shi

今回はSR-IOVでしたが、次回はOvS-DPDKなどにも挑戦できればと考えています。
f:id:metonymical:20191215111811p:plain

Kubernetesのネットワーク構成といった場合、flannelやCalicoの解説サイトがたくさんあったため、とても助かりました。
しかし、SR-IOVに関してVMIとPodの両方を解説しているサイトが皆無に等しかったため今回の記事を書きました。

今のネットワークのトレンドとしては、P4やeBPF+XDP、SRv6といった辺りかなと思っています。
このため、まだまだ私は遅れ気味だなと日々痛感しておりますが、これでようやく足元ぐらいに辿り着けていられればいいなぁ、と思っています。

また、クラウドネイティブといったキーワードが頻出していますが、実際に自分で手を動かしていじってみた結果、クラウドネイティブであることの意味とか意義とか優位性というモノが、理解できたような気がします。

今回、Podに加えて、KubeVirt上のVMIについても記載しましたが、私の個人的な感想として、一定の需要がありそうな気がしました。

というのも、
いきなり一足飛びでコンテナ化できない or コンテナ化するにはハードルが高いといったケースを鑑みるに、libvirtd上で仮想マシンを稼働させながらも、アーキテクチャk8sに(クラウドネイティブ化したシステムとして)統一したい、といった要件を満たせるかもしれないと思いました。

Migrate for Anthosなどは、まさしくこういった課題を解決するために提供され始めたのかな、という気がします。
Migrate for Anthos  |  Google Cloud

*1:おさらい程度に読み飛ばしてください。

*2:今回は無効化してしまいますが、本来はあまり良くないです。

*3:Masterは不要ですが念のため

*4:名前解決できるようにしておいてください。

*5:このため今回はNICを2枚挿しにしています。

*6:これに気付くまでに2週間程度掛かりました。。。

*7:kubectl get pods上ではrunningになりますが。

*8:virshのようにStart & StopやConsoleログインができます。

*9:私の環境では、tar.gzをDLするとハッシュ値が異なるというエラーで弾かれてしまったためインストールしていません。最近、KubeVirtがv0.24.0にアップデートされた影響かもしれません。

*10:Multusが3番目なのですが、先にインストールしても大丈夫かなと思っています。

*11:Master&Workerにて、それぞれsriov-device-pluginを起動させるため、5-3 & 5-4にて、Docker Imageのビルドをしています。

*12:Cloud Initからイメージファイルを落とした場合、証明書認証が必要となるため、公開鍵を仕込む必要がありますので、私は自前でqcow2ファイルを作っています。

*13:即ち、vfio-pciを使用する設定

*14:これに気付くのに1週間程度掛かりました。。

*15:flannelからアサインされるIP

*16:これの理由は未だによくわかっていません。。

*17:即ち、ixgbevfを使用する設定

*18:この辺りの仕様が正直よくわかっていません。。

*19:構成図右側のスイッチ

*20:何度か作り直しをしているためIPやMACなどが一部異なっていると思います。

CentOS8 ovs(Open vSwitch)+DPDKのビルドとネットワーク設定方法

CentOS8によるovs(Open vSwitch)+DPDKのビルドとネットワーク設定方法について記載しました。
基本的にはCentOS7と同様ですが、CentOS8の場合はdpdkのパッケージがあるため、比較的楽に導入出来ます。

1.構成

1-1.環境
筐体                             : ProLiant DL360e Gen8
System ROM                       : P73 01/22/2018
NIC                              : Intel X540-AT2
OS                               : CentOS8.0(1905)
Kernel                           : 4.18.0-80.el8.x86_64
Installed Environment Groups     : 
  @^graphical-server-environment
  @container-management
  @development
  @virtualization-client
  @virtualization-hypervisor
  @virtualization-tools 
ovs                              : 2.12.90
DPDK                             : 18.11.3
1-2.全体の流れ

事前準備
DPDKインストール
OvSソースビルド
OvS+DPDKのネットワーク設定
仮想マシンのvirsh edit

2.事前準備

2-1.qemu-kvmの実行ユーザをrootへ変更

qemu-kvmの実行ユーザをqemu→rootに変更します。

vi /etc/libvirt/qemu.conf

user = "root"  #コメントを外す
group = "root"  #コメントを外す

viで/etc/libvirt/qemu.confを開き、上記ユーザとグループの行をコメントアウト

2-2.必要なパッケージのインストール
sed -i -e s/enabled=0/enabled=1/g /etc/yum.repos.d/CentOS-PowerTools.repo
dnf -y install libpcap-devel elfutils-libelf-devel numactl-devel libmnl-devel clang
2-3.HugePageとIOMMUの有効化
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ default_hugepagesz=1G hugepagesz=1G hugepages=16\"/g" /etc/default/grub
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub
grub2-mkconfig -o /etc/grub2.cfg
reboot

hugepageの有効化
iommuの有効化*1
grubに設定反映
再起動

2-4.HugePageの確認とマウント
grep Huge /proc/meminfo

出力例
# grep Huge /proc/meminfo
AnonHugePages:    135168 kB
HugePages_Total:      16
HugePages_Free:       16
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB

vi /etc/fstab

最終行に以下を追記
nodev  /mnt/huge_1GB hugetlbfs pagesize=1GB    0 0

HugePageの割り当て状況確認
HugePageの永続化マウント

2-5.vfio-pciの設定
echo "vfio-pci" > /etc/modules-load.d/vfio-pci.conf
echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modules-load.d/iommu.conf

vfio-pciの永続化設定
vfio-pciのiommu利用の永続化

2-5’.uio_pci_generic設定

vfio-pciが利用できない場合は、uio_pci_genericを使用します。

echo "uio_pci_generic" > /etc/modules-load.d/uio_pci_generic.conf

uio_pci_genericの永続化設定

ここまでの準備が整ったら一旦再起動してください。

reboot

3.DPDKインストール

3-1.インストール
dnf -y install dpdk dpdk-devel dpdk-doc dpdk-tools

4.OvSソースビルド

4-1.ビルド環境準備

ビルド環境の準備をします。

cd /usr/src
git clone https://github.com/openvswitch/ovs.git

ディレクトリ移動
git cloneにてソースのダウンロード

4-2.ビルド

ソースからビルドします。

export DPDK_BUILD=/usr/share/dpdk/x86_64-default-linuxapp-gcc && \
cd /usr/src/ovs && \
./boot.sh && \
./configure --with-dpdk=$DPDK_BUILD CC=clang && \
make && \
make install

dpdk-develへのパスを指定
ディレクトリ移動
boot.sh実行
configure実行*2
ビルド
インストール

多少時間は掛かりますが、最後の方は以下のような出力がでれば正常にビルドが完了しています。

onitor-ipsec vtep/ovs-vtep '/usr/local/share/openvswitch/scripts'
make[3]: Leaving directory '/usr/src/ovs'
make[2]: Leaving directory '/usr/src/ovs'
make[1]: Leaving directory '/usr/src/ovs'

5.OvS+DPDKのネットワーク設定

5-1.全体構成

f:id:metonymical:20190106225241j:plain
前回記事の構成図と比較してください。
グレーアウト&斜体文字になっているのが前回設定した箇所です。
今回は(1)~(6)の黒文字になっている箇所を設定していきます。

5-2.全体の流れ ~概要~
  1. DPDKにバインド:(1)(2)
  2. Bridge作成:(3)
  3. Bond作成:(4)
  4. vHostUserClientポート作成:(5)
  5. 仮想マシンの設定:(6)
5-3.コマンド投入前準備1

コマンド投入前には以下のようにパスを通しておいてください。*3

vi /root/.bash_profile

PATH=$PATH:$HOME/bin:/usr/local/share/openvswitch/scripts
export PATH
5-4.コマンド投入前準備2

OvSを起動後、DPDK周りの詳細設定を追加しておきます。

ovs-ctl --system-id=random start
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024,1024
ovs-vsctl --no-wait set Open_vSwitch . other_config:vhost-iommu-support=true
ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x33
ovs-vsctl --no-wait get Open_vSwitch . other_config

OvSサービスの開始
DPDKの初期化
NUMA毎のメモリ設定(単位MB)
PMD-CPUマスクの設定
設定内容の確認

上記のうち、dpdk-init=true以外はチューニングパラメータなので、設定しなくてもとりあえずは動きます。

5-5.全体の流れ ~コマンドのみ~

以下のコマンドを投入していきます。
やりたいことが既に決まっている方は、構成図とコマンドの内容を見るだけでもよいと思います。

1.DPDKにバインド
(1)
dpdk-devbind --status
dpdk-devbind --bind=vfio-pci ens1f0
(2)
dpdk-devbind --bind=vfio-pci ens1f1
dpdk-devbind --status

2.Bridge作成
(3)
ovs-ctl --system-id=random stop
ovs-ctl --system-id=random start
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev

3.Bond作成
(4)
ovs-vsctl add-bond ovsbr0 bond0 dpdk0 dpdk1 \
 vlan_mode=trunk trunks=11,300-304 \
 bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \
 -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:08:00.0 \
 -- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:08:00.1

4.vHostUserClientポート作成
(5)
mkdir -p /usr/local/openvswitch/
touch /usr/local/openvswitch/vhuc0

ovs-vsctl add-port ovsbr0 vhuc0 \
 vlan_mode=access tag=300 \
 -- set Interface vhuc0 type=dpdkvhostuserclient \
 options:vhost-server-path=/usr/local/openvswitch/vhuc0

5.仮想マシンの設定
(6)
virsh edit Guest3

  <currentMemory unit='KiB'>1048576</currentMemory>
  <memoryBacking>
    <hugepages>
      <page size='1048576' unit='KiB' nodeset='0'/>
    </hugepages>
  </memoryBacking>
  
  <cpu mode='host-passthrough' check='none'>
    <numa>
      <cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/>
    </numa>
  </cpu>

  <interface type='vhostuser'>
    <source type='unix' path='/usr/local/openvswitch/vhuc0' mode='server'/>
    <model type='virtio'/>
  </interface>青=追記,緑=置換

6.DPDKにバインド

Kernel上で動作しているX540をDPDK上で動作されるようにバインドします。*4
(1)
dpdk-devbind --status
dpdk-devbind --bind=vfio-pci ens1f0
(2)
dpdk-devbind --bind=vfio-pci ens1f1
dpdk-devbind --status

[root@c80gmas ~]# dpdk-devbind --status

Network devices using kernel driver
===================================
0000:02:00.0 'I350 Gigabit Network Connection 1521' if=eno1 drv=igb unused=vfio-pci,uio_pci_generic *Active*
0000:02:00.1 'I350 Gigabit Network Connection 1521' if=eno2 drv=igb unused=vfio-pci,uio_pci_generic
0000:02:00.2 'I350 Gigabit Network Connection 1521' if=eno3 drv=igb unused=vfio-pci,uio_pci_generic
0000:02:00.3 'I350 Gigabit Network Connection 1521' if=eno4 drv=igb unused=vfio-pci,uio_pci_generic
0000:08:00.0 'Ethernet Controller 10-Gigabit X540-AT2 1528' if=ens1f0 drv=ixgbe unused=vfio-pci,uio_pci_generic
0000:08:00.1 'Ethernet Controller 10-Gigabit X540-AT2 1528' if=ens1f1 drv=ixgbe unused=vfio-pci,uio_pci_generic

[root@c80gmas ~]# dpdk-devbind.py --bind=vfio-pci ens1f0
[root@c80gmas ~]# dpdk-devbind.py --bind=vfio-pci ens1f1
[root@c80gmas ~]# dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
0000:08:00.0 'Ethernet Controller 10-Gigabit X540-AT2 1528' drv=vfio-pci unused=ixgbe,uio_pci_generic
0000:08:00.1 'Ethernet Controller 10-Gigabit X540-AT2 1528' drv=vfio-pci unused=ixgbe,uio_pci_generic

Network devices using kernel driver
===================================
0000:02:00.0 'I350 Gigabit Network Connection 1521' if=eno1 drv=igb unused=vfio-pci,uio_pci_generic *Active*
0000:02:00.1 'I350 Gigabit Network Connection 1521' if=eno2 drv=igb unused=vfio-pci,uio_pci_generic
0000:02:00.2 'I350 Gigabit Network Connection 1521' if=eno3 drv=igb unused=vfio-pci,uio_pci_generic
0000:02:00.3 'I350 Gigabit Network Connection 1521' if=eno4 drv=igb unused=vfio-pci,uio_pci_generic

バインドされると、X540がNetwork devices using DPDK-compatible driverに表示されます。

今回利用するドライバはvfio-pciですが、uio_pci_genericでも利用可能です。
利用したい場合は、以下のように変更すればOKです。

dpdk-devbind --bind=uio_pci_generic ens1f0

また、vfio-pciを利用するにあたり、ProLiant DL360G8を使用している方はRMRR設定が必要になる場合があります。
以下のサイトを参考にしてみてください。
DPDK and RMRR Compatibility Issues on the HP Proliant DL360e G8 | www.jimmdenton.com
https://support.hpe.com/hpsc/doc/public/display?sp4ts.oid=7271259&docId=emr_na-c04781229&docLocale=ja_JP

7.Bridge作成

念のため、ovsの再起動をした後、Bridge作成を行ってください。
(3)
ovs-ctl --system-id=random stop
ovs-ctl --system-id=random start
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev

[root@c80gmas ~]# ovs-ctl --system-id=random stop
Exiting ovs-vswitchd (20081)                               [  OK  ]
Exiting ovsdb-server (20063)                               [  OK  ]
[root@c80gmas ~]# ovs-ctl --system-id=random start
Starting ovsdb-server                                      [  OK  ]
Configuring Open vSwitch system IDs                        [  OK  ]
Enabling remote OVSDB managers                             [  OK  ]
[root@c80gmas ~]# ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev

正常にBridgeが作成されると上記のような出力となります。

8.Bond作成

ovsbr0上にアップリンクポート*5を追加し、Bondを組みます。また、TrunkとLACPの設定も同時に追加します。
(4)
ovs-vsctl add-bond ovsbr0 bond0 dpdk0 dpdk1 \
vlan_mode=trunk trunks=11,300-304 \
bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \
-- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:08:00.0 \
-- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:08:00.1
ovs-vsctl show

[root@c80gmas ~]# ovs-vsctl add-bond ovsbr0 bond0 dpdk0 dpdk1 \
>  vlan_mode=trunk trunks=11,300-304 \
>  bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \
>  -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:08:00.0 \
>  -- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:08:00.1
[root@c80gmas ~]# ovs-vsctl show
8daaa733-f6ef-4b67-a1a9-581875f33420
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "bond0"
            trunks: [11, 300, 301, 302, 303, 304]
            Interface "dpdk0"
                type: dpdk
                options: {dpdk-devargs="0000:08:00.0"}
            Interface "dpdk1"
                type: dpdk
                options: {dpdk-devargs="0000:08:00.1"}
    ovs_version: "2.12.90"
[root@c80gmas ~]#

上記のように追加されていればOKです。

FullTrunkにしたい場合は、以下の行を削除してください。

vlan_mode=trunk trunks=11,300-304 \

スイッチ側の仕様でLACPが組めない場合、以下のように修正してください。

 bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \
 ↓
 bond_mode=balance-slb \

9.vHostUserClientポート作成

ovsbr0上にダウンリンクポート*6を追加します。
先にSocketファイルとなるvhuc0を作成し、その後ovsbr0にポートを追加します。
(5)
mkdir -p /usr/local/openvswitch/
touch /usr/local/openvswitch/vhuc0

ovs-vsctl add-port ovsbr0 vhuc0 \
vlan_mode=access tag=300 \
-- set Interface vhuc0 type=dpdkvhostuserclient \
options:vhost-server-path=/usr/local/openvswitch/vhuc0

ovs-vsctl show

[root@c80gmas ~]# mkdir -p /usr/local/openvswitch/
[root@c80gmas ~]# touch /usr/local/openvswitch/vhuc0
[root@c80gmas ~]# ovs-vsctl add-port ovsbr0 vhuc0 \
>  vlan_mode=access tag=300 \
>  -- set Interface vhuc0 type=dpdkvhostuserclient \
>  options:vhost-server-path=/usr/local/openvswitch/vhuc0
[root@c80gmas ~]# ovs-vsctl show
8daaa733-f6ef-4b67-a1a9-581875f33420
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "bond0"
            trunks: [11, 300, 301, 302, 303, 304]
            Interface "dpdk1"
                type: dpdk
                options: {dpdk-devargs="0000:08:00.1"}
            Interface "dpdk0"
                type: dpdk
                options: {dpdk-devargs="0000:08:00.0"}
        Port "vhuc0"
            tag: 300
            Interface "vhuc0"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/usr/local/openvswitch/vhuc0"}
    ovs_version: "2.12.90"

上記のように追加されていればOKです。
ちなみに、vlan_mode=access tag=300としましたが、tag=300のみでも自動的にaccessポートにしてくれます。
また、trunkポートにしたい場合は、Bond設定で投入した「vlan_mode=trunk trunks=11,300-304」を参考に置換してください。

10.仮想マシンの設定

virshで仮想マシンの設定を編集します。
これにより、以下3点を実施します。
仮想マシン上でHugePageを利用可能にする
仮想マシンに対してCPUのパススルー機能を有効化する
・vHostUserにてNICを追加する
(6)
virsh edit Guest3

<currentMemory unit='KiB'>1048576</currentMemory>
<memoryBacking>
<hugepages>
<page size='1048576' unit='KiB' nodeset='0'/>
</hugepages>
</memoryBacking>


<cpu mode='host-passthrough' check='none'>
<numa>
<cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/>
</numa>
</cpu>

<interface type='vhostuser'>
<source type='unix' path='/usr/local/openvswitch/vhuc0' mode='server'/>
<model type='virtio'/>
</interface>


青=追記,緑=置換

[root@c80gmas ~]# virsh edit Guest3

  <currentMemory unit='KiB'>1048576</currentMemory>
  <memoryBacking>
    <hugepages>
      <page size='1048576' unit='KiB' nodeset='0'/>
    </hugepages>
  </memoryBacking>
  
  <cpu mode='host-passthrough' check='none'>
    <numa>
      <cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/>
    </numa>
  </cpu>

  <interface type='vhostuser'>
    <source type='unix' path='/usr/local/openvswitch/vhuc0' mode='server'/>
    <model type='virtio'/>
  </interface>青=追記,緑=置換

xmlファイルのため、virsh editで開くと、最初はどこを編集していいか探したり、迷ったりすると思いますが、通常のviエディタと同様に編集可能なため、「cpu mode」などで検索すればすぐに見つかると思います。
あと、vhostuserですが、mode=serverとなっています。以前はmode=clientだったのですが、現在はmode=serverが推奨されています。*7

11.仮想マシンの起動

仮想マシンを起動し、新規に追加されたインターフェースにIP設定後、疎通確認を行ってみてください。

virsh start Guest3

起動時にPermission Denyなどのエラーが出力される場合があります。
その場合、「2-2.qemu-kvmの実行ユーザをrootへ変更」を参照し、Qemuの実行ユーザが確実にrootとなっていることを確認してください。
その上で、

systemctl restart libvirtd.service

を実行し、それでもダメなら、ホストOSを再起動してみてください。

以上です。

12.最後に

CentOS7からの改編となります。

大きく変わっている点は、

  • qemu-kvm-evが不要*8
  • dpdkのビルドが不要*9
  • gccの代わりにclangを使用*10

といったあたりです。

一度勘所がわかると、いくらでも応用が効くようになるので、その積み重ねが大切なのかなと思います。
CentOS8にてopenstackはまだ各種パッケージなどが準備されていないようですが、ovs-dpdkは実装できたので諸々移行できそうです。
LinuxBridge&ovsにて、それぞれsriov&dpdkが使用できれば、概ねやりたいことはできるので。
また、nmcliコマンドはCentOS7でも8でも共通なので、そのまま転用可能です。

ちなみに、元々の動機はCentOS8でこれ↓がやりたかったので、CentOS8でもovs-dpdkを実装してみました。
f:id:metonymical:20191116061552p:plain
f:id:metonymical:20191116061611p:plain
github.com
これができれば、dpdk+dockerやk8sも包含されるため、現段階における仮想化されたネットワークの様々アーキテクチャは網羅されるかな、と考えています。
さらにその次のステップとして、SRv6によるネットワークスライシングなどにも踏み込めれば、楽しそうだなと考えています。

*1:IOMMUについては、DL360G8特有の設定(RMRRの設定)があるため、途中で補足を入れます。

*2:CentOS7のときは、gccを使用していましたが、今回はclangを使用しています。理由はコンパイル時間の短縮です。x86_64アーキテクチャのみの環境であれば、clang/llvmの方が早かったので。ちなみにgccでも問題ありませんが、3倍以上の時間を要しました、また、Warningメッセージが出まくるので少々不安になるかもしれません。

*3:.bash_profileに追記した場合は、ログアウト&ログインを忘れずに。またCentOS7のときとは異なり、dnfコマンドにてdpdkをインストールしているため、dpdk関連コマンドへのパス通しは不要となりました。

*4:CentOS7とは異なり、.pyの拡張子が無くなっています。.pyを入力してしまうと、No such a file or diretory~が出力されます。

*5:DPDK上で稼働しているX540のens1f0とens1f1

*6:仮想マシンが接続されるポート

*7:詳細は、 Data Plane Development Kit vHost User Client Mode with Open vSwitch* | Intel® Softwareに記載されています。

*8:CentOS8の場合、ver2.12となっているため

*9:dnfコマンドでインストールが可能なため

*10:コンパイル時間の短縮のため

CentOS8 小ネタ集その5:リポジトリの設定

CentOS8のリポジトリ設定方法を記載します。

設定するリポジトリは以下の通りです。

基本編

  • epel-release
  • elrepo
  • remi
  • PowerTools

番外編

  • fed2el-release

1.OSインストール直後の状態

[root@c80gmas ~]# dnf repolist all                                                                                      
Last metadata expiration check: 0:00:12 ago on Fri 15 Nov 2019 03:44:42 AM JST.                                         
repo id                                         repo name                                                 status        
AppStream                                       CentOS-8 - AppStream                                      enabled: 5,089
AppStream-source                                CentOS-8 - AppStream Sources                              disabled      
BaseOS                                          CentOS-8 - Base                                           enabled: 2,843
BaseOS-source                                   CentOS-8 - BaseOS Sources                                 disabled      
PowerTools                                      CentOS-8 - PowerTools                                     disabled      
base-debuginfo                                  CentOS-8 - Debuginfo                                      disabled      
c8-media-AppStream                              CentOS-AppStream-8 - Media                                disabled      
c8-media-BaseOS                                 CentOS-BaseOS-8 - Media                                   disabled      
centosplus                                      CentOS-8 - Plus                                           disabled      
centosplus-source                               CentOS-8 - Plus Sources                                   disabled      
cr                                              CentOS-8 - cr                                             disabled      
extras                                          CentOS-8 - Extras                                         enabled:     3
extras-source                                   CentOS-8 - Extras Sources                                 disabled      
fasttrack                                       CentOS-8 - fasttrack                                      disabled      

2.epel-release

dnf -y install epel-release

5.PowerTools

PowerToolsはdevelなどが多く含まれており、ビルドをする際には何かと重宝します。
デフォルトでインストールされていますがDisbaleになっているため、Enableにしてしまいます。

sed -i -e s/enabled=0/enabled=1/g /etc/yum.repos.d/CentOS-PowerTools.repo

<出力例>

[root@c80gmas ~]# sed -i -e s/enabled=0/enabled=1/g /etc/yum.repos.d/CentOS-PowerTools.repo
[root@c80gmas ~]# cat /etc/yum.repos.d/CentOS-PowerTools.repo
# CentOS-PowerTools.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#

[PowerTools]
name=CentOS-$releasever - PowerTools
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=PowerTools&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/PowerTools/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

ここまでの設定で、以下のようにリポジトリが追加されていると思います。

[root@c80gmas ~]# dnf repolist all                                                                                      
Remi's Modular repository for Enterprise Linux 8 - x86_64                               109 kB/s | 509 kB     00:04     
Safe Remi's RPM repository for Enterprise Linux 8 - x86_64                              271 kB/s | 1.4 MB     00:05     
repo id                       repo name                                                                   status        
AppStream                     CentOS-8 - AppStream                                                        enabled: 5,089
AppStream-source              CentOS-8 - AppStream Sources                                                disabled      
BaseOS                        CentOS-8 - Base                                                             enabled: 2,843
BaseOS-source                 CentOS-8 - BaseOS Sources                                                   disabled      
PowerTools                    CentOS-8 - PowerTools                                                       enabled: 1,507
base-debuginfo                CentOS-8 - Debuginfo                                                        disabled      
c8-media-AppStream            CentOS-AppStream-8 - Media                                                  disabled      
c8-media-BaseOS               CentOS-BaseOS-8 - Media                                                     disabled      
centosplus                    CentOS-8 - Plus                                                             disabled      
centosplus-source             CentOS-8 - Plus Sources                                                     disabled      
cr                            CentOS-8 - cr                                                               disabled      
elrepo                        ELRepo.org Community Enterprise Linux Repository - el8                      enabled:    25
elrepo-extras                 ELRepo.org Community Enterprise Linux Extras Repository - el8               disabled      
elrepo-kernel                 ELRepo.org Community Enterprise Linux Kernel Repository - el8               disabled      
elrepo-testing                ELRepo.org Community Enterprise Linux Testing Repository - el8              disabled      
*epel                         Extra Packages for Enterprise Linux 8 - x86_64                              enabled: 3,153
epel-debuginfo                Extra Packages for Enterprise Linux 8 - x86_64 - Debug                      disabled      
epel-playground               Extra Packages for Enterprise Linux 8 - Playground - x86_64                 disabled      
epel-playground-debuginfo     Extra Packages for Enterprise Linux 8 - Playground - x86_64 - Debug         disabled      
epel-playground-source        Extra Packages for Enterprise Linux 8 - Playground - x86_64 - Source        disabled      
epel-source                   Extra Packages for Enterprise Linux 8 - x86_64 - Source                     disabled      
epel-testing                  Extra Packages for Enterprise Linux 8 - Testing - x86_64                    disabled      
epel-testing-debuginfo        Extra Packages for Enterprise Linux 8 - Testing - x86_64 - Debug            disabled      
epel-testing-source           Extra Packages for Enterprise Linux 8 - Testing - x86_64 - Source           disabled      
extras                        CentOS-8 - Extras                                                           enabled:     3
extras-source                 CentOS-8 - Extras Sources                                                   disabled      
fasttrack                     CentOS-8 - fasttrack                                                        disabled      
remi                          Remi's RPM repository for Enterprise Linux 8 - x86_64                       disabled      
remi-debuginfo                Remi's RPM repository for Enterprise Linux 8 - x86_64 - debuginfo           disabled      
remi-modular                  Remi's Modular repository for Enterprise Linux 8 - x86_64                   enabled:    12
remi-modular-test             Remi's Modular testing repository for Enterprise Linux 8 - x86_64           disabled      
remi-safe                     Safe Remi's RPM repository for Enterprise Linux 8 - x86_64                  enabled: 2,014
remi-safe-debuginfo           Remi's RPM repository for Enterprise Linux 8 - x86_64 - debuginfo           disabled      
remi-test                     Remi's test RPM repository for Enterprise Linux 8 - x86_64                  disabled      
remi-test-debuginfo           Remi's test RPM repository for Enterprise Linux 8 - x86_64 - debuginfo      disabled      

およそ1万超のパッケージが利用可能になっていると思います。

[root@c80gmas ~]# dnf list available | wc -l
11976

これから有用なパッケージが徐々に増えてくると思いますが、現段階において、これだけでは心許無いという方は以下も追加してみてください。

6.fed2el-release

fedora28のリポジトリを追加することにより、6万超のパッケージが利用可能になります。

dnf -y install https://extras.getpagespeed.com/release-el8-latest.rpm
dnf -y install fed2el-release

<追加後の状態>

[root@c80gmas ~]# dnf repolist all                                                                                      
Last metadata expiration check: 0:00:06 ago on Fri 15 Nov 2019 04:02:00 AM JST.                                         
repo id                                            repo name                                              status        
AppStream                                          CentOS-8 - AppStream                                   enabled: 5,089
AppStream-source                                   CentOS-8 - AppStream Sources                           disabled      
BaseOS                                             CentOS-8 - Base                                        enabled: 2,843
BaseOS-source                                      CentOS-8 - BaseOS Sources                              disabled      
PowerTools                                         CentOS-8 - PowerTools                                  disabled      
base-debuginfo                                     CentOS-8 - Debuginfo                                   disabled      
c8-media-AppStream                                 CentOS-AppStream-8 - Media                             disabled      
c8-media-BaseOS                                    CentOS-BaseOS-8 - Media                                disabled      
centosplus                                         CentOS-8 - Plus                                        disabled      
centosplus-source                                  CentOS-8 - Plus Sources                                disabled      
cr                                                 CentOS-8 - cr                                          disabled      
elrepo                                             ELRepo.org Community Enterprise Linux Repository - el8 enabled:    25
elrepo-extras                                      ELRepo.org Community Enterprise Linux Extras Repositor disabled      
elrepo-kernel                                      ELRepo.org Community Enterprise Linux Kernel Repositor disabled      
elrepo-testing                                     ELRepo.org Community Enterprise Linux Testing Reposito disabled      
*epel                                              Extra Packages for Enterprise Linux 8 - x86_64         enabled: 3,153
epel-debuginfo                                     Extra Packages for Enterprise Linux 8 - x86_64 - Debug disabled      
epel-playground                                    Extra Packages for Enterprise Linux 8 - Playground - x disabled      
epel-playground-debuginfo                          Extra Packages for Enterprise Linux 8 - Playground - x disabled      
epel-playground-source                             Extra Packages for Enterprise Linux 8 - Playground - x disabled      
epel-source                                        Extra Packages for Enterprise Linux 8 - x86_64 - Sourc disabled      
epel-testing                                       Extra Packages for Enterprise Linux 8 - Testing - x86_ disabled      
epel-testing-debuginfo                             Extra Packages for Enterprise Linux 8 - Testing - x86_ disabled      
epel-testing-source                                Extra Packages for Enterprise Linux 8 - Testing - x86_ disabled      
extras                                             CentOS-8 - Extras                                      enabled:     3
extras-source                                      CentOS-8 - Extras Sources                              disabled      
fasttrack                                          CentOS-8 - fasttrack                                   disabled      
fedora                                             Fedora 28 - x86_64                                     disabled      
fedora-debuginfo                                   Fedora 28 - x86_64 - Debug                             disabled      
fedora-rpmfusion-free                              RPM Fusion for Fedora 28 - Free                        disabled      
fedora-rpmfusion-free-debuginfo                    RPM Fusion for Fedora 28 - Free - Debug                disabled      
fedora-rpmfusion-free-source                       RPM Fusion for Fedora 28 - Free - Source               disabled      
fedora-rpmfusion-free-updates                      RPM Fusion for Fedora 28 - Free - Updates              disabled      
fedora-rpmfusion-free-updates-debuginfo            RPM Fusion for Fedora 28 - Free - Updates Debug        disabled      
fedora-rpmfusion-free-updates-source               RPM Fusion for Fedora 28 - Free - Updates Source       disabled      
fedora-rpmfusion-free-updates-testing              RPM Fusion for Fedora 28 - Free - Test Updates         disabled      
fedora-rpmfusion-free-updates-testing-debuginfo    RPM Fusion for Fedora 28 - Free - Test Updates Debug   disabled      
fedora-rpmfusion-free-updates-testing-source       RPM Fusion for Fedora 28 - Free - Test Updates Source  disabled      
fedora-rpmfusion-nonfree                           RPM Fusion for Fedora 28 - Nonfree                     disabled      
fedora-rpmfusion-nonfree-debuginfo                 RPM Fusion for Fedora 28 - Nonfree - Debug             disabled      
fedora-rpmfusion-nonfree-source                    RPM Fusion for Fedora 28 - Nonfree - Source            disabled      
fedora-rpmfusion-nonfree-updates                   RPM Fusion for Fedora 28 - Nonfree - Updates           disabled      
fedora-rpmfusion-nonfree-updates-debuginfo         RPM Fusion for Fedora 28 - Nonfree - Updates Debug     disabled      
fedora-rpmfusion-nonfree-updates-source            RPM Fusion for Fedora 28 - Nonfree - Updates Source    disabled      
fedora-rpmfusion-nonfree-updates-testing           RPM Fusion for Fedora 28 - Nonfree - Test Updates      disabled      
fedora-rpmfusion-nonfree-updates-testing-debuginfo RPM Fusion for Fedora 28 - Nonfree - Test Updates Debu disabled      
fedora-rpmfusion-nonfree-updates-testing-source    RPM Fusion for Fedora 28 - Nonfree - Test Updates Sour disabled      
fedora-russian-free                                Russian Fedora for Fedora 28 - Free                    disabled      
fedora-russian-free-debuginfo                      Russian Fedora for Fedora 28 - Free - Debug            disabled      
fedora-russian-free-source                         Russian Fedora for Fedora 28 - Free - Source           disabled      
fedora-russian-free-updates                        Russian Fedora for Fedora 28 - Free - Updates          disabled      
fedora-russian-free-updates-debuginfo              Russian Fedora for Fedora 28 - Free - Updates Debug    disabled      
fedora-russian-free-updates-source                 Russian Fedora for Fedora 28 - Free - Updates Source   disabled      
fedora-russian-nonfree                             Russian Fedora for Fedora 28 - Nonfree                 disabled      
fedora-russian-nonfree-debuginfo                   Russian Fedora for Fedora 28 - Nonfree - Debug         disabled      
fedora-russian-nonfree-source                      Russian Fedora for Fedora 28 - Nonfree - Source        disabled      
fedora-russian-nonfree-updates                     Russian Fedora for Fedora 28 - Nonfree - Updates       disabled      
fedora-russian-nonfree-updates-debuginfo           Russian Fedora for Fedora 28 - Nonfree - Updates Debug disabled      
fedora-russian-nonfree-updates-source              Russian Fedora for Fedora 28 - Nonfree - Updates Sourc disabled      
fedora-source                                      Fedora 28 - Source                                     disabled      
fedora-updates                                     Fedora 28 - x86_64 - Updates                           disabled      
fedora-updates-debuginfo                           Fedora 28 - x86_64 - Updates - Debug                   disabled      
fedora-updates-source                              Fedora 28 - Updates Source                             disabled      
getpagespeed-extras                                GetPageSpeed packages for Enterprise Linux 8 - x86_64  enabled:   369
getpagespeed-extras-mainline                       GetPageSpeed packages of mainline NGINX for Enterprise disabled      
getpagespeed-extras-nginx-mod                      GetPageSpeed packages with patched NGINX for Enterpris disabled      
getpagespeed-extras-noarch                         GetPageSpeed packages for Enterprise Linux 8 - noarch  enabled:    52
getpagespeed-extras-varnish60                      GetPageSpeed packages of Varnish 6.0.x for Enterprise  disabled      
remi                                               Remi's RPM repository for Enterprise Linux 8 - x86_64  disabled      
remi-debuginfo                                     Remi's RPM repository for Enterprise Linux 8 - x86_64  disabled      
remi-modular                                       Remi's Modular repository for Enterprise Linux 8 - x86 enabled:    12
remi-modular-test                                  Remi's Modular testing repository for Enterprise Linux disabled      
remi-safe                                          Safe Remi's RPM repository for Enterprise Linux 8 - x8 enabled: 2,014
remi-safe-debuginfo                                Remi's RPM repository for Enterprise Linux 8 - x86_64  disabled      
remi-test                                          Remi's test RPM repository for Enterprise Linux 8 - x8 disabled      
remi-test-debuginfo                                Remi's test RPM repository for Enterprise Linux 8 - x8 disabled      

これだけあれば一先ず困らないのでは?と思います。
ちなみに、fedora28のリポジトリを使用する場合、デフォルトでは全てDisbaleとなっており、これを全てEnableにするのはしんどいので、以下のようにdnfplusコマンドを使用してください。
<サンプル>

dnfplus -y install filezilla

これでも不足するようであれば、頑張ってビルドしましょう!

以上です。

7.最後に

以下のサイトを参考にさせて頂きました。
50k+ packages for CentOS/RHEL 8, even before EPEL is up - GetPageSpeed
https://centos.pkgs.org/

CentOS8は、まだ実用的ではない部分もありますが、少しづつでも使っていかないと勿体ないので慣れていきましょう。

私事ですが、ovsやovn、openstackなどが使えないと死活問題になるため、CentOS8への移行は少し躊躇っています。
ovsはビルドすればOKなのですが、ovs-dpdkの場合、--with-dpdkの後にmakeするとコケたりするので、ちょっと困っています。。

CentOS7 NextEPCによるEPC構築方法

前回記事のスピンオフとして、CentOS7でのNextEPCの構築方法を記載します。

Redhat系の方が使い慣れている人には最適かなと思います。

1.環境

1-1.VMWare
筐体                             : 自作PC(Win10pro)
CPU                           : Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
VMWare              : VMware(R) Workstation 15 Pro 15.1.0 build-13591040  
OS                               : CentOS Linux release 7.7.1908 (Core)
Kernel                           : 3.10.0-1062.el7.x86_64
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools, development
1-2.全体構成

f:id:metonymical:20191022195027p:plain
緑色の箇所がUbuntu16.04からCentOS7.7に変わっています。
それ以外は全て同じです。

1-3 .全体の流れ ~概要~
  1. 事前準備
  2. NextEPC設定
  3. OAISIM設定(省略)*1
  4. NextEPCの分離

2.事前準備

2-1.c77g132:NextEPCのNW設定
nmcli con add type tun mode tun autoconnect yes ifname pgwtun con-name pgwtun
nmcli con mod pgwtun ipv4.method manual ipv4.addresses 25.0.0.1/8
nmcli con mod pgwtun ipv6.method manual ipv6.addresses cafe::1/64
nmcli con up pgwtun

nmcli con add type ethernet autoconnect yes ifname ens33 con-name ens33
nmcli con mod ens33 ipv4.method manual ipv4.addresses 10.10.0.135/24
nmcli con up ens33

nmcli con add type ethernet autoconnect yes ifname ens35 con-name ens35
nmcli con mod ens35 ipv4.method manual ipv4.addresses 10.20.0.132/24
nmcli con mod ens35 ipv4.method manual +ipv4.addresses 10.20.0.133/24
nmcli con mod ens35 ipv4.method manual +ipv4.addresses 10.20.0.134/24
nmcli con mod ens35 ipv4.method manual +ipv4.addresses 10.20.0.135/24
nmcli con mod ens35 ipv4.method manual +ipv4.addresses 10.20.0.136/24
nmcli con up ens35

3.NextEPC設定

分離するまでは、c77g132のみで設定を行っていきます。

3-1.MongoDBのインストール
sudo sh -c 'cat << EOF > /etc/yum.repos.d/mongodb-org-3.4.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
EOF'

yum -y install mongodb-org && \
systemctl start mongod && \
systemctl enable mongod
3-2.mongo-c-driver-develのインストール
yum -y install epel-release && \
yum -y install mongo-c-driver-devel

<補足>
NextEPCの公式サイトを読むと、外部サイトを参照することになります。
そこでは、

yum install mongo-c-driver

と記載されていますが、これをそのまま真に受けると、makeファイル作成時にエラーを吐いて止まります。
NextEPCのビルドで必要とされるのは、mongo-c-driver-develの方です。*2

3-3.依存関係パッケージのインストール
yum -y install git flex bison autoconf libtool \
lksctp-tools-devel libidn-devel gnutls-devel libgcrypt-devel \
openssl-devel cyrus-sasl-devel libyaml-devel
3-4.ビルド
git clone https://github.com/nextepc/nextepc && \
cd nextepc && \
autoreconf -iv

./configure --prefix=`pwd`/install && \
make -j `nproc` && \
make install
3-5.WebUIのインストール
curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash - && \
yum -y install nodejs

cd /root/nextepc/webui && \
npm install

#サービス起動
npm run dev

#2回目以降、起動する際はwebuiのディレクトリに入った状態で実行してください。
cd /root/nextepc/webui && \
npm run dev

#アクセス先URL
http://192.168.11.132:3000/

インストール完了後、以下のページが表示されればOKです。
Username/Passwdは以下の通り。
admin/1423
f:id:metonymical:20191020140814p:plain

3-6.SIM情報の登録

上記のアクセス先URLから以下のSIM情報を登録します。

IMSI 001010100001111
Subscriber Key(Ki) 8baf473f2f8fd09487cccbd7097c6862
Operator Key(OPc) e734f8734007d6c5ce7a0508809e7e9c
USIM Type OPc
APN lte.md.jp
MSISDN 33611123456
IMSI 001010100001112
Subscriber Key(Ki) 8baf473f2f8fd09487cccbd7097c6862
Operator Key(OPc) e734f8734007d6c5ce7a0508809e7e9c
USIM Type OPc
APN lte.md.jp
MSISDN 33611123457

f:id:metonymical:20191021014216p:plain
IMSI, Subscriber Key(Ki), Operator Key(OPc), USIM Typeが必須項目となります。
APNは任意で構いません。

3-7.nextepc.conf設定

設定変更箇所のみ抜粋。*3

vi /root/nextepc/install/etc/nextepc/nextepc.conf

追記:青 コメントアウト&追記:緑

db_uri: mongodb://localhost/nextepc

logger:
    file: /root/nextepc/install/var/log/nextepc/nextepc.log
    trace:
        app: 1
        s1ap: 1
        nas: 1
        diameter: 1
        gtpv2: 1
        gtp: 1

parameter:
    no_ipv6: true

mme:
    freeDiameter: mme.conf

    s1ap:
      - addr: 10.20.0.132

    gtpc:
      - addr: 10.20.0.132

    gummei:
      plmn_id:
        mcc: 001
        mnc: 01
      mme_gid: 2
      mme_code: 1

    tai:
      plmn_id:
        mcc: 001
        mnc: 01
#      tac: 12345
      tac: 1

    security:
        integrity_order : [ EIA1, EIA2, EIA0 ]
        ciphering_order : [ EEA0, EEA1, EEA2 ]

    network_name:
        full: NextEPC

hss:
    freeDiameter: hss.conf

sgw:
    gtpc:
#      addr: 127.0.0.2
      addr: 10.20.0.134

    gtpu:
      - addr: 10.20.0.134

pgw:
    freeDiameter: pgw.conf

    gtpc:
      addr:
#        - 127.0.0.3
        - 10.20.0.135
        - ::1

    gtpu:
#      - addr: 127.0.0.3
      - addr: 10.20.0.135
      - addr: ::1

    ue_pool:
#      - addr: 45.45.0.1/16
      - addr: 25.0.0.1/8
      - addr: cafe::1/64

    dns:
      - 8.8.8.8
      - 8.8.4.4
      - 2001:4860:4860::8888
      - 2001:4860:4860::8844

pcrf:
    freeDiameter: pcrf.conf

3-8.mme.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/mme.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.2";
ListenOn = "10.20.0.132";

#ConnectPeer = "hss.localdomain" { ConnectTo = "127.0.0.4"; No_TLS; };
ConnectPeer = "hss.localdomain" { ConnectTo = "10.20.0.133"; No_TLS; };

#もしくは
sed -i -e /^ListenOn/s/127.0.0.2/10.20.0.132/g \
/root/nextepc/install/etc/nextepc/freeDiameter/mme.conf
sed -i -e /^ConnectPeer/s/127.0.0.4/10.20.0.133/g \
/root/nextepc/install/etc/nextepc/freeDiameter/mme.conf
3-9.hss.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/hss.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.4";
ListenOn = "10.20.0.133";

#ConnectPeer = "mme.localdomain" { ConnectTo = "127.0.0.2"; No_TLS; };
ConnectPeer = "mme.localdomain" { ConnectTo = "10.20.0.132"; No_TLS; };

#もしくは
sed -i -e /^ListenOn/s/127.0.0.4/10.20.0.133/g \
/root/nextepc/install/etc/nextepc/freeDiameter/hss.conf
sed -i -e /^ConnectPeer/s/127.0.0.2/10.20.0.132/g \
/root/nextepc/install/etc/nextepc/freeDiameter/hss.conf
3-10.pgw.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/pgw.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.3";
ListenOn = "10.20.0.135";

#ConnectPeer = "pcrf.localdomain" { ConnectTo = "127.0.0.5"; No_TLS; };
ConnectPeer = "pcrf.localdomain" { ConnectTo = "10.20.0.136"; No_TLS; };

#もしくは
sed -i -e /^ListenOn/s/127.0.0.3/10.20.0.135/g \
/root/nextepc/install/etc/nextepc/freeDiameter/pgw.conf
sed -i -e /^ConnectPeer/s/127.0.0.5/10.20.0.136/g \
/root/nextepc/install/etc/nextepc/freeDiameter/pgw.conf
3-11.pcrf.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/pcrf.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.5";
ListenOn = "10.20.0.136";

#ConnectPeer = "pgw.localdomain" { ConnectTo = "127.0.0.3"; No_TLS; };
ConnectPeer = "pgw.localdomain" { ConnectTo = "10.20.0.135"; No_TLS; };

#もしくは
sed -i -e /^ListenOn/s/127.0.0.5/10.20.0.136/g \
/root/nextepc/install/etc/nextepc/freeDiameter/pcrf.conf
sed -i -e /^ConnectPeer/s/127.0.0.3/10.20.0.135/g \
/root/nextepc/install/etc/nextepc/freeDiameter/pcrf.conf
3-12.ip forwarding設定

最終行に追記

vi /etc/sysctl.d/99-sysctl.conf

net.ipv4.ip_forward=1

即時反映させる場合は以下のコマンド。

sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
3-13.NextEPC起動

「-d」オプションはDaemonとして起動させます。

/root/nextepc/install/bin/nextepc-epcd -d

出力例
以下のようにDaemonが起動していればOKです。

root@c77g132:~# /root/nextepc/install/bin/nextepc-epcd -d
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44

[10/20 23:18:44.126] WARN: pid file /root/nextepc/install/var/run/nextepc-epcd/pid overwritten -- Unclean shutdown of previous NextEPC run? (application.c:133)
  PID[2136] : '/root/nextepc/install/var/run/nextepc-epcd/pid'
root@c77g132:~#   File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/20 23:18:44.129] PCRF try to initialize
[10/20 23:18:44.148] PCRF initialize...done
[10/20 23:18:44.148] PGW try to initialize
[10/20 23:18:44.207] PGW initialize...done
[10/20 23:18:44.207] gtp_server() [10.20.0.135]:2123
[10/20 23:18:44.208] gtp_server() [10.20.0.135]:2152
[10/20 23:18:44.208] SGW try to initialize
[10/20 23:18:44.209] INFO: CONNECTED TO 'pgw.localdomain' (TCP,soc#7): (fd_logger.c:93)
[10/20 23:18:44.210] INFO: CONNECTED TO 'pcrf.localdomain' (TCP,soc#10): (fd_logger.c:93)
[10/20 23:18:44.217] SGW initialize...done
[10/20 23:18:44.218] gtp_server() [10.20.0.134]:2123
[10/20 23:18:44.218] gtp_server() [10.20.0.134]:2152
[10/20 23:18:44.218] HSS try to initialize
[10/20 23:18:44.268] HSS initialize...done
[10/20 23:18:44.268] MME try to initialize
[10/20 23:18:44.380] gtp_server() [10.20.0.132]:2123
[10/20 23:18:44.380] gtp_client() [10.20.0.134]:2123
[10/20 23:18:44.380] MME initialize...done


[10/20 23:18:44.380] INFO: NextEPC daemon start (main.c:177)
[10/20 23:18:44.381] INFO: CONNECTED TO 'mme.localdomain' (TCP,soc#7): (fd_logger.c:93)
[10/20 23:18:44.381] INFO: CONNECTED TO 'hss.localdomain' (TCP,soc#10): (fd_logger.c:93)
[10/20 23:18:44.387] s1ap_server() [10.20.0.132]:36412

終了させるときは、kill -9などで停止させてください。

分離させた後は以下のコマンドで個別に起動させますが、後ほど詳しく紹介します。

#c77g132:MME,HSS,SGW
/root/nextepc/install/bin/nextepc-sgwd -d
/root/nextepc/install/bin/nextepc-hssd -d
/root/nextepc/install/bin/nextepc-mmed -d

#c77g135:PGW,PCRF
/root/nextepc/install/bin/nextepc-pcrfd -d
/root/nextepc/install/bin/nextepc-pgwd -d

4.OAISIM設定

省略します。
前回記事を参照してください。

5.NextEPCの分離

5-1.クローン作成&c77g135の起動

c77g132をシャットダウン後、c77g132のクローンをc77g135として作成してください。
c77g135を起動後、ネットワーク設定やホスト名を以下のように変更します。

#c77g135の設定
nmcli con del ens35
nmcli con add type ethernet autoconnect yes ifname ens35 con-name ens35
nmcli con mod ens35 ipv4.method manual ipv4.addresses 10.20.0.135/24
nmcli con mod ens35 ipv4.method manual +ipv4.addresses 10.20.0.136/24
nmcli con up ens35

#ホスト名の変更 
vi /etc/hostname

c77g135

#再起動
reboot 
5-2.c77g132のネットワーク設定変更

c77g132を起動してください。そして、以下の通りネットワーク設定を変更してください。

#c77g132の設定
nmcli con mod ens35 ipv4.method manual -ipv4.addresses 10.20.0.135/24
nmcli con mod ens35 ipv4.method manual -ipv4.addresses 10.20.0.136/24
nmcli con up ens35

nmcli con del ens33
nmcli con del pgwtun

#再起動
reboot 
5-3.各種サービス起動

S5/S8でSPGW間を分離していますので、

/root/nextepc/install/bin/nextepc-epcd -d

は使用せず、それぞれ個別にサービスを起動します。

c77g132 MME, HSS, SGW
c77g135 PGW, PCRF
#c77g132のサービス起動:MME, HSS, SGW
/root/nextepc/install/bin/nextepc-sgwd -d
/root/nextepc/install/bin/nextepc-hssd -d
/root/nextepc/install/bin/nextepc-mmed -d

#c77g135のサービス起動:PGW, PCRF
/root/nextepc/install/bin/nextepc-pcrfd -d
/root/nextepc/install/bin/nextepc-pgwd -d

これ以降は前回記事を参照してください。

以上です。

6.最後に

以下のサイトを参考にさせて頂きました。
NextEPC | Installation | CentOS
Installing the MongoDB C Driver (libmongoc) and BSON library (libbson) — MongoDB C Driver 1.15.1

<少し余談な話>
2-1.c77g132:NextEPCのNW設定の項で、UE用インターフェースとしてpgwtunに25.0.0.0/8を設定しましたが、検証用途としてたまに利用させてもらっています。

というのも、
元々25.0.0.0/8のprefixは、英国国防省の機関であるDINSA(Defence Interoperable Network Services Authority)が所有しているそうです。
しかし、既に10年以上(15年くらいだったかも?)、インターネット上にアドバタイズされていないPrefixとなっています。
下記のようなLooking glassサイトで確認しても、フルルート上に載っていないことがわかります。
Looking Glass - NTT - www.gin.ntt.net

この情報ソースは、下記サイトのvirtual-privateの項にNoteとして記載されています。*4
libreswan

そこには、25.0.0.0/8のprefixがあまりにも長期間アドバタイズされていないため、米国のT-MobileやカナダのRogers/Fidoという通信事業者が、CGNATの前で(恐らくUE用として)使用し始めているようだ、と記載されています。

上記のように商用で使うのは、さすがに怖くてできませんが、内部的に閉じられた環境における検証用途*5であれば、Shared Address*6と同様に使ってもよいのかな?と個人的には思います。*7

*1:OAISIMについては、前回記事を参照してください。

*2:よくよく考えれば当たり前なことですし、カーネルのビルドなどをやったことある人であればdevelが必要だと気付けると思うのですが、初めてやる人にとっては、かなり敷居が高いのではないかと個人的には思います。

*3:YAML形式なのでケタ合わせは慎重に。

*4:サイトにアクセス後、25.0で検索すれば見つかります。

*5:一時的に作ってすぐ壊すような環境

*6:100.64.0.0/10として、RFC6598に記載されています。

*7:少なくてもデフォルトで設定されている45.45.0.0/16をそのまま使うのは気が引けたので。

OAISIM + NextEPCによるE-UTRAN + EPC構築方法

3GPPのお勉強や簡易検証を目的として使えそうなE-UTRAN & EPC構築方法を記載します。
UEとeNBはOAISIMにて構築し、残り*1はNextEPCで構築します。
また、MVNOライクにSGWとPGW間(S5/S8)を分離させます。

というのも、

  • SPGW間にLBを入れてPGWのメンテ検証や移行設計したり
  • QCIによる帯域制御検証したり

と色々遊べそうなので。

1.環境

1-1.VMWare
筐体                             : 自作PC(Win10pro)
CPU                           : Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
VMWare              : VMware(R) Workstation 15 Pro 15.1.0 build-13591040  
OS                               : Ubuntu 16.04.6 LTS
Kernel                           : 4.4.0-142-generic
1-2.全体構成

f:id:metonymical:20191021014131p:plain

1-3 .全体の流れ ~概要~
  1. 事前準備
  2. NextEPC設定
  3. OAISIM設定
  4. NextEPCの分離*2

2.事前準備

2-1.u16c132:NextEPCのNW設定

NextEPCは後ほど分離しますが、まずはまとめて設定だけしておきます。*3
そして、ワンコール確認まで完了した後、分離します。

vi /etc/network/interfaces

auto ens33
iface ens33 inet static
    address 192.168.11.132
    netmask 255.255.255.0
    gateway 192.168.11.1
    dns-nameserver 192.168.11.1

auto ens34
iface ens34 inet static
    address 10.10.0.135
    netmask 255.255.255.0

auto ens35
iface ens35 inet static
    address 10.20.0.132
    netmask 255.255.255.0

auto ens35:3
iface ens35:3 inet static
    address 10.20.0.133
    netmask 255.255.255.0

auto ens35:4
iface ens35:4 inet static
    address 10.20.0.134
    netmask 255.255.255.0

auto ens35:5
iface ens35:5 inet static
    address 10.20.0.135
    netmask 255.255.255.0

auto ens35:6
iface ens35:6 inet static
    address 10.20.0.136
    netmask 255.255.255.0
2-2.u16c131:OAISIMのNW設定
vi /etc/network/interfaces

auto ens33
iface ens33 inet static
    address 192.168.11.131
    netmask 255.255.255.0
    gateway 192.168.11.1
    dns-nameserver 192.168.11.1

auto ens35
iface ens35 inet static
    address 10.20.0.131
    netmask 255.255.255.0

3.NextEPC設定

分離するまでは、u16c132のみで設定を行っていきます。

3-1.MongoDBのインストール
apt-get -y update && \
apt-get -y install mongodb && \
systemctl enable mongodb && \
systemctl start mongodb

systemctl status mongodb
3-2.pgwtunの設定

PGWのGTP終端インターフェースを作成します。

sh -c "cat << EOF > /etc/systemd/network/99-nextepc.netdev
[NetDev]
Name=pgwtun
Kind=tun
EOF"

sh -c "cat << EOF > /etc/systemd/network/99-nextepc.network
[Match]
Name=pgwtun
[Network]
Address=25.0.0.1/8
Address=cafe::1/64
EOF"

systemctl enable systemd-networkd && \
systemctl restart systemd-networkd
3-3.依存関係パッケージのインストール
apt-get -y install autoconf libtool gcc pkg-config git flex bison libsctp-dev \
libgnutls28-dev libgcrypt-dev libssl-dev libidn11-dev libmongoc-dev libbson-dev libyaml-dev
3-4.ビルド
git clone https://github.com/nextepc/nextepc && \
cd /root/nextepc && \
autoreconf -iv

./configure --prefix=`pwd`/install && \
make -j `nproc` && \
make install
3-5.WebUIのインストール
apt-get -y install curl && \
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - && \
apt-get -y install nodejs

cd /root/nextepc/webui/ && \
npm install

#サービス起動
npm run dev

#アクセス先URL
http://192.168.11.132:3000/

インストール完了後、以下のページが表示されればOKです。
Username/Passwdは以下の通り。
admin/1423
f:id:metonymical:20191020140814p:plain

3-6.SIM情報の登録

上記のアクセス先URLから以下のSIM情報を登録します。

IMSI 001010100001111
Subscriber Key(Ki) 8baf473f2f8fd09487cccbd7097c6862
Operator Key(OPc) e734f8734007d6c5ce7a0508809e7e9c
USIM Type OPc
APN lte.md.jp
MSISDN 33611123456
IMSI 001010100001112
Subscriber Key(Ki) 8baf473f2f8fd09487cccbd7097c6862
Operator Key(OPc) e734f8734007d6c5ce7a0508809e7e9c
USIM Type OPc
APN lte.md.jp
MSISDN 33611123457

f:id:metonymical:20191021014216p:plain
IMSI, Subscriber Key(Ki), Operator Key(OPc), USIM Typeが必須項目となります。
APNは任意で構いません。
MSISDNは、ここでは設定不要ですが、OAISIMのビルド前に必要となりますので、念のため記載しています。

3-7.nextepc.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/nextepc.conf

追記:青 コメントアウト&追記:緑

db_uri: mongodb://localhost/nextepc

logger:
    file: /root/nextepc/install/var/log/nextepc/nextepc.log
    trace:
        app: 1
        s1ap: 1
        nas: 1
        diameter: 1
        gtpv2: 1
        gtp: 1

parameter:
    no_ipv6: true

mme:
    freeDiameter: mme.conf

    s1ap:
      - addr: 10.20.0.132

    gtpc:
      - addr: 10.20.0.132

    gummei:
      plmn_id:
        mcc: 001
        mnc: 01
      mme_gid: 2
      mme_code: 1

    tai:
      plmn_id:
        mcc: 001
        mnc: 01
#      tac: 12345
      tac: 1

    security:
        integrity_order : [ EIA1, EIA2, EIA0 ]
        ciphering_order : [ EEA0, EEA1, EEA2 ]

    network_name:
        full: NextEPC

hss:
    freeDiameter: hss.conf

sgw:
    gtpc:
#      addr: 127.0.0.2
      addr: 10.20.0.134

    gtpu:
      - addr: 10.20.0.134

pgw:
    freeDiameter: pgw.conf

    gtpc:
      addr:
#        - 127.0.0.3
        - 10.20.0.135
        - ::1

    gtpu:
#      - addr: 127.0.0.3
      - addr: 10.20.0.135
      - addr: ::1

    ue_pool:
#      - addr: 45.45.0.1/16
      - addr: 25.0.0.1/8
      - addr: cafe::1/64

    dns:
      - 8.8.8.8
      - 8.8.4.4
      - 2001:4860:4860::8888
      - 2001:4860:4860::8844

pcrf:
    freeDiameter: pcrf.conf

3-8.mme.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/mme.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.2";
ListenOn = "10.20.0.132";

#ConnectPeer = "hss.localdomain" { ConnectTo = "127.0.0.4"; No_TLS; };
ConnectPeer = "hss.localdomain" { ConnectTo = "10.20.0.133"; No_TLS; };
3-9.hss.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/hss.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.4";
ListenOn = "10.20.0.133";

#ConnectPeer = "mme.localdomain" { ConnectTo = "127.0.0.2"; No_TLS; };
ConnectPeer = "mme.localdomain" { ConnectTo = "10.20.0.132"; No_TLS; };
3-10.pgw.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/pgw.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.3";
ListenOn = "10.20.0.135";

#ConnectPeer = "pcrf.localdomain" { ConnectTo = "127.0.0.5"; No_TLS; };
ConnectPeer = "pcrf.localdomain" { ConnectTo = "10.20.0.136"; No_TLS; };
3-11.pcrf.conf設定

設定変更箇所のみ抜粋。

vi /root/nextepc/install/etc/nextepc/freeDiameter/pcrf.conf

追記:青 コメントアウト&追記:緑

#ListenOn = "127.0.0.5";
ListenOn = "10.20.0.136";

#ConnectPeer = "pgw.localdomain" { ConnectTo = "127.0.0.3"; No_TLS; };
ConnectPeer = "pgw.localdomain" { ConnectTo = "10.20.0.135"; No_TLS; };
3-12.ip forwarding設定

設定変更箇所のみ抜粋。

vi /etc/sysctl.conf

追記:青 コメントアウト&追記:緑

#net.ipv4.ip_forward=0
net.ipv4.ip_forward=1

即時反映させる場合は以下のコマンド。

sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
3-13.NextEPC起動

「-d」オプションはDaemonとして起動させます。

/root/nextepc/install/bin/nextepc-epcd -d

出力例
以下のようにDaemonが起動していればOKです。

root@u16c132:~# /root/nextepc/install/bin/nextepc-epcd -d
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44

[10/20 23:18:44.126] WARN: pid file /root/nextepc/install/var/run/nextepc-epcd/pid overwritten -- Unclean shutdown of previous NextEPC run? (application.c:133)
  PID[2136] : '/root/nextepc/install/var/run/nextepc-epcd/pid'
root@u16c132:~#   File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/20 23:18:44.129] PCRF try to initialize
[10/20 23:18:44.148] PCRF initialize...done
[10/20 23:18:44.148] PGW try to initialize
[10/20 23:18:44.207] PGW initialize...done
[10/20 23:18:44.207] gtp_server() [10.20.0.135]:2123
[10/20 23:18:44.208] gtp_server() [10.20.0.135]:2152
[10/20 23:18:44.208] SGW try to initialize
[10/20 23:18:44.209] INFO: CONNECTED TO 'pgw.localdomain' (TCP,soc#7): (fd_logger.c:93)
[10/20 23:18:44.210] INFO: CONNECTED TO 'pcrf.localdomain' (TCP,soc#10): (fd_logger.c:93)
[10/20 23:18:44.217] SGW initialize...done
[10/20 23:18:44.218] gtp_server() [10.20.0.134]:2123
[10/20 23:18:44.218] gtp_server() [10.20.0.134]:2152
[10/20 23:18:44.218] HSS try to initialize
[10/20 23:18:44.268] HSS initialize...done
[10/20 23:18:44.268] MME try to initialize
[10/20 23:18:44.380] gtp_server() [10.20.0.132]:2123
[10/20 23:18:44.380] gtp_client() [10.20.0.134]:2123
[10/20 23:18:44.380] MME initialize...done


[10/20 23:18:44.380] INFO: NextEPC daemon start (main.c:177)
[10/20 23:18:44.381] INFO: CONNECTED TO 'mme.localdomain' (TCP,soc#7): (fd_logger.c:93)
[10/20 23:18:44.381] INFO: CONNECTED TO 'hss.localdomain' (TCP,soc#10): (fd_logger.c:93)
[10/20 23:18:44.387] s1ap_server() [10.20.0.132]:36412

終了させるときは、kill -9などで停止させてください。


分離させた後は以下のコマンドで個別に起動させますが、後ほど詳しく紹介します。

#u16c132:MME,HSS,SGW
/root/nextepc/install/bin/nextepc-sgwd -d
/root/nextepc/install/bin/nextepc-hssd -d
/root/nextepc/install/bin/nextepc-mmed -d

#u16c135:PGW,PCRF
/root/nextepc/install/bin/nextepc-pcrfd -d
/root/nextepc/install/bin/nextepc-pgwd -d

4.OAISIM設定

4-1.git リポジトリの取得
apt-get install git && \
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git && \
cd /root/openairinterface5g && \
git reset --hard 67df8e0e7b46200b2ee43a2705def3340ddfd719
4-2.SIM情報の設定

変更箇所のみ抜粋。UEを2台アタッチさせられるように1台追加しています。

vi /root/openairinterface5g/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf

#画面下の方にスクロール

追記:青 コメントアウト&追記:緑

UE0:
{
    USER: {
        IMEI="356113022094149";
        MANUFACTURER="EURECOM";
        MODEL="LTE Android PC";
        PIN="0000";
    };

    SIM: {
        MSIN="0100001111";
        USIM_API_K="8baf473f2f8fd09487cccbd7097c6862";
        OPC="e734f8734007d6c5ce7a0508809e7e9c";
        MSISDN="33611123456";
    };

    # Home PLMN Selector with Access Technology
#    HPLMN= "20893";
    HPLMN= "00101";

    # User controlled PLMN Selector with Access Technology
    UCPLMN_LIST = ();

    # Operator PLMN List
    OPLMN_LIST = ("00101", "20810", "20811", "20813", "20893", "310280", "310028");

    # Operator controlled PLMN Selector with Access Technology
    OCPLMN_LIST = ("22210", "21401", "21406", "26202", "26204");

    # Forbidden plmns
    FPLMN_LIST = ();

    # List of Equivalent HPLMNs
#TODO: UE does not connect if set, to be fixed in the UE
#    EHPLMN_LIST= ("20811", "20813");
    EHPLMN_LIST= ();
};

UE1:
{
    USER: {
        IMEI="356113022094150";
        MANUFACTURER="EURECOM";
        MODEL="LTE Android PC";
        PIN="0000";
    };

    SIM: {
        MSIN="0100001112";
        USIM_API_K="8baf473f2f8fd09487cccbd7097c6862";
        OPC="e734f8734007d6c5ce7a0508809e7e9c";
        MSISDN="33611123457";
    };

    # Home PLMN Selector with Access Technology
    HPLMN= "00101";

    # User controlled PLMN Selector with Access Technology
    UCPLMN_LIST = ();

    # Operator PLMN List
    OPLMN_LIST = ("00101", "20810", "20811", "20813", "20893", "310280", "310028");

    # Operator controlled PLMN Selector with Access Technology
    OCPLMN_LIST = ("22210", "21401", "21406", "26202", "26204");

    # Forbidden plmns
    FPLMN_LIST = ();

    # List of Equivalent HPLMNs
#TODO: UE does not connect if set, to be fixed in the UE
#    EHPLMN_LIST= ("20811", "20813");
    EHPLMN_LIST= ();
};
4-3.ビルド
cd /root/openairinterface5g/cmake_targets && \
./build_oai -I --oaisim --install-system-files

ビルドの最後の方で、以下のように文字化けしますが、ビルドは正常に完了している(ハズなので)ので、exitで抜けて、再度ログインし直してください。

出力例
文字化けしますが、前項で修正したue_eurecom_test_sfr.confの変更点が反映されていることが確認できます。
赤文字箇所

Log file for compilation has been written to: /root/openairinterface5g/cmake_targets/log/usim.Rel14.txt
usim compiled
Log file for compilation has been written to: /root/openairinterface5g/cmake_targets/log/nvram.Rel14.txt
nvram compiled
Log file for compilation has been written to: /root/openairinterface5g/cmake_targets/log/conf2uedata.Rel14.txt
conf2uedata compiled
generate .ue_emm.nvram .ue.nvram

UE's non-volatile data:

IMEI            = 356113022094149
manufacturer    = EURECOM
model           = LTE Android PC
PIN             = 0000
UE identity data file: /root/openairinterface5g/targets/bin/.ue.nvram0

EMM non-volatile data:

IMSI            = 001.010.100001111
RPLMN           = 00101
EPS Mobility Management data file: /root/openairinterface5g/targets/bin/.ue_emm.nvram0

UE's non-volatile data:

IMEI            = 356113022094150
manufacturer    = EURECOM
model           = LTE Android PC
PIN             = 0000
UE identity data file: /root/openairinterface5g/targets/bin/.ue.nvram1

EMM non-volatile data:

IMSI            = 001.010.100001112
RPLMN           = 00101
EPS Mobility Management data file: /root/openairinterface5g/targets/bin/.ue_emm.nvram1
generate .usim.nvram

USIM data:

Administrative Data:
        UE_Operation_Mode       = 0x00
        Additional_Info         = 0xffff
        MNC_Length              = 2

IMSI:
        length  = 8
        parity  = Odd
        digits  = 15
        digits  = 001010100001111

Ciphering and Integrity Keys:
        KSI     : 0x07
        CK      : ""
        IK      : ""

        usim_api_k: 8b af 47 3f 2f 8f d0 94 87 cc cb d7 09 7c 68 62
        opc       : e7 34 f8 73 40 07 d6 c5 ce 7a 05 08 80 9e 7e 9c

EPS NAS security context:
        KSIasme : 0x07
        Kasme   : ""
        ulNAScount      : 0x00000000
        dlNAScount      : 0x00000000
        algorithmID     : 0x02

MSISDN  = 336 1112 3456

PNN[0]  = {Test network, OAI4G}
PNN[1]  = {SFR France, SFR}
PNN[2]  = {SFR France, SFR}
PNN[3]  = {SFR France, SFR}
PNN[4]  = {OAI LTEBOX, OAIALU}
PNN[5]  = {T-Mobile USA, T-MobileCニノテヤノヤノマユモ ユモチ
ミホホロカン  ス 鈼ノテヤノヤノマユモ ユモチャ ニノテヤノヤノマ
ミホホロキン  ス 譿 

マミフローン  ス ーーアーアャ ヤチテ ス ローーーア ュ 跏趾ンャ 胥゚鱠 ス ー
マミフロアン  ス イークアーャ ヤチテ ス ローーーア ュ 跏趾ンャ 胥゚鱠 ス ア

~~~ 中略 ~~~

ホチモテマホニノヌコ
        ホチモ゚モ鱸髜・鴃醪・鴟・         コ ーー
        ホヘマ゚ノ゚ツ裴磋鴆                 コ ーー
        チ矼鞅鴟靄炫・                 コ ーア
        ヘ鴃鳫ミ褪鴆蓚耨裔靫鳫褪      コ ーー
        ナ褓蒟菽聽褫碪鰀           コ ーー
        ヤ鳫褪゚ヤウイエオ゚ツ裴磋鴆           コ ーー
ユモノヘ 蓊 跌・コ ッ・ッ・褓硅ⅵ褪趁肄オ遽襁粳鉧ョ鳫ョⅷ敎
フ・ 跌・ 跣・胥瀇鴈磑鴆・鞦・粢褓 鴟・コ ッ・ッ・褓硅ⅵ褪趁肄オ遽肬硴裃襁・遽・鱇襁鞜碚ョメ褌アエョ・
・鱇襁鞜碚 胥瀇鴈裝
・糀硅゚碚ョ 鴣 ・鸙裝  ナヤネナメホナヤ ・糘碪・
アーョ ツ碯鰀 ・ヤ褫 ョョョ
・タカ羈ウアコッ・褓硅ⅵ褪趁肄オ遽肬硴裃襁

<補足1>
ビルド実行時、バイナリ化されたnvramファイル*4にSIM情報が書き込まれ、以下のパスに保存されます。*5

/openairinterface5g/targets/bin

SIM情報を追加・変更・削除したい場合は、以下のファイルを再度編集の上、

vi /root/openairinterface5g/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf

以下のコマンドで再ビルドしてください。

./build_oai -c --oaisim

<補足2>
以前*6は、以下のコマンドにてSIM情報の書き換えが可能でした。

cd ~/openairinterface5g/targets/bin/
./conf2uedata -c /root/openairinterface5g/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o ./

しかし、今回利用したリポジトリ

git reset --hard 67df8e0e7b46200b2ee43a2705def3340ddfd719

では、
conf2uedataコマンドを実行しても変更したSIM情報がnvramファイルに反映されなかったので、再ビルドしたところ正常に反映されました。

4-4.S1インターフェース周りの設定
vi /root/openairinterface5g/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_mme.conf

修正箇所

    mobile_country_code =  "001";

    mobile_network_code =  "01";

#画面下の方までスクロール

    ////////// MME parameters:
    mme_ip_address      = ( { ipv4       = "10.20.0.132";
                              ipv6       = "192:168:30::17";
                              active     = "yes";
                              preference = "ipv4";
                            }
                          );

    NETWORK_INTERFACES :
    {
        ENB_INTERFACE_NAME_FOR_S1_MME            = "ens35";
        ENB_IPV4_ADDRESS_FOR_S1_MME              = "10.20.0.131/24";

        ENB_INTERFACE_NAME_FOR_S1U               = "ens35";
        ENB_IPV4_ADDRESS_FOR_S1U                 = "10.20.0.131/24";
        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
    };
4-5.UEの起動台数変更
vi /root/openairinterface5g/cmake_targets/tools/run_enb_ue_virt_s1

修正箇所

#vi上で、「AAWG」で検索してください。

#  exe_arguments="$exe_arguments -s15 -AAWGN -y1 -b1 -u1 -Q0"
  exe_arguments="$exe_arguments -s15 -AAWGN -y1 -b1 -u2 -Q0"
4-6.eNB起動

以下のコマンドでeNBを起動させます。

/root/openairinterface5g/cmake_targets/tools/run_enb_ue_virt_s1

もし、u16c132:NextEPC側でEPC関連サービスを起動していない場合は、先に以下のコマンドを実行してから、上記のeNB起動を行ってください。

/root/nextepc/install/bin/nextepc-epcd -d

出力例1
u16c132:EPC側の出力例

root@u16c132:~# /root/nextepc/install/bin/nextepc-epcd -d
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44

[10/21 00:16:27.288] WARN: pid file /root/nextepc/install/var/run/nextepc-epcd/pid overwritten -- Unclean shutdown of previous NextEPC run? (application.c:133)
root@u16c132:~#   PID[2495] : '/root/nextepc/install/var/run/nextepc-epcd/pid'
  File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/21 00:16:27.290] PCRF try to initialize
[10/21 00:16:27.344] PCRF initialize...done
[10/21 00:16:27.346] PGW try to initialize
[10/21 00:16:27.418] PGW initialize...done
[10/21 00:16:27.418] gtp_server() [10.20.0.135]:2123
[10/21 00:16:27.418] gtp_server() [10.20.0.135]:2152
[10/21 00:16:27.420] SGW try to initialize
[10/21 00:16:27.420] INFO: CONNECTED TO 'pgw.localdomain' (TCP,soc#7): (fd_logger.c:93)
[10/21 00:16:27.421] INFO: CONNECTED TO 'pcrf.localdomain' (TCP,soc#13): (fd_logger.c:93)
[10/21 00:16:27.426] SGW initialize...done
[10/21 00:16:27.427] gtp_server() [10.20.0.134]:2123
[10/21 00:16:27.427] gtp_server() [10.20.0.134]:2152
[10/21 00:16:27.427] HSS try to initialize
[10/21 00:16:27.462] HSS initialize...done
[10/21 00:16:27.462] MME try to initialize
[10/21 00:16:27.583] MME initialize...done


[10/21 00:16:27.584] INFO: NextEPC daemon start (main.c:177)
[10/21 00:16:27.584] INFO: CONNECTED TO 'mme.localdomain' (TCP,soc#7): (fd_logger.c:93)
[10/21 00:16:27.584] INFO: CONNECTED TO 'hss.localdomain' (TCP,soc#10): (fd_logger.c:93)
[10/21 00:16:27.584] gtp_server() [10.20.0.132]:2123
[10/21 00:16:27.584] gtp_client() [10.20.0.134]:2123
[10/21 00:16:27.584] s1ap_server() [10.20.0.132]:36412

#NextEPC起動時はここまで出力されます。
eNBが起動しS1の通信が開始&アタッチ処理が正常に完了すると、さらに以下のログが出力されます。
UEにアドレスがアサインされていることが確認できます。

[10/21 00:18:07.933] eNB-S1 accepted[10.20.0.131]:36412 in s1_path module
[10/21 00:18:07.934] eNB-S1 accepted[10.20.0.131] in master_sm module
[10/21 00:18:13.416] gtp_client() [10.20.0.132]:2123
[10/21 00:18:13.416] gtp_client() [10.20.0.135]:2123
[10/21 00:18:13.416] gtp_client() [10.20.0.134]:2123
[10/21 00:18:13.416] UE IPv4:[25.0.0.2] IPv6:
[10/21 00:18:13.416] gtp_client() [10.20.0.134]:2152
[10/21 00:18:13.419] gtp_client() [10.20.0.135]:2152
[10/21 00:18:13.821] gtp_client() [10.20.0.131]:2152
[10/21 00:18:14.204] UE IPv4:[25.0.0.3] IPv6:

出力例2
u16c131:eNB側の出力例
以下のようなログが最終的に出力している、かつ、UEのIPアドレスが確認できれば、アタッチは正常に完了しています。
ちなみに、eNB側のログは不定期に出力し続けます。また、ErrorやWarning、Fatalといったメッセージも、ちらほら見受けられますが、あまり気にしないでください。
eNB起動時のログは大量に出力されるため、こちらにアップしました。

[SCTP][I][4][50] Msg of length 62 received from port 36412, on stream 1, PPID 18
[S1AP][I]Decoding message S1ap_DownlinkNASTransportIEs (/root/openairinterface5g/cmake_targets/oaisim_build_oai/build/CMakeFiles/R10.5/s1ap_decoder.c:3150)
[RRC][I][eNB 0] Received S1AP_DOWNLINK_NAS: ue_initial_id 0, eNB_ue_s1ap_id 116541
[PDCP][I][FRAME 00000][eNB][MOD 00][RNTI c745]Received RRC_DCCH_DATA_REQ from TASK_RRC_ENB: instance 0, rb_id 2, muiP 6, confirmP 0, mode 1
[RLC][I][FRAME 00000][eNB][MOD 00][RNTI c745][SRB AM 02] RLC_AM_DATA_REQ size 44 Bytes,  NB SDU 1 current_sdu_index=0 next_sdu_index=1 conf 0 mui 6 vtA 0 vtS 0
[MAC][I][eNB 0], Frame 72, DCCH1->DLSCH, CC_id 0, Requesting 125 bytes from RLC (RRC message)
[PHY][E]Format1A Retransmission but TBS are different: consider it as new transmission !!!
[OSA][E]Mismatch found in integrity for algorithm 2,
        got 60.38.89.c0, expecting 00.00.00.00
[PDCP][E][OSA][RB 2] UE failed to validate MAC-I of incoming PDU
[RRC][N][UE 0] Frame 72: received a DCCH 2 message on SRB 2 with Size 39 from eNB 0
[RRC][E][UE 0] Frame 72: Received message on DL-DCCH (SRB2), should not have ...
[MAC][I][eNB 0], Frame 73, DCCH1->DLSCH, CC_id 0, Requesting 125 bytes from RLC (RRC message)
bad DCI 1A !!!
[PHY][I]bad dci mcs + round
bad DCI 1 !!!
[PHY][E][UE  0] Frame 287, subframe 8: Problem in DCI!
[PHY][E]frame 681, subframe 7, rnti c745, format 0: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc[450] > RIV_max[324]
[PHY][E]Wrong DCI0 detection, do not transmit PUSCH for HARQID: 5
[PHY][I][UE  0] frame 683, subframe 2: received DCI 0 with RNTI=0 (C-RNTI:c745, CBA_RNTI 0) and format 2!
[PHY][I]bad dci rballoc rballoc 7346  RIV_max 324
bad DCI 1 !!!
[PHY][E][UE  1] Frame 795, subframe 9: Problem in DCI!
4-7.UEアドレス確認

oip1というインターフェースに25.0.0.x/8のアドレスがアサインされていれば、UEのアタッチ成功です。
今回はUE0とUE1の2台分のIPアドレスアサインされています。

ip add show

root@u16c131:~# ip add show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:41:02:e1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.131/24 brd 192.168.11.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe41:2e1/64 scope link
       valid_lft forever preferred_lft forever
3: ens34:  mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 00:0c:29:41:02:eb brd ff:ff:ff:ff:ff:ff
4: ens35:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:41:02:f5 brd ff:ff:ff:ff:ff:ff
    inet 10.20.0.131/24 brd 10.20.0.255 scope global ens35
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe41:2f5/64 scope link
       valid_lft forever preferred_lft forever
65: oip0:  mtu 1500 qdisc noop state DOWN group default qlen 100
    link/generic 00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00
66: oip1:  mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/generic 00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00
    inet 25.0.0.5/8 brd 25.255.255.255 scope global oip1
       valid_lft forever preferred_lft forever
67: oip2:  mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/generic 00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00
    inet 25.0.0.4/8 brd 25.255.255.255 scope global oip2
       valid_lft forever preferred_lft forever
68: oip3:  mtu 1500 qdisc noop state DOWN group default qlen 100
    link/generic 00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00
~~~ 中略 ~~~
84: oip19:  mtu 1500 qdisc noop state DOWN group default qlen 100
    link/generic 00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00

SGiのGWアドレスにoip1を指定して、Pingを飛ばしてみてください。*7

root@u16c131:~# ping 10.10.0.254 -I oip1
PING 10.10.0.254 (10.10.0.254) from 25.0.0.5 oip1: 56(84) bytes of data.
64 bytes from 10.10.0.254: icmp_seq=1 ttl=63 time=131 ms
64 bytes from 10.10.0.254: icmp_seq=2 ttl=63 time=86.7 ms
64 bytes from 10.10.0.254: icmp_seq=3 ttl=63 time=98.3 ms
64 bytes from 10.10.0.254: icmp_seq=4 ttl=63 time=83.4 ms
^C
--- 10.10.0.254 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 83.452/99.940/131.223/18.888 ms
4-8.route追加

うまくPingが飛ばない場合は、u16c131側にDefaultGWアドレスを設定し、既存のDefaultGWアドレスは削除してみてください。

DefaultGWアドレスの設定

route add default gw 25.0.0.1

既存DefaultGWアドレスの削除

vi /etc/network/interfaces

削除箇所

auto ens33
iface ens33 inet static
    address 192.168.11.131
    netmask 255.255.255.0
    gateway 192.168.11.1
    dns-nameserver 192.168.11.1

auto ens35
iface ens35 inet static
    address 10.20.0.131
    netmask 255.255.255.0

systemctl restart networking

ここまでで、ほぼ完成です。
あとは、MVNOライクにS5/S8でSPGWを分離する手順となります。

Pingが飛ばなかったり、IPアドレスアサインされない場合は、u16c132のens35とens34をtcpdumpしてみてください。*8

5.NextEPCの分離

5-1.クローン作成&u16c135の起動

u16c132をシャットダウン後、u16c132のクローンをu16c135として作成してください。
u16c135を起動後、ネットワーク設定やホスト名を以下のように変更します。

#u16c135の設定

vi /etc/network/interfaces

追記箇所 修正箇所 削除箇所

auto ens33
iface ens33 inet static
    address 192.168.11.135
    netmask 255.255.255.0
    gateway 192.168.11.1
    dns-nameserver 192.168.11.1

auto ens34
iface ens34 inet static
    address 10.10.0.135
    netmask 255.255.255.0
    gateway 10.10.0.254

auto ens35
iface ens35 inet static
    address 10.20.0.135
    netmask 255.255.255.0

auto ens35:3
iface ens35:3 inet static
    address 10.20.0.133
    netmask 255.255.255.0

auto ens35:4
iface ens35:4 inet static
    address 10.20.0.134
    netmask 255.255.255.0

auto ens35:5
iface ens35:5 inet static
    address 10.20.0.135
    netmask 255.255.255.0

auto ens35:6
iface ens35:6 inet static
    address 10.20.0.136
    netmask 255.255.255.0

#ホスト名の変更 
vi /etc/hostname

u16c135

#再起動
reboot 
5-2.u16c132のネットワーク設定変更

u16c132を起動してください。そして、以下の通りネットワーク設定を変更してください。

#u16c132の設定

vi /etc/network/interfaces

削除箇所

auto ens33
iface ens33 inet static
    address 192.168.11.132
    netmask 255.255.255.0
    gateway 192.168.11.1
    dns-nameserver 192.168.11.1

auto ens34
iface ens34 inet static
    address 10.10.0.135
    netmask 255.255.255.0

auto ens35
iface ens35 inet static
    address 10.20.0.132
    netmask 255.255.255.0

auto ens35:3
iface ens35:3 inet static
    address 10.20.0.133
    netmask 255.255.255.0

auto ens35:4
iface ens35:4 inet static
    address 10.20.0.134
    netmask 255.255.255.0

auto ens35:5
iface ens35:5 inet static
    address 10.20.0.135
    netmask 255.255.255.0

auto ens35:6
iface ens35:6 inet static
    address 10.20.0.136
    netmask 255.255.255.0

#再起動
reboot 
5-3.各種サービス起動

S5/S8でSPGW間を分離していますので、

/root/nextepc/install/bin/nextepc-epcd -d

は使用せず、それぞれ個別にサービスを起動します。

u16c132 MME, HSS, SGW
u16c135 PGW, PCRF
#u16c132のサービス起動:MME, HSS, SGW
/root/nextepc/install/bin/nextepc-sgwd -d
/root/nextepc/install/bin/nextepc-hssd -d
/root/nextepc/install/bin/nextepc-mmed -d

#u16c135のサービス起動:PGW, PCRF
/root/nextepc/install/bin/nextepc-pcrfd -d
/root/nextepc/install/bin/nextepc-pgwd -d
5-4.eNBの起動

以下のコマンドで再度eNBを起動します。
S5/S8で分離されても、「4-6.eNB起動」以降で動作確認したのと同様に疎通確認してください。

#u16c131で実行

/root/openairinterface5g/cmake_targets/tools/run_enb_ue_virt_s1
5-5.起動時のログ

eNB起動時の

  • u16c132:MME,HSS,SGW
  • u16c135:PGW,PCRF

におけるログとPcapファイルをアップしておきます。
なお、u16c131:UE,eNBの出力ログは4-6の出力例2に載せたものと同様です。

#u16c132の出力例

root@u16c132:~# /root/nextepc/install/bin/nextepc-sgwd -d
root@u16c132:~# /root/nextepc/install/bin/nextepc-hssd -d
root@u16c132:~# /root/nextepc/install/bin/nextepc-mmed -d
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44
  PID[1857] : '/root/nextepc/install/var/run/nextepc-sgwd/pid'
  File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/21 00:59:10.412] SGW try to initialize
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44
  PID[1860] : '/root/nextepc/install/var/run/nextepc-hssd/pid'
  File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/21 00:59:10.421] HSS try to initialize
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44
[10/21 00:59:10.463] HSS initialize...done
[10/21 00:59:10.464] INFO: NextEPC daemon start (main.c:177)
  PID[1873] : '/root/nextepc/install/var/run/nextepc-mmed/pid'
  File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/21 00:59:10.466] MME try to initialize
[10/21 00:59:10.478] SGW initialize...done
[10/21 00:59:10.478] INFO: NextEPC daemon start (main.c:177)
[10/21 00:59:10.478] gtp_server() [10.20.0.134]:2123
[10/21 00:59:10.478] gtp_server() [10.20.0.134]:2152
[10/21 00:59:10.607] gtp_server() [10.20.0.132]:2123
[10/21 00:59:10.607] gtp_client() [10.20.0.134]:2123
[10/21 00:59:10.607] MME initialize...done
[10/21 00:59:10.607] INFO: NextEPC daemon start (main.c:177)
[10/21 00:59:10.608] INFO: CONNECTED TO 'mme.localdomain' (TCP,soc#8): (fd_logger.c:93)
[10/21 00:59:10.608] INFO: CONNECTED TO 'hss.localdomain' (TCP,soc#11): (fd_logger.c:93)
[10/21 00:59:10.615] s1ap_server() [10.20.0.132]:36412

~~~以下はeNBが接続してきた際に出力されるログ~~~
[10/21 01:00:41.550] eNB-S1 accepted[10.20.0.131]:36412 in s1_path module
[10/21 01:00:41.550] eNB-S1 accepted[10.20.0.131] in master_sm module
[10/21 01:00:46.461] gtp_client() [10.20.0.132]:2123
[10/21 01:00:46.461] gtp_client() [10.20.0.135]:2123
[10/21 01:00:46.466] gtp_client() [10.20.0.135]:2152
[10/21 01:00:46.868] gtp_client() [10.20.0.131]:2152

#u16c135の出力例

root@u16c135:~# /root/nextepc/install/bin/nextepc-pcrfd -d
root@u16c135:~# /root/nextepc/install/bin/nextepc-pgwd -d
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44
  PID[1870] : '/root/nextepc/install/var/run/nextepc-pcrfd/pid'
  File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
NextEPC daemon v0.3.10 - Oct 20 2019 23:04:44
MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/21 00:59:23.198] PCRF try to initialize
  PID[1873] : '/root/nextepc/install/var/run/nextepc-pgwd/pid'
  File Logging : '/root/nextepc/install/var/log/nextepc/nextepc.log'
  MongoDB URI : 'mongodb://localhost/nextepc'
  Configuration : '/root/nextepc/install/etc/nextepc/nextepc.conf'
[10/21 00:59:23.199] PGW try to initialize
[10/21 00:59:23.235] PCRF initialize...done
[10/21 00:59:23.236] INFO: NextEPC daemon start (main.c:177)
[10/21 00:59:23.352] PGW initialize...done
[10/21 00:59:23.352] INFO: NextEPC daemon start (main.c:177)
[10/21 00:59:23.352] gtp_server() [10.20.0.135]:2123
[10/21 00:59:23.352] gtp_server() [10.20.0.135]:2152
[10/21 00:59:23.354] INFO: CONNECTED TO 'pgw.localdomain' (TCP,soc#9): (fd_logger.c:93)
[10/21 00:59:23.355] INFO: CONNECTED TO 'pcrf.localdomain' (TCP,soc#13): (fd_logger.c:93)

~~~以下はUEにIPアドレスアサインされた際に出力されるログ~~~
[10/21 01:00:46.409] gtp_client() [10.20.0.134]:2123
[10/21 01:00:46.409] UE IPv4:[25.0.0.2] IPv6:
[10/21 01:00:46.409] gtp_client() [10.20.0.134]:2152
[10/21 01:00:46.573] UE IPv4:[25.0.0.3] IPv6:

eNB起動時のPcapファイルはこちらにアップしました。
u16c135のens35でpcapしています。

以上です。

6.最後に

以下のサイトを参考にさせて頂きました。
【プライベートLTE】 第3回:プライベートLTE設備の構築 ~Open Air Interface(OAISIM)による端末(UE)・基地局(eNB)擬似環境の紹介~
LTEを自作してみる(Part2) - Qiita
LTEを自作してみる(Part3) - Qiita

最初の記事が@m0ch1_m0ch1さん、残り2つの記事が@K5Kさんによって書かれています。
お二方はE-UTRANやEPCに関して造詣が深く、大変よくまとめられた記事となっており、これらのサイトが無ければ、今回の記事は書けなかったので、ぜひぜひ読んでみてください。

私個人的にですが、モバイルネットワークの技術は、もっとコモディティ化してもよいと考えています。
最近、プライベートLTEやローカル5Gといった言葉(キーワード)をよく耳にしますが、誰でも簡単に扱えるか?というと、まだもう少し時間がかかるのだろうと思います。
とはいえ、ただただ時間が経つのを待っていれば扱えるようになるか?といえば、それもまた違うと思うで、自ら積極的かつ能動的にこれらの技術を獲りに行ける環境を、まずは構築してみるのが良いのでは?と考えています。

今回の記事はまだ初期段階ですが、次のステップとしては、最初に書いたようなことに加えて、

  • LXC/LXDやDockerなどでコンテナ化してみる
  • SGi側でBGPがしゃべれるようにQuaggaを入れてみる
  • OAISIMが重く不安定なのでリッチな物理サーバに換装してみる

など、色々できることはあるのかなと考えています

*1:MME,HSS,SGW,PGW,PCRF

*2:S5/S8でMME, HSS, SGWとPGW, PCRFを2つのNextEPCに分離します。

*3:分離する際に削除すればいいので。

*4:出力例に表示されている通り、.ue.nvram0とか.ue.nvram1など

*5:本来はUSRPなどでH/W処理されるプロセスをOAISIMとしてS/Wでシミュレートするためバイナリ化するのだと考えています。実際、バイナリ化していても、UE&eNodeBを起動すると、4CoreのCPU使用率が30~40%くらいで推移するため、S/Wでシミュレートするには相当負荷が掛かる処理のようです。

*6:v0.6.1のbranchでは大丈夫でした。

*7:GWアドレスを持つL3デバイスに25.0.0.0/8宛の戻り経路を忘れずに設定してください。

*8:出力例2にも記載しましたが、Phy層でFatal Errorなどのログが出力されていてもPingが飛びます。このため、一度でも成功したことがないと、どういう状態になっていればOKか?の判断が極めて困難だと思います。私自身も最初は勘所が全く掴めなかったので苦労しました。

CentOS7 OpenStack Neutron SR-IOV設定方法

CentOS7.7上でOpenStackを構築した後、SR-IOVの設定方法を記載します。*1

1.概要

1-1.環境
筐体                             : ProLiant DL360e Gen8
System ROM                       : P73 01/22/2018
NIC                              : Intel X540-AT2
OS                               : CentOS7.7(1908)
Installed Environment Groups     : Server with GUI
Add-Ons for Selected Environment : Virtualization Client, Virtualization Hypervisor, Virtualization Tools 
1-2.構成

f:id:metonymical:20191014185533p:plain

1-3.全体の流れ

SR-IOVの設定項目だけであれば以下の公式Docで十分ですが、
OpenStack Docs: SR-IOV
再現性が怪しいので、素の状態からの設定方法を記載します。*2
とはいえ、SR-IOV設定がメインなため、それ以外の細かい説明は省略します。

  • 事前設定
  • Controller事前準備
  • Keystone設定
  • Glance設定
  • Nova設定:Controller
  • Nova設定:Compute
  • Neutron設定:Controller
  • Neutron設定:Compute
  • Horizon設定
  • SR-IOV設定:Controller
  • SR-IOV設定:Compute
  • SR-IOVによるインスタンスの起動

2.全体的な事前準備

  • ControllerとComputeのhostsファイルなどを編集の上、名前解決できるようにしておいてください。
  • firewalldとNetworkManagerはDisableとし、networkをEnableにしてください。
  • SELinuxはDisableとしてください。
  • ens33とeno1に相当するインターフェースは、Internetへの疎通性を確保しておいてください。*3
  • ens36とeno2に相当するインターフェースは、OvSのアップリンクとして使用しますが、現段階では設定不要です。
  • ens1f0とens1f1については、過去記事などを参照の上、ComputeにてSR-IOVの設定を行っておいてください。*4
  • ControllerとComputeのMgmtIPやホスト名は以下とします。
Controller c76os11 192.168.11.101/24
Compute c76os12 192.168.11.102/24

3.Controller事前準備

Controllerのみ

3-1.リポジトリの設定
yum install -y centos-release-openstack-queens && \
yum upgrade -y

sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-OpenStack-queens.repo

reboot
3-2.MariaDBのインスト
yum --enablerepo=centos-openstack-queens -y install mariadb mariadb-server python2-PyMySQL

vi /etc/my.cnf

#Charsetを追記
[mysqld]
character-set-server=utf8

systemctl start mariadb && \
systemctl enable mariadb

#初期設定
mysql_secure_installation

#初期設定時の出力例

[root@c76os11 ~]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 空Enter
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y
New password: 任意のパスワード設定
Re-enter new password: 任意のパスワード設定
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
3-3.RabbitMQ&Memcachedのインスト
yum --enablerepo=centos-openstack-queens -y install rabbitmq-server memcached

vi /etc/sysconfig/memcached

#ControllerのIPアドレスを追記
OPTIONS="-l 127.0.0.1,::1,192.168.11.101"

systemctl start rabbitmq-server memcached && \
systemctl enable rabbitmq-server memcached

rabbitmqctl add_user openstack password
rabbitmqctl set_permissions openstack ".*" ".*" ".*"

4.Keystone設定

Controllerのみ

4-1.MariaDBに登録
mysql -u root -p

create database keystone;
grant all privileges on keystone.* to keystone@'localhost' identified by 'password';
grant all privileges on keystone.* to keystone@'%' identified by 'password';
flush privileges;
exit
4-2.Keystoneのインスト
yum --enablerepo=centos-openstack-queens -y install openstack-keystone openstack-utils python-openstackclient httpd mod_wsgi

vi /etc/keystone/keystone.conf

#以下を追記*5
[DEFAULT]
memcache_servers = 192.168.11.101:11211
[database]
connection = mysql+pymysql://keystone:password@192.168.11.101/keystone
[token]
provider = fernet

#db sync
su -s /bin/bash keystone -c "keystone-manage db_sync"

#初期化
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
keystone-manage credential_setup --keystone-user keystone --keystone-group keystone

4-3.bootstepの設定
# ControllerのIPを定義
export controller=192.168.11.101

# keystoneのbootstep (TESTPASSWD は任意のパスワード)
keystone-manage bootstrap --bootstrap-password TESTPASSWD \
--bootstrap-admin-url http://$controller:5000/v3/ \
--bootstrap-internal-url http://$controller:5000/v3/ \
--bootstrap-public-url http://$controller:5000/v3/ \
--bootstrap-region-id RegionOne
4-4.httpdの起動
ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/
systemctl start httpd && \
systemctl enable httpd
4-5.ログイン用環境変数ファイル設定(任意)

任意設定ですが、都度Credentialを求められるため、実施しておいた方が良いと思います。
「export OS_PASSWORD=」は、4-3.bootstepの設定と同一のPasswdを設定してください。

vi ~/keystonerc

export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=TESTPASSWD
export OS_AUTH_URL=http://192.168.11.101:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export PS1='[\u@\h \W(ks)]\$ '

chmod 600 ~/keystonerc
source ~/keystonerc
echo "source ~/keystonerc " >> ~/.bash_profile
4-6.Project作成
openstack project create --domain default --description "Default Project" service
openstack project list

5.Glance設定

Controllerのみ

5-1.ユーザ登録&Endpoint設定
openstack user create --domain default --project service --password servicepassword glance
openstack role add --project service --user glance admin
openstack service create --name glance --description "OpenStack Image service" image

export controller=192.168.11.101
openstack endpoint create --region RegionOne image public http://$controller:9292
openstack endpoint create --region RegionOne image internal http://$controller:9292
openstack endpoint create --region RegionOne image admin http://$controller:9292
5-2.MariaDBに登録
mysql -u root -p

create database glance;
grant all privileges on glance.* to glance@'localhost' identified by 'password';
grant all privileges on glance.* to glance@'%' identified by 'password';
flush privileges;
exit
5-3.Glanceのインストと設定
yum --enablerepo=centos-openstack-queens -y install openstack-glance

#glance-api.confの設定
mv /etc/glance/glance-api.conf /etc/glance/glance-api.conf.org
vi /etc/glance/glance-api.conf

[DEFAULT]
bind_host = 0.0.0.0

[glance_store]
stores = file,http
default_store = file
filesystem_store_datadir = /var/lib/glance/images/

[database]
connection = mysql+pymysql://glance:password@192.168.11.101/glance

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = glance
password = servicepassword

[paste_deploy]
flavor = keystone


#glance-registry.confの設定
mv /etc/glance/glance-registry.conf /etc/glance/glance-registry.conf.org
vi /etc/glance/glance-registry.conf

[DEFAULT]
bind_host = 0.0.0.0

[database]
connection = mysql+pymysql://glance:password@192.168.11.101/glance

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = glance
password = servicepassword

[paste_deploy]
flavor = keystone

#Permissionや起動設定*6
chmod 640 /etc/glance/glance-api.conf /etc/glance/glance-registry.conf
chown root:glance /etc/glance/glance-api.conf /etc/glance/glance-registry.conf
su -s /bin/bash glance -c "glance-manage db_sync"
systemctl start openstack-glance-api openstack-glance-registry && \
systemctl enable openstack-glance-api openstack-glance-registry
5-4.イメージ登録
mkdir /tmp/images

#cirrosの登録
wget -P /tmp/images http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img

openstack image create "cirros-0.4.0" \
--file /tmp/images/cirros-0.4.0-x86_64-disk.img \
--disk-format qcow2 \
--container-format bare \
--public

openstack image list

#centos7の登録
wget -P /tmp/images http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2

openstack image create "centos7" \
--file /tmp/images/CentOS-7-x86_64-GenericCloud.qcow2 \
--disk-format qcow2 \
--container-format bare \
--public

openstack image list

6.Nova設定:Controller

Controllerのみ

6-1.ユーザ登録&Endpoint設定
openstack user create --domain default --project service --password servicepassword nova
openstack role add --project service --user nova admin
openstack user create --domain default --project service --password servicepassword placement
openstack role add --project service --user placement admin
openstack service create --name nova --description "OpenStack Compute service" compute
openstack service create --name placement --description "OpenStack Compute Placement service" placement

export controller=192.168.11.101
openstack endpoint create --region RegionOne compute public http://$controller:8774/v2.1/%\(tenant_id\)s && \
openstack endpoint create --region RegionOne compute internal http://$controller:8774/v2.1/%\(tenant_id\)s && \
openstack endpoint create --region RegionOne compute admin http://$controller:8774/v2.1/%\(tenant_id\)s && \
openstack endpoint create --region RegionOne placement public http://$controller:8778 && \
openstack endpoint create --region RegionOne placement internal http://$controller:8778 && \
openstack endpoint create --region RegionOne placement admin http://$controller:8778
6-2.MariaDB登録
mysql -u root -p

create database nova;
grant all privileges on nova.* to nova@'localhost' identified by 'password';
grant all privileges on nova.* to nova@'%' identified by 'password';
create database nova_api;
grant all privileges on nova_api.* to nova@'localhost' identified by 'password';
grant all privileges on nova_api.* to nova@'%' identified by 'password';
create database nova_placement;
grant all privileges on nova_placement.* to nova@'localhost' identified by 'password';
grant all privileges on nova_placement.* to nova@'%' identified by 'password';
create database nova_cell0;
grant all privileges on nova_cell0.* to nova@'localhost' identified by 'password';
grant all privileges on nova_cell0.* to nova@'%' identified by 'password';
flush privileges;
exit
6-3.Novaのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-nova

#nova.confの設定
mv /etc/nova/nova.conf /etc/nova/nova.conf.org
vi /etc/nova/nova.conf

[DEFAULT]
my_ip = 192.168.11.101
state_path = /var/lib/nova
enabled_apis = osapi_compute,metadata
log_dir = /var/log/nova
transport_url = rabbit://openstack:password@192.168.11.101

[api]
auth_strategy = keystone

[glance]
api_servers = http://192.168.11.101:9292

[oslo_concurrency]
lock_path = $state_path/tmp

[api_database]
connection = mysql+pymysql://nova:password@192.168.11.101/nova_api

[database]
connection = mysql+pymysql://nova:password@192.168.11.101/nova

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = servicepassword

[placement]
auth_url = http://192.168.11.101:5000
os_region_name = RegionOne
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = placement
password = servicepassword

[placement_database]
connection = mysql+pymysql://nova:password@192.168.11.101/nova_placement

[wsgi]
api_paste_config = /etc/nova/api-paste.ini

#Permission変更
chmod 640 /etc/nova/nova.conf
chgrp nova /etc/nova/nova.conf

#00-nova-placement-api.confの設定
vi /etc/httpd/conf.d/00-nova-placement-api.conf

#</VirtualHost>の直上に追記
<Directory /usr/bin>
    Require all granted
</Directory>
6-4.DB登録とサービス起動
#novaコマンドは、一行づつ投入してください。
su -s /bin/bash nova -c "nova-manage api_db sync"
su -s /bin/bash nova -c "nova-manage cell_v2 map_cell0"
su -s /bin/bash nova -c "nova-manage db sync"
su -s /bin/bash nova -c "nova-manage cell_v2 create_cell --name cell1"

systemctl restart httpd
chown nova. /var/log/nova/nova-placement-api.log

for service in api consoleauth conductor scheduler novncproxy; do
systemctl start openstack-nova-$service
systemctl enable openstack-nova-$service
done

openstack compute service list

#一旦Reboot
reboot

#出力例:以下のコマンド(su -s /bin/bash nova -c "nova-manage db sync")投入時にWarningが出力されますが、気にせず先に進んでください。

[root@c76os11 images(keystone)]# su -s /bin/bash nova -c "nova-manage db sync"
/usr/lib/python2.7/site-packages/pymysql/cursors.py:166: Warning: (1831, u'Duplicate index `block_device_mapping_instance_uuid_virtual_name_device_name_idx`. This is deprecated and will be disallowed in a future release.')
  result = self._query(query)
/usr/lib/python2.7/site-packages/pymysql/cursors.py:166: Warning: (1831, u'Duplicate index `uniq_instances0uuid`. This is deprecated and will be disallowed in a future release.')
  result = self._query(query)

7.Nova設定:Compute

Computeのみ

7-1.事前準備
yum install -y centos-release-openstack-queens && \
yum upgrade -y

sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-OpenStack-queens.repo

reboot
7-2.Novaインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-nova-compute

#nova.confの設定
mv /etc/nova/nova.conf /etc/nova/nova.conf.org
vi /etc/nova/nova.conf

[DEFAULT]
my_ip = 192.168.11.102
state_path = /var/lib/nova
enabled_apis = osapi_compute,metadata
log_dir = /var/log/nova
transport_url = rabbit://openstack:password@192.168.11.101
compute_driver = libvirt.LibvirtDriver

[libvirt]
virt_type=kvm
cpu_mode=host-passthrough
hw_machine_type=x86_64=pc-i440fx-rhel7.6.0

[api]
auth_strategy = keystone

[vnc]
enabled = True
server_listen = 0.0.0.0
server_proxyclient_address = $my_ip
novncproxy_base_url = http://192.168.11.101:6080/vnc_auto.html

[glance]
api_servers = http://192.168.11.101:9292

[oslo_concurrency]
lock_path = $state_path/tmp

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = nova
password = servicepassword

[placement]
auth_url = http://192.168.11.101:5000
os_region_name = RegionOne
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = placement
password = servicepassword

[wsgi]
api_paste_config = /etc/nova/api-paste.ini


#Permission変更
chmod 640 /etc/nova/nova.conf
chgrp nova /etc/nova/nova.conf

#サービス起動
systemctl start openstack-nova-compute && \
systemctl enable openstack-nova-compute
7-3.ComputeNodeのDiscovery

Controllerのみ

su -s /bin/bash nova -c "nova-manage cell_v2 discover_hosts"
openstack compute service list

#出力例
[root@c76os11 ~(keystone)]# openstack compute service list
+----+------------------+---------------+----------+----------+-------+----------------------------+
| ID | Binary           | Host          | Zone     | Status   | State | Updated At                 |
+----+------------------+---------------+----------+----------+-------+----------------------------+
|  7 | nova-consoleauth | c76os11.md.jp | internal | enabled  | up    | 2019-10-14T01:49:01.000000 |
|  8 | nova-conductor   | c76os11.md.jp | internal | enabled  | up    | 2019-10-14T01:49:01.000000 |
| 10 | nova-scheduler   | c76os11.md.jp | internal | enabled  | up    | 2019-10-14T01:49:02.000000 |
| 11 | nova-compute     | c76os12.md.jp | nova     | enabled  | up    | 2019-10-14T01:49:00.000000 |
+----+------------------+---------------+----------+----------+-------+----------------------------+

8.Neutron設定:Controller

Controllerのみ

8-1.ユーザ&Endpoint登録
openstack user create --domain default --project service --password servicepassword neutron
openstack role add --project service --user neutron admin
openstack service create --name neutron --description "OpenStack Networking service" network

export controller=192.168.11.101
openstack endpoint create --region RegionOne network public http://$controller:9696 && \
openstack endpoint create --region RegionOne network internal http://$controller:9696 && \
openstack endpoint create --region RegionOne network admin http://$controller:9696
8-2.DB登録
mysql -u root -p

create database neutron_ml2;
grant all privileges on neutron_ml2.* to neutron@'localhost' identified by 'password';
grant all privileges on neutron_ml2.* to neutron@'%' identified by 'password';
flush privileges;
exit
8-3.Neutronのインストと設定
yum --enablerepo=centos-openstack-queens -y install openstack-neutron openstack-neutron-ml2

#neutron.conf設定
mv /etc/neutron/neutron.conf /etc/neutron/neutron.conf.org
vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2
service_plugins = router
auth_strategy = keystone
state_path = /var/lib/neutron
dhcp_agent_notification = True
allow_overlapping_ips = True
notify_nova_on_port_status_changes = True
notify_nova_on_port_data_changes = True
transport_url = rabbit://openstack:password@192.168.11.101

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = servicepassword

[database]
connection = mysql+pymysql://neutron:password@192.168.11.101/neutron_ml2

[nova]
auth_url = http://192.168.11.101:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = nova
password = servicepassword

[oslo_concurrency]
lock_path = $state_path/tmp

#Permission設定
chmod 640 /etc/neutron/neutron.conf
chgrp neutron /etc/neutron/neutron.conf
8-4.metadata_agent.ini設定
vi /etc/neutron/metadata_agent.ini

[DEFAULT]
nova_metadata_host = 192.168.11.101
metadata_proxy_shared_secret = metadata_secret

[cache]
memcache_servers = 192.168.11.101:11211
8-5.ml2_conf.ini設定
vi /etc/neutron/plugins/ml2/ml2_conf.ini

[ml2]
type_drivers = flat,vlan,gre,vxlan
tenant_network_types = flat,vlan
mechanism_drivers = openvswitch,l2population

[ml2_type_vlan]
network_vlan_ranges = physnet8:4000:4094

<補足>
physnet8:4000:4094は任意の名前と値です。
今回の構成においては以下の定義とします。

  • physnet8は、InstanceのMgmt用として使用します。
  • 4000:4094は、OvS内部で使用されるVLANレンジとなります。
8-6.nova.confの追加設定
vi /etc/nova/nova.conf

#追記
[DEFAULT]
use_neutron = True
linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver

#[neutron]セクションを最終行へ追記
[neutron]
auth_url = http://192.168.11.101:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = neutron
password = servicepassword
service_metadata_proxy = True
metadata_proxy_shared_secret = metadata_secret

#サービス起動
ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini
su -s /bin/bash neutron -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini upgrade head"
systemctl start neutron-server neutron-metadata-agent && \
systemctl enable neutron-server neutron-metadata-agent && \
systemctl restart openstack-nova-api
8-7.その他Agent&OVSのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-neutron openstack-neutron-ml2 openstack-neutron-openvswitch

#L3agent設定
vi /etc/neutron/l3_agent.ini

[DEFAULT]
interface_driver = openvswitch

#DHCPagent設定
vi /etc/neutron/dhcp_agent.ini

[DEFAULT]
interface_driver = openvswitch
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
enable_isolated_metadata = true

#ovs設定&サービス起動
ovs-vsctl add-br br-int

systemctl start openvswitch && \
systemctl enable openvswitch

for service in dhcp-agent l3-agent metadata-agent openvswitch-agent; do
systemctl start neutron-$service
systemctl enable neutron-$service
done

9.Neutron設定:Compute

Computeのみ

9-1.Neutronのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-neutron openstack-neutron-ml2 openstack-neutron-openvswitch

#neutron.conf設定
mv /etc/neutron/neutron.conf /etc/neutron/neutron.conf.org
vi /etc/neutron/neutron.conf

[DEFAULT]
core_plugin = ml2
service_plugins = router
auth_strategy = keystone
state_path = /var/lib/neutron
allow_overlapping_ips = True
transport_url = rabbit://openstack:password@192.168.11.101

[keystone_authtoken]
www_authenticate_uri = http://192.168.11.101:5000
auth_url = http://192.168.11.101:5000
memcached_servers = 192.168.11.101:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = neutron
password = servicepassword

[oslo_concurrency]
lock_path = $state_path/lock

#Permission変更
chmod 640 /etc/neutron/neutron.conf
chgrp neutron /etc/neutron/neutron.conf
9-2.ml2_conf.ini設定
vi /etc/neutron/plugins/ml2/ml2_conf.ini

[ml2]
type_drivers = flat,vlan,gre,vxlan
tenant_network_types =flat,vlan
mechanism_drivers = openvswitch,l2population

[ml2_type_vlan]
network_vlan_ranges = physnet8:4000:4094
9-3.nova.confの追加設定
vi /etc/nova/nova.conf

#追記
[DEFAULT]
use_neutron = True
linuxnet_interface_driver = nova.network.linux_net.LinuxOVSInterfaceDriver
firewall_driver = nova.virt.firewall.NoopFirewallDriver
vif_plugging_is_fatal = True
vif_plugging_timeout = 300

#[neutron]セクションを最終行へ追記
[neutron]
auth_url = http://192.168.11.101:5000
auth_type = password
project_domain_name = default
user_domain_name = default
region_name = RegionOne
project_name = service
username = neutron
password = servicepassword
service_metadata_proxy = True
metadata_proxy_shared_secret = metadata_secret

#サービス起動
ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini
systemctl start openvswitch && \
systemctl enable openvswitch
9-4.OvS設定
ovs-vsctl add-br br-int
systemctl restart openstack-nova-compute

systemctl start neutron-openvswitch-agent && \
systemctl enable neutron-openvswitch-agent
9-5.Mgmtインターフェース設定

ControllerとCompute
metadata-agent & dhcp-agentの通信用NWインターフェースとして利用します。

#Controllerにて設定
ovs-vsctl add-br br-ens36
ovs-vsctl add-port br-ens36 ens36


vi /etc/sysconfig/network-scripts/ifcfg-br-ens36

NAME=br-ens36
DEVICE=br-ens36
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no


vi /etc/sysconfig/network-scripts/ifcfg-ens36

NAME=ens36
DEVICE=ens36
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-ens36
BOOTPROTO=none
NM_CONTROLLED=no
HOTPLUG=no


vi /etc/neutron/plugins/ml2/ml2_conf.ini

[ml2_type_flat]
flat_networks = *


vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[ovs]
bridge_mappings = physnet8:br-ens36

systemctl restart neutron-openvswitch-agent


#Computeにて設定
ovs-vsctl add-br br-eno2
ovs-vsctl add-port br-eno2 eno2

vi /etc/sysconfig/network-scripts/ifcfg-br-eno2

NAME=br-eno2
DEVICE=br-eno2
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
NM_CONTROLLED=no
ONBOOT=yes
HOTPLUG=no


vi /etc/sysconfig/network-scripts/ifcfg-eno2

NAME=eno2
DEVICE=eno2
ONBOOT=yes
DEVICETYPE=ovs
TYPE=OVSPort
OVS_BRIDGE=br-eno2
BOOTPROTO=none
NM_CONTROLLED=no
HOTPLUG=no


vi /etc/neutron/plugins/ml2/ml2_conf.ini

[ml2_type_flat]
flat_networks = *


vi /etc/neutron/plugins/ml2/openvswitch_agent.ini

[ovs]
bridge_mappings = physnet8:br-eno2

systemctl restart neutron-openvswitch-agent

10.Horizon設定

Controllerのみ

10-1.Horizonのインスト&設定
yum --enablerepo=centos-openstack-queens -y install openstack-dashboard

#local_settingsの設定
vi /etc/openstack-dashboard/local_settings

ALLOWED_HOSTS = ['dlp.srv.world', 'localhost', '*']

OPENSTACK_API_VERSIONS = {
    "data-processing": 1.1,
    "identity": 3,
    "image": 2,
    "volume": 2,
    "compute": 2,
}

OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True

OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '192.168.11.101:11211',
    },
}

OPENSTACK_HOST = "192.168.11.101"

#openstack-dashboard.confの設定
#WSGISocketPrefix run/wsgiの直下に追記
vi /etc/httpd/conf.d/openstack-dashboard.conf

WSGIApplicationGroup %{GLOBAL}

#サービス再起動
systemctl restart httpd.service memcached.service
10-2.flavorの作成

事前にflavorを作成しておきます。

openstack flavor create --id 0 --vcpus 1 --ram 1024 --disk 10 m1.small
openstack flavor list
10-3.簡易動作確認

動作確認用として、mgmtネットワークを作成し、テストインスタンスの起動確認をしてください。

#nw-mgmt作成
openstack network create \
--share \
--no-default \
--enable \
--project admin \
--external \
--provider-network-type flat \
--provider-physical-network physnet8 \
nw-mgmt

#subnet-mgmt作成
openstack subnet create \
--project admin \
--gateway 10.10.0.254 \
--subnet-range 10.10.0.0/24 \
--allocation-pool start=10.10.0.16,end=10.10.0.127 \
--network nw-mgmt \
subnet-mgmt

#インスタンス起動
netID=$(openstack network list | grep nw-mgmt | awk '{ print $2 }')
openstack server create --flavor m1.small --image cirros-0.4.0 --nic net-id=$netID inst01
openstack server list

#出力例
[root@c76os11 ~(keystone)]# openstack server list
+--------------------------------------+---------+---------+----------------------------------------------------------------------------+---------------------+----------+
| ID                                   | Name    | Status  | Networks                                                                   | Image               | Flavor   |
+--------------------------------------+---------+---------+----------------------------------------------------------------------------+---------------------+----------+
| 2d2af2b3-89eb-4508-b425-49e67b3dbcaa | inst01  | ACTIVE  | nw-mgmt=10.10.0.28                                                         | cirros-0.4.0        | m1.small |
+--------------------------------------+---------+---------+----------------------------------------------------------------------------+---------------------+----------+

#Dashboradの動作確認
http://192.168.11.101/dashboard/
f:id:metonymical:20191014120535p:plain
ユーザ名:admin
パスワード:TESTPASSWD 

ここまででSR-IOVを設定する準備ができました。
上記インスタンスへの疎通確認なども実施しておいてください。
上手く疎通確認が取れない場合は、Controller&Computeを再起動してみてください。

11.SR-IOV設定:Controller

Controllerのみ

#nova.confの追加設定
vi /etc/nova/nova.conf

[DEFAULT]
scheduler_default_filters = RetryFilter, AvailabilityZoneFilter, RamFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, PciPassthroughFilter
scheduler_available_filters = nova.scheduler.filters.all_filters

#ml2_conf.iniの追加設定
#青文字の箇所を追記してください。
vi /etc/neutron/plugins/ml2/ml2_conf.ini
[ml2]
type_drivers = flat,vlan,gre,vxlan
tenant_network_types = flat,vlan
mechanism_drivers = openvswitch,l2population,sriovnicswitch

[ml2_type_vlan]
network_vlan_ranges = physnet8:4000:4094,physnet0:300:304,physnet1:300:304

#neutron.confの追加設定
vi /etc/neutron/neutron.conf

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

#openvswitch-agent再起動
systemctl restart neutron-openvswitch-agent

12.SR-IOV設定:Compute

Computeのみ

#sriov-nic-agentのインスト
yum --enablerepo=centos-openstack-queens -y install openstack-neutron-sriov-nic-agent

#nova.confの追加設定
vi /etc/nova/nova.conf

[DEFAULT]
pci_passthrough_whitelist = {"devname":"ens1f0","physical_network":"physnet0"}
pci_passthrough_whitelist = {"devname":"ens1f1","physical_network":"physnet1"}


#sriov_agent.ini設定
vi /etc/neutron/plugins/ml2/sriov_agent.ini

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

[sriov_nic]
physical_device_mappings = physnet0:ens1f0,physnet1:ens1f1


#neutron.confの追加設定
vi /etc/neutron/neutron.conf

[securitygroup]
firewall_driver = neutron.agent.firewall.NoopFirewallDriver

#サービス起動
systemctl restart neutron-openvswitch-agent && \
systemctl start neutron-sriov-nic-agent && \
systemctl enable neutron-sriov-nic-agent

#NIC設定
vi /etc/sysconfig/network-scripts/ifcfg-ens1f0

TYPE=Ethernet
BOOTPROTO=none
NAME=ens1f0
DEVICE=ens1f0
ONBOOT=yes

vi /etc/sysconfig/network-scripts/ifcfg-ens1f1

TYPE=Ethernet
BOOTPROTO=none
NAME=ens1f1
DEVICE=ens1f1
ONBOOT=yes

systemctl restart network

13.SR-IOVによるインスタンスの起動

Controllerのみ

13-1.VLAN300のNW,Subnet,Portの作成

ここからSR-IOV用のNWなどを作成していきますが、Errorで弾かれる場合には、ControllerとComputeを一度再起動してみてください。*7

openstack network create \
--share \
--no-default \
--enable \
--project admin \
--external \
--provider-network-type vlan \
--provider-physical-network physnet0 \
--provider-segment 300 \
sriov300

openstack subnet create \
--project admin \
--no-dhcp \
--gateway 192.168.30.254 \
--subnet-range 192.168.30.0/24 \
--allocation-pool start=192.168.30.16,end=192.168.30.127 \
--network sriov300 \
sriov300_sb

openstack port create \
--network sriov300 \
--vnic-type direct \
--fixed-ip subnet=sriov300_sb,ip-address=192.168.30.128 \
--no-security-group \
--enable \
sriov300_port128

openstack port create \
--network sriov300 \
--vnic-type direct \
--fixed-ip subnet=sriov300_sb,ip-address=192.168.30.129 \
--no-security-group \
--enable \
sriov300_port129
13-2.VLAN301のNW,Subnet,Portの作成
openstack network create \
--share \
--no-default \
--enable \
--project admin \
--external \
--provider-network-type vlan \
--provider-physical-network physnet1 \
--provider-segment 301 \
sriov301

openstack subnet create \
--project admin \
--no-dhcp \
--gateway 192.168.31.254 \
--subnet-range 192.168.31.0/24 \
--allocation-pool start=192.168.31.16,end=192.168.31.127 \
--network sriov301 \
sriov301_sb

openstack port create \
--network sriov301 \
--vnic-type direct \
--fixed-ip subnet=sriov301_sb,ip-address=192.168.31.128 \
--no-security-group \
--enable \
sriov301_port128

openstack port create \
--network sriov301 \
--vnic-type direct \
--fixed-ip subnet=sriov301_sb,ip-address=192.168.31.129 \
--no-security-group \
--enable \
sriov301_port129

<補足>
Portの作成はCLI or APIにて実施してください。
公式Docに以下の記載があります。
SR-IOV is not integrated into the OpenStack Dashboard (horizon). Users must use the CLI or API to configure SR-IOV interfaces.

13-3.UserDataの作成
vi udata.txt

#cloud-config
password: TESTPASSWD
chpasswd: { expire: False }
ssh_pwauth: True
13-4.CLIによるインスタンスの起動
netID=$(openstack network list | grep nw-mgmt | awk '{ print $2 }')
portID01=$(openstack port list |grep sriov300_port128 | awk '{ print $2 }')
portID02=$(openstack port list |grep sriov301_port128 | awk '{ print $2 }')

openstack server create \
--flavor m1.small \
--image centos7 \
--user-data udata.txt \
--nic net-id=$netID \
--nic port-id=$portID01 \
--nic port-id=$portID02 \
inst02

<補足>
SR-IOVインターフェースはnet-idではなく、port-idとして指定してください。
次項のGUIによるインスタンスの起動においても同様に、「ネットワークのポート」画面にて設定してください。*8

13-5.GUIによるインスタンスの起動

プロジェクト>コンピュート>インスタンスインスタンスの起動をクリック。
f:id:metonymical:20191014182457p:plain
インスタンス名を入力。次へをクリック。
f:id:metonymical:20191014182538p:plain
centos7を割り当てし、次へをクリック。
f:id:metonymical:20191014182649p:plain
m1.smallを割り当てし、次へをクリック。
f:id:metonymical:20191014182739p:plain
nw-mgmtを割り当てし、次へをクリック。
f:id:metonymical:20191014182822p:plain
作成したPortを割り当てし、次へをクリック。「設定」まで次へをクリック。
f:id:metonymical:20191014182855p:plain
13-3.UserDataの作成の内容をコピペし、インスタンスの起動をクリック。f:id:metonymical:20191014183035p:plain
以下の通り起動すればOKです。
f:id:metonymical:20191014183107p:plain

13-5.NICの確認
[root@c76os11 ~(keystone)]# openstack server list
+--------------------------------------+--------+---------+----------------------------------------------------------------------+--------------+----------+
| ID                                   | Name   | Status  | Networks                                                             | Image        | Flavor   |
+--------------------------------------+--------+---------+----------------------------------------------------------------------+--------------+----------+
| a6f54ee9-6c3d-4497-b2f5-61ab0b493e94 | inst03 | ACTIVE  | sriov300=192.168.30.129; sriov301=192.168.31.129; nw-mgmt=10.10.0.22 | centos7      | m1.small |
| afe80655-2c2c-4349-82cb-5843256d1d05 | inst02 | ACTIVE  | sriov300=192.168.30.128; sriov301=192.168.31.128; nw-mgmt=10.10.0.21 | centos7      | m1.small |
| c13aeb0a-85b3-4174-a977-d317b7c84cc3 | inst01 | SHUTOFF | nw-mgmt=10.10.0.18                                                   | cirros-0.4.0 | m1.small |
+--------------------------------------+--------+---------+----------------------------------------------------------------------+--------------+----------+

#ここでは例としてinst02にssh接続します。
[root@c76os11 ~(keystone)]# ip netns
qdhcp-5561d190-1fbf-4d06-aa54-253935fdce59 (id: 0)
[root@c76os11 ~(keystone)]# ip netns exec qdhcp-5561d190-1fbf-4d06-aa54-253935fdce59 ssh centos@10.10.0.21
centos@10.10.0.21's password:
Last login: Mon Oct 14 09:15:26 2019 from host-10-10-0-16.openstacklocal
[centos@inst02 ~]$ sudo su -
Last login: Mon Oct 14 09:15:29 UTC 2019 on pts/0

#inst02のens5とens6のMACアドレスを確認します。
[root@inst02 ~]# ip link show
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens5:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether fa:16:3e:43:a0:c5 brd ff:ff:ff:ff:ff:ff
3: ens6:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether fa:16:3e:43:f0:66 brd ff:ff:ff:ff:ff:ff
4: eth0:  mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether fa:16:3e:13:21:cb brd ff:ff:ff:ff:ff:ff

#ComputeNodeのVFのMACアドレスと一致していることを確認します。
[root@c76os12 ~]# ip link show
6: ens1f0:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:68 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC fa:16:3e:ae:b4:91, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC fa:16:3e:43:a0:c5, vlan 300, spoof checking on, link-state auto, trust off, query_rss off
7: ens1f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:6a brd ff:ff:ff:ff:ff:ff
    vf 0 MAC fa:16:3e:b7:1f:74, vlan 301, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC fa:16:3e:43:f0:66, vlan 301, spoof checking on, link-state auto, trust off, query_rss off
13-6.NICの設定

inst02のens5とens6にIPの設定し、networkサービスの再起動をしてください。

[root@inst02 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens5

NAME=ens5
DEVICE=ens5
BOOTPROTO=none
ONBOOT=yes
HOTPLUG=no
IPADDR=192.168.30.128
PREFIX=24

[root@inst02 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens6

NAME=ens6
DEVICE=ens6
BOOTPROTO=none
ONBOOT=yes
HOTPLUG=no
IPADDR=192.168.31.128
PREFIX=24


以上です。

14.最後に

以下のサイトを参考にさせて頂きました。
CentOS 7 : OpenStack Queens インストールと設定 : Server World
OpenStack Docs: SR-IOV

一度でも成功していれば勘所がわかってくるのですが、一度も成功したことがないと、ControllerとComputeのiniファイルやconfファイルを何度も編集したり、再起動したりと、ハマりやすいと思います。

*1:図はc76となっていますが、7.7でも動作確認を行っています。ちなみに最近、CentOSミラーサイトの7.6関連のファイルが軒並み削除されているため、7.7を使用しないとyum updateでもコケる可能性があります。

*2:個人的にとても苦労したので、この方法で最初から構築したら上手くいった、という内容を記載したいと思います。

*3:yum updateなどを実行するので。

*4:過去記事を参照する場合、10は設定しないでください。環境によっては、9も設定不要です。

*5:正確にどのセクションの何行目くらいかを知りたい場合は、memcache_serversやmysql+pymysqlなどで検索してください。

*6:待ちが必要な箇所には、&& \を記載しています

*7:各agentの整合性が取れてない可能性があるためです。

*8:net-idで指定すると失敗します。理由を考察するに、SR-IOVのVFを動的に割り当てているためではないかな、と考えています。

CentOS8 小ネタ集その4:SR-IOVの設定

CentOS8のSR-IOV設定方法を記載します。

基本的な注意事項などは過去記事と同様となりますので、そちらを参照してください。

1.環境

筐体                           :ProLiant DL360e Gen8
System ROM                     :P73 01/22/2018
NIC                            :Intel X540-AT2 *1
OS                             :CentOS8.0
Installed Environment Groups:
  @^graphical-server-environment
  @container-management
  @development
  @virtualization-client
  @virtualization-hypervisor
  @virtualization-tools

BIOS上でSR-IOVを有効化する方法はHPガイドを参照してください。

2.iommuの有効化

vi /etc/default/grub

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt pci=realloc"

もしくは
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub


以下のコマンドでgrub2.cfgに反映

grub2-mkconfig -o /etc/grub2.cfg

3.SR-IOVの自動起動設定

vi /etc/rc.local

echo 2 > /sys/class/net/ens1f0/device/sriov_numvfs
echo 2 > /sys/class/net/ens1f1/device/sriov_numvfs
exit 0

chmod +x /etc/rc.d/rc.local

4.modprobeのblacklistへの追加

ixgbevfを外すことによりホストOS上でVFがNICとして認識されるのを防ぎます。
但し、ホストOS上ではPCIバイスとして認識しているため、ゲストOSにアタッチすることは可能です。

vi /lib/modprobe.d/dist-blacklist.conf

# ixgbevf driver
blacklist ixgbevf

もしくは

cat << EOF >> /lib/modprobe.d/dist-blacklist.conf

# ixgbevf driver
blacklist ixgbevf
EOF


ここで一旦再起動してください。

5.仮想マシンでの設定方法

Cockpitでは設定できないため、Virt-Managerで設定していきます。
f:id:metonymical:20191013214413p:plain
仮想マシンをOpenで開き、Add Hardwareをクリック。
f:id:metonymical:20191013214505p:plain
PCI Host Deviceを選択。
Host Device:から、Virtual Functionを選択。

以下の通り、VFとPFのポートは偶数と奇数で分かれています。*2

Domain:Bus:Slot:Function -> PFのポート
0000  :08 :10  :0        -> enp1s0(0000:08:00:0)
0000  :08 :10  :1        -> enp1s1(0000:08:00:1)
0000  :08 :10  :2        -> enp1s0(0000:08:00:0)
0000  :08 :10  :3        -> enp1s1(0000:08:00:1)
0000  :08 :10  :4        -> enp1s0(0000:08:00:0)
0000  :08 :10  :5        -> enp1s1(0000:08:00:1)
0000  :08 :10  :6        -> enp1s0(0000:08:00:0)
0000  :08 :10  :7        -> enp1s1(0000:08:00:1)

f:id:metonymical:20191013215103p:plain
上記のようになっていればOKです。
仮想マシンを起動してください。

仮想マシン起動後にホストOSにて、ip link showコマンドにより、仮想マシンがVFを掴んでいることが確認できます。
仮想マシン上でも同一MACアドレスになっていればOKです。

[root@c80g240 ~]# ip link show
6: ens1f0:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:68 brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 12:af:d7:6e:fa:20, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
7: ens1f1:  mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether a0:36:9f:3e:6d:6a brd ff:ff:ff:ff:ff:ff
    vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 2 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off
    vf 3 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off, query_rss off


以上です。

6.最後に

小ネタ集は一旦終了しようと思いますが、今後もちょくちょく追加できればと考えています。

*1:X540-T2として販売されているもので、HP純正ではなくAmazonで購入したOEM提供のものです。

*2:Slotの箇所は、Deviceと記載されている場合もあります。