Come verificare le prestazioni dei dischi con fio per etcd

Nota di traduzione.: questo articolo è il risultato di uno studio condotto dagli ingegneri di IBM Cloud alla ricerca di una soluzione a un problema reale legato all'uso del database etcd. Per noi era rilevante una questione simile, tuttavia il corso di pensiero e le azioni degli autori possono risultare interessanti anche in un contesto più ampio.

Come verificare le prestazioni dei dischi con fio per etcd

Sintesi dell'intero articolo: fio e etcd

Le prestazioni del cluster etcd dipendono fortemente dalla velocità dello storage sottostante. Per monitorare le prestazioni, etcd esporta varie metriche Prometheus. Una di esse è wal_fsync_duration_seconds. Nella documentazione di etcd si afferma, che lo storage può essere considerato sufficientemente veloce se il 99° percentile di questa metrica non supera i 10 ms…

Se stai considerando la possibilità di organizzare un cluster etcd su macchine con Linux e vuoi verificare se gli storage sono sufficientemente veloci (ad esempio, SSD), ti consigliamo di utilizzare un popolare tester I/O chiamato fio. È sufficiente eseguire il seguente comando (la directory test-data deve trovarsi nella partizione montata dello storage testato):

fio --rw=write --ioengine=sync --fdatasync=1 --directory=test-data --size=22m --bs=2300 --name=mytest

Non resta che osservare l'output e verificare se il 99° percentile fdatasync rientra nei 10 ms. Se è così, significa che il tuo storage è abbastanza veloce. Ecco un esempio di output:

fsync/fdatasync/sync_file_range:
  sync (usec): min=534, max=15766, avg=1273.08, stdev=1084.70
  sync percentiles (usec):
   | 1.00th=[ 553], 5.00th=[ 578], 10.00th=[ 594], 20.00th=[ 627],
   | 30.00th=[ 709], 40.00th=[ 750], 50.00th=[ 783], 60.00th=[ 1549],
   | 70.00th=[ 1729], 80.00th=[ 1991], 90.00th=[ 2180], 95.00th=[ 2278],
   | 99.00th=[ 2376], 99.50th=[ 9634], 99.90th=[15795], 99.95th=[15795],
   | 99.99th=[15795]

Alcuni commenti:

  1. Nell'esempio sopra, abbiamo adattato i parametri --size e --bs per un caso specifico. Per ottenere un risultato significativo da fio, specifica valori adatti al tuo scenario d'uso. Come sceglierli sarà trattato più avanti.
  2. Durante il test, solo fio carica il sottosistema di archiviazione. Nella vita reale, è probabile che al disco scrivano anche altri processi (oltre a quelli legati a wal_fsync_duration_seconds). Tale carico aggiuntivo può portare a un aumento di wal_fsync_duration_seconds. In altre parole, se il 99° percentile ottenuto al termine del test con fio, è appena inferiore a 10 ms, è probabile che le prestazioni dello storage non siano sufficienti.
  3. Per il test avrai bisogno della versione fio non inferiore a 3.5, poiché le versioni più vecchie non aggregano i risultati fdatasync sotto forma di percentili.
  4. L'output sopra riportato è solo un piccolo estratto dell'output totale fio.

Dettagli su fio ed etcd

Qualche parola sui WAL di etcd

In generale, i database utilizzano la registrazione anticipata (write-ahead logging, WAL). Anche etcd è interessato a questo. La discussione sui WAL va oltre l'ambito di questo articolo, tuttavia per i nostri scopi è importante sapere che ogni membro del cluster etcd memorizza il WAL in uno storage persistente. etcd registra alcune operazioni con lo storage key-value (ad esempio, aggiornamenti) nel WAL prima di eseguirle. Se un nodo va in crash e si riavvia tra uno snapshot e l'altro, etcd sarà in grado di ripristinare le transazioni effettuate dal precedente snapshot, basandosi sul contenuto del WAL.

Quindi, ogni volta che un cliente aggiunge una chiave allo storage KV o aggiorna il valore di una chiave esistente, etcd aggiunge una descrizione dell'operazione nel WAL, che è un file normale nel storage persistente. Prima di continuare il lavoro, etcd DEVE essere certo al 100% che la scrittura nel WAL sia stata effettivamente salvata. Per ottenere questo in Linux, non è sufficiente utilizzare una chiamata di sistema write, poiché l'operazione di scrittura su un dispositivo fisico potrebbe essere ritardata. Ad esempio, Linux può trattenere per un certo periodo la scrittura WAL nella cache del kernel in memoria (ad esempio, nella cache delle pagine). Per garantire che i dati siano scritti sul supporto, dopo la scrittura deve essere utilizzata una chiamata di sistema fdatasync — questo è ciò che fa etcd (come si può vedere nell'output seguente strace; qui 8 — il descrittore del file WAL):

21:23:09.894875 lseek(8, 0, SEEK_CUR)   = 12808 
21:23:09.894911 write(8, ".      20210220361223255266632$10 20103026"34"rn3fo"..., 2296) = 2296 
21:23:09.895041 fdatasync(8)            = 0

Sfortunatamente, la scrittura nello storage persistente richiede tempo. Un'esecuzione prolungata della chiamata fdatasync può influenzare le prestazioni di etcd. Nella documentazione dello storage viene specificato, si menziona che per prestazioni adeguate è necessario che il 99° percentile della durata di tutte le chiamate fdatasync per la scrittura nel file WAL sia inferiore a 10 ms. Ci sono altre metriche relative allo storage, ma in questo articolo parleremo specificamente di questa.

Valutiamo lo storage utilizzando fio

Per valutare se uno storage è adatto all'uso con etcd, si può utilizzare l'utility fio — tester I/O popolare. Tieni presente che l'input/output su disco può avvenire in modi diversi: sync/async, una varietà di classi di chiamate di sistema, ecc. Il rovescio della medaglia è che fio è estremamente complesso da usare. L'utility ha numerosi parametri, e le varie combinazioni dei loro valori portano a risultati completamente diversi. Per ottenere una valutazione ragionevole nel caso di etcd, devi assicurarti che il carico di scrittura generato da fio somigli il più possibile al carico di etcd durante la scrittura nei file WAL:

  • Questo significa che il carico generato fio deve almeno rappresentare una serie di scritture sequenziali nel file, in cui ogni operazione di scrittura consiste in una chiamata di sistema write, seguita da fdatasync.
  • Per abilitare la scrittura sequenziale, è necessario specificare il flag --rw=write.
  • Per fio ha effettuato scritture utilizzando chiamate write (e non altre chiamate di sistema — ad esempio, pwrite), utilizza il flag --ioengine=sync.
  • Infine, il flag --fdatasync=1 garantisce che dopo ogni write si deve fdatasync.
  • Due altri parametri nel nostro esempio: --size e --bs — possono variare a seconda dello specifico scenario d'uso. La loro configurazione sarà descritta nella sezione successiva.

Perché abbiamo scelto fio e come abbiamo imparato a configurarlo

Questa nota è emersa da un caso reale che abbiamo incontrato. Avevamo un cluster su Kubernetes v1.13 con monitoraggio su Prometheus. Gli SSD erano utilizzati come storage per etcd v3.2.24. Le metriche di etcd mostrano latenze eccessivamente elevate fdatasync, anche quando il cluster era inattivo. Queste metriche ci sembravano alquanto sospette, e non eravamo certi di cosa rappresentassero realmente. Inoltre, il cluster era composto da macchine virtuali, quindi non eravamo in grado di dire se la latenza fosse legata alla virtualizzazione o se fosse colpa degli SSD.

Inoltre, stavamo considerando varie modifiche alla configurazione hardware e software, quindi era necessario un modo per valutarle. Certo, si poteva eseguire etcd in ogni configurazione e osservare le metriche corrispondenti su Prometheus, ma ciò avrebbe richiesto uno sforzo significativo. Avevamo bisogno di un modo semplice per valutare una configurazione specifica. Volevamo mettere alla prova la nostra comprensione delle metriche Prometheus provenienti da etcd.

Per questo era necessario risolvere due problemi:

  • In primo luogo, come appare il carico I/O generato da etcd durante la scrittura nei file WAL? Quali chiamate di sistema vengono utilizzate? Qual è la dimensione dei blocchi di scrittura?
  • In secondo luogo, supponiamo di avere risposte alle domande sopra menzionate. Come riprodurre il carico corrispondente con fio? Ведь fio — uno strumento estremamente flessibile con una miriade di opzioni (questo è facilmente verificabile, ad esempio, qui ­— nota dell'autore).

Abbiamo risolto entrambi i problemi utilizzando lo stesso approccio, basato sui comandi lsof e strace:

  • Utilizzando lsof è possibile visualizzare tutti i descrittori di file utilizzati dal processo, così come i file a cui si riferiscono.
  • Utilizzando strace si può analizzare un processo già in esecuzione oppure avviare un processo e osservarlo. Il comando mostra tutte le chiamate di sistema effettuate da questo processo e, se necessario, dai suoi discendenti. Questo è importante per i processi che si biforcano, e etcd è uno di questi processi.

La prima cosa che abbiamo fatto è stata utilizzare strace per esaminare il server etcd nel cluster Kubernetes mentre era inattivo.

È stato quindi scoperto che i blocchi di registrazione nel WAL erano molto densamente raggruppati, la maggior parte aveva una dimensione compresa tra 2200 e 2400 byte. Per questo motivo, nel comando all'inizio di questo articolo viene utilizzato il flag --bs=2300 (bs — la dimensione in byte di ogni blocco di scrittura in fio).

Si noti che la dimensione dei blocchi di scrittura di etcd può variare a seconda della versione, del deployment, dei valori dei parametri, ecc. — questo influisce sulla durata fdatasync. Se hai uno scenario d'uso simile, analizza con strace i tuoi processi etcd per ottenere valori aggiornati.

Poi, per avere un quadro chiaro e completo sul funzionamento di etcd con il file system, l'abbiamo eseguito da strace con i flag -ffttT. Questo ha permesso di coprire i processi discendenti e di registrare l'output di ciascuno in un file separato. Inoltre, sono state ottenute informazioni dettagliate sul momento di avvio e sulla durata di ciascuna chiamata di sistema.

Abbiamo anche utilizzato il comando lsof, per confermare la nostra comprensione dell'output strace in termini di quale descrittore di file fosse utilizzato per quale scopo. È stata prodotta un'uscita strace, simile a quella fornita sopra. Le manipolazioni statistiche sui tempi di sincronizzazione hanno confermato che la metrica wal_fsync_duration_seconds di etcd corrisponde alle chiamate fdatasync con i descrittori dei file WAL.

Per generare utilizzando fio Il carico di lavoro analogo a quello di etcd è stato studiato attraverso la documentazione dell'utilità e sono stati selezionati parametri adeguati al nostro compito. Ci siamo assicurati che vengano effettuate le chiamate di sistema necessarie e abbiamo confermato la loro durata eseguendo fio da strace (come è stato fatto nel caso di etcd).

Particolare attenzione è stata dedicata alla definizione del valore del parametro --size. Rappresenta il carico totale di I/O generato dall'utilità fio. Nel nostro caso, è il numero totale di byte scritto sul supporto. È direttamente proporzionale al numero di chiamate write (e fdatasync). Per un certo bs numero di chiamate fdatasync è uguale a size / bs.

Poiché ci interessava il percentile, abbiamo cercato di avere un numero di campioni sufficientemente grande per la significatività statistica. E abbiamo deciso che 10^4 (che corrisponde a una dimensione di 22 MB) sarebbe stato sufficiente. Valori più piccoli del parametro --size generavano un rumore più evidente (ad esempio, chiamate fdatasync, che richiedono molto più tempo del solito e influenzano il 99° percentile).

Ora tocca a voi

L'articolo mostra come utilizzare fio per valutare se un supporto destinato all'uso con etcd è sufficiently veloce. Ora tocca a voi! È possibile esplorare le macchine virtuali con archiviazione basata su SSD attraverso il servizio IBM Cloud.

P.S. dal traduttore

Con esempi pronti all'uso fio per affrontare altri compiti, è possibile consultare documentazione o direttamente su repository del progetto (dove ce ne sono molti più di quanti ne vengano menzionati nella documentazione).

P.P.S. dal traduttore

Leggi anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS - ProHoster