Saluton al ĉiuj, mia nomo estas Sergej Jemeljanĉik. Mi estas la ĉefoficisto de Audit-Telecom kaj la ĉefa programisto kaj aŭtoro de la sistemo Veliam. Mi decidis verki artikolon pri kiel mi kaj amiko kreis subkontraktan kompanion, verkis programaron por ni mem, kaj poste komencis distribui ĝin al ĉiu interesato per SaaS. Mi rakontos al vi, ke mi kategorie ne kredis, ke tio eblas. La artikolo ne nur traktos la historion, sed ankaŭ la teknikajn detalojn pri kiel Veliam estis kreita, inkluzive de kelkaj fragmentoj de fontkodo. Mi ankaŭ dividos la erarojn, kiujn ni faris, kaj kiel ni korektis ilin. Mi hezitis publikigi ĉi tiun artikolon, sed mi pensis, ke estus pli bone fari ĝin, ricevi reagojn kaj plibonigi, anstataŭ ne publikigi la artikolon kaj demandi min, kio okazus se...
antaŭhistorio
Mi laboris kiel IT-specialisto ĉe firmao. Ĝi estis sufiĉe granda kaj havis vastan retstrukturon. Mi ne detale priskribos miajn laborrespondecojn, sed mi diros, ke ili certe ne implikis ian ajn evoluigan laboron.
Ni havis monitoradon, sed pro sole akademia intereso, mi volis provi verki mian propran, eĉ la plej simplan. La ideo estis havi ĝin ret-bazita, por ke ĉiu povu facile aliri la reton de iu ajn aparato, inkluzive de portebla aparato per Wi-Fi, sen instali iujn ajn klientojn. Mi ankaŭ vere volis rapide identigi la ĉambron, en kiu troviĝis la ekipaĵo, kiu funkciis, ĉar ni havis tre striktajn respondtempojn por tiaj problemoj. Fine, mi elpensis planon verki simplan retpaĝon kun JPEG-fona bildo de la reto, eltondi la aparatojn mem kun iliaj IP-adresoj el tiu ĉi bildo, kaj poste montri dinamikan enhavon super la bildo ĉe la dezirataj koordinatoj, en la formo de verda aŭ fulmanta ruĝa IP-adreso. La tasko estis farita, ni komencu.
Antaŭe, mi programis per Delphi, PHP, JS, kaj havis tre bazan komprenon pri C++. Mi havas sufiĉe bonan komprenon pri retigado, inkluzive de VLAN-oj, vojigo (OSPF, EIGRP, BGP), kaj NAT. Ĉi tio sufiĉis por mem verki bazan prototipon de monitorado.
Mi verkis la planon en PHP. La serviloj Apache kaj PHP estis sur Vindozo, ĉar Linukso estis io nekomprenebla kaj tre kompleksa por mi tiutempe. Kiel poste montriĝis, mi grave eraris, kaj laŭ multaj manieroj Linukso estas multe pli simpla ol Vindozo, sed tio estas tute alia temo, kaj ni ĉiuj scias kiom da sanktaj militoj ekzistas pri ĉi tiu temo. La Vindoza Taskplanilo funkciigis PHP-skripton je mallongaj intervaloj (mi ne memoras precize, sed ion kiel unufoje ĉiujn tri sekundojn) kiu pridemandis ĉiujn objektojn per simpla ping kaj konservis la staton al dosiero.
system(“ping -n 3 -w 100 {$ip_address}“);
Jes, labori kun la datumbazo ankaŭ estis nova por mi tiutempe. Mi ne sciis, ke procezoj povus esti paraleligitaj, kaj trairi ĉiujn retnodojn daŭris longe, ĉar ĉio estis farita en ununura fadeno. Problemoj aparte ekestis kiam pluraj nodoj ne estis disponeblaj, ĉar ĉiu tenis la skripton dum 300 ms. Ĉe la klienta flanko, ekzistis simpla bukla funkcio, kiu elŝutis ĝisdatigitajn informojn de la servilo per Ajax-peto ĉiujn kelkajn sekundojn kaj ĝisdatigis la interfacon. Tiam, post tri sinsekvaj malsukcesaj pingoj, se la monitora retpaĝo estis malfermita sur la komputilo, gaja kanto ludus.
Kiam ĉio bone funkciis, mi vere inspiriĝis de la rezulto kaj pripensis, kion alian mi povus fari (konsiderante mian scion kaj kapablojn). Sed mi ĉiam malŝatis sistemojn kun miliono da grafeoj, kiujn mi tiam konsideris, kaj ankoraŭ hodiaŭ konsideras, plejparte nenecesaj. Mi volis aldoni nur tion, kio vere helpus min en mia laboro. Ĉi tiu principo restas fundamenta en la disvolviĝo de Veliam. Tiam mi komprenis, ke estus vere bonege, se mi ne devus teni la monitoradon malfermita kaj esti atenta pri problemoj, kaj kiam unu okazus, mi povus malfermi paĝon kaj vidi, kie troviĝas la problema retnodo kaj kion fari poste. Mi tiam ne vere kontrolis retpoŝton; mi simple ne uzis ĝin. Mi trovis SMS-enirejojn interrete, al kiuj oni povas sendi GET- aŭ POST-peton, kaj ili sendos al mi SMS-on kun la teksto, kiun mi enigas, al mia poŝtelefono. Mi tuj sciis, ke mi vere volis tion. Do mi komencis studi la dokumentaron. Post iom da tempo, mi sukcesis, kaj nun mi ricevis SMS-mesaĝojn pri retproblemoj sur mia poŝtelefono, kune kun la nomo de la "falinta objekto". Kvankam la sistemo estis primitiva, mi mem skribis ĝin, kaj la plej grava afero, kiu instigis min disvolvi ĝin, estis ke ĝi estis aplikaĵo, kiu efektive helpas min en mia laboro.
Tiam venis la tago kiam unu el la interretaj ligiloj ĉe la laborejo paneis, kaj mia monitorado donis al mi neniun ideon. La DNS de Google ankoraŭ pingis perfekte. Estis tempo pripensi kiel monitori la sanon de la ligilo. Mi havis diversajn ideojn pri kiel fari tion. Mi ne havis aliron al la tuta ekipaĵo. Mi devis eltrovi manieron determini kiu ligilo estis aktiva sen povi vidi ĝin sur la reta ekipaĵo mem. Tiam kolego sugestis, ke eble la spurvojo al publikaj serviloj povus diferenci depende de kiu ligilo nuntempe aliris la interreton. Mi kontrolis, kaj tio estis ĉio. Estis malsamaj vojoj dum la spurvojo.
system(“tracert -d -w 500 8.8.8.8”);
Do alia skripto estis kreita, aŭ pli ĝuste, spuritinero estis iel aldonita al la fino de la sama skripto, kiu pingis ĉiujn aparatojn en la reto. Fine, ĉi tio estis alia longa procezo, kiu funkciis en la sama fadeno kaj malrapidigis la tutan skripton. Sed ĝi ne estis tiel evidenta tiam. Tamen, ĝi plenumis sian taskon; la kodo strikte difinis la bezonatan spuritineron por ĉiu kanalo. Tiel, sistemo komencis funkcii, kiu monitoris (tio estas troigo, ĉar ĝi ne kolektis iujn ajn metrikojn, nur pingojn) retajn aparatojn (enkursigilojn, ŝaltilojn, Wi-Fi, ktp.) kaj komunikajn kanalojn kun la ekstera mondo. SMS-mesaĝoj alvenis regule, kaj la problemo ĉiam estis klare videbla sur la diagramo.
Poste, en mia ĉiutaga laboro, mi devis trakti kruc-konektojn. Kaj ensaluti en Cisco-ŝaltilojn ĉiufoje por vidi kiun interfacon uzi fariĝis teda. Kiel bonege estus alklaki objekton en la monitora ilo kaj vidi liston de ĝiaj interfacoj kun priskriboj. Tio ŝparus al mi tempon. Krome, per ĉi tiu aliro, mi ne devus lanĉi Putty aŭ SecureCRT kaj enigi akreditaĵojn kaj komandojn. Mi povus simple alklaki la monitoran ilon, vidi kion mi bezonas, kaj komenci fari mian laboron. Mi komencis serĉi manierojn interagi kun la ŝaltiloj. Du ebloj tuj venis al mia menso: SNMP aŭ ensaluti en la ŝaltilon per SSH, enigi la necesajn komandojn kaj analizi la rezultojn. Mi malakceptis SNMP pro la komplekseco de la efektivigo; mi volis vidi la rezultojn. Kun SNMP, mi devintus pasigi multan tempon fosante tra la MIB kaj uzante tiujn datumojn por generi interfacajn datumojn. Estas bonega teamo ĉe Cisco.
show interface statusĜi montras precize tion, kion mi bezonas por kruc-konektoj. Kial ĝeni min per SNMP kiam mi nur volas vidi la rezulton de ĉi tiu komando, mi pensis. Post iom da tempo, mi efektivigis ĉi tiun funkcion. Mi alklakus objekton en la retpaĝo. Evento ekfunkcius, igante la klienton uzi AJAX por kontakti la servilon, kiu siavice konektus per SSH al la ŝaltilo, kiun mi bezonis (la akreditaĵoj estis fikse koditaj; mi ne volis ludi kun ĝi, kreante apartajn menuojn kie mi povus ŝanĝi akreditaĵojn de la interfaco; mi bezonis rezultojn, kaj rapide). Mi enigus la supran komandon tie kaj resendus ĝin al la retumilo. Tiel, mi povus vidi interfacajn informojn per unu klako. Ĉi tio estis ekstreme oportuna, precipe kiam mi devis vidi ĉi tiujn informojn samtempe sur pluraj ŝaltiloj.
Monitori ligilojn bazitan sur spuritinero montriĝis ne la plej bona ideo, ĉar foje okazis retprizorgado, kaj la spuritinero ŝanĝiĝis, kaŭzante ke la monitorado komencus krii al mi pri ligproblemoj. Sed post pasigado de tuno da tempo analizante, mi rimarkis, ke ĉiuj ligiloj funkciis, kaj mia monitorado trompis min. Fine, mi petis miajn kolegojn, kiuj administris la lig-formajn ŝaltilojn, simple sendi al mi syslog-mesaĝojn kiam ajn la najbara videbleco-stato ŝanĝiĝis. Ĉi tio estis multe pli simpla, pli rapida kaj pli preciza ol spuritinero. Okazaĵo de "najbaro perdita" alvenus, kaj mi tuj ekigus alarmon pri la ligfiasko.
Poste, alklakoj por objektoj estis aldonitaj, kune kun kelkaj pliaj komandoj, kaj SNMP estis aldonita por kolekti iujn metrikojn, kaj tio estis preskaŭ ĉio. La sistemo ne plu evoluis. Ĝi faris ĉion, kion mi bezonis; ĝi estis bona ilo. Multaj legantoj verŝajne diros al mi, ke ekzistas amaso da programaro havebla interrete por ĉi tiuj taskoj. Sed reale, mi ne povis trovi iujn ajn senpagajn tiajn produktojn tiutempe, kaj mi vere volis disvolvi miajn programajn kapablojn, kaj kia pli bona maniero fari tion ol per real-monda aplikaĵo. Tio estis la fino de la unua versio de la monitora sistemo kaj ĝi ne estis modifita de tiam.
Establado de la Audit-Telekomunika kompanio
Kun la paso de la tempo, mi komencis labori partatempe ĉe aliaj firmaoj, feliĉe mia laborhoraro permesis tion al mi. Kiam oni laboras por malsamaj firmaoj, oni tre rapide disvolviĝas kapabloj en diversaj kampoj, kaj plilarĝiĝas horizontoj. Ekzistas firmaoj, kie, kiel oni diras, oni estas multfakulo. Unuflanke, ĝi estas defia, sed aliflanke, se oni laboras forte, oni fariĝas multkapabla specialisto, kio permesas al oni solvi problemojn pli rapide kaj pli efike, ĉar oni scias kiel funkcias la koncerna fako.
Mia amiko Pavel (ankaŭ IT-specialisto) konstante provis kuraĝigi min komenci mian propran entreprenon. Ni havis sennombrajn ideojn por diversaj komercaj projektoj. Ni diskutis tion dum jaroj. Fine, nenio sukcesos, ĉar mi estas skeptikulo kaj Pavel estas viziulo. Ĉiufoje kiam li proponis ideon, mi ĉiam malkredis ĝin kaj rifuzis partopreni. Sed ni vere volis komenci nian propran entreprenon.
Fine, ni trovis solvon, kiu taŭgis por ambaŭ de ni kaj fokusiĝis al tio, pri kio ni estis bonaj. En 2016, ni decidis krei IT-kompanion, kiu helpus entreprenojn kun iliaj IT-bezonoj. Tio inkluzivis la deplojon de IT-sistemoj (1C, terminalservilo, poŝtservilo, ktp.), ilian bontenadon, la provizadon de klasika Helposervo por uzantoj, kaj la retadministradon.
Sincere, kiam mi fondis la firmaon, mi havis ĉirkaŭ 99,9% nekredemon je ĝi. Sed iel Pavel sukcesis konvinki min provi ĝin, kaj antaŭrigardante, li pravis. Pavel kaj mi ĉiu kontribuis 300 000 rublojn, registris novan LLC, Audit-Telecom, luis malgrandan oficejon, faris ŝikajn prezentokartojn — baze, kiel plej multaj nespertaj, aspirantaj komercistoj — kaj komencis serĉi klientojn. Trovi klientojn estas tute alia afero. Ni eble verkus apartan artikolon por la entreprena blogo se iu interesiĝas. Malvarmaj vokoj, flugfolioj, kaj tiel plu. Ĝi ne donis iujn ajn rezultojn. Kiel mi nun legas el multaj komercaj rakontoj, multe dependas de bonŝanco, tiel aŭ alie. Ni estis bonŝancaj. Kaj laŭvorte kelkajn semajnojn post la fondo de la firmao, mia frato, Vladimir, kontaktis nin kaj alportis al ni nian unuan klienton. Mi ne enuigos vin per la detaloj de nia klienta laboro — pri tio ne temas ĉi tiu artikolo. Permesu al mi nur diri, ke ni faris revizion, identigis kritikajn areojn, kaj tiuj areoj paneis dum oni decidis ĉu kunlabori kun ni konstante kiel subkontraktanto. Post tio, la decido tuj estis pozitiva.
Poste, plejparte per vorto-de-buŝo kaj konatoj, aliaj kompanioj komencis aperi por niaj servoj. Helpdesko estis en unu sistemo. Konektoj al reta ekipaĵo kaj serviloj estis en alia, aŭ pli ĝuste, ĉiu havis sian propran sistemon. Kelkaj konservis mallongigojn, aliaj uzis RDP-adresarojn. Monitorado estis alia aparta sistemo. Labori kiel teamo en diversaj sistemoj estas tre malkomforta. Gravaj informoj perdiĝas. Ekzemple, la terminalservilo de kliento paneas. Petoj de la uzantoj de tiu kliento tuj komencas alveni. Subtena specialisto malfermas peton (ĝi estis ricevita telefone). Se okazaĵoj kaj petoj estus registritaj en ununura sistemo, la subtena specialisto tuj vidus la problemon de la uzanto kaj informus ilin pri ĝi, samtempe konektante al la taŭga loko por pritrakti la situacion. Ĉiuj konscias pri la taktika situacio kaj kunlaboras senprobleme. Ni ne povis trovi sistemon, kiu kunigus ĉion ĉi. Fariĝis klare, ke estas tempo krei nian propran produkton.
Daŭrigante labori pri nia monitorada sistemo
Estis klare, ke la antaŭe skribita sistemo tute ne taŭgas por la nunaj taskoj, kaj laŭ funkcieco kaj laŭ kvalito. Do oni decidis skribi la sistemon de nulo. Grafike, ĝi devis aspekti tute alimaniere. Ĝi devis esti hierarkia sistemo, permesante rapidan kaj facilan aliron al la dezirata objekto por la dezirata kliento. La aranĝo de la unua versio estis tute nepravigebla en la nuna kazo, ĉar la klientoj estis malsamaj, kaj ne gravis, kie troviĝis la ekipaĵo. Ĉi tio jam estis delegita al la dokumentado.
Do, la taskoj estas:
- Hierarkia strukturo;
- Ia servila parto, kiu povas esti lokita ĉe la flanko de la kliento kiel virtuala maŝino por kolekti la metrikojn, kiujn ni bezonas, kaj sendi ilin al centra servilo, kiu resumos ĉion ĉi kaj montros ĝin al ni;
- Avertoj. La speco, kiun oni ne povis pretervidi, ĉar tiutempe ne eblis al iu ajn simple sidi kaj rigardi ekranon;
- Biletsistemo. Ni komencis akiri klientojn, por kiuj ni servis ne nur servilajn kaj retajn ekipaĵojn, sed ankaŭ laborstaciojn;
- La kapablo rapide konektiĝi al serviloj kaj ekipaĵoj de la sistemo;
La taskoj estis difinitaj, kaj ni komencis skribi. Dumvoje, ni prilaboris petojn de klientoj. Tiam, ni jam estis kvar. Ni komencis skribi ambaŭ komponantojn samtempe: la centran servilon kaj la servilon por klienta instalado. Tiam, Linukso jam ne estis fremda al ni, kaj oni decidis, ke la virtualaj maŝinoj, kiuj estus instalitaj sur klientoj, estus Debian. Ne estus instaliloj; ni simple kreus la servilan komponanton sur unu specifa virtuala maŝino, kaj poste simple klonus ĝin al la bezonata kliento. Tio estis alia eraro. Poste, evidentiĝis, ke ĉi tiu dezajno tute ne havis ĝisdatigan mekanismon. Alivorte, ni aldonus iun novan funkcion, kaj tiam estus tuta problemo distribui ĝin al ĉiuj klientaj serviloj. Sed ni atingos tion poste, siatempe.
Ni konstruis la unuan prototipon. Ĝi povis pingi la necesajn klientajn kaj servilajn retajn aparatojn kaj sendi ĉi tiujn datumojn al nia centra servilo. Ĉi tiu servilo, siavice, ĝisdatigis ĉi tiujn datumojn kolektive sur la centra servilo. Ĉi tie mi rakontos la historion ne nur pri kiel kaj kion ni sukcesis fari, sed ankaŭ pri la amatorecaj eraroj, kiujn ni faris, kaj kiel ni poste devis pagi por ili ĝustatempe. Do, la tuta objekta arbo estis stokita en ununura dosiero kiel seriigita objekto. Dum ni konektis kelkajn klientojn al la sistemo, ĉio estis pli-malpli bone, kvankam foje estis iuj artefaktoj, kiuj estis tute nekompreneblaj. Sed kiam ni konektis dekduon da serviloj al la sistemo, magio komencis okazi. Foje, sen ŝajna kialo, ĉiuj objektoj en la sistemo simple malaperis. Gravas noti, ke la serviloj de la klientoj sendis datumojn al la centra servilo ĉiujn kelkajn sekundojn per POST-petoj. Atenta leganto kaj sperta programisto jam divenis, ke ekzistis problemo kun pluraj aliroj al la dosiero mem, kiu stokis la seriigitan objekton de malsamaj fadenoj samtempe. Kaj ĝuste kiam tio okazis, magiaj objektoj malaperis. La dosiero simple malpleniĝis. Tamen, ĉi tio ne estis malkovrita tuj, sed nur dum operacio kun pluraj serviloj. Dum ĉi tiu tempo, oni aldonis la funkcion de pordoskanado (la serviloj sendis informojn al la centra servilo ne nur pri la havebleco de aparatoj sed ankaŭ pri iliaj malfermitaj pordoj). Ĉi tio estis farita per alvoko de la komando:
$connection = @fsockopen($ip, $port, $errno, $errstr, 0.5);
La rezultoj ofte estis malĝustaj kaj la skanado daŭris tre longe. Mi tute forgesis pri ping; ĝi estis farita per fping:
system("fping -r 3 -t 100 {$this->ip}");
Ankaŭ ĉi tio ne estis paraleligita, do la procezo estis tre malrapida. Poste, la tuta listo de IP-adresoj bezonataj por kontrolado estis transdonita al fping samtempe, kaj kompleta listo de tiuj, kiuj respondis, estis resendita. Male al ni, fping povis paraleligi procezojn.
Alia ofta, rutina tasko estis starigi certajn servojn per la reto. Ekzemple, la ECP de MS Exchange. Ĝi estas esence nur ligilo. Do ni decidis, ke ni bezonas ebligi al ni aldoni tiajn ligilojn rekte al la sistemo, forigante la bezonon serĉi tra dokumentado aŭ aliaj legosignoj por trovi kiel aliri la ECP de specifa kliento. Tiel aperis la koncepto de rimedaj ligiloj por la sistemo; ilia funkcio restas havebla ĝis hodiaŭ kaj restis plejparte senŝanĝa.
Kiel Funkcias Rimedaj Ligiloj en Veliam

Malproksimaj konektoj
Jen kiel ĝi aspektas en ago en la nuna versio de Veliam

Unu el la defioj estis rapida kaj facila konekto al serviloj, kiuj fariĝis multnombraj (centoj), kaj traserĉi milionojn da antaŭkonservitaj RDP-mallongigoj estis ekstreme malkomforta. Ilo estis bezonata. Ekzistas programaro interrete, kiu funkcias kiel ia adresaro por ĉi tiuj RDP-konektoj, sed ĝi ne estas integrita kun la monitorada sistemo, kaj akreditaĵoj ne povas esti konservitaj. Enigi akreditaĵojn por malsamaj klientoj ĉiufoje estas pura infero kiam vi konektas al malsamaj serviloj dekojn da fojoj tage. SSH estas iom pli bona; ekzistas multe da bona programaro, kiu permesas al vi organizi ĉi tiujn konektojn en dosierujojn kaj memori akreditaĵojn por ili. Sed estas du problemoj. Unue, ni ne povis trovi unuopan programon por ambaŭ RDP- kaj SSH-konektoj. Due, se mi estas for de mia komputilo iam ajn kaj bezonas rapide konekti, aŭ mi simple reinstalis la sistemon, mi devas esplori la dokumentaron por serĉi la akreditaĵojn por tiu kliento. Ĉi tio estas malkomforta kaj tempoperdo.
La hierarkia strukturo de klientaj serviloj, kiun ni bezonis, jam troviĝis en nia interna produkto. Ni nur devis eltrovi kiel efektivigi rapidajn konektojn al la necesa ekipaĵo. Almenaŭ ene de nia propra reto, por komenci.
Ĉar la kliento de nia sistemo estis retumilo, kiu ne havis aliron al la lokaj rimedoj de la komputilo, kaj ni ne povis simple lanĉi la bezonatan aplikaĵon per komando, ni elpensis la ideon fari ĉion per "Vindoza kutima URL-skemo". Tio kondukis al la kreado de "kromprogramo" por nia sistemo, kiu simple inkluzivis Putty kaj Remote Desktop Plus kaj, post instalado, simple registris la URI-skemon en Vindozo. Nun, kiam ajn ni volis konektiĝi al objekto per RDP aŭ SSH, ni alklakus tiun agon en nia sistemo, kaj "Kutima URI" ekfunkcius. Tio lanĉus la norman mstsc.exe enkonstruitan en Vindozo aŭ Putty, kiu estis inkluzivita kun la "kromprogramo". Mi metis la vorton "kromprogramo" en citilojn ĉar ĝi ne estas retumila kromprogramo en la klasika senco.
Almenaŭ tio estis io. Oportuna adresaro. Kaj per Putty, ĉio estis bonega; ĝi povis akcepti kaj IP-adresojn kaj uzantnomojn kaj pasvortojn kiel enigajn parametrojn. Tio signifis, ke ni povis konektiĝi al Linuksaj serviloj en nia reto per unu sola klako, sen devi enigi pasvortojn. Sed per RDP, aferoj ne estas tiel simplaj. Vi ne povas transdoni akreditaĵojn kiel parametrojn al la norma mstsc. Remote Desktop Plus venis al la savo. Ĝi permesis al ni fari ĝuste tion. Ni de tiam travivis sen ĝi, sed dum longa tempo ĝi estis fidela asistanto en nia sistemo. HTTP(S)-retejoj estas facilaj; ili simple malfermiĝas en la retumilo kaj jen. Oportuna kaj praktika. Sed tio estis nur beno por la interna reto.
Ĉar ni solvis la vastan plimulton de problemoj malproksime de la oficejo, la plej facila maniero estis starigi VPN-ojn por la klientoj. Tiam ni povis konektiĝi al ili de nia sistemo. Sed ĝi ankoraŭ estis iom malkomforta. Por ĉiu kliento, ni devis konservi amason da konservitaj pasvortoj sur ĉiu komputilo. VPN Konektojn, kaj antaŭ ol konekti al iu ajn, la koncerna VPN devis esti ebligita. Ni uzis ĉi tiun solvon dum sufiĉe longa tempo. Sed la nombro da klientoj kreskis, same kiel la nombro da VPN-oj, kaj ĉio ĉi komencis fariĝi ĝena, kaj io devis esti farita pri tio. Estis aparte larmoplene post reinstalo de la sistemo, kiam mi devis reenmeti dekojn da VPN-konektoj en novan Vindozan profilon. Mi diris, "Mi sufiĉe havis pri tio," kaj komencis pensi pri kio povus esti farita pri tio.
Okazis, ke ĉiuj niaj klientoj havis Mikrotik-enkursigilojn kiel siajn enkursigilojn. Ili estas sufiĉe funkciaj kaj oportunaj por preskaŭ ajna tasko. Unu malavantaĝo estas, ke ili ŝteliĝas. Ni solvis ĉi tiun problemon simple blokante ĉian eksteran aliron. Sed ni devis iel aliri ilin sen viziti la retejon de la kliento, ĉar tio daŭrus longe. Ni simple kreis tunelojn al ĉiu Mikrotik-enkursigilo kaj asignis ilin al aparta naĝejo, sen ia ajn vojigo, por malhelpi, ke nia reto estu interkonektita kun la retoj de niaj klientoj, aŭ kun iliaj retoj.
Mi havis la ideon krei manieron por ke la centra monitorada servilo konektu al la dezirata gastiganto kaj pordo kiam mi alklakis specifan objekton en la sistemo, sciante la SSH-akreditaĵojn de ĉiuj Mikrotik-klientoj. Tio kaŭzis plurajn problemojn. La solvo ne estis universala — ĝi funkcius nur por Mikrotik, ĉar ĉiu enkursigilo havas sian propran komandsintakson. Tia plusendado ankaŭ devus esti forigita, kaj la servila flanko de nia sistemo esence ne havus manieron spuri ĉu mi finis mian RDP-sesion. Krome, tia plusendado estis grava proplempunkto por la kliento. Ni ne celis universalecon, ĉar la produkto estis uzata nur interne, kaj ni eĉ ne konsideris publikigi ĝin.
Ĉiu problemo estis solvita laŭ sia propra maniero. Kiam la regulo estis kreita, plusendado estis havebla nur por unu specifa ekstera IP-adreso (tiu, de kiu la konekto estis iniciatita). Do sekurectruo estis evitata. Sed kun ĉiu tia konekto, Mikrotik-regulo estis aldonita al la NAT-paĝo kaj ne forigita. Kaj ĉiuj scias, ke ju pli da reguloj estas, des pli da ŝarĝo la procesoro de la enkursigilo metas sur ĝin. Kaj ĝenerale, mi ne povis akcepti la ideon, ke mi iam ensalutus Mikrotik-servilon kaj trovus centojn da mortaj, senutilaj reguloj.
Ĉar nia servilo ne povas spuri la konektostaton, mi lasis Mikrotik mem spuri ĝin. Mi skribis skripton, kiu konstante monitoris ĉiujn plusendajn regulojn kun specifa priskribo kaj kontrolis ĉu TCP-konekto kongruis kun regulo. Se ne ekzistis unu dum iom da tempo, la konekto verŝajne estis finita kaj la plusendado povus esti forigita. Ĉio funkciis bone; la skripto funkciis bone.
Cetere, jen ĝi estas:
global atmonrulecounter {"dontDelete"="dontDelete"}
:foreach i in=[/ip firewall nat find comment~"atmon_script_main"] do={
local dstport [/ip firewall nat get value-name="dst-port" $i]
local dstaddress [/ip firewall nat get value-name="dst-address" $i]
local dstaddrport "$dstaddress:$dstport"
#log warning message=$dstaddrport
local thereIsCon [/ip firewall connection find dst-address~"$dstaddrport"]
if ($thereIsCon = "") do={
set ($atmonrulecounter->$dstport) ($atmonrulecounter->$dstport + 1)
#:log warning message=($atmonrulecounter->$dstport)
if (($atmonrulecounter->$dstport) > 5) do={
#log warning message="Removing nat rules added automaticaly by atmon_script"
/ip firewall nat remove [/ip firewall nat find comment~"atmon_script_main_$dstport"]
/ip firewall nat remove [/ip firewall nat find comment~"atmon_script_sub_$dstport"]
set ($atmonrulecounter->$dstport) 0
}
} else {
set ($atmonrulecounter->$dstport) 0
}
}
Ĝi certe povus esti pli bela, pli rapida, ktp., sed ĝi funkciis, ne troŝarĝis Mikrotik, kaj funkciis perfekte. Ni fine povis konektiĝi al la serviloj kaj retaj ekipaĵoj de klientoj per nur unu klako, sen starigi VPN-on aŭ enigi pasvortojn. La sistemo fariĝis vere uzanto-amika. La bontenadotempo reduktiĝis, kaj ni ĉiuj pasigis tempon laborante, ne provante konektiĝi al la necesaj objektoj.
Mikrotik-sekurkopio
Ni havis ĉiujn Mikrotik-aparatojn agorditajn por sekurkopii per FTP. Ĉio estis bone ĝenerale. Sed kiam ni bezonis preni sekurkopion, ni devis malfermi la FTP-on kaj serĉi ĝin tie. Ni havis sistemon kie ĉiuj enkursigiloj estis konektitaj, kaj ni sciis kiel komuniki kun la aparatoj per SSH. Mi pensis, "Kial ni ne igu la sistemon aŭtomate preni sekurkopiojn de ĉiuj Mikrotik-aparatoj ĉiutage?" Do mi eklaboris pri ĝi. Ni konektis, faris sekurkopion, kaj konservis ĝin en la memoro.
PHP-skriptkodo por krei sekurkopion de Mikrotik:
<?php
$IP = '0.0.0.0';
$LOGIN = 'admin';
$PASSWORD = '';
$BACKUP_NAME = 'test';
$connection = ssh2_connect($IP, 22);
if (!ssh2_auth_password($connection, $LOGIN, $PASSWORD)) exit;
ssh2_exec($connection, '/system backup save name="atmon" password="atmon"');
stream_get_contents($connection);
ssh2_exec($connection, '/export file="atmon.rsc"');
stream_get_contents($connection);
sleep(40); // Waiting bakup makes
$sftp = ssh2_sftp($connection);
// Download backup file
$size = filesize("ssh2.sftp://$sftp/atmon.backup");
$stream = fopen("ssh2.sftp://$sftp/atmon.backup", 'r');
$contents = '';
$read = 0;
$len = $size;
while ($read < $len && ($buf = fread($stream, $len - $read))) {
$read += strlen($buf);
$contents .= $buf;
}
file_put_contents ($BACKUP_NAME . ‘.backup’,$contents);
@fclose($stream);
sleep(3);
// Download RSC file
$size = filesize("ssh2.sftp://$sftp/atmon.rsc");
$stream = fopen("ssh2.sftp://$sftp/atmon.rsc", 'r');
$contents = '';
$read = 0;
$len = $size;
while ($read < $len && ($buf = fread($stream, $len - $read))) {
$read += strlen($buf);
$contents .= $buf;
}
file_put_contents ($BACKUP_NAME . ‘.rsc’,$contents);
@fclose($stream);
ssh2_exec($connection, '/file remove atmon.backup');
ssh2_exec($connection, '/file remove atmon.rsc');
?>
La sekurkopio haveblas en du formatoj: duuma dosiero kaj tekst-bazita agordodosiero. La duuma dosiero helpas rapide restarigi la bezonatan agordodosieron, dum la tekst-bazita agordodosiero helpas kompreni kion fari se aparatara ĝisdatigo estas necesa kaj la duuma dosiero ne povas esti alŝutita. Ĉi tio aldonis alian oportunan funkcion al la sistemo. Krome, aldonante novajn Mikrotik-aparatojn, ne necesis agordi ion ajn; mi simple aldonis la objekton al la sistemo kaj asignis SSH-konton por ĝi. La sistemo tiam pritraktis sekurkopiojn aŭtomate. Ĉi tiu funkcio ankoraŭ ne haveblas en la nuna versio de Veliam SaaS, sed ni baldaŭ portos ĝin.
Ekrankopioj pri kiel ĝi aspektis en la interna sistemo

Transiro al normala datumbazstokado
Mi jam menciis la artefaktojn, kiuj aperis. Iafoje la tuta listo de objektoj en la sistemo simple malaperis; iafoje, redaktante objekton, la informoj ne konserviĝis, kaj mi devis renomi la objekton tri fojojn. Tio estis nekredeble ĝena por ĉiuj. Malaperoj de objektoj malofte okazis kaj estis facile reakireblaj per restarigo de la dosiero mem, sed fiaskoj dum redaktado de objektoj estis oftaj. Mi verŝajne komence ne efektivigis tion per la datumbazo, ĉar mi ne povis imagi, kiel arbo kun ĉiuj siaj rilatoj povus esti konservita en plata tabelo. Fine, tabelo estas plata, dum arbo estas hierarkia. Sed bona solvo por plurobla aliro, kaj poste (kiam la sistemo fariĝas pli kompleksa) por transaga aliro, estas DBMS. Mi certas, ke mi ne estas la unua persono, kiu renkontis ĉi tiun problemon. Mi komencis serĉi per Guglo. Montriĝis, ke ĉio jam estis inventita antaŭ mi, kaj ekzistas pluraj algoritmoj, kiuj konstruas arbon el plata tabelo. Post rigardado de ĉiu, mi efektivigis unu el ili. Sed tio jam estis nova versio de la sistemo, ĉar... Esence, tio postulis signifan kvanton da reverkado. La rezulto estis antaŭvidebla: la hazardaj kondutaj problemoj de la sistemo malaperis. Kelkaj eble dirus, ke la eraroj estis sufiĉe amatorecaj en la kampo de programara disvolviĝo (unufadenaj skriptoj, stokado de informoj aliritaj plurfoje samtempe el malsamaj fadenoj en dosiero, ktp.). Tio eble estas vera, sed mia ĉefa laboro estis administrado, kaj programado estis flanka laboro, kaj mi simple ne havis la sperton labori en teamo de programistoj, kie pli spertaj kolegoj instigus min per tiaj bazaj konceptoj. Do mi lernis ĉiujn ĉi tiujn lecionojn mem, sed mi lernis la materialon tre bone. Administri vian propran entreprenon ankaŭ signifas renkontiĝi kun klientoj, provi reklami la kompanion, trakti tunon da administraj problemoj ene de la kompanio, kaj multe, multe pli. Sed tiel aŭ alie, tio, kio jam ekzistis, estis postulata. Mia teamo kaj mi uzis la produkton en nia ĉiutaga laboro. Estis kelkaj tute malbonaj ideoj kaj solvoj, kiuj prenis tempon, sed finfine evidentiĝis, ke ĝi ne estis funkcia ilo, neniu uzis ĝin, kaj ĝi ne sukcesis eniri Veliam.
Helposervo
Indas mencii kiel HelpDesk ekestis. Tio estas tute alia rakonto, ĉar ĉi tiu jam estas la tria tute nova versio de Veliam, kaj ĝi estas tute malsama ol ĉiuj antaŭaj versioj. Ĝi nun estas simpla, intuicia sistemo sen nenecesaj ekstraĵoj, kun la kapablo integriĝi kun domajno kaj aliri la saman uzantoprofilon de ie ajn per ligilo en retpoŝto. Kaj plej grave, eblas konekti al la petanto per VNC de ie ajn (hejme aŭ en la oficejo) rekte de la petformularo, sen VPN aŭ havenplusendado. Mi rakontos al vi kiel ni alvenis ĉi tien, kio okazis antaŭe, kaj kiajn terurajn decidojn ni faris.
Ni konektiĝis kun uzantoj per la konata TeamViewer. Ĉiuj komputiloj, kies uzantojn ni servas, havas instalitan televidilon. La unua afero, kiun ni faris malĝuste, kaj poste forigis, estis la ligado de ĉiu HD-kliento al aparataro. Kiel la uzanto ensalutiĝis en la HD-sistemon por sendi peton? Krom televidiloj, ĉiu havis specialan ilon skribitan en Lazarus instalitan sur siaj komputiloj (multaj tiam larĝigos siajn okulojn kaj eble eĉ komencos serĉi per Guglo kio ĝi estas, sed tiu, kiun mi plej bone konis inter kompilitaj lingvoj, estis Delphi, kaj Lazarus estas preskaŭ la sama afero, nur senpaga). Esence, la uzanto lanĉis specialan aro-dosieron, kiu lanĉis ĉi tiun ilon, kiu siavice legis la HWID-on de la sistemo, post kio la retumilo lanĉiĝis kaj rajtigo okazis. Kial ĉi tio estis farita? En iuj kompanioj, la nombro de servataj uzantoj estas kalkulata individue, kaj la prezo por ĉiu monato estas determinita surbaze de la nombro de homoj. Tio estas komprenebla, vi diras, sed kial la konekto al aparataro? Estas tre simple: kelkaj individuoj venis hejmen kaj faris peton per sia hejma tekokomputilo en la stilo de "faru ĉion ĉi tie bela por mi". Aldone al legado de la HWID de la sistemo, la ilo eltiris la nunan ID-on de TeamViewer el la registro kaj transdonis ĝin al ni. Teamviewer havas API-on por integriĝo. Kaj ni faris ĉi tiun integriĝon. Sed estis unu problemo. Ĉi tiuj API-oj ne povas esti uzataj por konekti al la komputilo de uzanto krom se la uzanto eksplicite iniciatas la sesion, kaj post provo konekti, la uzanto devas klaki "konfirmi". Tiam ŝajnis al ni logike, ke neniu konektu sen la permeso de la uzanto, kaj ĉar la persono estus ĉe la komputilo, tiu komencus la sesion kaj respondus jese al la peto pri fora konekto. Ĉio rezultis alimaniere. Kandidatoj forgesis premi komenci sesion, kaj devis diri tion al ili dum telefona konversacio. Tio estis tempopostula kaj frustranta por ambaŭ koncernaj partioj. Krome, ne estas malofte, ke persono lasas peton, sed nur permesas konekton kiam li iras tagmanĝi. Ĉar la problemo ne estas kritika kaj li ne volas, ke lia laborprocezo estu interrompita. Sekve, li ne premos iujn ajn butonojn por ebligi la konekton. Jen kiel aperis plia funkcio dum rajtigado en HelpDesk: legado de la TeamViewer ID. Ni sciis la permanentan pasvorton, kiu estis uzata dum la instalado de Teamviewer. Pli precize, nur la sistemo sciis pri ĝi, ĉar ĝi estis enkonstruita en la instalilon kaj en nian sistemon. Sekve, ekzistis konekta butono de la aplikaĵo, post alklako de kiu ne necesis atendi ion ajn, sed Teamviewer tuj malfermiĝis kaj konekto estis establita. Rezulte, ekzistis du specoj de eblaj ligoj. Per la oficiala Teamviewer API kaj nia propra. Je mia surprizo, la unua preskaŭ tuj ĉesis esti uzata, kvankam estis instrukcio uzi ĝin nur en specialaj kazoj kaj kiam la uzanto mem donas permeson por tio. Ni ankoraŭ bezonas sekurecon nun. Sed montriĝis, ke la kandidatoj ne bezonis ĉi tion. Ili ĉiuj tute akceptas esti konektitaj sen konfirmbutono. Kaj ĉar tio estas la kazo, la API-konekta funkcio estis poste forigita kiel nenecesa.
Transiro al Plurfadenado en Linukso
La demando pri rapidigo de retskanado por antaŭdifinita listo de malfermitaj pordoj kaj simple pingado de retobjektoj jam delonge pliiĝas. La unua solvo, kiu venas al la menso, estas plurfadenigo. Ĉar la ĉefa tempo pasigita por pingado estas atendado de pakaĵeto por reveni, kaj la sekva pingado ne povas komenciĝi ĝis la antaŭa pakaĵeto revenas, tio fariĝis sufiĉe malrapida por kompanioj kun eĉ pli ol 20 serviloj kaj reta ekipaĵo. La problemo estas, ke unuopa pakaĵeto povas perdiĝi, kaj ne utilas tuj sciigi la sistemadministranton. Ili rapide ĉesos aŭskulti tian spamon. Tial necesas pingi ĉiun objekton plurfoje antaŭ ol konkludi, ke ĝi ne estas disponebla. Sen tro da detaloj, estas esence paraleligi la procezon, ĉar alie la sistemadministranto verŝajne ekscios pri la problemo de la kliento, ne de la monitora sistemo.
PHP mem ne subtenas plurfadenan traktadon tuj el la skatolo. Ĝi ja subtenas plurtraktadon, kaj oni povas krei forkon por ĝi. Sed mi jam havis skribitan balotmekanismon, kaj mi volis fari ĝin tiel, ke mi povus legi ĉiujn bezonatajn nodojn el la datumbazo unufoje, pingi ilin ĉiujn samtempe, atendi respondon de ĉiu, kaj nur poste skribi la datumojn. Tio ŝparas legpetojn. Plurfadenado perfekte kongruis kun ĉi tiu ideo. PHP havas modulon nomatan PThreads, kiu ebligas veran plurfadenadon. Agordi ĝin en PHP 7.2 postulis iom da manipulado, sed ĝi funkciis. Havenskanado kaj pingado fariĝis pli rapidaj. Anstataŭ, ekzemple, 15 sekundoj por ĉiu tien-reen, ĉi tiu procezo nun daŭras 2 sekundojn. Ĝi estis bona rezulto.
Rapida revizio de novaj kompanioj
Kiel ekestis la funkcio por kolekti diversajn metrikojn kaj aparatarajn karakterizaĵojn? Estas simple. Ni kelkfoje ricevas komision por simple revizii la nunan IT-infrastrukturon. La sama afero ankaŭ necesas por rapidigi la revizion de nova kliento. Ni bezonis ion, kio permesus al ni veni al meza aŭ granda kompanio kaj rapide kompreni, kion ili havas. Laŭ mia opinio, nur tiuj, kiuj volas malfaciligi la vivon al si, blokas ping-on en la interna reto, kaj laŭ nia sperto, tiaj homoj estas malmultaj. Sed ili ekzistas. Tial ni povas rapide skani retojn por aparatoj per simpla ping-o. Poste ni povas aldoni ilin kaj skani malfermajn havenojn de intereso. Esence, ĉi tiu funkcio jam ekzistis; ni nur bezonis aldoni komandon de la centra servilo al la sklava servilo, por ke ĝi skanu la specifitajn retojn kaj aldonu ĉion, kion ĝi trovas, al la listo. Mi forgesis mencii, ke ni supozis, ke ni jam havas pretan bildon kun agordita sistemo (sklava monitorada servilo), kiun ni povus simple deploji al la kliento dum la revizio kaj konekti ĝin al nia nubo.
Sed la rezulto de la revizio kutime inkluzivas tunon da diversaj informoj, kaj unu el ili estas la naturo de la aparatoj en la reto. Ni ĉefe interesiĝis pri Vindozaj serviloj kaj Vindozaj laborstacioj en domajno. En mezgrandaj kaj grandaj kompanioj, la manko de domajno estas probable la escepto prefere ol la regulo. Por esti sur la sama paĝo, mezgranda kompanio, laŭ mia opinio, estas pli ol 100 homoj. Ni devis elpensi manieron kolekti datumojn de ĉiuj Vindozaj maŝinoj kaj serviloj, sciante iliajn IP-adresojn kaj domajnajn administrantajn kontojn, sen instali ian ajn programaron sur ĉiu. La WMI-interfaco venis al la savo. Windows Management Instrumentation (WMI) laŭvorte signifas Windows Management Instrumentation. WMI estas unu el la bazaj teknologioj por centralizita administrado kaj monitorado de diversaj partoj de komputila infrastrukturo funkcianta per la Vindoza platformo. Prenite el la vikio. Poste ni devis denove ludi por konstrui wmic (WMI-kliento) por Debian. Post kiam ĉio estis preta, simple necesis pridemandi la deziratajn nodojn per wmic por la bezonataj informoj. WMI povas preni preskaŭ ajnajn informojn de Vindoza komputilo, kaj krome, ĝi ankaŭ povas esti uzata por kontroli la komputilon, ekzemple, devigante ĝin restartiĝi. Tiel ni komencis kolekti informojn pri Vindozaj laborstacioj kaj serviloj en nia sistemo. Krome, ni ankaŭ kolektis datumojn pri aktuala sistema ŝarĝo. Ni petas tion pli ofte, dum informoj pri aparataro malpli ofte. Post tio, la revizio fariĝis iom pli plaĉa.
Decido pri programara distribuado
Ni uzas la sistemon ĉiutage, kaj ĉiu teknika stabano ĉiam havas ĝin malfermita. Ni pensis, ke ni povus dividi tion, kion ni jam havis, kun aliaj. La sistemo ankoraŭ ne estis tute preta por distribuo. Multe bezonis esti reverkita por transformi la surlokan version en SaaS-solvon. Tio inkluzivis ŝanĝojn al diversaj teknikaj aspektoj de la sistemo (malproksimaj konektoj, subteno), analizon de modulaj licencoj, fragmentigon de klientaj datumbazoj, skaladon de ĉiu servo, kaj disvolvon de aŭtomataj ĝisdatigaj sistemoj por ĉiuj komponantoj. Sed tion traktos la dua parto de ĉi tiu artikolo.
Ĝisdatigu
fonto: www.habr.com
