Automatisera diskbyte med Ansible

Automatisera diskbyte med Ansible

Hej alla. Jag arbetar som ledande systemadministratör på OK och ansvarar för en stabil drift av portalen. Jag vill prata om hur vi byggde en process för att automatiskt ersätta diskar, och sedan hur vi uteslöt administratören från denna process och ersatte honom med en bot.

Den här artikeln är en sorts translitteration föreställningar på HighLoad+ 2018

Att bygga en diskbytesprocess

Först några siffror

OK är en jättetjänst som används av miljontals människor. Den betjänas av cirka 7 tusen servrar, som finns i 4 olika datacenter. Servrarna innehåller mer än 70 tusen diskar. Om du staplar dem ovanpå varandra får du ett mer än 1 km högt torn.

Hårddiskar är den serverkomponent som oftast misslyckas. Med sådana volymer måste vi byta cirka 30 diskar per vecka, och denna procedur har blivit en inte särskilt trevlig rutin.

Automatisera diskbyte med Ansible

Incidenter

Vårt företag har infört fullfjädrad incidenthantering. Vi registrerar varje incident i Jira och löser och reder ut det. Om en incident haft effekt på användarna, då samlas vi definitivt och funderar på hur man kan reagera snabbare i sådana fall, hur man kan minska effekten och, naturligtvis, hur man förhindrar en upprepning.

Lagringsenheter är inget undantag. Deras status övervakas av Zabbix. Vi övervakar meddelanden i Syslog för skriv-/läsfel, analyserar status för HW/SW-raider, övervakar SMART och beräknar slitage för SSD:er.

Hur diskar byttes förut

När en trigger inträffar i Zabbix skapas en incident i Jira och tilldelas automatiskt lämpliga ingenjörer i datacentren. Det gör vi med alla HW-incidenter, det vill säga sådana som kräver något fysiskt arbete med utrustning i datacentret.
En datacenteringenjör är en person som löser problem relaterade till hårdvara och ansvarar för att installera, underhålla och demontera servrar. Efter att ha fått biljetten går ingenjören till jobbet. I diskhyllor byter han diskar självständigt. Men om han inte har tillgång till den nödvändiga enheten vänder sig ingenjören till systemadministratörerna i tjänst för att få hjälp. Först och främst måste du ta bort skivan från rotation. För att göra detta måste du göra nödvändiga ändringar på servern, stoppa applikationer och avmontera disken.

Jourhavande systemförvaltare ansvarar för driften av hela portalen under arbetspasset. Han undersöker incidenter, reparerar och hjälper utvecklare att utföra små uppgifter. Han sysslar inte bara med hårddiskar.

Tidigare kommunicerade datacenteringenjörer med systemadministratören via chatt. Ingenjörer skickade länkar till Jira-biljetter, administratören följde dem, förde en logg över arbetet i något anteckningsblock. Men chattar är obekväma för sådana uppgifter: informationen där är inte strukturerad och går snabbt förlorad. Och administratören kunde helt enkelt gå bort från datorn och inte svara på förfrågningar på ett tag, medan ingenjören stod vid servern med en hög diskar och väntade.

Men det värsta var att administratörerna inte såg hela bilden: vilka diskincidenter som fanns, där ett problem potentiellt kunde uppstå. Detta beror på att vi delegerar alla HW-incidenter till ingenjörer. Ja, det var möjligt att visa alla incidenter på administratörens instrumentpanel. Men det finns många av dem, och administratören var inblandad bara för några av dem.

Dessutom kunde ingenjören prioritera korrekt, eftersom han inte vet något om syftet med specifika servrar eller distributionen av information mellan enheter.

Nytt bytesprocedur

Det första vi gjorde var att flytta alla diskincidenter till en separat typ "HW disk" och la till fälten "block device name", "size" och "disk type" till den så att denna information skulle lagras i biljetten och skulle inte behöva ständigt utbyta i chatten.

Automatisera diskbyte med Ansible
Vi kom också överens om att under en incident skulle vi bara byta en disk. Detta förenklade avsevärt automatiseringsprocessen, statistikinsamlingen och arbetet i framtiden.

Dessutom har vi lagt till fältet "ansvarig administratör". Den jourhavande systemadministratören är automatiskt insatt där. Detta är väldigt bekvämt, för nu ser ingenjören alltid vem som är ansvarig. Du behöver inte gå till kalendern och söka. Det var detta fält som gjorde det möjligt att visa biljetter på administratörens instrumentpanel som kunde kräva hans hjälp.

Automatisera diskbyte med Ansible
För att säkerställa att alla deltagare fick maximal nytta av innovationer skapade vi filter och instrumentpaneler och berättade om dem för killarna. När människor förstår förändringar tar de inte avstånd från dem som något onödigt. Det är viktigt för en ingenjör att känna till racknumret där servern är placerad, storleken och typen av disk. Administratören måste först och främst förstå vilken typ av grupp av servrar detta är och vad effekten kan bli när man byter ut en disk.

Närvaron av fält och deras visning är bekvämt, men det räddade oss inte från behovet av att använda chattar. För att göra detta var vi tvungna att ändra arbetsflödet.

Tidigare var det så här:

Automatisera diskbyte med Ansible
Det är så ingenjörer fortsätter att arbeta idag när de inte behöver administratörshjälp.

Det första vi gjorde var att införa en ny status Undersöka. Biljetten är i denna status när ingenjören ännu inte har bestämt sig för om han kommer att behöva en administratör eller inte. Genom denna status kan ingenjören överföra ärendet till administratören. Dessutom använder vi denna status för att markera biljetter när en disk behöver bytas ut, men själva disken inte finns på plats. Detta händer i fallet med CDN:er och fjärrplatser.

Vi har också lagt till status Klar. Biljetten överförs till den efter att skivan har bytts ut. Det vill säga allt har redan gjorts, men HW/SW RAID är synkroniserat på servern. Detta kan ta ganska lång tid.

Om en handläggare är inblandad i arbetet blir upplägget lite mer komplicerat.

Automatisera diskbyte med Ansible
Från status Öppen Biljetten kan översättas av både systemadministratören och ingenjören. I status Pågår administratören tar bort disken från rotation så att ingenjören helt enkelt kan dra ut den: sätter på bakgrundsbelysningen, avmonterar disken, stoppar applikationer, beroende på den specifika gruppen av servrar.

Biljetten överförs sedan till Redo att byta: Detta är en signal till ingenjören att skivan kan dras ut. Alla fält i Jira är redan ifyllda, ingenjören vet vilken typ och storlek på disken. Dessa uppgifter läggs antingen in automatiskt på föregående status eller av administratören.

Efter byte av disken ändras biljettstatusen till Ändrats. Den kontrollerar att rätt disk har satts i, partitionering är gjord, applikationen startas och vissa uppgifter för dataåterställning startas. Biljetten kan också överföras till status Klar, i det här fallet kommer administratören att förbli ansvarig, eftersom han satte skivan i rotation. Hela diagrammet ser ut så här.

Automatisera diskbyte med Ansible
Att lägga till nya fält gjorde vårt liv mycket enklare. Killarna började jobba med strukturerad information, det blev tydligt vad som behövde göras och i vilket skede. Prioriteringar har blivit mycket mer relevanta, eftersom de nu bestäms av administratören.

Det finns inget behov av chattar. Naturligtvis kan administratören skriva till ingenjören "det här måste bytas ut snabbare" eller "det är redan kväll, kommer du att hinna byta det?" Men vi kommunicerar inte längre dagligen i chattar om dessa frågor.

Diskar började bytas ut i omgångar. Om administratören kom till jobbet lite tidigt, han har ledig tid, och ingenting har hänt ännu, kan han förbereda ett antal servrar för utbyte: fyll i fälten, ta bort diskar från rotation och överför uppgiften till en ingenjör. Ingenjören kommer till datacentret lite senare, ser uppgiften, tar de nödvändiga enheterna från lagret och ersätter dem omedelbart. Som ett resultat har ersättningsgraden ökat.

Lärdomar när man bygger Workflow

  • När du konstruerar en procedur måste du samla in information från olika källor.
    Vissa av våra administratörer visste inte att ingenjören själv byter diskar. Vissa människor trodde att MD RAID-synkronisering hanterades av ingenjörer, även om vissa av dem inte ens hade tillgång till det. Några ledande ingenjörer gjorde detta, men inte alltid eftersom processen inte beskrevs någonstans.
  • Proceduren ska vara enkel och begriplig.
    Det är svårt för en person att hålla många steg i åtanke. De viktigaste grannstatusarna i Jira bör placeras på huvudskärmen. Du kan byta namn på dem, till exempel kallar vi Pågår Redo att ändra. Och andra statusar kan döljas i en rullgardinsmeny så att de inte är ett öga. Men det är bättre att inte begränsa människor, för att ge dem möjlighet att göra övergången.
    Förklara värdet av innovation. När folk förstår accepterar de det nya förfarandet mer. Det var väldigt viktigt för oss att folk inte klickar sig igenom hela processen, utan följer den. Sedan byggde vi automatisering på detta.
  • Vänta, analysera, ta reda på det.
    Det tog oss ungefär en månad att bygga upp proceduren, teknisk implementering, möten och diskussioner. Och implementeringen tar mer än tre månader. Jag såg hur folk sakta börjar använda innovationen. Det var mycket negativitet i de tidiga stadierna. Men det var helt oberoende av själva proceduren och dess tekniska genomförande. En administratör använde till exempel inte Jira, utan Jira-pluginen i Confluence, och vissa saker var inte tillgängliga för honom. Vi visade honom Jira, och administratörens produktivitet ökade både för allmänna uppgifter och för att byta ut diskar.

Automatisering av diskbyte

Vi närmade oss automatisering av diskbyte flera gånger. Vi hade redan utvecklingar och skript, men de fungerade alla antingen interaktivt eller manuellt och krävde lansering. Och först efter att vi infört det nya förfarandet insåg vi att det var precis vad vi saknade.

Eftersom nu vår ersättningsprocess är uppdelad i etapper, som var och en har en specifik utförare och en lista med åtgärder, kan vi aktivera automatisering i etapper, och inte alla på en gång. Till exempel kan det enklaste steget - Ready (kontrollera RAID/datasynkronisering) enkelt delegeras till en bot. När boten har lärt sig lite kan du ge den en viktigare uppgift - att sätta disken i rotation osv.

Zoo inställningar

Innan vi pratar om boten, låt oss ta en kort utflykt till vår zoo med installationer. För det första beror det på den gigantiska storleken på vår infrastruktur. För det andra försöker vi välja den optimala hårdvarukonfigurationen för varje tjänst. Vi har ett 20-tal hårdvaru-RAID-modeller, mestadels LSI och Adaptec, men det finns även HP och DELL av olika versioner. Varje RAID-kontroller har sitt eget hanteringsverktyg. Uppsättningen av kommandon och utfärdandet av dem kan skilja sig från version till version för varje RAID-kontroller. Där HW-RAID inte används kan mdraid användas.

Vi gör nästan alla nyinstallationer utan diskbackup. Vi försöker att inte längre använda hård- och mjukvaru-RAID, eftersom vi säkerhetskopierar våra system på datacenternivå, inte servrar. Men naturligtvis finns det många äldre servrar som behöver stödjas.

Någonstans överförs diskarna i RAID-kontroller till råa enheter, någonstans används JBODs. Det finns konfigurationer med en systemdisk i servern, och om den behöver bytas ut måste du installera om servern med installationen av operativsystemet och applikationerna av samma versioner, sedan lägga till konfigurationsfiler, starta applikationer. Det finns också många servergrupper där säkerhetskopiering utförs inte på diskundersystemsnivå, utan direkt i själva applikationerna.

Totalt har vi över 400 unika servergrupper som kör nästan 100 olika applikationer. För att täcka ett så stort antal alternativ behövde vi ett multifunktionellt automationsverktyg. Gärna med en enkel DSL, så att inte bara den som skrivit det kan stödja det.

Vi valde Ansible eftersom det är agentlöst: det fanns inget behov av att förbereda infrastruktur, en snabb start. Dessutom är det skrivet i Python, vilket är accepterat som standard inom teamet.

Allmän ordning

Låt oss titta på det allmänna automatiseringsschemat med en incident som exempel. Zabbix upptäcker att sdb-disken har misslyckats, triggern tänds och en biljett skapas i Jira. Administratören tittade på det, insåg att det inte var en dubblett och inte en falsk positiv, det vill säga att skivan behövde ändras, och överförde biljetten till Pågår.

Automatisera diskbyte med Ansible
Applikationen DiskoBot, skriven i Python, söker med jämna mellanrum Jira efter nya biljetter. Den märker att en ny pågående biljett har dykt upp, motsvarande tråd triggas, vilket startar spelboken i Ansible (detta görs för varje status i Jira). I det här fallet startas Prepare2change.

Ansible skickas till värden, tar bort disken från rotation och rapporterar status till applikationen via Callbacks.

Automatisera diskbyte med Ansible
Baserat på resultaten överför boten automatiskt biljetten till Ready to change. Ingenjören får ett meddelande och går för att byta disk, varefter han överför biljetten till Changed.

Automatisera diskbyte med Ansible
Enligt schemat som beskrivs ovan går biljetten tillbaka till boten, som lanserar en annan spelbok, går till värden och sätter skivan i rotation. Boten stänger biljetten. Hurra!

Automatisera diskbyte med Ansible
Låt oss nu prata om några komponenter i systemet.

Diskobot

Denna applikation är skriven i Python. Den väljer biljetter från Jira enligt JQL. Beroende på biljettens status går den senare till motsvarande hanterare, som i sin tur startar Ansible-spelboken som motsvarar statusen.

JQL och avfrågningsintervall definieras i programmets konfigurationsfil.

jira_states:
  investigate:
    jql: '… status = Open and "Disk Size" is EMPTY'
    interval: 180

  inprogress:
    jql: '…  and "Disk Size" is not EMPTY and "Device Name" is not EMPTY'
 
  ready:
    jql: '… and (labels not in ("dbot_ignore") or labels is EMPTY)'
    interval: 7200

Till exempel, bland biljetter i statusen Pågår, väljs endast de med fälten Diskstorlek och Enhetsnamn ifyllda. Enhetsnamn är namnet på den blockenhet som behövs för att köra spelboken. Diskstorlek behövs så att ingenjören vet vilken storlek disk som behövs.

Och bland biljetter med Ready-status filtreras biljetter med dbot_ignore-etiketten bort. Vi använder förresten Jira-etiketter både för sådan filtrering och för att markera dubbletter av biljetter och samla in statistik.

Om en spelbok misslyckas tilldelar Jira etiketten dbot_failed så att den kan redas ut senare.

Interoperabilitet med Ansible

Applikationen kommunicerar med Ansible via Ansible Python API. Till playbook_executor skickar vi filnamnet och en uppsättning variabler. Detta gör att du kan behålla Ansible-projektet i form av vanliga yml-filer, snarare än att beskriva det i Python-kod.

Även i Ansible, via *extra_vars*, namnet på blockeringsenheten, statusen för biljetten, samt callback_url, som innehåller utfärdandenyckeln - den används för callback i HTTP.

För varje lansering genereras en tillfällig inventering, bestående av en värd och gruppen som denna värd tillhör, så att group_vars tillämpas.

Här är ett exempel på en uppgift som implementerar HTTP-återuppringning.

Vi får resultatet av att köra playbooks med callaback(s). De är av två typer:

  • Ansible callback plugin, ger den data om resultaten av körning av playbook. Den beskriver de uppgifter som har lanserats, slutförts framgångsrikt eller misslyckat. Denna återuppringning anropas när spelboken har spelat klart.
  • HTTP-återuppringning för att ta emot information medan du spelar en spelbok. I Ansible-uppgiften utför vi en POST/GET-förfrågan till vår applikation.

Variabler skickas genom HTTP-återuppringning(er) som definierades under körningen av spelboken och som vi vill spara och använda i efterföljande körningar. Vi skriver denna data i sqlite.

Vi lämnar även kommentarer och ändrar biljettstatus via HTTP-återuppringning.

HTTP-återuppringning

# Make callback to Diskobot App
# Variables:
#    callback_post_body: # A dict with follow keys. All keys are optional
#       msg: If exist it would be posted to Jira as comment
#       data: If exist it would be saved in Incident.variables
#       desire_state: Set desire_state for incident
#       status: If exist Proceed issue to that status

  - name: Callback to Diskobot app (jira comment/status)
    uri:
      url: "{{ callback_url }}/{{ devname }}"
      user: "{{ diskobot_user }}"
      password: "{{ diskobot_pass }}"
      force_basic_auth: True
      method: POST
      body: "{{ callback_post_body | to_json }}"
      body_format: json
    delegate_to: 127.0.0.1

Liksom många uppgifter av samma typ lägger vi den i en separat gemensam fil och inkluderar den om det behövs, för att inte ständigt upprepa det i spelböcker. Detta inkluderar callback_ url, som innehåller problemnyckeln och värdnamnet. När Ansible kör denna POST-begäran förstår boten att den kom som en del av en sådan och en incident.

Och här är ett exempel från spelboken, där vi matar ut en skiva från en MD-enhet:

  # Save mdadm configuration
  - include: common/callback.yml
    vars:
      callback_post_body:
        status: 'Ready to change'
        msg: "Removed disk from mdraid {{ mdadm_remove_disk.msg | comment_jira }}"
        data:
          mdadm_data: "{{ mdadm_remove_disk.removed }}"
          parted_info: "{{ parted_info | default() }}"
    when:
      - mdadm_remove_disk | changed
      - mdadm_remove_disk.removed

Denna uppgift överför Jira-biljetten till statusen "Redo att ändra" och lägger till en kommentar. Variabeln mdam_data lagrar också en lista över md-enheter från vilka disken togs bort, och parted_info lagrar en partitionsdump från parted.

När ingenjören sätter in en ny disk kan vi använda dessa variabler för att återställa partitionsdumpen, samt sätta in disken i md-enheterna från vilka den togs bort.

Ansible check mode

Det var läskigt att slå på automatiken. Därför bestämde vi oss för att köra alla playbooks i läget
torrkörning, där Ansible inte utför några åtgärder på servrarna, utan bara emulerar dem.

En sådan lansering körs genom en separat callback-modul, och resultatet av playbook-körningen sparas i Jira som en kommentar.

Automatisera diskbyte med Ansible

För det första gjorde detta det möjligt att validera botens och spelböckernas arbete. För det andra ökade det administratörernas förtroende för boten.

När vi klarade valideringen och insåg att du inte bara kan köra Ansible i torrkörningsläge, gjorde vi en Kör Diskobot-knapp i Jira för att starta samma spelbok med samma variabler på samma värd, men i normalt läge.

Dessutom används knappen för att starta om spelboken om den kraschar.

Playbooks struktur

Jag har redan nämnt att beroende på statusen för Jira-biljetten lanserar boten olika spelböcker.

För det första är det mycket lättare att organisera entrén.
För det andra är det i vissa fall helt enkelt nödvändigt.

Till exempel, när du byter ut en systemdisk måste du först gå till distributionssystemet, skapa en uppgift, och efter korrekt distribution blir servern tillgänglig via ssh och du kan rulla ut applikationen på den. Om vi ​​gjorde allt detta i en spelbok, skulle Ansible inte kunna slutföra det på grund av att värden inte är tillgänglig.

Vi använder Ansible-roller för varje grupp av servrar. Här kan du se hur spelböckerna är organiserade i en av dem.

Automatisera diskbyte med Ansible

Detta är bekvämt eftersom det omedelbart är tydligt var vilka uppgifter finns. I main.yml, som är ingången för Ansible-rollen, kan vi helt enkelt inkludera per biljettstatus eller allmänna uppgifter som krävs för alla, till exempel att passera identifiering eller ta emot en token.

utredning.yml

Körs för biljetter i Utredning och Öppet status. Det viktigaste för den här spelboken är blockenhetens namn. Denna information är inte alltid tillgänglig.

För att få det analyserar vi Jira-sammanfattningen, det sista värdet från Zabbix-utlösaren. Den kan innehålla namnet på blockenheten - tur. Eller så kan den innehålla en monteringspunkt, då måste du gå till servern, analysera den och beräkna den nödvändiga disken. Utlösaren kan också sända en scsi-adress eller annan information. Men det händer också att det inte finns några ledtrådar, och man måste analysera.

Efter att ha tagit reda på namnet på blockenheten samlar vi in ​​information om typen och storleken på skivan från den för att fylla i fälten i Jira. Vi tar också bort information om leverantör, modell, firmware, ID, SMART och infogar allt detta i en kommentar i Jira-biljetten. Administratören och ingenjören behöver inte längre söka efter dessa data. 🙂

Automatisera diskbyte med Ansible

prepare2change.yml

Ta bort skivan från rotation, förberedelse för utbyte. Det svåraste och viktigaste stadiet. Det är här du kan stoppa applikationen när den inte borde stoppas. Eller ta ut en disk som inte hade tillräckligt många repliker, och därigenom påverka användarna och förlora en del data. Här har vi flest kontroller och notiser i chatten.

I det enklaste fallet talar vi om att ta bort en disk från en HW/MD RAID.

I mer komplexa situationer (i våra lagringssystem), när säkerhetskopieringen utförs på applikationsnivå, behöver du gå till applikationen via API:t, rapportera diskutmatningen, avaktivera den och starta återställningen.

Vi migrerar nu en masse till cloud, och om servern är molnbaserad, så anropar Diskobot molnets API, säger att det kommer att fungera med denna minion - servern som kör behållare - och frågar "migrera alla behållare från denna minion." Och slår samtidigt på bakgrundsbelysningen på skivan så att ingenjören omedelbart kan se vilken som måste dras ut.

ändrad.yml

Efter att ha bytt ut en disk kontrollerar vi först dess tillgänglighet.

Ingenjörer installerar inte alltid nya enheter, så vi lade till en kontroll för SMART-värden som tillfredsställer oss.

Vilka egenskaper tittar vi på?Antal omfördelade sektorer (5) < 100
Aktuellt väntande sektorantal (107) == 0

Om frekvensomriktaren inte klarar testet, meddelas ingenjören att den ska bytas ut igen. Om allt är i sin ordning stängs bakgrundsbelysningen av, markeringar appliceras och skivan roteras.

redo.yml

Det enklaste fallet: kontrollera HW/SW-raidsynkronisering eller slutföra datasynkronisering i applikationen.

Application API

Jag har nämnt flera gånger att boten ofta kommer åt applikations-API:er. Naturligtvis hade inte alla applikationer de nödvändiga metoderna, så de måste modifieras. Här är de viktigaste metoderna vi använder:

  • Status. Status för ett kluster eller disk för att förstå om det går att arbeta med;
  • Starta/stoppa. Diskaktivering/deaktivering;
  • Migrera/återställa. Datamigrering och återställning under och efter utbyte.

Lärdomar från Ansible

Jag älskar verkligen Ansible. Men ofta, när jag tittar på olika opensource-projekt och ser hur folk skriver spelböcker, blir jag lite rädd. Komplexa logiska sammanvävningar av när/loop, bristande flexibilitet och idempotens på grund av frekvent användning av skal/kommando.

Vi bestämde oss för att förenkla allt så mycket som möjligt och dra nytta av fördelen med Ansible - modularitet. På den högsta nivån finns det spelböcker, de kan skrivas av alla administratörer, tredjepartsutvecklare som kan lite Ansible.

- name: Blink disk
  become: True
  register: locate_action
  disk_locate:
      locate: '{{ locate }}'
      devname: '{{ devname }}'
      ids: '{{ locate_ids | default(pd_id) | default(omit) }}'

Om någon logik är svår att implementera i playbooks, flyttar vi den till en Ansible-modul eller ett filter. Skript kan skrivas i Python eller något annat språk.

De är lätta och snabba att skriva. Till exempel består skivbakgrundsbelysningsmodulen, ett exempel på som visas ovan, av 265 rader.

Automatisera diskbyte med Ansible

På den lägsta nivån ligger biblioteket. För det här projektet skrev vi en separat applikation, en sorts abstraktion över hårdvaru- och mjukvaru-RAID:er som utför motsvarande förfrågningar.

Automatisera diskbyte med Ansible

Ansibles största styrkor är dess enkelhet och tydliga spelböcker. Jag tror att du måste använda detta och inte generera läskiga yaml-filer och ett stort antal villkor, skalkod och loopar.

Om du vill upprepa vår erfarenhet av Ansible API, tänk på två saker:

  • Playbook_executor och playbooks i allmänhet kan inte ges en timeout. Det finns en timeout på ssh-sessionen, men det finns ingen timeout på spelboken. Om vi ​​försöker avmontera en disk som inte längre finns i systemet kommer spelboken att köras oändligt, så vi var tvungna att linda in dess lansering i ett separat omslag och döda den med en timeout.
  • Ansible körs på forked processer, så dess API är inte trådsäkert. Vi kör alla våra lekböcker entrådiga.

Som ett resultat kunde vi automatisera utbytet av cirka 80 % av diskarna. Sammantaget har ersättningsgraden fördubblats. Idag tittar administratören bara på händelsen och bestämmer om disken behöver bytas eller inte, och gör sedan ett klick.

Men nu börjar vi stöta på ett annat problem: vissa nya administratörer vet inte hur man byter diskar. 🙂

Källa: will.com

Lägg en kommentar