Azure NetApp Filesのパフォーマンス

Azureにおいて高速なストレージが必要な場合、Azure NetApp Files(ANF)が候補となるため、そのパフォーマンスを見てみました。
ANFのパフォーマンス(スループット)は以下の要素で決まります。

- 容量プールのサービスレベル
- 容量プールのQoSの種類 (自動/手動)
- ボリュームのクオータ(容量)

# サービスレベル
| Standard | Premium | Ultra |
|:-:|:-:|:-:|
| 16MiB/s /TiB | 64MiB/s /TiB | 128MiB/s /TiB |
> 出典: [サポートされているサービス レベル](https://docs.microsoft.com/ja-jp/azure/azure-netapp-files/azure-netapp-files-service-levels#supported-service-levels)
> **最大**パフォーマンスという定義です。

# パフォーマンスの考え方 (スループットの例)
- サービスレベル：Standard
- 容量プール：4TiB
- QoSの種類: Auto

この場合の容量プール全体のスループットは、 16 MiB/s (Standard) x 4 TiB = **64 MiB/s**となります。
実際のスループットはボリュームのクオータに依存します。注意すべきは、TiB単位に階段状になるのではなく、そのクオータに比例した直線状になるという点です。
グラフにするとこんな感じです。

![diagram1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/ab59e7bb-f748-2f6c-bd14-c1e9773576da.png)

このグラフにあるように、1TiBのクオータの場合は16MiB/sですが、その1/10の100GiBだとスループットも1/10の**1.6MiB/s**になるはずです。
実際に見てみます。
ANFのボリュームは下記のように設定してあります。
![anf1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/2d4fd442-4897-d44f-ea83-1bf5d95d6e0e.png)
計測するマシンは、同じVNet内の異なるサブネットに、`Standard D2s v3 (2 vcpu 数、8 GiB メモリ)`のVMを作り、`Oracle Linux 7.8`を立て、NFS v3でマウントしています。

```
[root@myoracle myvol1]# fio -rw=randwrite -bs=8k -size=1000m -numjobs=40 -runtime=180 -direct=1 -invalidate=1 -ioengine=libaio -iodepth=32 -iodepth_batch=32 -group_reporting -name=S_randwrite
S_randwrite: (g=0): rw=randwrite, bs=(R) 8192B-8192B, (W) 8192B-8192B, (T) 8192B-8192B, ioengine=libaio, iodepth=32
...
fio-3.7
Starting 40 processes
S_randwrite: Laying out IO file (1 file / 1000MiB)
[omit]
Jobs: 40 (f=40): [w(40)][0.5%][r=0KiB/s,w=0KiB/s][r=0,w=0 IOPS][eta 10h:35m:52s]
S_randwrite: (groupid=0, jobs=40): err= 0: pid=10928: Sat Nov 28 02:28:14 2020
  write: IOPS=205, BW=1643KiB/s (1682kB/s)(299MiB/186241msec)
    slat (usec): min=3, max=829, avg=17.54, stdev=32.95
    clat (usec): min=541, max=12110k, avg=5405716.02, stdev=1759453.37
     lat (usec): min=767, max=12110k, avg=5405733.60, stdev=1759444.74
    clat percentiles (msec):
     |  1.00th=[  776],  5.00th=[ 1586], 10.00th=[ 2400], 20.00th=[ 4010],
     | 30.00th=[ 5604], 40.00th=[ 6275], 50.00th=[ 6275], 60.00th=[ 6275],
     | 70.00th=[ 6275], 80.00th=[ 6275], 90.00th=[ 6275], 95.00th=[ 6275],
     | 99.00th=[10134], 99.50th=[11342], 99.90th=[12147], 99.95th=[12147],
     | 99.99th=[12147]
   bw (  KiB/s): min=   15, max= 1232, per=2.91%, avg=47.86, stdev=36.98, samples=12351
   iops        : min=    1, max=  154, avg= 5.91, stdev= 4.63, samples=12351
  lat (usec)   : 750=0.01%, 1000=0.01%
  lat (msec)   : 2=0.04%, 4=0.11%, 10=0.11%, 20=0.01%, 50=0.02%
  lat (msec)   : 100=0.03%, 250=0.08%, 500=0.13%, 750=0.44%, 1000=0.89%
  cpu          : usr=0.01%, sys=0.01%, ctx=28510, majf=0, minf=295
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=98.3%, >=64=0.0%
     submit    : 0=0.0%, 4=99.9%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=99.9%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,38246,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=1643KiB/s (1682kB/s), 1643KiB/s-1643KiB/s (1682kB/s-1682kB/s), io=299MiB (313MB), run=186241-186241msec
[root@myoracle myvol1]#
```
`1643KiB/s` = `1.604492MiB/s`ということで、きれいに**`1.6MiB/s`**出ています。

クオータを1TiBにした結果はこちら。

```
Jobs: 40 (f=40): [w(40)][100.0%][r=0KiB/s,w=16.0MiB/s][r=0,w=2050 IOPS][eta 00m:00s]
S_randwrite: (groupid=0, jobs=40): err= 0: pid=52433: Sat Nov 28 05:29:43 2020
  write: IOPS=2053, BW=16.0MiB/s (16.8MB/s)(2898MiB/180625msec)
    slat (usec): min=3, max=3915, avg=11.19, stdev=19.40
    clat (usec): min=946, max=4980.2k, avg=614004.21, stdev=68499.18
     lat (usec): min=1218, max=4980.2k, avg=614015.45, stdev=68496.10
    clat percentiles (msec):
     |  1.00th=[  253],  5.00th=[  584], 10.00th=[  617], 20.00th=[  617],
     | 30.00th=[  617], 40.00th=[  617], 50.00th=[  617], 60.00th=[  634],
     | 70.00th=[  634], 80.00th=[  634], 90.00th=[  634], 95.00th=[  634],
     | 99.00th=[  684], 99.50th=[  726], 99.90th=[ 1053], 99.95th=[ 1133],
     | 99.99th=[ 1217]
   bw (  KiB/s): min=   15, max= 4080, per=2.53%, avg=415.63, stdev=87.15, samples=14230
   iops        : min=    1, max=  510, avg=51.88, stdev=10.90, samples=14230
  lat (usec)   : 1000=0.01%
  lat (msec)   : 2=0.01%, 4=0.04%, 10=0.21%, 20=0.05%, 50=0.02%
  lat (msec)   : 100=0.03%, 250=0.61%, 500=2.60%, 750=96.07%, 1000=0.24%
  cpu          : usr=0.05%, sys=0.08%, ctx=273832, majf=0, minf=322
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=99.8%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,370980,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=16.0MiB/s (16.8MB/s), 16.0MiB/s-16.0MiB/s (16.8MB/s-16.8MB/s), io=2898MiB (3039MB), run=180625-180625msec
[root@myoracle myvol1]#
```
ピッタリスペック通りの、**`16.0MiB/s`**。
クオータを4TiBにした時の結果。

```
Jobs: 40 (f=40): [w(40)][100.0%][r=0KiB/s,w=65.7MiB/s][r=0,w=8414 IOPS][eta 00m:00s]
S_randwrite: (groupid=0, jobs=40): err= 0: pid=52870: Sat Nov 28 05:36:48 2020
  write: IOPS=8413, BW=65.7MiB/s (68.9MB/s)(11.6GiB/180159msec)
    slat (usec): min=3, max=4798, avg= 9.36, stdev=17.72
    clat (usec): min=1111, max=648239, avg=151803.55, stdev=12171.43
     lat (usec): min=1176, max=648245, avg=151812.95, stdev=12170.21
    clat percentiles (msec):
     |  1.00th=[  133],  5.00th=[  144], 10.00th=[  146], 20.00th=[  146],
     | 30.00th=[  153], 40.00th=[  153], 50.00th=[  155], 60.00th=[  155],
     | 70.00th=[  155], 80.00th=[  155], 90.00th=[  157], 95.00th=[  163],
     | 99.00th=[  178], 99.50th=[  192], 99.90th=[  245], 99.95th=[  271],
     | 99.99th=[  330]
   bw (  KiB/s): min=   80, max= 7584, per=2.50%, avg=1684.57, stdev=165.54, samples=14381
   iops        : min=   10, max=  948, avg=210.53, stdev=20.70, samples=14381
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.03%, 20=0.05%, 50=0.27%
  lat (msec)   : 100=0.38%, 250=99.17%, 500=0.09%, 750=0.01%
  cpu          : usr=0.17%, sys=0.28%, ctx=1133970, majf=0, minf=301
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=100.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,1515744,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=65.7MiB/s (68.9MB/s), 65.7MiB/s-65.7MiB/s (68.9MB/s-68.9MB/s), io=11.6GiB (12.4GB), run=180159-180159msec
[root@myoracle myvol1]#
```
想定は`64MiB/s`でしたのでちょっと頑張っちゃったようですが、**`65.7MiB/s`**。実際には、このあとの手動設定をやってみるとわかるのですが、ドキュメント記載の値より最大値が若干大きいようです。

ボリュームのクオータ(容量)は、増やすだけでなく減らすこともできます。このクオータを任意にオンライン状態のまま接続元に全く影響を与えず増減できることで、例えばWVDでログインが集中する時間のみパフォーマンスを上げたり、月次バッチの処理を速めるようなシナリオで使えると思われます。

## 複数ボリュームの場合
ここまでは1ボリュームでしたが、複数のボリュームを作成した時の関係を見るとより理解が深まります。
![diagram2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/609dbe43-7e0a-3f61-8d70-5f1623b46844.png)
同じ条件

- サービスレベル：Standard
- 容量プール：4TB
- QoSの種類: Auto

で、このように2ボリューム(クオータ)を作成した場合、全体のスループット`64MiB/s`をそのクオータに応じて自動的に案分します。これはQoSの種類が`Auto`の場合です。

| ボリューム | 想定最大スループット |
|:-:|:-:|
| Vol1 | 16MiB/s |
| Vol2 | 48MiB/s |

### Vol1
```
S_randwrite: (groupid=0, jobs=40): err= 0: pid=56324: Sat Nov 28 06:24:06 2020
  write: IOPS=2103, BW=16.4MiB/s (17.2MB/s)(2967MiB/180609msec)
    slat (usec): min=3, max=4430, avg=10.70, stdev=32.09
    clat (usec): min=859, max=1191.2k, avg=599523.27, stdev=65723.18
     lat (usec): min=866, max=1191.2k, avg=599534.01, stdev=65719.69
    clat percentiles (msec):
     |  1.00th=[  241],  5.00th=[  600], 10.00th=[  609], 20.00th=[  609],
     | 30.00th=[  609], 40.00th=[  609], 50.00th=[  609], 60.00th=[  609],
     | 70.00th=[  609], 80.00th=[  609], 90.00th=[  609], 95.00th=[  609],
     | 99.00th=[  617], 99.50th=[  617], 99.90th=[  995], 99.95th=[ 1099],
     | 99.99th=[ 1183]
   bw (  KiB/s): min=   15, max= 4774, per=2.53%, avg=425.82, stdev=95.52, samples=14222
   iops        : min=    1, max=  596, avg=53.16, stdev=11.94, samples=14222
  lat (usec)   : 1000=0.01%
  lat (msec)   : 2=0.01%, 4=0.06%, 10=0.18%, 20=0.05%, 50=0.03%
  lat (msec)   : 100=0.03%, 250=0.76%, 500=2.55%, 750=96.10%, 1000=0.15%
  cpu          : usr=0.05%, sys=0.08%, ctx=273759, majf=0, minf=298
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=99.8%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,379829,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=16.4MiB/s (17.2MB/s), 16.4MiB/s-16.4MiB/s (17.2MB/s-17.2MB/s), io=2967MiB (3112MB), run=180609-180609msec
[root@myoracle myvol1]#
```
結果は、**`16.4MiB/s`**。

### Vol2
```
S_randwrite: (groupid=0, jobs=40): err= 0: pid=10740: Sat Nov 28 06:23:55 2020
  write: IOPS=6309, BW=49.3MiB/s (51.7MB/s)(8883MiB/180206msec)
    slat (usec): min=2, max=6090, avg=12.01, stdev=26.24
    clat (usec): min=626, max=455432, avg=202030.27, stdev=19136.84
     lat (usec): min=845, max=455438, avg=202042.31, stdev=19135.56
    clat percentiles (msec):
     |  1.00th=[  144],  5.00th=[  186], 10.00th=[  192], 20.00th=[  194],
     | 30.00th=[  197], 40.00th=[  201], 50.00th=[  203], 60.00th=[  203],
     | 70.00th=[  205], 80.00th=[  211], 90.00th=[  215], 95.00th=[  230],
     | 99.00th=[  251], 99.50th=[  257], 99.90th=[  292], 99.95th=[  326],
     | 99.99th=[  384]
   bw (  KiB/s): min=   32, max= 9488, per=2.51%, avg=1265.42, stdev=181.60, samples=14356
   iops        : min=    4, max= 1186, avg=158.11, stdev=22.70, samples=14356
  lat (usec)   : 750=0.01%
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.01%, 20=0.08%, 50=0.40%
  lat (msec)   : 100=0.06%, 250=98.38%, 500=1.05%
  cpu          : usr=0.14%, sys=0.26%, ctx=935388, majf=0, minf=300
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=100.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,1137036,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=49.3MiB/s (51.7MB/s), 49.3MiB/s-49.3MiB/s (51.7MB/s-51.7MB/s), io=8883MiB (9315MB), run=180206-180206msec
[root@myoracle2 myvol2]#
```
結果は、**`49.3MiB/s`**。
> 異なる同スペックのVMから同じ容量プールの異なるボリュームに対して同時に実行しています。これは同じVMから同時に`fio`を実行すると、VM側のオーバーヘッドにより正しく計測できないためです。

# パフォーマンス(スループット)の手動設定
ボリュームの容量(クオータ)によって自動的に設定されるのではなく、ボリュームの用途に合わせて手動で設定することもできます。
例えばテーブルデータは容量はコンパクトだけれども高速に(**Vol1**)、アーカイブデータは容量が大きいけれどもそれなりに(**Vol2**)、というような場合です。
![diagram3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/ec46137a-37c0-5404-2fcd-f94fb8595478.png)

この例では、**Vol1**に1TiB割り当て`48MiB/s`を、**Vol2**に3TiB割り当て`16MiB/s`を設定しています。

手動で設定するには、容量プールでQoSの種類を切り替えます。一度切り替えると元には戻せません。
![anf2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/a10ebc8d-4745-af75-ef34-20e0aea25921.png)

実際のスループットは、それぞれのボリュームで設定します。
![anf3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/20610311-8041-8f92-1e7a-1d2ad89084e1.png)

### Vol1
```
S_randwrite: (groupid=0, jobs=40): err= 0: pid=58980: Sat Nov 28 07:03:14 2020
  write: IOPS=6162, BW=48.1MiB/s (50.5MB/s)(8676MiB/180211msec)
    slat (usec): min=3, max=13209, avg= 9.49, stdev=24.58
    clat (usec): min=1081, max=428940, avg=206872.29, stdev=17332.96
     lat (usec): min=1275, max=428947, avg=206881.82, stdev=17331.57
    clat percentiles (msec):
     |  1.00th=[  148],  5.00th=[  197], 10.00th=[  199], 20.00th=[  199],
     | 30.00th=[  207], 40.00th=[  209], 50.00th=[  209], 60.00th=[  209],
     | 70.00th=[  209], 80.00th=[  211], 90.00th=[  220], 95.00th=[  222],
     | 99.00th=[  239], 99.50th=[  253], 99.90th=[  300], 99.95th=[  330],
     | 99.99th=[  384]
   bw (  KiB/s): min=   64, max= 9053, per=2.51%, avg=1236.12, stdev=178.34, samples=14354
   iops        : min=    8, max= 1131, avg=154.46, stdev=22.29, samples=14354
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.07%, 20=0.02%, 50=0.36%
  lat (msec)   : 100=0.07%, 250=98.91%, 500=0.55%
  cpu          : usr=0.12%, sys=0.21%, ctx=817040, majf=0, minf=297
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=100.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,1110475,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=48.1MiB/s (50.5MB/s), 48.1MiB/s-48.1MiB/s (50.5MB/s-50.5MB/s), io=8676MiB (9097MB), run=180211-180211msec
[root@myoracle myvol1]#
```
結果は、**`48.1MiB/s`**。
### Vol2
```
S_randwrite: (groupid=0, jobs=40): err= 0: pid=14439: Sat Nov 28 07:03:18 2020
  write: IOPS=2053, BW=16.0MiB/s (16.8MB/s)(2898MiB/180629msec)
    slat (usec): min=2, max=7577, avg=14.40, stdev=68.24
    clat (usec): min=531, max=1222.1k, avg=612928.24, stdev=70855.22
     lat (usec): min=1650, max=1222.2k, avg=612942.69, stdev=70846.76
    clat percentiles (msec):
     |  1.00th=[  222],  5.00th=[  600], 10.00th=[  617], 20.00th=[  617],
     | 30.00th=[  617], 40.00th=[  617], 50.00th=[  617], 60.00th=[  634],
     | 70.00th=[  634], 80.00th=[  634], 90.00th=[  634], 95.00th=[  634],
     | 99.00th=[  642], 99.50th=[  667], 99.90th=[ 1020], 99.95th=[ 1133],
     | 99.99th=[ 1217]
   bw (  KiB/s): min=   15, max= 4736, per=2.53%, avg=416.31, stdev=100.51, samples=14206
   iops        : min=    1, max=  592, avg=51.94, stdev=12.57, samples=14206
  lat (usec)   : 750=0.01%
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.07%, 20=0.22%, 50=0.03%
  lat (msec)   : 100=0.03%, 250=0.89%, 500=2.41%, 750=96.05%, 1000=0.16%
  cpu          : usr=0.06%, sys=0.09%, ctx=297901, majf=0, minf=298
  IO depths    : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=99.8%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,370974,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: bw=16.0MiB/s (16.8MB/s), 16.0MiB/s-16.0MiB/s (16.8MB/s-16.8MB/s), io=2898MiB (3039MB), run=180629-180629msec
[root@myoracle2 myvol2]#
```
結果は、**`16.0MiB/s`**。

実際の利用例として、[SAP HANAのものがdocs](https://docs.microsoft.com/ja-jp/azure/azure-netapp-files/azure-netapp-files-service-levels#throughput-limit-examples-of-volumes-in-a-manual-qos-capacity-pool)にあります。
![qos-sap-hana-volume-scenarios.png](https://docs.microsoft.com/ja-jp/azure/media/azure-netapp-files/qos-sap-hana-volume-scenarios.png)

# 参考
- [Azure NetApp Filesクイックスタート](https://docs.microsoft.com/ja-jp/azure/azure-netapp-files/azure-netapp-files-quickstart-set-up-account-create-volumes?tabs=azure-portal)
- [Azure NetApp Files のサービス レベル](https://docs.microsoft.com/ja-jp/azure/azure-netapp-files/azure-netapp-files-service-levels)
- [Azure NetApp Files のパフォーマンスに関する考慮事項](https://docs.microsoft.com/ja-jp/azure/azure-netapp-files/azure-netapp-files-performance-considerations)