ഞങ്ങളുടെ സെർവറുകളെ മരവിപ്പിച്ച കാണാതായ സ്വാപ്പ് ഫയൽ
സെപ്റ്റംബർ 24-ന്, ഞങ്ങളുടെ ഒരു പ്രൊഡക്ഷൻ സെർവർ മറുപടി നൽകുന്നത് നിർത്തി. ലോഡ് ബാലൻസർ ആ സെർവറിനെ അനാരോഗ്യകരം (unhealthy) എന്ന് അടയാളപ്പെടുത്തി, ഞങ്ങളുടെ റിമോട്ട്-കമാൻഡ് ടൂളിന് അതിലേക്ക് എത്താനും കഴിഞ്ഞില്ല — പക്ഷേ ഒന്നും ക്രാഷ് ആയിരുന്നില്ല, മെമ്മറി കൂടുതൽ ഉപയോഗിച്ചതിന്റെ പേരിൽ ഒരു പ്രോസസ്സും കൊല്ലപ്പെട്ടിരുന്നുമില്ല. സെർവർ ത്രാഷ് ചെയ്യുകയായിരുന്നു: സ്വാപ്പ് സ്പേസ് ഇല്ലാതെയും, കണ്ടെയ്നറുകൾക്ക് മെഷീനിലുള്ളതിലും കൂടുതൽ മെമ്മറി ഉപയോഗിക്കാൻ അനുവാദമുള്ളതിനാലും, ലിനക്സ് സമയം മുഴുവൻ ചെലവഴിച്ചത് ഓടാൻ ആവശ്യമായ ഫയലുകൾ ഒഴിവാക്കുന്നതിലും വീണ്ടും വായിക്കുന്നതിലുമായിരുന്നു; മുന്നോട്ട് നീങ്ങാൻ ഏതാണ്ട് കഴിഞ്ഞില്ല. ഓരോ സെർവറിലും 2 GB സ്വാപ്പ് ഫയൽ ചേർത്തപ്പോൾ പ്രശ്നം പരിഹരിച്ചു. കൂടുതൽ രസകരമായ പാഠം ഹെൽത്ത് ചെക്കുകളെക്കുറിച്ചായിരുന്നു.
"ഹാങ്ങ്" ആയതെങ്ങനെയിരുന്നു
- സെർവറിൽ ലോഡ് ബാലൻസറിന്റെ ഹെൽത്ത് ചെക്കുകൾ സമയം കഴിഞ്ഞു.
- AWS Systems Manager വഴി അയച്ച കമാൻഡുകൾ "Pending" ആയി കിടന്നു, ഒരിക്കലും പ്രവർത്തിച്ചില്ല.
- ലോഗുകളിൽ out-of-memory കിൽ ഇല്ലായിരുന്നു. ഒരു പ്രോസസ്സും ചത്തിരുന്നില്ല.
ഒരാഴ്ച മുമ്പ് ഞങ്ങൾ പ്രൊഡക്ഷൻ ചെറിയ ARM സെർവറുകളിലേക്ക് മാറ്റിയിരുന്നു, ഓരോന്നിനും 2 GB RAM വീതം. ഞങ്ങളുടെ സ്റ്റേജിംഗ് സെർവർ — അതിലും ചെറുത് — ഡിപ്ലോയ് സമയത്ത് ഒരു കണ്ടെയ്നർ ഇമേജ് അൺപാക്ക് ചെയ്യുമ്പോൾ ഇതേപോലെ മരവിച്ചിരുന്നു.
മെമ്മറി പിശക് എന്തുകൊണ്ടില്ല?
ലിനക്സ് ഒരു പ്രോസസ്സിനെ കൊല്ലുന്നത് യഥാർത്ഥത്തിൽ വീണ്ടെടുക്കാവുന്ന മെമ്മറി തീരുമ്പോൾ മാത്രമാണ്. അതിനുമുമ്പ്, അത് പേജ് കാഷെയിൽ നിന്നാണ് മെമ്മറി എടുക്കുന്നത് — RAM-ൽ സൂക്ഷിച്ചിരിക്കുന്ന ഫയലുകളുടെ പകർപ്പുകൾ, ഓരോ പ്രവർത്തിക്കുന്ന പ്രോഗ്രാമിന്റെയും കോഡ് ഉൾപ്പെടെ.
ഞങ്ങളുടെ സെർവറുകളിൽ, കണ്ടെയ്നറുകളുടെ മൊത്തം മെമ്മറി പരിധികൾ ഏകദേശം 3.3 GB ആയി കൂടി, എന്നാൽ മെഷീനിൽ ഉപയോഗയോഗ്യമായത് ഏകദേശം 1.8 GB മാത്രം. സാധാരണയായി അവയെല്ലാം ഒരുമിച്ച് പരിധി മുഴുവൻ ഉപയോഗിക്കാറില്ല. അങ്ങനെ ഉപയോഗിച്ചപ്പോൾ, കെർണൽ സ്ഥലമുണ്ടാക്കാൻ കാഷെയിൽ നിന്ന് പ്രോഗ്രാം കോഡ് ഒഴിവാക്കിക്കൊണ്ടിരുന്നു, ആ കോഡ് വീണ്ടും പ്രവർത്തിക്കുന്ന നിമിഷം തന്നെ ഡിസ്കിൽ നിന്ന് വീണ്ടും വായിക്കേണ്ടിയും വന്നു. ഈ ചക്രം — ത്രാഷിംഗ് — മെഷീനെ ഏതാണ്ട് പൂർണ്ണമായി പ്രതികരിക്കാത്തതാക്കാം, മെമ്മറി സാങ്കേതികമായി തീരാതെ തന്നെ. അതുകൊണ്ട് ഒന്നും കൊല്ലപ്പെടുന്നില്ല, ഒന്നും വീണ്ടെടുക്കുന്നുമില്ല.
സ്വാപ്പ് ഇല്ലെങ്കിൽ, അനുവദിച്ചിട്ടുള്ള എന്നാൽ അപൂർവ്വമായി ഉപയോഗിക്കുന്ന മെമ്മറി വെക്കാൻ കെർണലിന് സ്ഥലമില്ല, അതിനാൽ അത് കാഷെയിൽ നിന്നാണ് എടുക്കേണ്ടി വരുന്നത്.
പരിഹാരം
സെർവർ ബൂട്ട് ചെയ്യുമ്പോഴോ നന്നാക്കുമ്പോഴോ ഓരോ തവണയും സെർവർ ബൂട്ട്സ്ട്രാപ്പ് സ്ക്രിപ്റ്റ് ഇപ്പോൾ 2 GB സ്വാപ്പ് ഫയൽ സൃഷ്ടിക്കുന്നു, swappiness 10 ആയി സജ്ജമാക്കിയിരിക്കുന്നു. കുറഞ്ഞ swappiness എന്നാൽ പ്രവർത്തന മെമ്മറി RAM-ൽ തന്നെ സൂക്ഷിക്കാൻ കെർണൽ ഇപ്പോഴും ഇഷ്ടപ്പെടുന്നു, പക്ഷേ അപൂർവ്വമായി തൊടുന്ന പേജുകൾ ഡിസ്കിലേക്ക് മാറ്റാം; പ്രോഗ്രാം കോഡിനെ കാഷെയിൽ നിന്ന് പുറത്താക്കാൻ നിർബന്ധിക്കുന്നില്ല. ഞങ്ങൾ ഇത് രണ്ട് പ്രൊഡക്ഷൻ സെർവറുകളിലും സ്റ്റേജിംഗിലും തത്സമയം പ്രയോഗിച്ചു, കൂടാതെ ഓരോ പ്രൊഡക്ഷൻ ഡിപ്ലോയിലും ഡിപ്ലോയ് പൈപ്പ്ലൈൻ ബൂട്ട്സ്ട്രാപ്പ് സ്ക്രിപ്റ്റ് വീണ്ടും പ്രസിദ്ധീകരിക്കുന്നതിനാൽ മാറ്റിസ്ഥാപിക്കപ്പെടുന്ന സെർവറിനും ഇത് ലഭിക്കുന്നു.
ഞങ്ങളെ കൂടുതൽ അലട്ടിയ ഭാഗം: അനാരോഗ്യകരമായ സെർവർ നിലനിന്നു
ഞങ്ങളുടെ സെർവർ ഗ്രൂപ്പ് EC2 ഹെൽത്ത് ചെക്കുകൾ ഉപയോഗിച്ചിരുന്നു — "മെഷീൻ പ്രവർത്തിക്കുന്നുണ്ടോ?" എന്ന് ചോദിക്കുന്നത് — അല്ലാതെ ലോഡ് ബാലൻസർ ഹെൽത്ത് ചെക്കുകൾ — "അഭ്യർത്ഥനകൾക്ക് മറുപടി നൽകുന്നുണ്ടോ?" എന്ന് ചോദിക്കുന്നത് — അല്ലായിരുന്നു. അതിനാൽ ലോഡ് ബാലൻസർ ഉപേക്ഷിച്ച ഒരു സെർവർ ഗ്രൂപ്പിന്റെ കാഴ്ചപ്പാടിൽ ആരോഗ്യകരമായിരുന്നു. അത് ഒരിക്കലും മാറ്റിസ്ഥാപിക്കപ്പെടുമായിരുന്നില്ല. ആരെങ്കിലും ശ്രദ്ധിച്ച് മറ്റേ സെർവർ റീബൂട്ട് ചെയ്യുന്നതുവരെ പ്രൊഡക്ഷൻ ഒരൊറ്റ സെർവറിൽ നിശബ്ദമായി പ്രവർത്തിക്കുമായിരുന്നു.
ഗ്രൂപ്പിനെ ലോഡ് ബാലൻസർ ഹെൽത്ത് ചെക്കുകളിലേക്ക് മാറ്റുന്നത് വ്യക്തമായ പരിഹാരമെന്ന് തോന്നാം, പക്ഷേ ഞങ്ങൾക്ക് അത് എളുപ്പമല്ല: ഡിപ്ലോയ് സമയത്ത് സെർവറുകൾ ബോധപൂർവ്വം അവരുടെ ഹെൽത്ത് എൻഡ്പോയിന്റിൽ പിശക് നൽകുന്നു, ബാലൻസർ അവയെ ഒഴിപ്പിക്കാൻ (ഞങ്ങൾ ഡിപ്ലോയ്കൾ പൂജ്യം 502-കളിലേക്ക് എങ്ങനെ എത്തിച്ചു കാണുക). ആ സിഗ്നലിൽ സെർവറുകൾ മാറ്റിസ്ഥാപിക്കുന്ന ഗ്രൂപ്പ് ഓരോ ഡിപ്ലോയ്ക്കും നടുവിൽ അവയെ മാറ്റിസ്ഥാപിക്കും.
അതിനാൽ ഇപ്പോൾ ഡിപ്ലോയ് ചെക്ക്ലിസ്റ്റിൽ ഒരു ഘട്ടം ചേർത്തു: ഓരോ ഡിപ്ലോയ്ക്കും ശേഷം, ലോഡ് ബാലൻസറിൽ ഓരോ ടാർഗെറ്റിന്റെയും ഹെൽത്ത് പരിശോധിക്കുക, ഡിപ്ലോയ് ജോബ് വിജയിച്ചോ എന്ന് മാത്രമല്ല. ഒരു സെർവറിലേക്കുള്ള കമാൻഡുകൾ "Pending" ആയി കിടക്കുന്നുവെങ്കിൽ, അത് ത്രാഷ് ചെയ്യുകയാണ് — റീബൂട്ട് ചെയ്യുക; അത് ഇതിനകം റൊട്ടേഷനിൽ നിന്ന് പുറത്താണ്.
ഞങ്ങൾ ഇതിൽ നിന്ന് പഠിച്ചത്
- "ക്രാഷ് ആകാതിരിക്കുന്നത്" "ആരോഗ്യകരം" അല്ല. ത്രാഷിംഗ് ഒരു പിശകും ഉണ്ടാക്കുന്നില്ല, മെഷീൻ മറുപടി നൽകാതാകുന്നത്ര കടുത്ത മന്ദതമാത്രമാണ് ഉണ്ടാക്കുന്നത്.
- ചെറിയ സെർവറുകൾക്ക് സ്വാപ്പ് വേണം. ചെറുതാണെങ്കിലും, കുറഞ്ഞ swappiness-ഓടെ, തണുത്ത മെമ്മറി വെക്കാൻ കെർണലിന് ഒരു സ്ഥലം നൽകുന്നു.
- മെഷീനേക്കാൾ കൂടുതൽ ചേർക്കുന്ന മെമ്മറി പരിധികൾ ഒരു പന്തയമാണ്. ചിലപ്പോൾ അത് തോൽക്കും. അത് എപ്പോഴാണെന്ന് അറിഞ്ഞിരിക്കുക.
- നിങ്ങളുടെ ഓട്ടോസ്കെയിലിംഗ് ഏത് ഹെൽത്ത് ചെക്കിനെ വിശ്വസിക്കുന്നുവെന്ന് അറിയുക. "VM ഓണാണോ?" എന്ന് മാത്രം ചോദിക്കുന്ന ഹെൽത്ത് ചെക്ക് പ്രവർത്തനം നിലച്ച ഒരു സെർവറിനെ മാറ്റിസ്ഥാപിക്കില്ല.