Ceph — alates "kõik käib käsitsi" kuni "tootmisse"

CEPHi valik. Osa 1

Meil oli viis riiulit, kümme optilist lülitit, seadistatud BGP, paar tosinat SSD-d ja hunnik SAS kettaid igasuguste värvide ja suurustega, lisaks proxmox ja soov panna kogu staatika oma S3 salvestusse. Ei olnud see kõik virtualiseerimiseks vajalik, aga kui juba avatud lähtekoodiga kasutanud oled, siis mine oma hobi lõpuni. Ainus asi, mis mind muretses, oli BGP. Maailmas ei ole kedagi abitumat, vastutustundetumat ja moraalitundetumat kui sisemine marsruutimine BGP kaudu. Ja ma teadsin, et üsna pea me sellega kokku puutume.

Ceph — alates "kõik käib käsitsi" kuni "tootmisse"

Ülesanne oli tavaline — CEPH oli olemas, töötas aga mitte eriti hästi. Tuli teha "hästi".
Minule jäänud klaster oli heterogeenne, kiirkorras seadistatud ja praktiliselt mitte häälestatud. See koosnes kahest erinevate nodide grupist, ühise võrgu kaudu, mis täitis nii klastrit kui ka avalikku võrku. Nodid olid täidetud nelja tüüpi ketastega — kahe tüüpi SSD-d, mis olid koondatud kahte eraldi asetuse reegli ning kahe tüüpi HDD-d, millel olid erinevad suurused ja mis olid koondatud kolmandasse gruppi. Erinevate suuruste probleem lahendati erinevate OSD kaalu kaudu.

Seadistamine jagati kaheks osaks — operatsioonisüsteemi häälestamine ja CEPH-i ja selle seadistuste häälestamine. ja seadistustest.

OS-i tugevdamine

Võrk log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats timeout 30s user haproxy group haproxy daemondefaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000frontend http_front bind *:80 stats uri /haproxy?stats default_backend http_backbackend http_back balance roundrobin server server_name1 private_ip1:80 check server server_name2 private_ip2:80 check

Kõrge latency mõjutas nii kirjutamise kui tasakaalustamise protsesse. Kirjutamise korral ei saanud klient vastust edukast kirjutamisest enne, kui andmete koopiad teistes paigutusgruppides ei kinnitanud edu. Kuna meil olid replikatsiooni jagamise reeglid CRUSH kaardil ühe replikaga per host, siis kasutati võrku pidevalt.

Seetõttu otsustasin kõigepealt praegust võrku veidi seadistada, samal ajal üritades veenda liikuma eraldi võrkudele.

Alguses muutsin võrkaartide seadistusi. Alustasin järjekordade seadistamisest:

mis oli:

ethtool -l ens1f1

root@ceph01:~# ethtool -l ens1f1
Channel parameters for ens1f1:
Pre-set maximums:
RX:     0
TX:     0
Other:      1
Combined:   63
Current hardware settings:
RX:     0
TX:     0
Other:      1
Combined:   1
root@ceph01:~# ethtool -g ens1f1
Ring parameters for ens1f1:
Pre-set maximums:
RX:     4096
RX Mini:    0
RX Jumbo:   0
TX:     4096
Current hardware settings:
RX:     256
RX Mini:    0
RX Jumbo:   0
TX:     256
root@ceph01:~# ethtool -l ens1f1
Channel parameters for ens1f1:
Pre-set maximums:
RX:     0
TX:     0
Other:      1
Combined:   63
Current hardware settings:
RX:     0
TX:     0
Other:      1
Combined:   1

On näha, et current parameetrid jäävad kaugele maksimumist. Suurendasin:

root@ceph01:~#ethtool -G ens1f0 rx 4096
root@ceph01:~#ethtool -G ens1f0 tx 4096
root@ceph01:~#ethtool -L ens1f0 combined 63

Tuginedes suurepärasele artiklile

https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data/

suurendas saatmise järjekorra pikkust txqueuelen 1000-st 10 000-ndeni

root@ceph01:~#ip link set ens1f0  txqueuelen 10000

Järgides ceph'i dokumentatsiooni

https://ceph.com/geen-categorie/ceph-loves-jumbo-frames/

suurendas MTU 9000-ni.

root@ceph01:~#ip link set dev ens1f0  mtu 9000

Lisatud /etc/network/interfaces, et kõik eeltoodud õigesti käivituks

cat /etc/network/interfaces

root@ceph01:~# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto ens1f0
iface ens1f0 inet manual
post-up /sbin/ethtool -G ens1f0 rx 4096
post-up /sbin/ethtool -G ens1f0 tx 4096
post-up /sbin/ethtool -L ens1f0 combined 63
post-up /sbin/ip link set ens1f0  txqueuelen 10000
mtu 9000

auto ens1f1
iface ens1f1 inet manual
post-up /sbin/ethtool -G ens1f1 rx 4096
post-up /sbin/ethtool -G ens1f1 tx 4096
post-up /sbin/ethtool -L ens1f1 combined 63
post-up /sbin/ip link set ens1f1  txqueuelen 10000
mtu 9000

Pärast seda, järgides sama artiklit, hakkasin hoolikalt reguleerima tuuma 4.15. Arvestades, et sõlmedel on 128G RAM, sai looduslikult mingi konfigureerimisfail sysctl

cat /etc/sysctl.d/50-ceph.conf

net.core.rmem_max = 56623104  
#Maksimaalne andme vastuvõtupuhvri suurus kõigi ühenduste jaoks 54M

net.core.wmem_max = 56623104
#Maksimaalne andme saatmispuhvri suurus kõigi ühenduste jaoks 54M

net.core.rmem_default = 56623104
#Vaikimisi vastuvõtupuhvri suurus kõigi ühenduste jaoks 54M

net.core.wmem_default = 56623104
#Vaikimisi saatmispuhvri suurus kõigi ühenduste jaoks 54M  
# iga soketi jaoks

net.ipv4.tcp_rmem = 4096 87380 56623104
#Vektori (minimaalne, vaikimisi, maksimaalne) muutuja failis tcp_rmem
# sisaldab 3 täisarvu, mis määratlevad TCP soketite vastuvõtupuhvrisuuruse.
# Minimaalne: iga TCP soket saab kasutada seda mälu 
# oma loomise ajal. Sellise puhvri kasutamise võimalus 
# on tagatud isegi piirangut lähenedes (mõõdukas mälu surve).
# Vaikimisi minimaalne puhvri suurus on 8 Kb (8192).
#Vaikimisi: mälu kogus, mis on lubatud TCP soketi saatmispuhvrile. See väärtus rakendatakse 
# asenduseks parameetrile \/proc\/sys\/net\/core\/rmem_default, mida kasutavad teised protokollid.
# Vaikimisi kasutatava puhvri väärtus on tavaliselt (vaikimisi) 
# 87830 baiti. See määrab akna suuruse 65535 
# määratletud vaikimisi tcp_adv_win_scale-i ja tcp_app_win = 0 kaudu, 
# pisut väiksem, kui määrab vaikimisi tcp_app_win väärtus.
# Maksimaalne: maksimaalne puhvri suurus, mis võib automaatselt
# eraldada TCP soketi vastuvõtmiseks. See väärtus ei tühista maksimumi, 
# mis on määratud failis \/proc\/sys\/net\/core\/rmem_max. Statistilise
# mälu eraldamise korral SO_RCVBUF selle parameetri tähendust ei oma.

net.ipv4.tcp_wmem = 4096 65536 56623104
net.core.somaxconn = 5000    
# Maksimaalne avatud soketite arv, mis ootab ühendust.

net.ipv4.tcp_timestamps=1
# Lubab ajatempli (timestamps) kasutamist vastavalt RFC 1323.

net.ipv4.tcp_sack=1
# Lubada TCP protokolli osalist kinnitamist.

net.core.netdev_max_backlog=5000 (vaikimisi 1000)
# Maksimaalne paketihulk vastuvõtmiseks, kui 
# liides saab pakette kiiremini, kui tuum suudab neid töödelda.

net.ipv4.tcp_max_tw_buckets=262144
# Maksimaalne soketite arv, mis on samaaegselt TIME-WAIT seisundis.
# Kui see lävi ületatakse, hävitatakse "ülejäänud" soket ja kirjutatakse
# teade süsteemi logisse.

net.ipv4.tcp_tw_reuse=1
# Lubame TIME-WAIT soketite uuesti kasutamine, kui
# protokoll peab seda ohutuks.

net.core.optmem_max=4194304
# Suurendage maksimaalset üldist puhvrit, mis on eraldatud
# mõõdetakse lehekülgedes (4096 baiti)

net.ipv4.tcp_low_latency=1
# Lubab TCP/IP virna madala latentsuse eelise
# üle suurema läbilaskevõime.

net.ipv4.tcp_adv_win_scale=1
# See muutuja mõjutab TCP akna suuruse ja rakenduse puhvri 
# all oleva mälu mahtude arvutamist. Kui tcp_adv_win_scale
# väärtus on negatiivne, siis kasutatakse suuruse arvutamiseks järgnevat sisaldust:
# Bytes - bytes2 kõrgus -tcp_adv_win_scale
# Kus bytes on akna suurus baitides. Kui tcp_adv_win_scale
# väärtus on positiivne, siis kasutatud suuruse määramiseks kasutatakse järgnevat sisaldust:
# Bytes - bytes2 + tcp_adv_win_scale
# Muutujal peab olema täisväärtus. Vaikimisi on väärtus 2, 
# st, et rakenduse puhvri jaoks eraldatakse ¼ osa mahtudest, mis on määratletud muutuja
# tcp_rmem järgi.

net.ipv4.tcp_slow_start_after_idle=0
# aeglase käivitamise mehanism, mis taastab akna 
# ummistumise väärtuse, kui ühendust ei ole kasutatud määratud aja jooksul.
# Parim on SSR serveris välja lülitada, et, et
# pikaajalised ühendused oleksid parem.

net.ipv4.tcp_no_metrics_save=1
# Ärge salvestage TCP ühenduse mõõtmistulemusi vahemälles selle sulgemisel.

net.ipv4.tcp_syncookies=0
# Lülitage syncookie saatmise mehhanism välja.

net.ipv4.tcp_ecn=0
# Explicit Congestion Notification (Selge Üksikasjalik Teave Üksikasjalik Teave)
# TCP ühendustes. Seda kasutatakse teavitusel "ummistus" 
# teel määratud hosti või võrku. Saate hoiatada saatja hosti
# vajadusest vähendada pakettide edastamise kiirus.

net.ipv4.conf.all.send_redirects=0
# lülitab ICMP Redirecti välja … teistele hostidele. See valik peab olema
# lubatud, kui host tegutseb maruuterina.
# Me ei ole maruuter.

net.ipv4.ip_forward=0
# Mõeldud edasiviimise keelamiseks. Me ei ole värav, dokkerid ei ole tõstetud,
# me ei vaja seda.

net.ipv4.icmp_echo_ignore_broadcasts=1
#Ära vasta ICMP ECHO päringutele, mis saadetakse laialdaste pakettide kaudu.

net.ipv4.tcp_fin_timeout=10
# Määrab aja, mil soket jääb FIN-WAIT-2 staatuse alla, peale selle
# sulgemist kohalikust küljest. Vaikimisi on 60.

net.core.netdev_budget=600 # (vaikimisi 300)
# Kui programmide katkestused ei toimu piisavalt kaua,
# võib sissetuleva andme tempo ületada tuuma 
# võimet puhvrit tühjendada. Sellisel juhul võivad NIC-i puhvrit 
# ületäitumised ja liiklus kaotsi minna.
# Vahel tuleb SoftIRQ-de (programmide katkestuste) kestev aeg
# suurendada, sellega tegeleb netdev_budget. 
# Vaikimisi on väärtus 300. Parameeter käivitab SoftIRQ töötama
# 300 paketti NIC-ilt, enne kui vabastab CPU.

net.ipv4.tcp_fastopen=3
# TFO TCP Fast Open
# juhul, kui nii klient kui server toetavad TFO-d, mida märgitakse
# TCP paketti erilise lipuga. Meie puhul on see platseebo, lihtsalt
# näeb hea välja)

Cluster network oli eraldatud eraldi 10Gbps võrguliideseid eraldi tasasesse võrku. Iga masin oli varustatud kahtportiliste võrgukaartidega mellanox 10/25 Gbps, ühendatud kahe eraldi 10Gbps lülitiga. Agregeerimine toimus OSPF-i abil, kuna LACP kasutamine näitas mingil põhjusel maksimaalset koguvooluvõimet 16 Gbps, samas kui OSPF suudab täielikult ära kasutada mõlemat kümmet igas masinas. Edasi oli plaanis kasutada ROCE neid mellanoxide peal latentsuse vähendamiseks. Kuidas seadistada seda osa võrku:

  1. Kuna ise masinatel on välised IP-aadressid BGP-s, siis on vajalik meile tarkvara — ( täpsemalt, artikli kirjutamise hetkel oli see frr=6.0-1 ) juba paigaldatud.
  2. Kokku oli masinatel kaks võrguliidest kahe portiga — kokku 4 porti. Üks võrgukaart kahe portiga vaatas tehasesse ja sellel oli seadistatud BGP, teine — kahe portiga vaatas kahte erinevat lülitit ja sellele oli suunatud OSPF.

Lisateavet OSPF seadistamise kohta: Peamine ülesanne — agreggeerida kaks linki ja omada tõrketolerantsi.
kaks võrguliidest on seadistatud kahes lihtsas tasasesse võrku — 10.10.10.0/24 ja 10.10.20.0/24

1: ens1f0:  mtu 9000 qdisc mq state UP group default qlen 1000
    inet 10.10.10.2/24 brd 10.10.10.255 scope global ens1f0

2: ens1f1:  mtu 9000 qdisc mq state UP group default qlen 1000
    inet 10.10.20.2/24 brd 10.10.20.255 scope global ens1f1

mille, kus autod üksteist näevad.

KETTAS

Järgmiseks otsustasin optimeerida ketaste tööd. SSD-de jaoks vahetasin plaanikaitsja noop, HDD jaoks — deadline. Karmilt öeldes — NOOP töötab põhimõttel „kes esimesena tõusis, see sai ka kingad“, mis inglise keeles kõlab kui „FIFO (First In, First Out)“. Küsimused järgnevad järjekorras nende laekumise järgi. DEADLINE on rohkem loodud lugemise jaoks, pluss protsess järjekorrast saab praktiliselt monopolikujulise juurdepääsu kettale operatsiooni ajal. Meie süsteemile sobib see suurepäraselt — sest iga kettaga töötab ainult üks protsess — OSD daemon.
(Need, kes soovivad süveneda sisendi-väljundi plaanikaitsesse, saavad lugeda sellest siin:
http://www.admin-magazine.com/HPC/Articles/Linux-I-O-Schedulers

Eelistavad lugeda vene keeles: https://www.opennet.ru/base/sys/linux_shedulers.txt.html)

Linuxi häälestamise soovitustes soovitatakse samuti suurendada nr_request

nr_requests
nr_requests väärtus määrab I/O päringute arvu, mis vahepeal salvestatakse enne, kui I/O ajakava saadab / võtab andmeid plokkseadmest. Kui kasutate RAID-kaarti / plokkseadet, mis suudab hallata suuremat järjekorda kui see, mille I/O ajakava on seadistatud, võib nr_requests väärtuse tõstmine aidata parandada läbilaskevõimet ja vähendada serveri koormust suurtel I/O juhtudel. Kui kasutate Deadline'i või CFQ-d ajakavana, on soovitatav seada nr_request väärtus 2 korda järjekorra sügavuse väärtus.

KUID! CEPH-i arendajad kinnitavad meile, et nende prioriteetide süsteem töötab paremini

Ceph — alates "kõik käib käsitsi" kuni "tootmisse"

WBThrottle ja / või nr_requests

WBThrottle ja / või nr_requests
Failihaldus kasutab kirjutamiseks puhverdatud sisend\ väljundoperatsioone; see toob kaasa hulga eeliseid, eriti kui failihalduse ajakiri asub kiiremal kandjal. Kliendi päringud saavad teate, niipea kui andmed on ajakirja salvestatud, ja seejärel kirjutatakse need hiljem andmekettale, kasutades Linuxi standardfunktsioone. See võimaldab OSD spindli ketastel pakkuda kirjutamisviivitust, mis on sarnane SSD-dega väikeste paketiga kirjutamisel. Selline viivitatud kirjutamine võimaldab ka kernelil ümber korraldada kettale sisend\ väljundoperatsioonide päringuid, lootes kas ühendada need või lasta esialgsetel kettapeadel valida mingi optimaalse tee nende plaatide peal. Lõppkokkuvõttes tähendab see, et saate igalt kettalt välja pigistada veidi rohkem sisend\ väljundoperatsioone, kui oleks võimalik otse või sünkroonsete sisend\ väljundoperatsioonide korral.

Kuid kui tulevad sisendite kogused ületavad Ceph klastrisse põhinevaid võimalusi, tekib teatav probleem. Sellises stsenaariumis võivad ooteaegade arv, mis on seotud diskile kirjutamisega, kontrollimatult kasvada, mis võib põhjustada sisendi/väljundi operatsioonide järjekordade tekkimist, mis täidab kogu ketta. Lugemisettepanekud mõjutavad eriti halvasti, kuna need jäävad kirjutamisettepanekute vahele kinni, millel võib olla mitu sekundit, et need peavad peamisele kettale jõudma.

Selle probleemi lahendamiseks on Ceph-l allkirjastatud failihoidlas sisseehitatud kirjutamise edasilükkamise mehhanism nimega WBThrottle. See on loodud selleks, et piirata edasilükatud kirjutamise sisend-/väljastusoperatsioonide kogumahtu, mis võivad järjekorda sattuda ja alustada oma tühistamisprotsessi varem, kui see muidu juhtuks, aktiveerides sellele ise tuuma. Kahjuks näitavad testid, et vaikeseaded ei suuda endiselt vähendada oleku käitumist tasemele, mis võiks vähendada selle mõju lugemise latentsusele. Reguleerimine võib seda käitumist muuta ja vähendada üldisi kirjutamisjärjekordi, tehes nii, et mõju poleks liiga suur. Siiski on see nõnda kompromiss: piirates üldiselt lubatud järjekorda seatud kirjeid, saate vähendada tuuma võimalusi maksimeerida oma efektiivsust tulenevalt saabuvate päringute korraldamisest. Tasub mõelda, mis on teie konkreetse rakenduse, töökoormuse jaoks olulisem, ja reguleerida vastavalt.

Kuidas hallata sellise ooteaja sügavust, saate kas vähendada üldiselt täitmata sisend/väljundoperatsioonide maksimaalset arvu, rakendades WBThrottle seadeid, või vähendada maksimaalse väärtuse täitmata operatsioonide osas oma tuuma bloki tasemel. Mõlemad võib tõhusalt hallata sama käitumist ja just teie eelistused määravad selle seade rakendamise.
Samuti tasub märkida, et Ceph'i olemasolev operatsioonide prioriteetsüsteem on tõhusam lühikeste diskitaseme päringute korral. Kui vähendada üldist ooteaega selle kettaga, liigub peamine asukoht ootejärjekorras Ceph'i, kus tal on suurem kontroll selle üle, milline prioriteet sisend/väljundoperatsioonil on. Vaatame järgmist näidet:

echo 8 > /sys/block/sda/queue/nr_requests

http://onreader.mdl.ru/MasteringCeph/content/Ch09.html#030202

COMMON

Ja veel mõned tuuma seaded, mis aitavad teie masinat pehmeks ja siidiseks muuta, et välja pigistada veel natuke jõudlust riistvarast.

cat /etc/sysctl.d/60-ceph2.conf

 kernel.pid_max = 4194303
# Igas masinas on 25 ketast, seetõttu arvutasime, et protsesse saab olema palju
kernel.threads-max=2097152
# Niisuguseid lõime on ikka rohkem.
vm.max_map_count=524288
# Suurendasime protsessi mälu kaardistamise piirkondade arvu.
# Nagu on öeldud tuumamuutujate dokumentatsioonis
# Kaardistamise piirkondi kasutatakse malloc'i, mmap'i, mprotect'i ja madvise'i otseteena
# ning ka jagatud raamatukogude laadimisel.
fs.aio-max-nr=50000000
# Häälestame sisend-väljund parameetreid
# Linuxi tuum pakub asünkroonset mittetõkestavat sisend-väljundit (AIO),
# mis võimaldab protsessil alustada mitut sisend-väljund operatsiooni
# samaaegselt, ootamata ühegi neist lõpetamist.
# See aitab suurendada rakenduste jõudlust,
# mis suudavad töötlemise ja sisend-väljundi katkematuks teha.
# Aio-max-nr parameeter määrab maksimaalse lubatud
# samaaegsete päringute arvu.
vm.min_free_kbytes=1048576
# minimaalne vaba mälu suurus, mida tuleb toetada.
# Seatud 1GB, mis on täiesti piisav operatsioonisüsteemi tööks,
# ja aitab vältida OOM Killeri käivitamist OSD protsesside jaoks. Kuigi mälust on
# nii palju, et see on pea sama mis tühik, ei võta varu kukkervitusele.
vm.swappiness=10
# Ütleme, et kasutame swap'i, kui vaba mälu on vaid 10%.
# Masinatel on 128G operatiivmälu ja 10% on 12 GB. Rohkem kui piisavalt tööks.
# Tehase parameeter 60% sundis süsteemi aeglustuma, minnes swap'i,
# kui vaba mälu on endiselt palju.
vm.vfs_cache_pressure=1000
# Suurendame tehase 100 pealt. Sundime tuuma aktiivsemalt
# vabastama mittekasutatud mälulehekesi vahemälust.
vm.zone_reclaim_mode=0
# Lubab seadistada rohkem või vähem agressiivseid lähenemisviise
# mälu taastamiseks, kui piirkonnas hakkab mälu otsa saama.
# Kui see on nulliks seatud, ei toimu piirkonna taastamist.
# Failiserveritele või töökoormatele
# on kasulik, kui nende andmed on vahemälus, zone_reclaim_mode
# jätta välja lülitatuks, kuna vahemälu mõju
# on tõenäoliselt olulisem kui andmete asukoht.
vm.dirty_ratio=20
# Protsent operatiivmälu, mille võib määrata "mustadele" lehtedele
# Arvutasime umbkaudse arvutuse põhjal:
# süsteemias on 128 GB mälu.
# Umbes 20 SSD-d, mille seadistustes on CEPH määratud
# 3G operatiivmälu määramine vahemäluks.
# Umbes 40 HDD-d, mille jaoks see parameeter on 1G
# 20% 128-st on 25,6 GB. Kokku, maksimaalse mälu kasutamise korral,
# jääb süsteemile 2,4GB mälu. Seda peab piisama ellujäämiseks ja ootamiseks
# ratsaväe koputuste - see tähendab DevOpsi, kes kõik korda teeb.
vm.dirty_background_ratio=3
# protsent süsteemi mälust, mille võib täita mustade lehtedega enne,
# kui taustprotsessid pdflush/flush/kdmflush kirjutavad need diskile.
fs.file-max=524288
# Ja meil on tõenäoliselt avatud faile palju rohkem, kui vaikimisi on määratud. 

Süvenemine CEPH-i

Seaded, mille kohta sooviksime rohkem rääkida:

cat /etc/ceph/ceph.conf

osd:
    journal_aio: true               # Kolme parameetrit, mis hõlmavad 
    journal_block_align: true       # otsest i/o
    journal_dio: true               # ajakirja jaoks
    journal_max_write_bytes: 1073714824 # Laiendame maksimaalset suurust
                                        # ajakirja ühekordse kirjutamise operatsioonis
    journal_max_write_entries: 10000    # Ja samade kirjutiste arv
    journal_queue_max_bytes: 10485760000 
    journal_queue_max_ops: 50000
    rocksdb_separate_wal_dir: true      # Otsustasime teha eraldi wal                                                                            
                                        # Üritasime ka selle jaoks 
                                        # NVMe
    bluestore_block_db_create: true     # Tootame ajakirjale eraldi seade
    bluestore_block_db_size: '5368709120 #5G'
    bluestore_block_wal_create: true
    bluestore_block_wal_size: '1073741824   #1G' 
    bluestore_cache_size_hdd: '3221225472   # 3G' 
                                            # Suur hulk RAM-i võimaldab 
                                            # salvestada piisavalt suuri mahtusid
    bluestore_cache_size_ssd: '9663676416   # 9G' 

    keyring: /var/lib/ceph/osd/ceph-$id/keyring
    osd_client_message_size_cap: '1073741824 #1G'
    osd_disk_thread_ioprio_class: idle
    osd_disk_thread_ioprio_priority: 7
    osd_disk_threads: 2 # demonite teede arv ühe ketta kohta
    osd_failsafe_full_ratio: 0.95
    osd_heartbeat_grace: 5
    osd_heartbeat_interval: 3
    osd_map_dedup: true
    osd_max_backfills: 2 # samaaegsete täitmisoperatsioonide arv ühe OSD kohta.
    osd_max_write_size: 256
    osd_mon_heartbeat_interval: 5
    osd_op_threads: 16
    osd_op_num_threads_per_shard: 1
    osd_op_num_threads_per_shard_hdd: 2
    osd_op_num_threads_per_shard_ssd: 2
    osd_pool_default_min_size: 1     # Ahnuse eripärad. Kohe hakkas vähe olema
    osd_pool_default_size: 2         # ruumi, sest ajutise                                                                                                                                
                                     # lahenduse põhjal võttis see vähenenud arvu 
                                     # andme koopiate
    osd_recovery_delay_start: 10.000000
    osd_recovery_max_active: 2
    osd_recovery_max_chunk: 1048576
    osd_recovery_max_single_start: 3
    osd_recovery_op_priority: 1
    osd_recovery_priority: 1            # parameeter, mida reguleerime vastavalt vajadusele
    osd_recovery_sleep: 2
    osd_scrub_chunk_max: 4

Mõned parameetrid, mida testiti QA-s versioonil 12.2.12, puuduvad versioonis ceph 12.2.2, näiteks osd_recovery_threads. Seetõttu oli plaanis uuendada tootmisversioon kuni 12.2.12. Praktika näitas versioonide 12.2.2 ja 12.2.12 ühilduvust ühes klastris, mis võimaldab teostada rolling update’i.

Testklaster

Loomulikult oli testimiseks vajalik omada sama versiooni, mis oli tootmises, kuid minu klastriga alustamise hetkel oli repozitooriumis ainult uuem versioon. Vaadates, et minor versiooni erinevused ei olnud suured (1393 read konfigureerimistes võrreldes 1436 uuemas versioonis), otsustasime alustada uue testimist (niikuinii peaksime uuendama, miks jääda vanale versioonile)

Ainus asi, mida prooviti vanast versioonist alles jätta, oli pakett ceph-deploy, kuna osa utiliite (ja osa töötajatest) olid kohandatud selle süntaksiga. Uus versioon erines piisavalt, kuid ei mõjutanud klastrite tööd, nii et jätsime selle versiooni 1.5.39

Kuna käsk ceph-disk on selgelt märgitud kui deprecated ja soovitatakse kasutada käsku ceph-volume — alustasime OSD-de loomist just selle käsu abil, raiskamatta aega vanadele.

Plani oli selline — luua peegeldus kahest SSD-diskist, millele paigutame OSD ajakirjad, mis omakorda asuvad pöördlukustitel. Nii kindlustame end andmeprobleemide eest, kui ketas ajakirjaga ebaõnnestub.

Klastri loomine toimus dokumentatsiooni kohaselt.

cat /etc/ceph/ceph.conf

root@ceph01-qa:~# cat /etc/ceph/ceph.conf # eelnevalt ette valmistatud konfile
[client]
rbd_cache = true
rbd_cache_max_dirty = 50331648
rbd_cache_max_dirty_age = 2
rbd_cache_size = 67108864
rbd_cache_target_dirty = 33554432
rbd_cache_writethrough_until_flush = true
rbd_concurrent_management_ops = 10
rbd_default_format = 2
[global]
auth_client_required = cephx
auth_cluster_required = cephx
auth_service_required = cephx
cluster network = 10.10.10.0/24
debug_asok = 0/0
debug_auth = 0/0
debug_buffer = 0/0
debug_client = 0/0
debug_context = 0/0
debug_crush = 0/0
debug_filer = 0/0
debug_filestore = 0/0
debug_finisher = 0/0
debug_heartbeatmap = 0/0
debug_journal = 0/0
debug_journaler = 0/0
debug_lockdep = 0/0
debug_mon = 0/0
debug_monc = 0/0
debug_ms = 0/0
debug_objclass = 0/0
debug_objectcatcher = 0/0
debug_objecter = 0/0
debug_optracker = 0/0
debug_osd = 0/0
debug_paxos = 0/0
debug_perfcounter = 0/0
debug_rados = 0/0
debug_rbd = 0/0
debug_rgw = 0/0
debug_throttle = 0/0
debug_timer = 0/0
debug_tp = 0/0
fsid = d0000000d-4000-4b00-b00b-0123qwe123qwf9
mon_host = ceph01-q, ceph02-q, ceph03-q
mon_initial_members = ceph01-q, ceph02-q, ceph03-q
public network = 8.8.8.8/28 # aadress on loomulikult muudetud ))
rgw_dns_name = s3-qa.mycompany.ru # ja see aadress on muudetud
rgw_host = s3-qa.mycompany.ru # ja see ka
[mon]
mon allow pool delete = true
mon_max_pg_per_osd = 300 # rohkem kui kolm sada paigutusgruppi
                          # ei julgenud mahutavuse järgi otsustada
                     # kuigi parameeter sõltub loomulikult basseinide arvust,
                     # nende suurusest ja OSD-de arvust. Vähe, kuid terved PG
                        # ei ole ka parim valik - tasakaalu täpsus kannatab
mon_osd_backfillfull_ratio = 0.9
mon_osd_down_out_interval = 5
mon_osd_full_ratio = 0.95 # SSD ketaste puhul on nende
                          # logi koht sama seadme peal, mis OSD-l
                          # otsustasime, et 5% kettast (mis on suurusega 1.2Tb)
                          # peaks olema piisav ning korreleerub parameetriga
                          # bluestore_block_db_size ja variatiivsusega suuremate
                          # paigutusgruppide peale
mon_osd_nearfull_ratio = 0.9
mon_pg_warn_max_per_osd = 520
[osd]
bluestore_block_db_create = true
bluestore_block_db_size = 5368709120 #5G
bluestore_block_wal_create = true
bluestore_block_wal_size = 1073741824 #1G
bluestore_cache_size_hdd = 3221225472 # 3G
bluestore_cache_size_ssd = 9663676416 # 9G
journal_aio = true
journal_block_align = true
journal_dio = true
journal_max_write_bytes = 1073714824
journal_max_write_entries = 10000
journal_queue_max_bytes = 10485760000
journal_queue_max_ops = 50000
keyring = /var/lib/ceph/osd/ceph-$id/keyring
osd_client_message_size_cap = 1073741824 #1G
osd_disk_thread_ioprio_class = idle
osd_disk_thread_ioprio_priority = 7
osd_disk_threads = 2
osd_failsafe_full_ratio = 0.95
osd_heartbeat_grace = 5
osd_heartbeat_interval = 3
osd_map_dedup = true
osd_max_backfills = 4
osd_max_write_size = 256
osd_mon_heartbeat_interval = 5
osd_op_num_threads_per_shard = 1
osd_op_num_threads_per_shard_hdd = 2
osd_op_num_threads_per_shard_ssd = 2
osd_op_threads = 16
osd_pool_default_min_size = 1
osd_pool_default_size = 2
osd_recovery_delay_start = 10.0
osd_recovery_max_active = 1
osd_recovery_max_chunk = 1048576
osd_recovery_max_single_start = 3
osd_recovery_op_priority = 1
osd_recovery_priority = 1
osd_recovery_sleep = 2
osd_scrub_chunk_max = 4
osd_scrub_chunk_min = 2
osd_scrub_sleep = 0.1
rocksdb_separate_wal_dir = true

# создаем мониторы
root@ceph01-qa:~#ceph-deploy mon create ceph01-q
# генерируем ключи для аутентификации нод в кластере
root@ceph01-qa:~#ceph-deploy gatherkeys ceph01-q
# Это если поштучно. Если у нас несколько машин доступны - те, которые описаны в конфиге в секции 
# mon_initial_members = ceph01-q, ceph02-q, ceph03-q
# можно запустить эти две команды в виде одной
root@ceph01-qa:~#ceph-deploy mon create-initial
# Положим ключи в указанные в конфиге места
root@ceph01-qa:~#cat ceph.bootstrap-osd.keyring > /var/lib/ceph/bootstrap-osd/ceph.keyring 
root@ceph01-qa:~#cat ceph.bootstrap-mgr.keyring > /var/lib/ceph/bootstrap-mgr/ceph.keyring 
root@ceph01-qa:~#cat ceph.bootstrap-rgw.keyring > /var/lib/ceph/bootstrap-rgw/ceph.keyring
# создадим ключ для управления кластером
root@ceph01-qa:~#ceph-deploy admin ceph01-q
# и менеджер, плагинами управлять
root@ceph01-qa:~#ceph-deploy mgr create ceph01-q

Esimene, millega see versioon ceph-deploy töö juures kokku puutus, oli viga, kui proovisin luua OSD-d db-ga tarkvara RAID-iga —

root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
blkid ei suutnud määrata PARTUUID-d seadmele: /dev/md1

Tõepoolest, blkid ei näita PARTUUID-d, pidin osad käsitsi looma:

root@ceph01-qa:~#parted /dev/md0 mklabel GPT 
# osasid tuleb palju, 
# ilma GPT-ta ei õnnestu neid luua
# osa suurus, nagu ülalolevas konfigureerimises, on = bluestore_block_db_size: '5368709120 #5G'
# Mul on 20 ketast OSD-de jaoks, käsitsi osade loomine on tülikas
# seetõttu tegin tsükli
root@ceph01-qa:~#for i in {1..20}; do echo -e "nnnn+5Gnw" | fdisk /dev/md0; done

Tundub, et kõik on valmis, proovime veel kord OSD-d luua ja saame järgmise vea (mis tegelikult tootmises ei ilmnenud)

bluestore tüüpi OSD loomisel, ilma WAL-i teed määramata, kuid db-ga

root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
 stderr: 2019-04-12 10:39:27.211242 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) _read_fsid unparsable uuid
 stderr: 2019-04-12 10:39:27.213185 7eff461b6e00 -1 bdev(0x55824c273680 /var/lib/ceph/osd/ceph-0//block.wal) open open got: (22) Invalid argument
 stderr: 2019-04-12 10:39:27.213201 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) _open_db add block device(/var/lib/ceph/osd/ceph-0//block.wal) returned: (22) Invalid argument
 stderr: 2019-04-12 10:39:27.999039 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) mkfs failed, (22) Invalid argument
 stderr: 2019-04-12 10:39:27.999057 7eff461b6e00 -1 OSD::mkfs: ObjectStore::mkfs failed with error (22) Invalid argument
 stderr: 2019-04-12 10:39:27.999141 7eff461b6e00 -1  ** ERROR: error creating empty object store in /var/lib/ceph/osd/ceph-0/: (22) Invalid argument

Kui aga sama peegli (või muus kohas, vastavalt valikule) alla luua veel üks partitsioon WAL-i jaoks ja määrata see OSD loomise käigus — siis kõik läheb sujuvalt (välja arvatud eraldi WAL-i ilmumine, mida võib-olla soovisite vältida).

Kuna plaanis oli WAL viia NVMe-le, siis praktika ei olnud liialt kasutu.

root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sdf --block.wal  /dev/md0p2 --block.db /dev/md1p2

Loodud on monitorid, haldurid ja OSD. Nüüd sooviks neid erinevalt grupeerida, kuna plaanis on kasutada erinevat tüüpi kõvakettaid — kiireid SSD-poolide jaoks ja suuremaid, kuid aeglasemaid SAS-plaate.

Eeldame, et serverites on 20 ketast, kus esimene kümme on ühe tüübi ja teine kümme teise tüübi.
Esialgne, vaikekaart näeb välja järgmine:

ceph osd tree

root@ceph01-q:~# ceph osd tree
ID KLASS KALDUS Tüüp NIMI OLEK UUSKAAL PRIORITEET-SUHTE
-1 14.54799 juur vaike
-3 9.09200 host ceph01-q
0 ssd 1.00000 osd.0 üles 1.00000 1.00000
1 ssd 1.00000 osd.1 üles 1.00000 1.00000
2 ssd 1.00000 osd.2 üles 1.00000 1.00000
3 ssd 1.00000 osd.3 üles 1.00000 1.00000
4 hdd 1.00000 osd.4 üles 1.00000 1.00000
5 hdd 0.27299 osd.5 üles 1.00000 1.00000
6 hdd 0.27299 osd.6 üles 1.00000 1.00000
7 hdd 0.27299 osd.7 üles 1.00000 1.00000
8 hdd 0.27299 osd.8 üles 1.00000 1.00000
9 hdd 0.27299 osd.9 üles 1.00000 1.00000
10 hdd 0.27299 osd.10 üles 1.00000 1.00000
11 hdd 0.27299 osd.11 üles 1.00000 1.00000
12 hdd 0.27299 osd.12 üles 1.00000 1.00000
13 hdd 0.27299 osd.13 üles 1.00000 1.00000
14 hdd 0.27299 osd.14 üles 1.00000 1.00000
15 hdd 0.27299 osd.15 üles 1.00000 1.00000
16 hdd 0.27299 osd.16 üles 1.00000 1.00000
17 hdd 0.27299 osd.17 üles 1.00000 1.00000
18 hdd 0.27299 osd.18 üles 1.00000 1.00000
19 hdd 0.27299 osd.19 üles 1.00000 1.00000
-5 5.45599 host ceph02-q
20 ssd 0.27299 osd.20 üles 1.00000 1.00000
21 ssd 0.27299 osd.21 üles 1.00000 1.00000
22 ssd 0.27299 osd.22 üles 1.00000 1.00000
23 ssd 0.27299 osd.23 üles 1.00000 1.00000
24 hdd 0.27299 osd.24 üles 1.00000 1.00000
25 hdd 0.27299 osd.25 üles 1.00000 1.00000
26 hdd 0.27299 osd.26 üles 1.00000 1.00000
27 hdd 0.27299 osd.27 üles 1.00000 1.00000
28 hdd 0.27299 osd.28 üles 1.00000 1.00000
29 hdd 0.27299 osd.29 üles 1.00000 1.00000
30 hdd 0.27299 osd.30 üles 1.00000 1.00000
31 hdd 0.27299 osd.31 üles 1.00000 1.00000
32 hdd 0.27299 osd.32 üles 1.00000 1.00000
33 hdd 0.27299 osd.33 üles 1.00000 1.00000
34 hdd 0.27299 osd.34 üles 1.00000 1.00000
35 hdd 0.27299 osd.35 üles 1.00000 1.00000
36 hdd 0.27299 osd.36 üles 1.00000 1.00000
37 hdd 0.27299 osd.37 üles 1.00000 1.00000
38 hdd 0.27299 osd.38 üles 1.00000 1.00000
39 hdd 0.27299 osd.39 up 1.00000 1.00000
-7 6.08690 host ceph03-q
40 ssd 0.27299 osd.40 up 1.00000 1.00000
41 ssd 0.27299 osd.41 up 1.00000 1.00000
42 ssd 0.27299 osd.42 up 1.00000 1.00000
43 ssd 0.27299 osd.43 up 1.00000 1.00000
44 hdd 0.27299 osd.44 up 1.00000 1.00000
45 hdd 0.27299 osd.45 up 1.00000 1.00000
46 hdd 0.27299 osd.46 up 1.00000 1.00000
47 hdd 0.27299 osd.47 up 1.00000 1.00000
48 hdd 0.27299 osd.48 up 1.00000 1.00000
49 hdd 0.27299 osd.49 up 1.00000 1.00000
50 hdd 0.27299 osd.50 up 1.00000 1.00000
51 hdd 0.27299 osd.51 up 1.00000 1.00000
52 hdd 0.27299 osd.52 up 1.00000 1.00000
53 hdd 0.27299 osd.53 up 1.00000 1.00000
54 hdd 0.27299 osd.54 up 1.00000 1.00000
55 hdd 0.27299 osd.55 up 1.00000 1.00000
56 hdd 0.27299 osd.56 up 1.00000 1.00000
57 hdd 0.27299 osd.57 up 1.00000 1.00000
58 hdd 0.27299 osd.58 up 1.00000 1.00000
59 hdd 0.89999 osd.59 up 1.00000 1.00000

Loome oma virtuaalsed riiulid ja serverid – kamba mängude ja muu kaubaga:

root@ceph01-q:~#ceph osd crush add-bucket rack01 root #uus root loodud
root@ceph01-q:~#ceph osd crush add-bucket ceph01-q host #uus host loodud
root@ceph01-q:~#ceph osd crush move ceph01-q root=rack01 #server teise riiuli
root@ceph01-q:~#osd crush add 28 1.0 host=ceph02-q # lisatud OSD serverisse

# Kui midagi valesti loodud, siis saab kustutada
root@ceph01-q:~# ceph osd crush remove osd.4
root@ceph01-q:~# ceph osd crush remove rack01

Probleemid, millega me silmitsi seisame sõjaväes klastris, kui üritame luua uut hosti ja liigutada seda olemasolevasse riiuli — käsk ceph osd crush move ceph01-host root=rack01 kinnitas, ja monitorid hakkasid ükshaaval maha kukkuma. Käsk CTRL+C katkestas klaster tagasi elavate maailma.

Otsing näitas sellist probleemi: https://tracker.ceph.com/issues/23386

Lahenduseks osutus crushmap'i väljavõtmine ja sektsiooni kustutamine sealt rule replicated_ruleset

root@ceph01-prod:~#ceph osd getcrushmap -o crushmap.row #Väljavõtame kaardi toorelt
root@ceph01-prod:~#crushtool -d crushmap.row -o crushmap.txt #Tõlgime loetavaks
root@ceph01-prod:~#vim  crushmap.txt #Redigeerime, eemaldades rule replicated_ruleset
root@ceph01-prod:~#crushtool -c crushmap.txt  -o new_crushmap.row #Koostame tagasi
root@ceph01-prod:~#ceph osd setcrushmap -i  new_crushmap.row #Laadime klastrisse

Attention: see toiming võib põhjustada placement group'ide ümberbalanceerimist OSD-de vahel. Meil see juhtus, kuid väga vähe.

Ja kummalisus, millega me testklastris kokku puutusime — oli see, et pärast OSD-serveri taaskäivitamist unustasid nad, et olid uude serverisse ja riiulisse tõstetud, ja naasid root default'i.
Lõpuks, koostades lõpliku skeemi, kus eraldasime eraldi root ssd-derakendite jaoks ja eraldi spindlite jaoks, ja jagasime kõik OSD-d riiulitele ja lihtsalt kustutasime default root'i. Pärast taaskäivitamist jäid OSD-d oma kohtadele.
Hiljem dokumentatsioonis süvenedes leidsime parameetri, mis vastutab selle käitumise eest. Selle kohta teises osas.

Kuidas me gruppeerisime erinevaid ketaste tüüpe.

Kõigepealt lõime kaks root-i — SSD ja HDD jaoks.

root@ceph01-q:~#ceph osd crush add-bucket ssd-root root
root@ceph01-q:~#ceph osd crush add-bucket hdd-root root

Kuna füüsiliselt asuvad serverid erinevates rackides — mugavuse huvides lõime rackid ja panime neisse serverid.

# Стойки:
root@ceph01-q:~#ceph osd crush add-bucket ssd-rack01 rack
root@ceph01-q:~#ceph osd crush add-bucket ssd-rack02 rack
root@ceph01-q:~#ceph osd crush add-bucket ssd-rack03 rack

root@ceph01-q:~#ceph osd crush add-bucket hdd-rack01 rack
root@ceph01-q:~#ceph osd crush add-bucket hdd-rack01 rack
root@ceph01-q:~#ceph osd crush add-bucket hdd-rack01 rack

# Сервера
root@ceph01-q:~#ceph osd crush add-bucket ssd-ceph01-q host
root@ceph01-q:~#ceph osd crush add-bucket ssd-ceph02-q host
root@ceph01-q:~#ceph osd crush add-bucket ssd-ceph03-q host

root@ceph01-q:~#ceph osd crush add-bucket hdd-ceph01-q host
root@ceph01-q:~#ceph osd crush add-bucket hdd-ceph02-q host
root@ceph01-q:~#ceph osd crush add-bucket hdd-ceph02-q host

ja jaotasime kettad tüüpide järgi erinevatesse serveritesse.

root@ceph01-q:~# Kettad 0 kuni 3 on SSD, asuvad ceph01-q, paigaldame nad serverisse 
root@ceph01-q:~# ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 0 1 host=ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 1 1 host=ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 2 1 host=ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 3 1 host=ssd-ceph01-q
root-ceph01-q:~# samamoodi teiste serveritega.

Kettad jaotades SSD-root ja HDD-root-i, jätsime root-default-i tühjaks, seega saame selle eemaldada.

root-ceph01-q:~#ceph osd crush remove default

Järgmiseks tuleb luua jaotamisreeglid, mille me seome loodavatele basseinidele — reeglites määrame, millistel rootidel meie basseini andmed asuda saavad ja replika unikaalsuse taseme — näiteks peavad replikad olema kindlasti erinevates serveerides või erinevates rack’ides (võib isegi eri rootidel, kui meil on selline jaotamine).

Enne tüübivalikut tasub lugeda dokumentatsiooni:
http://docs.ceph.com/docs/jewel/rados/operations/crush-map/#crushmaprules

root-ceph01-q:~#ceph osd crush rule create-simple rule-ssd ssd-root host firstn
root-ceph01-q:~#ceph osd crush rule create-simple rule-hdd hdd-root host firstn
root-ceph01-q:~# Oleme määranud kaks reeglit, kus andmed replikeeritakse 
root-ceph01-q:~# hostide vahel — see tähendab, et replika peab asuma teisel hostil,
root-ceph01-q:~# isegi kui need on samas rack’is
root-ceph01-q:~# Produtsioonis, kui on võimalik, tasub hostsid siiski jaotada
root-ceph01-q:~# rack’ide vahel ja määrata replikate jaotamine rack’ide vahel:
root-ceph01-q:~# ##ceph osd crush rule create-simple rule-ssd ssd-root rack firstn

Ja loome basseinid, kus tulevikus soovime hoida meie virtualiseerimise kettapilte — PROXMOX:

    root-ceph01-q:~# #ceph osd pool create {NAME} {pg_num}  {pgp_num}
    root-ceph01-q:~# ceph osd pool create ssd_pool 1024 1024 
    root-ceph01-q:~# ceph osd pool create hdd_pool 1024 1024

Ja anname nendele basseinidele teada, milliseid jaotamisreegleid kasutada.

 root-ceph01-q:~#ceph osd crush rule ls # vaatame reeglite loetelu
    root-ceph01-q:~#ceph osd crush rule dump rule-ssd | grep rule_id # valime vajaliku ID
    root-ceph01-q:~#ceph osd pool set ssd_pool crush_rule 2

Grupi paigutusgruppide arvu valikul tuleb läheneda ettevaatlikult, olles juba varem määratlenud oma klastrit — kui palju OSD-sid seal ligikaudu on, kui suur osa andmetest (protsent kogu mahust) on puulis ja kui palju andmeid kokku on.

Kokku soovitatakse mitte ületada 300 paigutusgruppi ketta kohta ning väikeste paigutusgruppidega on lihtsam tasakaalu saavutada — see tähendab, et kui teie puul on 10 Tb ja seal on 10 PG — siis teraaÿtide (pg) ümbersuunamine oleks keeruline — liivakottide ümberlaadimine väiksemate teradega on lihtsam ja ühtlasem.

Aga tuleb meeles pidada, et mida rohkem on PG-sid — seda rohkem ressursse kulub nende asukoha arvutamiseks — hakkab kasutama mälu ja CPU-d.

Umbkaudne arusaam võib anda kalkulaator, mille on välja töötanud CEPH dokumentatsiooni arendajad.

Materjalide nimekiri:

https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data
http://www.admin-magazine.com/HPC/Articles/Linux-I-O-Schedulers
http://onreader.mdl.ru/MasteringCeph/content/Ch09.html#030202
https://tracker.ceph.com/issues/23386
https://ceph.com/pgcalc/

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster