ગુમ થયેલી સ્વૅપ ફાઇલ જેણે અમારા સર્વર થંભાવી દીધા
24 સપ્ટેમ્બરે અમારા એક પ્રોડક્શન સર્વરે જવાબ આપવાનું બંધ કર્યું. લોડ બેલેન્સરે તે સર્વરને અસ્વસ્થ ગણાવ્યું અને અમારું રિમોટ-કમાન્ડ ટૂલ તેના સુધી પહોંચી શક્યું નહીં — પણ કંઈ ક્રેશ થયું નહોતું અને વધુ મેમરી વાપરવાને કારણે કોઈ પ્રક્રિયા મારી નખાઈ નહોતી. સર્વર થ્રેશિંગ કરતું હતું: સ્વૅપ સ્પેસ વગર, અને કન્ટેનરોને મશીનની મેમરી કરતાં વધુ મેમરી વાપરવાની છૂટ હોવાથી, લિનક્સ પોતાનો સમય એવી ફાઇલો કાઢવામાં અને ફરી વાંચવામાં વિતાવતું હતું જેની તેને ચાલવા માટે જરૂર હતી, અને લગભગ કોઈ પ્રગતિ થતી નહોતી. દરેક સર્વર પર 2 GB ની સ્વૅપ ફાઇલ ઉમેરવાથી સમસ્યા ઉકેલાઈ. વધુ રસપ્રદ પાઠ હેલ્થ ચેક વિશે હતો.
“અટકી ગયું” કેવું દેખાતું હતું
- લોડ બેલેન્સરના હેલ્થ ચેક તે સર્વર પર ટાઇમ-આઉટ થયા.
- AWS Systems Manager દ્વારા મોકલેલા કમાન્ડ “Pending” સ્થિતિમાં અટકી રહ્યા અને ક્યારેય ચાલ્યા નહીં.
- લોગમાં કોઈ આઉટ-ઓફ-મેમરી કીલ નહોતી. કોઈ પ્રક્રિયા મરી નહોતી.
એક અઠવાડિયા પહેલાં અમે પ્રોડક્શનને નાના ARM સર્વરો પર ખસેડ્યું હતું, દરેકમાં 2 GB RAM. અમારું સ્ટેજિંગ સર્વર — જે હજી નાનું હતું — ડિપ્લોય દરમિયાન કન્ટેનર ઇમેજ અનપેક કરતી વખતે એ જ રીતે થીજી ગયું હતું.
મેમરી એરર કેમ નહોતી?
લિનક્સ ત્યારે જ કોઈ પ્રક્રિયાને મારે છે જ્યારે તે ખરેખર પુનઃપ્રાપ્ત કરી શકાય તેવી મેમરી ખતમ કરે. તે પહેલાં તે પેજ કેશ માંથી મેમરી લે છે — RAM માં રાખેલી ફાઇલોની નકલો, જેમાં ચાલતા દરેક પ્રોગ્રામનો કોડ પણ સામેલ છે.
અમારા સર્વરો પર કન્ટેનરોની સંયુક્ત મેમરી મર્યાદા આશરે 3.3 GB હતી, જ્યારે મશીન પર આશરે 1.8 GB વાપરી શકાય તેવી હતી. સામાન્ય રીતે તે બધા એક સાથે પોતાની મર્યાદા વાપરતા નથી. જ્યારે તેઓ વાપરતા, ત્યારે કર્નલ કેશમાંથી પ્રોગ્રામ કોડ કાઢતું રહેતું, અને તે કોડ ફરી ચાલે ત્યારે તરત ડિસ્કમાંથી ફરી વાંચવો પડતો. આ ચક્ર — થ્રેશિંગ — મશીનને લગભગ સંપૂર્ણપણે પ્રતિભાવહીન બનાવી શકે છે, છતાં તકનીકી રીતે મેમરી ખતમ ન થઈ હોય. એટલે કશું મરતું નથી, અને કશું પાછું ઠેકાણે પડતું નથી.
સ્વૅપ વગર, કર્નલ પાસે ફાળવેલી પણ ભાગ્યે જ વપરાતી મેમરી મૂકવાની જગ્યા નથી, એટલે તેણે તે કેશમાંથી જ લેવી પડે છે.
ઉકેલ
સર્વર બૂટસ્ટ્રેપ સ્ક્રિપ્ટ હવે દરેક વખતે સર્વર બૂટ થાય કે રિપેર થાય ત્યારે 2 GB ની સ્વૅપ ફાઇલ બનાવે છે, જેની swappiness સેટિંગ ઓછી (10) હોય છે. ઓછી swappiness નો અર્થ એ કે કર્નલ હજી પણ કાર્યકારી મેમરી RAM માં રાખવાનું પસંદ કરે છે, પણ ભાગ્યે જ સ્પર્શાતા પેજ ડિસ્ક પર જઈ શકે છે, જેથી પ્રોગ્રામ કોડને કેશમાંથી બળજબરીથી બહાર કાઢવો ન પડે. અમે તેને ચાલુ સર્વરો પર બંને પ્રોડક્શન સર્વરો અને સ્ટેજિંગ પર લાગુ કર્યું, અને દરેક પ્રોડક્શન ડિપ્લોય પર ડિપ્લોય પાઇપલાઇન બૂટસ્ટ્રેપ સ્ક્રિપ્ટ ફરી પ્રકાશિત કરે છે, જેથી બદલાયેલ સર્વરને પણ તે મળે.
જે ભાગે અમને વધુ ચિંતા કરાવી: અસ્વસ્થ સર્વર રહી ગયું
અમારો સર્વર ગ્રુપ EC2 હેલ્થ ચેક — “શું મશીન ચાલુ છે?” — વાપરતો હતો, લોડ બેલેન્સર હેલ્થ ચેક — “શું તે વિનંતીઓનો જવાબ આપે છે?” — નહીં. તેથી જે સર્વરને લોડ બેલેન્સરે છોડી દીધું હતું તે ગ્રુપની દૃષ્ટિએ હજી સ્વસ્થ હતું. તેને ક્યારેય બદલવામાં આવ્યું નહોતું. પ્રોડક્શન ચૂપચાપ એક જ સર્વર પર ચાલતું રહ્યું, જ્યાં સુધી કોઈએ નોંધ્યું નહીં અને બીજાને રીબૂટ ન કર્યું.
ગ્રુપને લોડ-બેલેન્સર હેલ્થ ચેક પર ફેરવવું સ્પષ્ટ ઉકેલ લાગે છે, પણ અમારા માટે તે સીધું નથી: ડિપ્લોય દરમિયાન સર્વરો જાણી જોઈને તેમના હેલ્થ એન્ડપોઇન્ટ પર એરર આપે છે, જેથી બેલેન્સર તેમને ખાલી કરે (જુઓ અમે ડિપ્લોયને શૂન્ય 502 સુધી કેવી રીતે લાવ્યા). જે ગ્રુપ એ સંકેત પર સર્વરો બદલે, તે દરેક ડિપ્લોયની મધ્યમાં તેમને બદલી નાખશે.
તેથી હાલ માટે અમે અમારી ડિપ્લોય ચેકલિસ્ટમાં એક પગલું ઉમેર્યું: દરેક ડિપ્લોય પછી, લોડ બેલેન્સર પર દરેક ટાર્ગેટનો હેલ્થ તપાસો, માત્ર ડિપ્લોય જોબ પાસ થયો કે નહીં એ નહીં. જો કોઈ સર્વર પરના કમાન્ડ “Pending” માં અટકે, તો તે થ્રેશિંગ કરી રહ્યું છે — તેને રીબૂટ કરો; તે પહેલેથી રોટેશનની બહાર છે.
અમે તેમાંથી શું શીખ્યા
- “ક્રેશ ન થવું” એટલે “સ્વસ્થ” નહીં. થ્રેશિંગ કોઈ એરર આપતું નથી, માત્ર એટલી ધીમાશ કે મશીન જવાબ આપવાનું બંધ કરી દે.
- નાનાં સર્વરોને સ્વૅપ જોઈએ. થોડી પણ, ઓછી swappiness સાથે, કર્નલને ઠંડી મેમરી મૂકવાની જગ્યા આપે છે.
- મશીન કરતાં વધુ ઉમેરેલી મેમરી મર્યાદા એક દાવ છે. ક્યારેક તમે તે હારો છો. ક્યારે દાવ લગાવ્યો છે તે જાણો.
- તમારું ઓટોસ્કેલિંગ કયા હેલ્થ ચેક પર ભરોસો કરે છે તે જાણો. જે હેલ્થ ચેક ફક્ત “શું VM ચાલુ છે?” પૂછે છે, તે કામ બંધ કરી દીધેલા સર્વરને બદલશે નહીં.