自鯖k8s導入の準備

自鯖にk8sを導入してそこでコンテナを運用してみようと思っている。
どのような構成にしたほうがいいのか、なにか障害となる要素がないかなどをClaudeと相談していた。
細かく現在の状態や理想の最終形態を送ってみると、まずディスクの書き込みレイテンシを確認しろと言われた。
k8sにとってetcdは基幹部分であり、記憶を司る者。(かっこよすぎる)
これだけ聞くとそこまで書き込まないように思うが、クラスタ内のあらゆる状態がここに保存されるため、ここの書き込みが遅いと他のetcdも巻き込んでどんどん遅くなる。
果てにはリーダー選挙にも応答が間に合わなくなり、生きてるのに死んだことにされたりするらしい。
下に分かりやすいフロー。書き込みの重要性がよくわかる。
etcdというよりRaftという分散合意アルゴリズムの話ではある。
クライアント → リーダーが WAL に fsync
→ フォロワーへ複製(ネットワーク)
→ 各フォロワーも WAL に fsync
→ 過半数の ACK が戻る
→ コミット確定 → 応答
そんなこんなでまずは現状の確認をした。
なお、すべてのfioの結果はVM内のもの。Proxmox側で測ってもあまり意味がない。
現状
ログ: fio
$ fio --name=fsync --rw=write --ioengine=sync --fdatasync=1 \
--bs=2300 --size=22m --runtime=60 --numjobs=1
fsync: (g=0): rw=write, bs=(R) 2300B-2300B, (W) 2300B-2300B, (T) 2300B-2300B, ioengine=sync, iodepth=1
fio-3.39
Starting 1 process
fsync: Laying out IO file (1 file / 22MiB)
Jobs: 1 (f=1): [W(1)][100.0%][w=209KiB/s][w=93 IOPS][eta 00m:00s]
fsync: (groupid=0, jobs=1): err= 0: pid=2309: Sun Aug 2 23:46:22 2026
write: IOPS=92, BW=209KiB/s (214kB/s)(12.2MiB/60004msec); 0 zone resets
clat (usec): min=11, max=1333, avg=35.80, stdev=22.88
lat (usec): min=12, max=1334, avg=36.79, stdev=26.83
clat percentiles (usec):
| 1.00th=[ 16], 5.00th=[ 17], 10.00th=[ 19], 20.00th=[ 22],
| 30.00th=[ 26], 40.00th=[ 34], 50.00th=[ 35], 60.00th=[ 39],
| 70.00th=[ 41], 80.00th=[ 46], 90.00th=[ 55], 95.00th=[ 62],
| 99.00th=[ 82], 99.50th=[ 94], 99.90th=[ 133], 99.95th=[ 139],
| 99.99th=[ 1336]
bw ( KiB/s): min= 161, max= 233, per=99.65%, avg=208.65, stdev=11.23, samples=119
iops : min= 72, max= 104, avg=93.05, stdev= 4.99, samples=119
lat (usec) : 20=15.71%, 50=71.47%, 100=12.48%, 250=0.30%, 500=0.02%
lat (msec) : 2=0.02%
fsync/fdatasync/sync_file_range:
sync (msec): min=4, max=109, avg=10.72, stdev= 6.97
sync percentiles (msec):
| 1.00th=[ 5], 5.00th=[ 5], 10.00th=[ 5], 20.00th=[ 5],
| 30.00th=[ 5], 40.00th=[ 5], 50.00th=[ 14], 60.00th=[ 14],
| 70.00th=[ 14], 80.00th=[ 14], 90.00th=[ 16], 95.00th=[ 19],
| 99.00th=[ 37], 99.50th=[ 39], 99.90th=[ 60], 99.95th=[ 71],
| 99.99th=[ 110]
cpu : usr=0.23%, sys=1.48%, ctx=16529, majf=0, minf=9
IO depths : 1=200.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,5576,0,0 short=5576,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=209KiB/s (214kB/s), 209KiB/s-209KiB/s (214kB/s-214kB/s), io=12.2MiB (12.8MB), run=60004-60004msec
Disk stats (read/write):
sda: ios=0/14377, sectors=0/145944, merge=0/6273, ticks=0/58930, in_queue=62388, util=96.66%
fsync/fdatasync のp99は37msだった。
閾値は10msなので圧倒的に足りない。
しかもこれはシングルスレッドでの計測値だ。
3メンバーstackedにするとうちの場合は物理鯖が一台のため、Raftのコミット1回につき3メンバーすべてが同一デバイスに流すことになる。
そうすると実効的なp99は50〜100ms帯まで悪化するだろうという結論になった。
RAIDカード
上記のログを投げて相談を進めていくと以下のように言われた。
原因の推定:writethrough に落ちている可能性が高い
分布が明確にバイモーダルなのが手がかりです。p1〜p30 が 5ms、p50〜p80 が 14ms と、2つの山に分かれています。
BBU 付き writeback が効いていれば、fsync はコントローラの DRAM で完了するので 0.1〜0.5ms になるはずです。5ms/14ms という値は、fsync が SSD の NAND まで抜けている挙動そのものです。
そしてRAIDカードのキャッシュ関連の設定はどうなっているかと聞かれた。
たしかにBBU付きなのは知っているが、アレイ構築時にキャッシュを設定した記憶はない。
なのでProxmox上から確認してみる。
Proxmox(ホスト)にssacliを導入
最新版はここから確認
HPE Smart Storage Administrator (HPE SSA) CLI for Linux 64ビット | HPE Support
※ 環境を汚したくなかったので別環境で解凍した
# 雑な Debian 鯖で
apt install rpm2cpio
curl -fL -o "ssacli-4.21-7.0.x86_64.rpm" https://downloads.hpe.com/pub/softlib2/software1/pubsw-linux/p1857046646/v183344/ssacli-4.21-7.0.x86_64.rpm
rpm2cpio ssacli-4.21-7.0.x86_64.rpm | cpio -idmv
# opt/ usr/ が出てくるので tar で固めて Proxmox へ転送
# Proxmox で解凍して
mv opt/smartstorageadmin opt/
cd usr/sbin/
./ssacli # 使えるようになる
ログ: show detail
# ssacli ctrl slot=0 show detail
HPE Smart Array P408i-a SR Gen10 in Slot 0 (Embedded)
Bus Interface: PCI
Slot: 0
Serial Number: ***HIDDEN***
RAID 6 (ADG) Status: Enabled
Controller Status: OK
Hardware Revision: B
Firmware Version: 6.52-0
Firmware Supports Online Firmware Activation: False
Rebuild Priority: High
Expand Priority: Medium
Surface Scan Delay: 3 secs
Surface Scan Mode: Idle
Parallel Surface Scan Supported: Yes
Current Parallel Surface Scan Count: 1
Max Parallel Surface Scan Count: 16
Queue Depth: Automatic
Monitor and Performance Delay: 60 min
Elevator Sort: Enabled
Degraded Performance Optimization: Disabled
Inconsistency Repair Policy: Disabled
Write Cache Bypass Threshold Size: 1040 KiB
Wait for Cache Room: Disabled
Surface Analysis Inconsistency Notification: Disabled
Post Prompt Timeout: 15 secs
Cache Board Present: True
Cache Status: Not Configured
Configured Drive Write Cache Policy: Disable
Unconfigured Drive Write Cache Policy: Default
Total Cache Size: 2.0
Total Cache Memory Available: 1.8
No-Battery Write Cache: Disabled
SSD Caching RAID5 WriteBack Enabled: True
SSD Caching Version: 2
Cache Backup Power Source: Batteries
Battery/Capacitor Count: 1
Battery/Capacitor Status: OK
SATA NCQ Supported: True
Spare Activation Mode: Activate on physical drive failure (default)
Controller Temperature (C): 57
Number of Ports: 2 Internal only
Encryption: Not Set
Driver Name: smartpqi
Driver Version: Linux 2.1.34-035
PCI Address (Domain:Bus:Device.Function): 0000:5D:00.0
Negotiated PCIe Data Rate: PCIe 3.0 x8 (7880 MB/s)
Controller Mode: Mixed
Port Max Phy Rate Limiting Supported: False
Latency Scheduler Setting: Disabled
Current Power Mode: MaxPerformance
Survival Mode: Enabled
Host Serial Number: JPN830402B
Sanitize Erase Supported: True
Sanitize Lock: None
Sensor ID: 0
Location: Inlet Ambient
Current Value (C): 49
Max Value Since Power On: 51
Sensor ID: 1
Location: ASIC
Current Value (C): 57
Max Value Since Power On: 59
Sensor ID: 2
Location: Top
Current Value (C): 48
Max Value Since Power On: 50
Primary Boot Volume: None
Secondary Boot Volume: None
ログ: ld all show detail
# ssacli ctrl slot=0 ld all show detail
HPE Smart Array P408i-a SR Gen10 in Slot 0 (Embedded)
Array A
Logical Drive: 1
Size: 931.48 GB
Fault Tolerance: 1adm
Heads: 255
Sectors Per Track: 32
Cylinders: 65535
Strip Size: 256 KB
Full Stripe Size: 256 KB
Status: OK
Unrecoverable Media Errors: None
MultiDomain Status: OK
Caching: Disabled
Unique Identifier: 1145141919810
Disk Name: /dev/sda
Mount Points: 1024 MiB Partition 2 /boot/efi
Disk Partition Information
Partition 2: Basic, 1024 MiB, /boot/efi
Logical Drive Label: Logical Drive 1
Mirror Group 1:
physicaldrive 1I:1:3 (port 1I:box 1:bay 3, SATA SED SSD, 1 TB, OK)
Mirror Group 2:
physicaldrive 1I:1:2 (port 1I:box 1:bay 2, SATA SED SSD, 1 TB, OK)
Mirror Group 3:
physicaldrive 1I:1:1 (port 1I:box 1:bay 1, SATA SED SSD, 1 TB, OK)
Drive Type: Data
LD Acceleration Method: Smart Path
Smart Pathが有効なことが原因であると判明した。
これは「SSDならコントローラのキャッシュやファームウェアを通すより直でドライブに投げたほうが速いっしょw」という機能であり、そのためキャッシュが無効になっていた。
なので3枚で組まれたRAID 1 TripleのSSDすべての書き込みの完了を待っていて37msもかかっていた模様。
なお、このRAIDカードのキャッシュはFBWC(フラッシュバックアップ式ライトキャッシュ)である。
コントローラのキャッシュを使うように設定を変更する。
ただしSmart Pathはランダムリードのレイテンシに効いていたためそれは失われることになる。
しかしメモリが潤沢にある自宅鯖ではVMのページキャッシュやホスト側で吸収できるだろうという見立て。
それにプラスで1:9でのキャッシュに設定するので一応200MBのリードキャッシュは残る。
もし後でリードが遅いと感じたら2:8にしたりと調整はできる。
VMなどをすべて停止してから行うこと。(もちろん稼働したままやった)
# 1. Smart Path を無効化
ssacli ctrl slot=0 array A modify ssdsmartpath=disable
# 2. バッテリーなしのライトバックを無効化(すでに無効だが明示的に)
ssacli ctrl slot=0 modify nobatterywritecache=disable
# 3. LD のコントローラキャッシュを有効化
ssacli ctrl slot=0 ld 1 modify caching=enable
# 4. キャッシュ配分を 10% Read / 90% Write に(etcd 用)
ssacli ctrl slot=0 modify cacheratio=10/90
# おまけ(SSD アレイでは Elevator Sort は不要)
ssacli ctrl slot=0 modify elevatorsort=disable
再度RAIDカードの設定を確認したものが以下のdiff
$ diff show-detail-old.txt show-detail-new.txt
21c21
< Elevator Sort: Enabled
---
> Elevator Sort: Disabled
29c29,30
< Cache Status: Not Configured
---
> Cache Status: OK
> Cache Ratio: 10% Read / 90% Write
$ diff ld-all-show-detail-old.txt ld-all-show-detail-new.txt
18c18
< Caching: Disabled
---
> Caching: Enabled
32c32
< LD Acceleration Method: Smart Path
---
> LD Acceleration Method: Controller Cache
完璧や。
再検証
RAIDカードの調整も済ませたので再度fioを走らせてみる。
ログ: fio
$ fio --name=fsync --rw=write --ioengine=sync --fdatasync=1 \
--bs=2300 --size=22m --runtime=60 --numjobs=1
fsync: (g=0): rw=write, bs=(R) 2300B-2300B, (W) 2300B-2300B, (T) 2300B-2300B, ioengine=sync, iodepth=1
fio-3.39
Starting 1 process
Jobs: 1 (f=1)
fsync: (groupid=0, jobs=1): err= 0: pid=5083: Mon Aug 3 03:16:54 2026
write: IOPS=6911, BW=15.2MiB/s (15.9MB/s)(22.0MiB/1451msec); 0 zone resets
clat (usec): min=2, max=384, avg=35.87, stdev=29.51
lat (usec): min=2, max=385, avg=36.00, stdev=29.51
clat percentiles (usec):
| 1.00th=[ 4], 5.00th=[ 4], 10.00th=[ 4], 20.00th=[ 4],
| 30.00th=[ 4], 40.00th=[ 5], 50.00th=[ 57], 60.00th=[ 58],
| 70.00th=[ 59], 80.00th=[ 60], 90.00th=[ 63], 95.00th=[ 70],
| 99.00th=[ 86], 99.50th=[ 95], 99.90th=[ 153], 99.95th=[ 180],
| 99.99th=[ 249]
bw ( KiB/s): min=15039, max=15893, per=99.62%, avg=15466.00, stdev=603.87, samples=2
iops : min= 6696, max= 7076, avg=6886.00, stdev=268.70, samples=2
lat (usec) : 4=38.60%, 10=5.04%, 20=0.20%, 50=0.01%, 100=55.78%
lat (usec) : 250=0.37%, 500=0.01%
fsync/fdatasync/sync_file_range:
sync (usec): min=88, max=468, avg=107.00, stdev=14.22
sync percentiles (usec):
| 1.00th=[ 93], 5.00th=[ 97], 10.00th=[ 99], 20.00th=[ 101],
| 30.00th=[ 101], 40.00th=[ 102], 50.00th=[ 103], 60.00th=[ 105],
| 70.00th=[ 108], 80.00th=[ 112], 90.00th=[ 120], 95.00th=[ 128],
| 99.00th=[ 153], 99.50th=[ 182], 99.90th=[ 265], 99.95th=[ 297],
| 99.99th=[ 363]
cpu : usr=3.17%, sys=14.41%, ctx=34443, majf=0, minf=11
IO depths : 1=200.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,10029,0,0 short=10029,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=15.2MiB/s (15.9MB/s), 15.2MiB/s-15.2MiB/s (15.9MB/s-15.9MB/s), io=22.0MiB (23.1MB), run=1451-1451msec
Disk stats (read/write):
sda: ios=5403/19244, sectors=43224/120120, merge=0/0, ticks=279/940, in_queue=1631, util=79.57%
なんと153usまで下がった。
完璧すぎる。
ただ、RAIDカードのキャッシュサイズは2GBで上記はそれに収まってしまっているため、もう少し時間を増やしてより現実的なアクセスで検証してみる。
ログ: fio 180秒 x 15.9MB/s ≈ 2.8GB
$ fio --name=fsync --rw=write --ioengine=sync --fdatasync=1 \
--bs=2300 --size=22m --time_based --runtime=180 --numjobs=1
fsync: (g=0): rw=write, bs=(R) 2300B-2300B, (W) 2300B-2300B, (T) 2300B-2300B, ioengine=sync, iodepth=1
fio-3.39
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][w=15.4MiB/s][w=7041 IOPS][eta 00m:00s]
fsync: (groupid=0, jobs=1): err= 0: pid=5144: Mon Aug 3 03:25:46 2026
write: IOPS=7220, BW=15.8MiB/s (16.6MB/s)(2851MiB/180000msec); 0 zone resets
clat (usec): min=2, max=2976, avg=34.65, stdev=30.39
lat (usec): min=2, max=2976, avg=34.82, stdev=30.41
clat percentiles (usec):
| 1.00th=[ 3], 5.00th=[ 3], 10.00th=[ 4], 20.00th=[ 4],
| 30.00th=[ 4], 40.00th=[ 6], 50.00th=[ 51], 60.00th=[ 53],
| 70.00th=[ 55], 80.00th=[ 56], 90.00th=[ 62], 95.00th=[ 78],
| 99.00th=[ 105], 99.50th=[ 119], 99.90th=[ 147], 99.95th=[ 159],
| 99.99th=[ 237]
bw ( KiB/s): min= 9298, max=18647, per=100.00%, avg=16229.86, stdev=1597.99, samples=359
iops : min= 4140, max= 8302, avg=7226.01, stdev=711.45, samples=359
lat (usec) : 4=37.87%, 10=5.52%, 20=0.37%, 50=2.25%, 100=52.60%
lat (usec) : 250=1.39%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.01%, 4=0.01%
fsync/fdatasync/sync_file_range:
sync (usec): min=79, max=9690, avg=101.91, stdev=28.46
sync percentiles (usec):
| 1.00th=[ 85], 5.00th=[ 86], 10.00th=[ 87], 20.00th=[ 89],
| 30.00th=[ 91], 40.00th=[ 93], 50.00th=[ 95], 60.00th=[ 97],
| 70.00th=[ 101], 80.00th=[ 106], 90.00th=[ 123], 95.00th=[ 155],
| 99.00th=[ 202], 99.50th=[ 221], 99.90th=[ 245], 99.95th=[ 262],
| 99.99th=[ 347]
cpu : usr=3.77%, sys=16.51%, ctx=4470936, majf=0, minf=11
IO depths : 1=200.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,1299697,0,0 short=1299696,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=15.8MiB/s (16.6MB/s), 15.8MiB/s-15.8MiB/s (16.6MB/s-16.6MB/s), io=2851MiB (2989MB), run=180000-180000msec
Disk stats (read/write):
sda: ios=729378/2597699, sectors=5835024/16216024, merge=0/35, ticks=35442/119156, in_queue=206532, util=84.42%
こっちも大丈夫そう。
帯域の min= 9298 が avg=16229.86 の6割程度まで落ちる瞬間があったのが飽和の証拠。
そしてそのキャッシュが埋まってもきちんと202us出ており、SSDへ吐き出す速度が追いついている証拠。
そして最後に3メンバーstacked相当の3並列
ログ: fio 120秒 3並列
$ fio --name=fsync --rw=write --ioengine=sync --fdatasync=1 \
--bs=2300 --size=22m --time_based --runtime=120 --numjobs=3 --group_reporting
fsync: (g=0): rw=write, bs=(R) 2300B-2300B, (W) 2300B-2300B, (T) 2300B-2300B, ioengine=sync, iodepth=1
...
fio-3.39
Starting 3 processes
fsync: Laying out IO file (1 file / 22MiB)
fsync: Laying out IO file (1 file / 22MiB)
Jobs: 3 (f=3): [W(3)][100.0%][w=44.4MiB/s][w=20.2k IOPS][eta 00m:00s]
fsync: (groupid=0, jobs=3): err= 0: pid=5197: Mon Aug 3 03:30:15 2026
write: IOPS=19.5k, BW=42.9MiB/s (44.9MB/s)(5142MiB/120001msec); 0 zone resets
clat (usec): min=2, max=3841, avg=37.49, stdev=31.88
lat (usec): min=2, max=3841, avg=37.66, stdev=31.89
clat percentiles (usec):
| 1.00th=[ 4], 5.00th=[ 4], 10.00th=[ 4], 20.00th=[ 4],
| 30.00th=[ 4], 40.00th=[ 5], 50.00th=[ 56], 60.00th=[ 59],
| 70.00th=[ 61], 80.00th=[ 65], 90.00th=[ 71], 95.00th=[ 79],
| 99.00th=[ 97], 99.50th=[ 106], 99.90th=[ 137], 99.95th=[ 153],
| 99.99th=[ 237]
bw ( KiB/s): min=21202, max=49677, per=100.00%, avg=43922.37, stdev=1709.18, samples=717
iops : min= 9440, max=22118, avg=19555.66, stdev=760.96, samples=717
lat (usec) : 4=37.31%, 10=6.43%, 20=0.49%, 50=0.24%, 100=54.76%
lat (usec) : 250=0.76%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2=0.01%, 4=0.01%
fsync/fdatasync/sync_file_range:
sync (usec): min=69, max=59210, avg=114.04, stdev=117.44
sync percentiles (usec):
| 1.00th=[ 86], 5.00th=[ 91], 10.00th=[ 95], 20.00th=[ 99],
| 30.00th=[ 102], 40.00th=[ 104], 50.00th=[ 108], 60.00th=[ 112],
| 70.00th=[ 116], 80.00th=[ 123], 90.00th=[ 135], 95.00th=[ 147],
| 99.00th=[ 198], 99.50th=[ 285], 99.90th=[ 441], 99.95th=[ 545],
| 99.99th=[ 5669]
cpu : usr=3.45%, sys=15.85%, ctx=7472416, majf=0, minf=34
IO depths : 1=200.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,2344377,0,0 short=2344377,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=42.9MiB/s (44.9MB/s), 42.9MiB/s-42.9MiB/s (44.9MB/s-44.9MB/s), io=5142MiB (5392MB), run=120001-120001msec
Disk stats (read/write):
sda: ios=1304006/4696747, sectors=10432048/29514000, merge=0/21675, ticks=70054/239480, in_queue=409915, util=76.79%
こちらも198usで問題なし。
現実的なテストでいけたし3メンバーstackedの方針で決定してよさそう。
おわり
一旦ここまで。
これでディスク性能は解決したので本格的に導入して検証とかを進められると思う。
それにしてもClaudeの状況把握能力や的確な指示はだいぶすごい。
ただこれもそもそも人間が適切な指示を出さないといけないので、なにも知らない人間には扱えない代物だと思う。
結局きちんと使える人間が得をするいつもの流れやなって。
あと知識欲もだいぶ関係ありそうね。
参考
結局オタクに教えてもらったところが一番よくわかる定期
