目的
近年、IoT の普及等の影響から、分散型アーキテクチャのエッジコンピューティングが注目を集めている。
エッジコンピューティングでは IoT 端末などのデバイスそのものや、近くに設置されたサーバでデータ処理・分析を行う。
この時、クラウドにデータを送らず、エッジ側でデータの処理・分析を行うためリアルタイム性が高く、負荷が分散されることで通信の遅延も起こりにくいという特徴を持つ。
エッジコンピューティングで求められるリアルタイム性にはデバイス間の物理的な距離が大きく関係する。
しかし、この物理的な距離を実現するために違うロケーションにデバイスを準備することは非効率である。
そこで、本記事では Linux ルータにてパケット遅延/ロスを再現する。
これにより、社内などのローカル空間であってもエッジ-クラウド間など、デバイス間の物理的な距離を再現できる。
構成
Linux Machine (Ubuntu 20.04) を 3 台を使用し、下記の構成を作成する。
- edge (192.168.30.0/24)
- 192.168.30.1
- router
- 10.100.2.45 (外部疎通用 IP)
- 192.168.20.254
- 192.168.30.254
- cloud (192.168.20.0/24)
- 192.168.20.1
手順
iptables-persistent
- 対象: router
iptables に NAT の設定を追加する。
再起動時に iptables の設定を削除されないようにするために iptables-persistent をインストールする。
下記コマンドで iptables-persistent のインストール可否を確認できる。
dpkg -l | grep iptables-persistent
iptables-persistent をインストールする。
この時、IPv4, IPv6 の設定は保持させる。
sudo apt install iptables-persistent
インストール後、iptables-persistent の有無を確認すると、下記のように確認できる。
$ dpkg -l | grep iptables-persistent
ii iptables-persistent 1.0.14ubuntu1 all boot-time loader for netfilter rules, iptables plugin
IP フォワード
- 対象: router
既存の IP フォワード設定を確認する。
デフォルトの設定では下記のようにコメントアウトされている。
$ grep net.ipv4.ip_forward /etc/sysctl.conf
#net.ipv4.ip_forward=1
コメントアウトを解除し、IP フォワードの設定値を変更する。
$ grep net.ipv4.ip_forward /etc/sysctl.conf
net.ipv4.ip_forward=1
NAT の設定
- 対象: router
現状の NAT 設定を確認する。
$ cat /etc/iptables/rules.v4
# Generated by iptables-save v1.8.4 on Thu Apr 20 10:10:21 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Thu Apr 20 10:10:21 2023
下記を実行することで NAT 設定が可能である。
今回は edge, cloud の両方が外部と疎通可能となるように設定している。
sudo iptables -t nat -A POSTROUTING -s 192.168.30.0/24 -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 192.168.20.0/24 -o eth0 -j MASQUERADE
Traffic Control
前確認
- 対象: edge, cloud
ping, iperf3 コマンドで疎通確認をする。
iperf3 コマンドのインストールする。
sudo apt install iperf3
- 対象: cloud
cloud-host:~$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.30.1, port 38368
[ 5] local 192.168.20.1 port 5201 connected to 192.168.30.1 port 38370
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 2.14 GBytes 18.4 Gbits/sec
[ 5] 1.00-2.00 sec 2.19 GBytes 18.8 Gbits/sec
[ 5] 2.00-3.00 sec 2.26 GBytes 19.4 Gbits/sec
[ 5] 3.00-4.00 sec 2.25 GBytes 19.3 Gbits/sec
[ 5] 4.00-5.00 sec 2.24 GBytes 19.3 Gbits/sec
[ 5] 5.00-6.00 sec 2.29 GBytes 19.6 Gbits/sec
[ 5] 6.00-7.00 sec 2.29 GBytes 19.7 Gbits/sec
[ 5] 7.00-8.00 sec 2.29 GBytes 19.7 Gbits/sec
[ 5] 8.00-9.00 sec 2.27 GBytes 19.5 Gbits/sec
[ 5] 9.00-10.00 sec 2.25 GBytes 19.3 Gbits/sec
[ 5] 10.00-10.00 sec 2.82 MBytes 18.4 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 22.5 GBytes 19.3 Gbits/sec receiver
- 対象: edge
現状は Bitrate に約 20G, ping の遅延も特に発生していない状態である。
edge-host:~$ sudo iperf3 -c 192.168.20.1
Connecting to host 192.168.20.1, port 5201
[ 5] local 192.168.30.1 port 38370 connected to 192.168.20.1 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 2.14 GBytes 18.4 Gbits/sec 0 3.04 MBytes
[ 5] 1.00-2.00 sec 2.19 GBytes 18.8 Gbits/sec 0 3.04 MBytes
[ 5] 2.00-3.00 sec 2.26 GBytes 19.4 Gbits/sec 0 3.04 MBytes
[ 5] 3.00-4.00 sec 2.25 GBytes 19.3 Gbits/sec 0 3.04 MBytes
[ 5] 4.00-5.00 sec 2.24 GBytes 19.3 Gbits/sec 0 3.04 MBytes
[ 5] 5.00-6.00 sec 2.29 GBytes 19.6 Gbits/sec 0 3.04 MBytes
[ 5] 6.00-7.00 sec 2.29 GBytes 19.7 Gbits/sec 0 3.04 MBytes
[ 5] 7.00-8.00 sec 2.29 GBytes 19.7 Gbits/sec 0 3.04 MBytes
[ 5] 8.00-9.00 sec 2.28 GBytes 19.5 Gbits/sec 0 3.04 MBytes
[ 5] 9.00-10.00 sec 2.25 GBytes 19.3 Gbits/sec 0 3.04 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 22.5 GBytes 19.3 Gbits/sec 0 sender
[ 5] 0.00-10.00 sec 22.5 GBytes 19.3 Gbits/sec receiver
iperf Done.
edge-host:~$ ping 192.168.20.1
PING 192.168.20.1 (192.168.20.1) 56(84) bytes of data.
64 bytes from 192.168.20.1: icmp_seq=1 ttl=63 time=0.615 ms
64 bytes from 192.168.20.1: icmp_seq=2 ttl=63 time=0.408 ms
64 bytes from 192.168.20.1: icmp_seq=3 ttl=63 time=0.445 ms
64 bytes from 192.168.20.1: icmp_seq=4 ttl=63 time=0.489 ms
64 bytes from 192.168.20.1: icmp_seq=5 ttl=63 time=0.484 ms
64 bytes from 192.168.20.1: icmp_seq=6 ttl=63 time=0.409 ms
^C
--- 192.168.20.1 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5104ms
rtt min/avg/max/mdev = 0.408/0.475/0.615/0.070 ms
- 対象: router
qdisc とは Queueing discipline のことであり、パケットを一時的に格納し、順番を並べ替えたり、遅延させたり、破棄したりすることができる。
初期状態の qdisc を確認する。
$ tc qdisc show
qdisc noqueue 0: dev lo root refcnt 2
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
qdisc fq_codel 0: dev eth1 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
qdisc fq_codel 0: dev eth2 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
レイテンシを大きくする
- 対象: router
インターフェースの情報を確認する。
router:~$ ip -c a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 5a:71:6f:5f:5f:e4 brd ff:ff:ff:ff:ff:ff
inet 10.100.2.45/22 brd 10.100.3.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5871:6fff:fe5f:5fe4/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 3e:14:39:9a:85:0f brd ff:ff:ff:ff:ff:ff
inet 192.168.20.254/24 brd 192.168.20.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::3c14:39ff:fe9a:850f/64 scope link
valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether ae:d0:2b:52:35:40 brd ff:ff:ff:ff:ff:ff
inet 192.168.30.254/24 brd 192.168.30.255 scope global eth2
valid_lft forever preferred_lft forever
inet6 fe80::acd0:2bff:fe52:3540/64 scope link
valid_lft forever preferred_lft forever
100ms のジッターのある 200ms のディレイを挿入する
sudo tc qdisc add dev eth1 root netem delay 200ms 100ms
上記設定後の qdisc を確認する。
$ tc qdisc show
qdisc noqueue 0: dev lo root refcnt 2
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
qdisc netem 8001: dev eth1 root refcnt 2 limit 1000 delay 200.0ms 100.0ms
qdisc fq_codel 0: dev eth2 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
- 対象: edge
ping の状況を確認すると遅延していることがわかる。
edge-host:~$ ping 192.168.20.1
...
64 bytes from 192.168.20.1: icmp_seq=637 ttl=63 time=0.380 ms
64 bytes from 192.168.20.1: icmp_seq=638 ttl=63 time=0.409 ms
64 bytes from 192.168.20.1: icmp_seq=639 ttl=63 time=0.372 ms
64 bytes from 192.168.20.1: icmp_seq=640 ttl=63 time=0.340 ms
64 bytes from 192.168.20.1: icmp_seq=641 ttl=63 time=0.517 ms
64 bytes from 192.168.20.1: icmp_seq=642 ttl=63 time=205 ms
64 bytes from 192.168.20.1: icmp_seq=643 ttl=63 time=235 ms
64 bytes from 192.168.20.1: icmp_seq=644 ttl=63 time=238 ms
64 bytes from 192.168.20.1: icmp_seq=645 ttl=63 time=181 ms
- 対象: router
追加した qdisc を削除する。
sudo tc qdisc delete dev eth1 root
パケットロスを生じさせる
- 対象: router
30% のパケットをロスさせる。
sudo tc qdisc add dev eth1 root netem loss random 30%
- 対象: edge
ping で確認する。
約 30% のパケットがロスしていることがわかる。
edge-host:~$ ping 192.168.20.1
...
^C
--- 192.168.20.1 ping statistics ---
100 packets transmitted, 73 received, 27% packet loss, time 101380ms
rtt min/avg/max/mdev = 0.297/0.374/0.526/0.046 ms
まとめ
tc コマンドを利用することで容易にパケットのコントロールが可能である。
今回はパケットの遅延とロスのみを試したが、データの破損やパケットの重複、帯域制限なども実行可能である。
これらを活用することで、本記事の物理的な距離再現以外に再現可能な事象は多く存在する。
例えば、迂回路の検証や通信負荷の検知検証なども同様の手法で再現可能であると考えている。
- 迂回路の検証
- 作成した迂回路上のインターフェースでパケットロス・遅延を発生させ、設定した迂回路を正しく利用できるか検証
- 通信負荷の検知検証
- 帯域を制限することで疑似的な通信負荷を再現