Ó Latency High Ceph go Paiste Eithne ag baint úsáide as eBPF/BCC

Ó Latency High Ceph go Paiste Eithne ag baint úsáide as eBPF/BCC

Tá líon mór uirlisí ag Linux chun an eithne agus na feidhmchláir a dhífhabhtú. Bíonn tionchar diúltach ag an gcuid is mó díobh ar fheidhmíocht iarratais agus ní féidir iad a úsáid i dtáirgeadh.

Cúpla bliain ó shin bhí tá uirlis eile forbartha - eBPF. Fágann sé gur féidir na feidhmchláir eithne agus úsáideora a rianú le forchostais íseal agus gan gá le cláir a atógáil agus modúil tríú páirtí a luchtú isteach san eithne.

Tá go leor fóntais feidhmchláir ann cheana féin a úsáideann eBPF, agus san Airteagal seo féachfaimid ar conas do áirgiúlacht próifílithe féin a scríobh bunaithe ar an leabharlann PythonBCC. Tá an t-alt bunaithe ar imeachtaí fíor. Rachaimid ó fhadhb go réiteach chun a thaispeáint conas is féidir fóntais atá ann cheana a úsáid i gcásanna sonracha.

Tá Ceph mall

Tá óstach nua curtha le braisle Ceph. Tar éis dúinn cuid de na sonraí a aistriú chuige, thugamar faoi deara go raibh an luas próiseála iarratais scríofa aige i bhfad níos ísle ná mar a bhí ar fhreastalaithe eile.

Ó Latency High Ceph go Paiste Eithne ag baint úsáide as eBPF/BCC
Murab ionann agus ardáin eile, bhain an t-óstach seo úsáid as bcache agus an eithne nua linux 4.15. Ba é seo an chéad uair a úsáideadh óstach den chumraíocht seo anseo. Agus ag an nóiméad sin bhí sé soiléir go bhféadfadh an fhréamh na faidhbe teoiriciúil rud ar bith.

Imscrúdú ar an Óstach

Let tús le breathnú ar cad a tharlaíonn taobh istigh den phróiseas ceph-osd. Chun seo a úsáidfimid foirfe и lasairscóip (tuilleadh ar féidir leat léamh faoi anseo):

Ó Latency High Ceph go Paiste Eithne ag baint úsáide as eBPF/BCC
Insíonn an pictiúr dúinn go bhfuil an fheidhm fdatasync() chaith sé go leor ama ag seoladh iarratas chuig feidhmeanna cineálach_make_request(). Ciallaíonn sé seo gur dócha go bhfuil cúis na bhfadhbanna áit éigin lasmuigh den deamhan OSD féin. Is féidir é seo a bheith ar an eithne nó dioscaí. Léirigh an t-aschur iostat go raibh an-fholach i bpróiseáil iarratais ó dhioscaí bcache.

Agus an t-óstach á sheiceáil, fuair muid amach go n-ídíonn an deamhan systemd-udevd cuid mhór ama LAP - thart ar 20% ar roinnt cores. Is iompar aisteach é seo, mar sin ní mór duit a fháil amach cén fáth. Ós rud é go n-oibríonn Systemd-udevd le uevents, bheartaíomar breathnú orthu tríd monatóireacht a dhéanamh ar udevadm. Tharlaíonn sé go raibh líon mór imeachtaí athraithe ginte do gach feiste bloc sa chóras. Tá sé seo neamhghnách go leor, mar sin beidh orainn breathnú ar cad a ghineann na himeachtaí seo go léir.

Ag baint úsáide as Foireann Uirlisí BCC

Mar atá faighte amach againn cheana féin, caitheann an eithne (agus an deamhan ceph sa ghlao córais) go leor ama i cineálach_make_request(). Déanaimis iarracht luas na feidhme seo a thomhas. IN BCC Tá áirgiúlacht iontach ann cheana féin - feidhmiúlacht. Déanfaimid an deamhan a rianú trína PID le heatramh 1 soicind idir aschuir agus aschuirfimid an toradh i milleasoicindí.

Ó Latency High Ceph go Paiste Eithne ag baint úsáide as eBPF/BCC
De ghnáth oibríonn an ghné seo go tapa. Níl le déanamh aige ach an t-iarratas a chur ar aghaidh chuig scuaine tiománaí an ghléis.

Bcache is gléas casta é ina bhfuil trí dhiosca i ndáiríre:

  • gléas tacaíochta (diosca i dtaisce), sa chás seo is HDD mall é;
  • gléas taisce (diosca caching), seo deighilt amháin den fheiste NVMe;
  • an gléas fíorúil bcache lena ritheann an feidhmchlár.

Tá a fhios againn go bhfuil tarchur iarratais mall, ach cé acu de na gléasanna seo? Déileálfaimid leis seo beagán níos déanaí.

Tá a fhios againn anois gur dócha go gcruthóidh imeachtaí fadhbanna. Níl sé chomh furasta cad is cúis lena nginiúint a fháil go díreach. Glacaimid leis gur bogearraí de chineál éigin é seo a sheoltar go tréimhsiúil. A ligean ar a fheiceáil cén cineál bogearraí a ritheann ar an gcóras ag baint úsáide as script execsnoop as an gcéanna Foireann fóntais BCC. A ligean ar rith sé agus an t-aschur a sheoladh chuig comhad.

Mar shampla mar seo:

/usr/share/bcc/tools/execsnoop  | tee ./execdump

Ní thaispeánfaimid an t-aschur iomlán execsnoop anseo, ach bhí cuma mar seo ar líne spéise amháin:

sh 1764905 5802 0 sudo arcconf getconfig 1 AD | grep Temperature | awk -F '[:/]' '{print $2}' | sed 's/^ ([0-9]*) C.*/1/'

Is é an tríú colún an PPID (PID tuismitheora) den phróiseas. Bhí an próiseas le PID 5802 ar cheann de na snáitheanna dár gcóras monatóireachta. Nuair a bhí cumraíocht an chórais monatóireachta á seiceáil, fuarthas paraiméadair earráideacha. Tógadh teocht an adapter HBA gach 30 soicind, atá i bhfad níos minice ná mar is gá. Tar éis an t-eatramh seiceála a athrú go heatramh níos faide, fuaireamar amach nár sheas an fhoighne próiseála iarratais ar an óstach seo amach a thuilleadh i gcomparáid le hóstach eile.

Ach níl sé soiléir fós cén fáth a raibh an gléas bcache chomh mall. D’ullmhaigh muid ardán tástála le cumraíocht chomhionann agus rinneamar iarracht an fhadhb a atáirgeadh trí fio ar bcache a rith, ag rith truicear udevadm go tréimhsiúil chun uevents a ghiniúint.

Uirlisí BCC-Bhunaithe a scríobh

Déanaimis iarracht fóntais shimplí a scríobh chun na glaonna is moille a rianú agus a thaispeáint cineálach_make_request(). Tá suim againn freisin in ainm an tiomántáin ar tugadh an fheidhm seo air.

Tá an plean simplí:

  • Clár kprobe ar cineálach_make_request():
    • Sábhálann muid an t-ainm diosca i gcuimhne, inrochtana tríd an argóint feidhme;
    • Sábhálann muid an stampa ama.

  • Clár créatúr le haghaidh filleadh ó cineálach_make_request():
    • Faighimid an stampa ama reatha;
    • Lorgaimid an stampa ama a shábháiltear agus cuirimid i gcomparáid é leis an gceann reatha;
    • Má tá an toradh níos mó ná an ceann sonraithe, ansin aimsímid an t-ainm diosca shábháil agus é a thaispeáint ar an teirminéal.

Kprobes и próistí meicníocht brisphointe a úsáid chun an cód feidhme ar an eitilt a athrú. Is féidir leat léamh doiciméadú и maith alt ar an ábhar seo. Má fhéachann tú ar chód na bhfóntas éagsúla i BCC, ansin is féidir leat a fheiceáil go bhfuil struchtúr comhionann acu. Mar sin san Airteagal seo beimid ag scipeáil argóintí scripte a pharsáil agus bogadh ar aghaidh go dtí an clár BPF féin.

Breathnaíonn an téacs eBPF taobh istigh den script python mar seo:

bpf_text = “”” # Here will be the bpf program code “””

Chun sonraí a mhalartú idir feidhmeanna, úsáideann cláir eBPF táblaí hash. Déanfaimid an rud céanna. Bainfimid úsáid as an bpróiseas PID mar an eochair, agus saineoidh muid an struchtúr mar an luach:

struct data_t {
	u64 pid;
	u64 ts;
	char comm[TASK_COMM_LEN];
	u64 lat;
	char disk[DISK_NAME_LEN];
};

BPF_HASH(p, u64, struct data_t);
BPF_PERF_OUTPUT(events);

Anseo táimid ag clárú tábla hash ar a dtugtar p, le cineál eochair u64 agus luach cineáil struct data_t. Beidh an tábla ar fáil i gcomhthéacs ár gclár BPF. Cláraíonn an macra BPF_PERF_OUTPUT tábla eile ar a dtugtar imeachtaí, a úsáidtear le haghaidh tarchur sonraí isteach sa spás úsáideora.

Agus moilleanna á dtomhas idir glaoch ar fheidhm agus filleadh uaithi, nó idir glaonna chuig feidhmeanna éagsúla, ní mór duit a chur san áireamh go gcaithfidh na sonraí a fuarthas a bheith bainteach leis an gcomhthéacs céanna. I bhfocail eile, ní mór duit cuimhneamh ar sheoladh comhthreomhar féideartha feidhmeanna. Tá an cumas againn an fhoighne a thomhas idir glao a chur ar fheidhm i gcomhthéacs próiseas amháin agus filleadh ón bhfeidhm sin i gcomhthéacs próisis eile, ach is dócha go bhfuil sé seo gan úsáid. Sampla maith a bheadh ​​anseo fóntais bithlatency, áit a bhfuil an eochair tábla hash socraithe go pointeoir go iarratas struchtúr, a léiríonn iarratas diosca amháin.

Ansin, ní mór dúinn an cód a scríobh a rithfidh nuair a thugtar an fheidhm atá á staidéar:

void start(struct pt_regs *ctx, struct bio *bio) {
	u64 pid = bpf_get_current_pid_tgid();
	struct data_t data = {};
	u64 ts = bpf_ktime_get_ns();
	data.pid = pid;
	data.ts = ts;
	bpf_probe_read_str(&data.disk, sizeof(data.disk), (void*)bio->bi_disk->disk_name);
	p.update(&pid, &data);
}

Anseo cuirfear an chéad argóint den fheidhm a thugtar air in ionad an dara argóint cineálach_make_request(). Ina dhiaidh sin, faigheann muid PID an phróisis ina bhfuilimid ag obair sa chomhthéacs, agus an stampa ama atá ann faoi láthair i nana-soicindí. Scríobhaimid go léir síos i úr roghnaithe struct sonraí data_t. Faighimid ainm an diosca ón struchtúr bhith, a ritheann nuair a ghlaonn tú cineálach_make_request(), agus é a shábháil sa struchtúr céanna dáta. Is é an chéim dheireanach ná iontráil a chur leis an tábla hash a luadh níos luaithe.

Tabharfar an fheidhm seo a leanas ar fhilleadh ó cineálach_make_request():

void stop(struct pt_regs *ctx) {
    u64 pid = bpf_get_current_pid_tgid();
    u64 ts = bpf_ktime_get_ns();
    struct data_t* data = p.lookup(&pid);
    if (data != 0 && data->ts > 0) {
        bpf_get_current_comm(&data->comm, sizeof(data->comm));
        data->lat = (ts - data->ts)/1000;
        if (data->lat > MIN_US) {
            FACTOR
            data->pid >>= 32;
            events.perf_submit(ctx, data, sizeof(struct data_t));
        }
        p.delete(&pid);
    }
}

Tá an fheidhm seo cosúil leis an gceann roimhe seo: faighimid amach PID an phróisis agus an stampa ama, ach ní leithroinnimid cuimhne don struchtúr sonraí nua. Ina áit sin, déanaimid cuardach ar an tábla hash le haghaidh struchtúr atá ann cheana féin ag baint úsáide as an eochair == PID reatha. Má aimsítear an struchtúr, ansin faighimid amach ainm an phróisis reatha agus cuirimid leis é.

Is gá an t-aistriú dénártha a úsáidimid anseo chun an GID snáithe a fháil. siúd. PID den phríomhphróiseas a chuir tús leis an snáithe i gcomhthéacs a bhfuilimid ag obair. An fheidhm tugaimid bpf_get_current_pid_tgid() cuireann sé GID an tsnáithe agus a PID ar ais i luach amháin 64-giotán.

Nuair a bheidh an t-aschur chuig an teirminéal, níl suim againn sa snáithe faoi láthair, ach tá suim againn sa phríomhphróiseas. Tar éis dúinn an mhoill mar thoradh air a chur i gcomparáid le tairseach ar leith, rachaimid thar ár struchtúr dáta isteach sa spás úsáideora tríd an tábla imeachtaí, ina dhiaidh sin scriosaimid an iontráil ó p.

Sa script python a luchtóidh an cód seo, ní mór dúinn na tairseacha moille agus na haonaid ama a chur in ionad MIN_US agus FACTOR, a rachaimid trí na hargóintí:

bpf_text = bpf_text.replace('MIN_US',str(min_usec))
if args.milliseconds:
	bpf_text = bpf_text.replace('FACTOR','data->lat /= 1000;')
	label = "msec"
else:
	bpf_text = bpf_text.replace('FACTOR','')
	label = "usec"

Anois ní mór dúinn an clár BPF a ullmhú trí Macra BPF agus samplaí a chlárú:

b = BPF(text=bpf_text)
b.attach_kprobe(event="generic_make_request",fn_name="start")
b.attach_kretprobe(event="generic_make_request",fn_name="stop")

Beidh orainn a chinneadh freisin struct data_t inár script, nó ní bheidh muid in ann aon rud a léamh:

TASK_COMM_LEN = 16	# linux/sched.h
DISK_NAME_LEN = 32	# linux/genhd.h
class Data(ct.Structure):
	_fields_ = [("pid", ct.c_ulonglong),
            	("ts", ct.c_ulonglong),
            	("comm", ct.c_char * TASK_COMM_LEN),
            	("lat", ct.c_ulonglong),
            	("disk",ct.c_char * DISK_NAME_LEN)]

Is í an chéim dheireanach ná sonraí a aschur chuig an teirminéal:

def print_event(cpu, data, size):
    global start
    event = ct.cast(data, ct.POINTER(Data)).contents
    if start == 0:
        start = event.ts
    time_s = (float(event.ts - start)) / 1000000000
    print("%-18.9f %-16s %-6d   %-1s %s   %s" % (time_s, event.comm, event.pid, event.lat, label, event.disk))

b["events"].open_perf_buffer(print_event)
# format output
start = 0
while 1:
    try:
        b.perf_buffer_poll()
    except KeyboardInterrupt:
        exit()

Tá an script féin ar fáil ag GItHub. Déanaimis iarracht é a rith ar ardán tástála ina bhfuil fio ar siúl, ag scríobh chuig bcache, agus cuir glaoch ar mhonatóir udevadm:

Ó Latency High Ceph go Paiste Eithne ag baint úsáide as eBPF/BCC
Ar deireadh! Anois feicimid gur glao stadála é an rud a d’fhéach cosúil le gléas cache stalla cineálach_make_request() le haghaidh diosca i dtaisce.

Déan tochailt isteach san Eithne

Cad é go díreach atá ag moilliú le linn tarchuir iarratais? Feicimid go dtarlaíonn an mhoill fiú roimh thús na cuntasaíochta iarratais, i.e. níl tús curtha fós le cuntas a thabhairt ar iarratas sonrach ar thuilleadh aschuir staidrimh ina leith (/proc/diosca nó iostat). Is féidir é seo a fhíorú go héasca trí iostat a rith agus an fhadhb a atáirgeadh, nó Bithlatency script BCC, atá bunaithe ar thús agus deireadh na cuntasaíochta iarratais. Ní thaispeánfaidh aon cheann de na fóntais seo fadhbanna le hiarratais ar an diosca i dtaisce.

Má táimid ar an fheidhm cineálach_make_request(), ansin feicfimid sula dtosaíonn an t-iarratas ar chuntasaíocht, go dtugtar dhá fheidhm eile. Ar dtús - seiceálacha_cineálacha_make_request_(), déanann sé seiceálacha ar dhlisteanacht an iarratais maidir le socruithe an diosca. Dara - blk_queue_enter(), a bhfuil dúshlán suimiúil ann fan_imeacht_idirbhriste():

ret = wait_event_interruptible(q->mq_freeze_wq,
	(atomic_read(&q->mq_freeze_depth) == 0 &&
	(preempt || !blk_queue_preempt_only(q))) ||
	blk_queue_dying(q));

Inti, fanann an eithne go scaoilfidh an scuaine. Déanaimis an mhoill a thomhas blk_queue_enter():

~# /usr/share/bcc/tools/funclatency  blk_queue_enter -i 1 -m               	 
Tracing 1 functions for "blk_queue_enter"... Hit Ctrl-C to end.

 	msecs           	: count 	distribution
     	0 -> 1      	: 341  	|****************************************|

 	msecs           	: count 	distribution
     	0 -> 1      	: 316  	|****************************************|

 	msecs           	: count 	distribution
     	0 -> 1      	: 255  	|****************************************|
     	2 -> 3      	: 0    	|                                    	|
     	4 -> 7      	: 0    	|                                    	|
     	8 -> 15     	: 1    	|                                    	|

Tá an chuma ar an scéal go bhfuilimid gar do réiteach. Is iad na feidhmeanna a úsáidtear chun scuaine a reo/díreo blk_mq_reoite_scuaine и blk_mq_unfreeze_scuaine. Úsáidtear iad nuair is gá socruithe na scuaine iarratais a athrú, rud a d’fhéadfadh a bheith contúirteach d’iarratais sa scuaine seo. Agus é ag glaoch blk_mq_ reoite_scuaine() feidhm blk_freeze_queue_start() tá an cuntar méadaithe q-> mq_ reoite_doimhneacht. Tar éis seo, fanann an eithne go bhfolmhóidh an scuaine isteach blk_mq_reo_scuaine_fan().

Is ionann an t-am a thógann sé an scuaine seo a ghlanadh agus foilsiú an diosca mar go bhfanann an t-eithne ar gach oibríocht scuaine a chur i gcrích. Nuair a bhíonn an scuaine folamh, cuirtear na hathruithe socruithe i bhfeidhm. Tar éis a dtugtar é blk_mq_unfreeze_queue(), ag laghdú an chuntar reo_doimhneacht.

Anois tá a fhios againn go leor chun an scéal a cheartú. Is cúis leis an ordú truicear udevadm na socruithe don bhlocghléas a chur i bhfeidhm. Déantar cur síos ar na socruithe seo i rialacha udev. Is féidir linn a fháil amach cé na socruithe atá ag reo na scuaine trí iarracht a dhéanamh iad a athrú trí sysfs nó trí bhreathnú ar an gcód foinse eithne. Is féidir linn triail a bhaint as fóntais BCC freisin rianú, a aschuirfidh rianta eithne agus spásanna úsáideora do gach glao chuig an teirminéal blk_reo_scuaine, mar shampla:

~# /usr/share/bcc/tools/trace blk_freeze_queue -K -U
PID 	TID 	COMM        	FUNC        	 
3809642 3809642 systemd-udevd   blk_freeze_queue
    	blk_freeze_queue+0x1 [kernel]
    	elevator_switch+0x29 [kernel]
    	elv_iosched_store+0x197 [kernel]
    	queue_attr_store+0x5c [kernel]
    	sysfs_kf_write+0x3c [kernel]
    	kernfs_fop_write+0x125 [kernel]
    	__vfs_write+0x1b [kernel]
    	vfs_write+0xb8 [kernel]
    	sys_write+0x55 [kernel]
    	do_syscall_64+0x73 [kernel]
    	entry_SYSCALL_64_after_hwframe+0x3d [kernel]
    	__write_nocancel+0x7 [libc-2.23.so]
    	[unknown]

3809631 3809631 systemd-udevd   blk_freeze_queue
    	blk_freeze_queue+0x1 [kernel]
    	queue_requests_store+0xb6 [kernel]
    	queue_attr_store+0x5c [kernel]
    	sysfs_kf_write+0x3c [kernel]
    	kernfs_fop_write+0x125 [kernel]
    	__vfs_write+0x1b [kernel]
    	vfs_write+0xb8 [kernel]
    	sys_write+0x55 [kernel]
    	do_syscall_64+0x73 [kernel]
    	entry_SYSCALL_64_after_hwframe+0x3d [kernel]
    	__write_nocancel+0x7 [libc-2.23.so]
    	[unknown]

Is annamh a athraíonn rialacha Udev agus de ghnáth tarlaíonn sé seo ar bhealach rialaithe. Mar sin feicimid go n-eascraíonn fiú na luachanna atá socraithe cheana féin a chur i bhfeidhm go mór leis an moill a bhaineann leis an iarratas a aistriú ón bhfeidhmchlár chuig an diosca. Ar ndóigh, ní dea-chleachtas é imeachtaí udev a ghiniúint nuair nach bhfuil aon athruithe ar chumraíocht an diosca (mar shampla, nach bhfuil an gléas gléasta/dícheangailte). Mar sin féin, is féidir linn cabhrú leis an eithne gan obair neamhriachtanach a dhéanamh agus an scuaine iarratais a reoite mura bhfuil gá leis. Trí beag tiomantas an scéal a cheartú.

Conclúid

Uirlis thar a bheith solúbtha agus chumhachtach is ea eBPF. San alt bhreathnaíomar ar chás praiticiúil amháin agus léirigh muid cuid bheag den méid is féidir a dhéanamh. Más spéis leat fóntais BCC a fhorbairt, is fiú breathnú air teagaisc oifigiúil, a chuireann síos go maith ar na bunghnéithe.

Tá uirlisí dífhabhtaithe agus próifílithe suimiúla eile bunaithe ar eBPF. Ceann acu - bpftrace, a ligeann duit aon-líneáil chumhachtach agus cláir bheaga a scríobh sa teanga awk-mhaith. Eile - ebpf_onnmhaireoir, is féidir leat méadracht ardtaifigh ardleibhéil a bhailiú go díreach isteach i do fhreastalaí prometheus, leis an gcumas léirshamhlú álainn agus fiú foláirimh a fháil níos déanaí.

Foinse: will.com

Add a comment