SSD Nodes Learn 🎉 VPS $5.50/மாதம் முதல்
கல்வி வழிகாட்டிகள் Matt Connorஆல் Matt Connor · புதுப்பிக்கப்பட்டது 2026-08-13

systemd மூலம் process memory மற்றும் CPU-ஐக்

VPS-ல் ஒரு process-ன் வளங்களை வரையறுக்க MemoryMax மற்றும் CPUQuota-வை எவ்வாறு பயன்படுத்துவது என்பதை அறியுங்கள். OOM killer பிழைகளைத் தவிர்க்க சரியான configuration முறைகள் இங்கே.

systemd drop-in கோப்பைப் பயன்படுத்தி process memory மற்றும் CPU-ஐக் கட்டுப்படுத்துதல்

Linux VPS-ல் இயங்கும் ஒரு process-ன் memory மற்றும் CPU பயன்பாட்டைக் கட்டுப்படுத்த, அந்த process-ஐ இயக்கும் unit கோப்பில் சில வரிகளைச் சேர்க்க வேண்டும். MemoryMax= என்பது memory-க்கான கடினமான உச்சவரம்பு (hard ceiling) ஆகும். CPUQuota= என்பது processor நேரத்திற்கான உச்சவரம்பு ஆகும். இவை இரண்டும் cgroup v2 (control groups, version 2) மூலம் செயல்படுத்தப்படுகின்றன. இது systemd ஏற்கனவே server-ல் உள்ள ஒவ்வொரு service-ஐயும் கண்காணிக்கப் பயன்படுத்தும் kernel வசதியாகும்.

sudo systemctl edit myapp.service

இது குறிப்புகளுடன் கூடிய ஒரு drop-in கோப்பைத் திறக்கும். அதற்கு மேலே பின்வருவனவற்றைச் சேர்க்கவும்:

[Service]
MemoryHigh=512M
MemoryMax=768M
MemorySwapMax=0
CPUQuota=80%
TasksMax=128
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemctl show myapp.service -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec -p TasksMax

systemctl show கட்டளையானது, kernel-ன் சொந்த அலகுகளான MemoryMax=805306368 மற்றும் CPUQuotaPerSecUSec=800ms ஆகியவற்றில் உங்கள் எண்களை மீண்டும் காட்ட வேண்டும். அது MemoryMax=infinity என்று காட்டினால், drop-in கோப்பு ஏற்றப்படவில்லை என்று அர்த்தம். அந்தக் கோப்பு /etc/systemd/system/myapp.service.d/override.conf என்ற பாதையில் உள்ளதா என்பதையும், அது [Service] தலைப்புடன் தொடங்குகிறதா என்பதையும் சரிபார்க்கவும். ஏனெனில், தலைப்பு இல்லாத settings வரி இருந்தால், systemd Assignment outside of section. Ignoring. என்று log செய்துவிட்டு, எந்தக் கட்டுப்பாடும் இன்றி service-ஐத் தொடங்கிவிடும்.

இந்த வழிகாட்டியின் மீதமுள்ள பகுதி, அந்த எண்களை எவ்வாறு தேர்வு செய்வது மற்றும் அவற்றை அமைத்த பிறகும் என்னென்ன சிக்கல்கள் ஏற்படலாம் என்பது பற்றியது.

நிறைந்து வழியாத ஒரு VPS-ஐ runaway process ஏன் உறைய வைக்கிறது

ஒரு process அதன் hard memory cap-ஐ எட்டும்போது, அது ஒரு நொடியில் செயலிழந்து service மீண்டும் தொடங்கும். இது நல்ல நிலை. மோசமான நிலை என்னவென்றால், எதுவும் செயலிழக்காது: box ping-க்கு பதில் அளிக்கும், SSH connection-ஐ ஏற்கும், ஆனால் shell prompt வராது. இயந்திரம் இயங்கிக்கொண்டிருக்கும், ஆனால் எந்த வேலையும் பயனுள்ளதாக இருக்காது.

இதற்கான காரணம் வெளிப்படையானது அல்ல, அதன் நுட்பம் இதோ. free memory குறையும்போது, kernel புதிய பக்கங்களை (pages) வழங்குவதற்குப் பதிலாக, ஏற்கனவே உள்ள பக்கங்களை மீட்டெடுக்கிறது (reclaim). file-backed பக்கங்களை மீட்டெடுப்பது எளிது, மேலும் இயங்கிக்கொண்டிருக்கும் அனைத்து நிரல்களின் executable code-ம் page cache-ல் இருக்கும். எனவே, kernel sshd-ன் text பக்கங்களை நீக்குகிறது. அடுத்ததாக sshd இயங்கும்போது, அந்த bytes-ஐ storage-லிருந்து மீண்டும் படிக்க வேண்டிய page fault ஏற்படுகிறது. ஒவ்வொரு process-ம் இயங்குவதற்குப் பதிலாக disk-க்காகக் காத்திருக்கிறது. ஒரே பக்கங்கள் வெளியேறுவதும் மீண்டும் வருவதுமாக இருக்கும் இந்தச் சுழற்சிக்கு thrashing என்று பெயர்.

laptop-ஐ விட VPS-ல் இது இரண்டு காரணங்களால் மோசமாகிறது. storage பெரும்பாலும் network attached அல்லது shared ஆக இருக்கும், எனவே ஒவ்வொரு fault-க்கும் local NVMe சாதனத்தை விட அதிக மில்லிசெகண்டுகள் செலவாகும். மேலும், kernel நேரத்தை அளவிடுவதில்லை, தோல்வியை மட்டுமே அளவிடுகிறது: reclaim செயல்முறை எவ்வளவு மெதுவாக இருந்தாலும் ஒரு பக்கத்தை வழங்கிக்கொண்டிருக்கும் வரை, kernel தான் முன்னேற்றம் அடைவதாகவே கருதுகிறது, எனவே அது out of memory (OOM) killer-ஐ அழைப்பதில்லை. எதையும் கொல்லும் முன் ஒரு box பல நிமிடங்கள் இந்த நிலையில் இருக்கலாம்.

இது நடப்பதை நீங்கள் கவனிக்கலாம். Linux 4.20 மற்றும் அதற்குப் பிந்தைய பதிப்புகளில் kernel pressure stall information (PSI)-ஐ வழங்குகிறது:

cat /proc/pressure/memory
cat /proc/pressure/io
some avg10=63.72 avg60=41.02 avg300=12.33 total=13729481
full avg10=48.15 avg60=30.44 avg300=8.90 total=9114233

full வரிதான் முக்கியமானது. full avg10=48.15 என்பது, கடந்த பத்து வினாடிகளில், box-ல் உள்ள ஒவ்வொரு runnable task-ம் memory பணிக்காகக் காத்திருந்து stalled நிலையில் இருந்ததைக் குறிக்கிறது, எனவே எதுவும் இயங்கவில்லை. ஆரோக்கியமான server-ல் full மதிப்பு பூஜ்ஜியத்திற்கு அருகில் இருக்கும். 10-க்கு மேல் இருந்தால் மனிதர்களுக்கு வேகம் குறைவாகத் தெரியும், 40 அல்லது அதற்கு மேல் இருந்தால் அது உறைந்த நிலை (frozen) என்று அழைக்கப்படுகிறது.

இதனால்தான் ஒரு limit மட்டும் தீர்வாகாது. MemoryHigh=-ன் கீழ் உள்ள ஒரு unit கொல்லப்படுவதற்குப் பதிலாக throttled செய்யப்படுகிறது, எனவே அது மெதுவாக இருந்தாலும் உயிருடன் இருக்கும். systemd-ன் பார்வையில் அது தோல்வியடையாததால், எதுவும் அதை restart செய்யாது. swap செய்ய அனுமதிக்கப்பட்ட ஒரு capped unit, shared சாதனத்தைப் பயன்படுத்தி read/write செயல்பாடுகளை உருவாக்குகிறது, இது box-ல் உள்ள மற்ற அனைத்து service-களுக்கும் /proc/pressure/io-ஐ உயர்த்தக்கூடும். பற்றாக்குறைக்கு யார் பொறுப்பேற்க வேண்டும் என்பதைத்தான் limits தீர்மானிக்கின்றன, அவை கூடுதல் திறனை (capacity) உருவாக்க முடியாது.

உங்கள் VPS-ல் cgroup v2 இயங்குகிறதா எனச் சரிபார்க்கவும்

stat -fc %T /sys/fs/cgroup

cgroup2fs என்பது ஒருங்கிணைந்த படிநிலை (unified hierarchy) ஆகும், இது கீழே உள்ள அனைத்து அமைப்புகளுக்கும் அவசியமானது. tmpfs என்பது பழைய v1 அமைப்பில் கணினி boot ஆகியுள்ளது என்பதைக் குறிக்கிறது; இதில் MemoryHigh= மற்றும் MemorySwapMax= ஆகியவை இருக்காது, மேலும் ஒவ்வொரு unit-க்கும் உரிய OOM செயல்பாடு மாறுபடும். Ubuntu 22.04 மற்றும் அதற்குப் பிந்தைய பதிப்புகளும், Debian 11 மற்றும் அதற்குப் பிந்தைய பதிப்புகளும் இயல்பாகவே v2-ஐப் பயன்படுத்துகின்றன. பழைய image அல்லது systemd.unified_cgroup_hierarchy=0 கொண்டு boot செய்யப்பட்ட kernel-ல் இது இருக்காது.

cgroup v2-ல் systemd ஒவ்வொரு unit-க்கும் memory accounting-ஐ இயல்பாகவே செயல்படுத்துகிறது, எனவே அந்த எண்கள் ஏற்கனவே அங்கு இருக்கும்:

systemd-cgtop -m

இது memory பயன்பாட்டின் அடிப்படையில் cgroups-ஐ வரிசைப்படுத்தும். சர்வர் பதிலளிக்கும் நிலையில் இருக்கும்போது, "எது இந்த சர்வரின் வளங்களை அதிகம் பயன்படுத்துகிறது" என்பதைக் கண்டறிய இதுவே விரைவான வழியாகும். சர்வர் புதியது என்றால், புதிய VPS-ன் முதல் பத்து நிமிடங்களில் செய்ய வேண்டிய கணக்கு மற்றும் firewall அமைப்புகளை இதற்கு முன்பே முடிக்க வேண்டும்.

MemoryHigh மற்றும் MemoryMax ஆகியவற்றின் செயல்பாடுகள்.

இந்த இரண்டு memory அமைப்புகளுக்கும் இடையே உள்ள வேறுபாடு, ஒரு service தோல்வியடையும் போது அது எவ்வாறு வெளிப்படும் என்பதைத் தீர்மானிக்கிறது.

  • MemoryHigh= என்பது ஒரு மென்மையான வரம்பு (soft cap). இந்த அளவைத் தாண்டும்போது, kernel அந்த cgroup-லிருந்து நினைவகத்தை தீவிரமாக மீட்டெடுத்து, அதன் ஒதுக்கீடுகளை வேண்டுமென்றே மெதுவாக்கும். பயன்பாடு இந்த எண்ணைத் தாண்டலாம், ஆனால் எந்த process-ம் நிறுத்தப்படாது.
  • MemoryMax= என்பது ஒரு கடுமையான வரம்பு (hard cap). இந்த வரம்பிற்குள் ஒரு memory ஒதுக்கீட்டை நிறைவேற்ற முடியாவிட்டால், OOM killer அந்த cgroup-க்குள் இயங்கி, அந்த unit-ன் ஏதேனும் ஒரு process-ஐ நிறுத்திவிடும்.

நீங்கள் முழுமையாக நம்பாத எதற்கும் MemoryMax= அமைப்பதுதான், அந்த இரண்டாவது பாதிக்கு உண்மையான காரணம். வரம்பு இல்லையென்றால், நினைவகப் பற்றாக்குறை முழு server-க்கும் பாதிப்பை ஏற்படுத்தும். அப்போது global OOM killer, oom_score அடிப்படையில் ஒரு process-ஐத் தேர்ந்தெடுக்கும்; இது பெரும்பாலும் அதிக நினைவகத்தைப் பயன்படுத்தும் process-ஆக இருக்கும். பொதுவாக, நினைவகம் கசியும் script-ஐ விட, உங்கள் database-தான் அதிக நினைவகத்தைப் பயன்படுத்தும். ஒரு வரம்பு இருக்கும்போது, அந்தத் தவறுக்குக் காரணமான unit-க்குள் மட்டுமே பாதிப்பு ஏற்படும்.

MemoryHigh=-ஐ MemoryMax=-க்குக் கீழே 20 முதல் 30 சதவீதம் இருக்குமாறு இரண்டையும் அமைக்கவும். இந்த இடைவெளி ஒரு எச்சரிக்கை மண்டலமாகும்: மெதுவான கசிவு High-ஐத் தாண்டும்போது service மெதுவாகும், ஆனால் திடீர் அதிகரிப்பு Max-ஐத் தாண்டி நேரடியாக service-ஐ நிறுத்திவிடும்.

சதவீத மதிப்புகள் நிறுவப்பட்ட physical memory-ஐ அடிப்படையாகக் கொண்டவை. எனவே, 4 GB திட்டத்தில் MemoryMax=25% என்பது 1 GB ஆகும்; நீங்கள் திட்டத்தை மாற்றினாலும் அது அந்த அளவில் கால் பங்காகவே இருக்கும். MemorySwapMax=0 அந்த unit-ஐ swap-லிருந்து முழுமையாகத் தவிர்க்கிறது, இது நீண்ட கால மந்தநிலையைத் தவிர்த்து, விரைவான மற்றும் தெளிவான நிறுத்தத்தை உறுதி செய்கிறது.

ஒரு வரம்பிற்கு அருகில் restart policy இருக்க வேண்டும், இல்லையெனில் service நிறுத்தப்பட்ட நிலையிலேயே இருக்கும்.

[Unit]
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Restart=on-failure
RestartSec=5s

StartLimit* என்பது [Unit] பகுதியிலும், Restart= என்பது [Service] பகுதியிலும் இருக்க வேண்டும். தவறான பகுதியில் வைத்தால் systemd அதை நிராகரித்துவிடும். ஐந்து நிமிடங்களில் ஐந்து முறை restart ஆவது என்பது ஒரு சிறிய சிக்கல் அல்ல, அது ஒரு கசிவு. எனவே, அதற்குப் பிறகு systemd முயற்சியைக் கைவிட்டு unit-ஐ failed நிலைக்குக் கொண்டு செல்லும். சிக்கலை மறைக்கும் crash loop-ஐ விட, இந்த நிலையே நீங்கள் கண்டறிய வேண்டியது.

CPUQuota மூலம் CPU-வை கட்டுப்படுத்துதல் அல்லது CPUWeight மூலம் பகிர்ந்தளித்தல்

CPUQuota= என்பது ஒரு CPU-வில் கிடைக்கும் நேரத்தில் ஒரு குறிப்பிட்ட சதவீதத்தை எடுத்துக்கொள்கிறது. CPUQuota=50% என்பது ஒரு கோர்-ன் பாதியாகும். CPUQuota=200% என்பது இரண்டு கோர்களுக்கு இணையானது, இதை அந்த unit தனக்குத் தேவையான எத்தனை threads-களில் வேண்டுமானாலும் பிரித்துக்கொள்ளலாம். 2 vCPU கொண்ட திட்டத்தில், CPUQuota=200% என்பது முழு இயந்திரத்தின் திறனையும் குறிக்கும்.

பெரும்பாலான services-க்கு CPUWeight= சிறந்த இயல்புநிலை அமைப்பாகும். இது 1 முதல் 10000 வரையிலான ஒரு சார்புப் பகிர்வு (relative share) ஆகும், kernel-ன் இயல்புநிலை 100 ஆகும். மற்றொன்றுடன் போட்டி இருக்கும்போது மட்டுமே இது செயல்படும்: அதிக சுமை இருக்கும்போது CPUWeight=20-ல் இயங்கும் ஒரு backup job, 100-ல் இயங்கும் web server-க்கு முன்னுரிமை அளிக்கும், அதே சமயம் இயந்திரம் சும்மா இருக்கும்போது முழு திறனையும் பயன்படுத்திக்கொள்ளும். ஒரு hard quota-வை அமைத்தால், அந்த உபரித் திறன் வீணாகிவிடும்.

CPU limit எதைக் கொடுக்கிறது என்பதில் தெளிவாக இருங்கள். ஒரு CPU-bound process அரிதாகவே Linux-ஐ முடக்கும், ஏனெனில் scheduler அனைவருக்கும் நேரத்தை ஒதுக்கித் தரும். Memory பற்றாக்குறையே ஒரு இயந்திரத்தை செயலிழக்கச் செய்யும். ஒரு build அல்லது agent போன்ற, ஒரு மணி நேரம் தொடர்ந்து முழு வேகத்தில் இயங்கக்கூடிய பணிகளுக்கு, கணிக்கக்கூடிய ஒரு உச்ச வரம்பு தேவைப்படும்போது CPUQuota=-ஐப் பயன்படுத்தவும். அத்தகைய workload-க்கு எவ்வளவு அளவு தேவை என்பது தனிப்பட்ட கேள்வி, அது ஒரு coding agent VPS-க்கு எவ்வளவு RAM மற்றும் CPU தேவை என்பதில் விவரிக்கப்பட்டுள்ளது.

உங்கள் processes எதுவும் பெரிய அளவில் வேலை செய்யாதபோதும் CPU பிஸியாக இருப்பதாகக் காட்டினால், அதற்கான காரணம் hypervisor-ன் மறுபக்கத்தில் இருக்கலாம். அது noisy neighbour-ஆல் ஏற்படும் CPU steal time ஆகும், இதற்கு நீங்கள் எந்த quota-வை அமைத்தாலும் மாற்றம் இருக்காது.

TasksMax ஒரு fork loop-ஐத் தடுக்கிறது

TasksMax= என்பது ஒரு unit வைத்திருக்கக்கூடிய processes மற்றும் threads-ன் எண்ணிக்கையாகும். Threads-ம் கணக்கில் கொள்ளப்படுவதால், ஒரு Java அல்லது Go service-க்கு process பட்டியலில் தெரிவதை விட கூடுதல் headroom தேவைப்படும். ஒரு script loop-ல் fork ஆகும்போது, system முழுவதிலும் உள்ள process ID-கள் தீர்ந்துபோவதற்குப் பதிலாக, அந்த unit-க்குள்ளேயே fork தோல்வியடைவதால், இது மிகக் குறைந்த செலவில் கிடைக்கும் பாதுகாப்பாகும்.

TasksMax=128

ஒரு unit அதன் எல்லையை எட்டும்போது, kernel அந்த cgroup-ன் பெயரை உள்ளடக்கிய ஒரு வரியை log-ல் பதிவு செய்யும்:

cgroup: fork rejected by pids controller in /system.slice/myapp.service

நிரல் பொதுவாக fork: retry: Resource temporarily unavailable பிழையைப் புகாரளிக்கும். systemctl show -p DefaultTasksMax கட்டளையைப் பயன்படுத்தி, manager இயல்பாக என்ன வரம்புகளைப் பயன்படுத்துகிறது என்பதைச் சரிபார்க்கவும்.

systemd-run மூலம் ஒருமுறை மட்டுமே இயங்கும் பணியைக் கட்டுப்படுத்துதல்

இதற்கு நீங்கள் எந்த unit file-உம் உருவாக்க வேண்டிய அவசியமில்லை. systemd-run ஒரு கட்டளையைச் சுற்றி தற்காலிகமான (transient) unit-ஐ உருவாக்குகிறது.

sudo systemd-run --scope -p MemoryMax=1G -p MemorySwapMax=0 -p CPUQuota=50% -p TasksMax=64 ./import-data.sh

--scope கட்டளையை உங்கள் terminal-ல் இயக்குகிறது, அதற்கு முன் Running scope as unit: run-r7c1a....scope-ஐ அச்சிடுகிறது. கட்டளை இயங்கும்போது அதன் வெளியீடு உங்கள் திரையிலேயே இருக்கும், அது முடிந்தவுடன் கட்டுப்பாடுகள் நீக்கப்படும். systemd.resource-control-ல் உள்ள எந்தவொரு property-யும் -p-க்கு பிறகு வேலை செய்யும்.

நீண்ட நேரம் இயங்கும் பணிக்கு, --scope-ஐ நீக்கிவிட்டு அதற்கு ஒரு பெயரை வழங்கவும். இது பின்னணியில் ஒரு தற்காலிக service-ஆக இயங்கும் மற்றும் அதன் பதிவுகள் journal-ல் சேமிக்கப்படும்:

sudo systemd-run --unit=nightly-import -p MemoryMax=1G -p CPUWeight=20 ./import-data.sh
journalctl -u nightly-import -f

நீங்கள் root பயனராக இல்லாதபோதும் இதே விருப்பங்கள் --user-உடன் வேலை செய்யும். இருப்பினும், உங்கள் user manager-க்கு வழங்கப்பட்ட controllers மட்டுமே அங்கு செயல்படும் என்பதால், சில property-கள் நிராகரிக்கப்படலாம். அப்படி நடந்தால், அதை sudo மூலம் இயக்கவும். ஒரு பணி நிரந்தரமான இடத்தைப் பெறும்போது, அதன் அமைப்புகளை அப்படியே ஒரு உண்மையான unit-க்கு மாற்றலாம்: systemd service மற்றும் timer மூலம் script-ஐ இயக்குதல் என்பதைப் பார்க்கவும்.

Swap குறித்த கேள்வி, நேர்மையான பதில்

Swap என்பது தோல்வியைத் தடுப்பதற்குப் பதிலாக, அதன் தன்மையை மாற்றுகிறது.

Swap இல்லையெனில், memory கசிவு உச்சத்தை அடைந்தவுடன் ஏதேனும் ஒரு செயல்முறை நொடிகளில் நின்றுவிடும். இந்தச் செயலிழப்பு சத்தமாகவும், குறுகிய காலமாகவும் இருக்கும்; பின்னர் journal-ல் இதைக் கண்டறிவது எளிது. Swap இருந்தால், kernel பயன்படுத்தப்படாத anonymous pages-ஐ disk-க்கு மாற்றி நேரத்தை ஈட்டித் தரும். அந்தச் செயல்முறை ஒரு குறிப்பிட்ட அளவோடு நின்றுவிடும் என்றால், swap உங்களைக் காப்பாற்றும். அது ஒரு runaway process என்றால், swap ஐந்து வினாடி செயலிழப்பை இருபது நிமிட முடக்கமாக மாற்றும். இந்த முடக்கம் மிகவும் மோசமானது; ஏனெனில், ஒரு செயல்முறை நின்றுவிட்டால் உங்களுக்குக் கிடைக்கும் working shell, இந்தத் தத்தளிக்கும் நிலையில் கிடைக்காது.

swapon --show
free -h

சிறிய VPS-ல் ஒரு நடைமுறைச் சாத்தியமான வழி: ஒருமுறை ஒதுக்கப்பட்டு மீண்டும் பயன்படுத்தப்படாத பக்கங்களுக்காக ஒரு சிறிய swap file-ஐ வைத்துக்கொள்ளுங்கள். நீங்கள் இழக்கத் தயாராக இருக்கும் units-க்கு MemorySwapMax=0-ஐ அமைக்கவும். முக்கியமான சேவைகள் அவற்றின் swap-ஐத் தக்கவைத்துக் கொள்ளும். கணிக்க முடியாத சேவைகள் விரைவில் எல்லையை அடைந்து restart ஆகும்.

vm.swappiness-ஐக் குறைப்பது ஒரு பலவீனமான தீர்வாகும், இதற்கான காரணத்தை அறிவது அவசியம். இது page cache-ஐ நீக்குவதற்கும் anonymous pages-ஐ swap செய்வதற்கும் இடையிலான சமநிலையை மட்டுமே மாற்றுகிறது; இவை இரண்டுமே பிற்காலத்தில் disk read செலவை ஏற்படுத்தும். இது எந்தப் பக்கங்கள் தத்தளிக்கின்றன என்பதை மாற்றுகிறதே தவிர, கணினி தத்தளிப்பதைத் தடுப்பதில்லை.

முன்கூட்டியே செயல்படும் OOM daemon, stall ஏற்படுவதற்கு முன்பே செயல்முறைகளை நிறுத்துதல்

Kernel ஆனது memory reclaim தோல்வியடையும் வரை காத்திருக்கும். சிறிய VPS-களில், அந்த காத்திருப்பு நேரத்தில்தான் நீங்கள் server-ன் கட்டுப்பாட்டை இழக்கிறீர்கள். இரண்டு userspace daemon-கள் memory-ஐத் தொடர்ந்து கண்காணித்து, முன்கூட்டியே செயல்முறைகளை நிறுத்துவதன் மூலம் இந்த சிக்கலைத் தவிர்க்கின்றன.

earlyoom என்பது கிடைக்கும் memory மற்றும் free swap-ஐக் கண்காணிக்கும். இவை ஏதேனும் ஒரு குறிப்பிட்ட அளவை விடக் குறையும்போது, அதிக memory-ஐப் பயன்படுத்தும் செயல்முறையை (process) இது நிறுத்திவிடும்.

sudo apt install earlyoom
systemctl status earlyoom

Debian மற்றும் Ubuntu package-களில், நிறுவிய உடனேயே இந்த service தானாகவே தொடங்கிவிடும். இதற்கான விருப்பத்தேர்வுகள் /etc/default/earlyoom-ல் உள்ளன:

EARLYOOM_ARGS="-m 5,2 -s 5,2 --avoid '^(sshd|systemd)$' --prefer '^(node|python3)$'"

-m PERCENT என்பது குறைந்தபட்ச memory அளவையும், -s PERCENT என்பது குறைந்தபட்ச free swap அளவையும் குறிக்கும். இவை இரண்டும் இயல்பாக 10 சதவீதமாக இருக்கும். ஒவ்வொரு ஜோடியிலும் உள்ள இரண்டாவது எண் SIGKILL புள்ளியைக் குறிக்கும்: முதல் மதிப்பை விடக் குறையும்போது earlyoom முதலில் SIGTERM-ஐ அனுப்பும், இரண்டாவது மதிப்பை விடக் குறையும்போது SIGKILL-ஐ அனுப்பும். இது இயல்பாக முதல் மதிப்பில் பாதியாக இருக்கும். மாற்றங்களைச் செயல்படுத்த sudo systemctl restart earlyoom-ஐப் பயன்படுத்தவும். எந்த செயல்முறை நிறுத்தப்பட்டது மற்றும் அது எவ்வளவு memory-ஐப் பயன்படுத்தியது என்பதை அறிய journalctl -u earlyoom-ஐப் பார்க்கவும்.

systemd-oomd என்பது மற்றொரு விருப்பத்தேர்வு. இதன் manual page-ல், "இது cgroups-v2 மற்றும் pressure stall information (PSI)-ஐப் பயன்படுத்தி, kernel space-ல் OOM ஏற்படுவதற்கு முன்பே கண்காணித்து நடவடிக்கை எடுக்கும் ஒரு system service" என்று குறிப்பிடப்பட்டுள்ளது. இது தனிப்பட்ட செயல்முறைகளுக்குப் பதிலாக, முழு cgroup-களையும் கையாளும். எனவே, இது ஒரு தனிப்பட்ட child process-ஐ மட்டும் நிறுத்தாமல், முழு unit-ஐயும் நிறுத்தும். Unit-கள் ManagedOOMMemoryPressure=kill அல்லது ManagedOOMSwap=kill மூலம் இதில் சேரலாம் (opt-in). இதற்கான வரம்புகள் /etc/systemd/oomd.conf-ல் உள்ளன.

systemctl status systemd-oomd
oomctl

oomctl தற்போது எதைக் கண்காணிக்கிறது என்பதை அச்சிடும். server image-களில் இது பெரும்பாலும் எதையும் காட்டாது, ஏனெனில் ஒவ்வொரு unit-க்கும் இது தனித்தனியாகச் சேர்க்கப்பட வேண்டும். ஏதேனும் ஒரு daemon-ஐ மட்டும் தேர்வு செய்து பயன்படுத்தவும். இரண்டையும் ஒரே நேரத்தில் இயக்கினால், எதை நிறுத்துவது என்பதில் போட்டி ஏற்படும், மேலும் ஒரு செயல்முறை ஏன் நிறுத்தப்பட்டது என்பதைக் கண்டறிவது கடினமாகிவிடும்.

எந்த unit இதற்குப் பொறுப்பானது?

Kernel-லிருந்து தொடங்கவும், ஏனெனில் அது செய்யும் ஒவ்வொரு kill நடவடிக்கையையும் அது பதிவு செய்கிறது.

journalctl -k --grep "Killed process" --since "2 hours ago"

Global OOM killer-ஆல் செய்யப்படும் ஒரு kill இவ்வாறு இருக்கும்:

Out of memory: Killed process 4127 (node) total-vm:2731084kB, anon-rss:1874232kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:4212kB oom_score_adj:0

anon-rss என்பது அந்த process இறந்தபோது RAM-ல் வைத்திருந்த நினைவக அளவு, இங்கே சுமார் 1.8 GB. அடைப்புக்குறிக்குள் உள்ள பெயரைச் சந்தேகத்துடன் கவனிக்கவும். அது kernel தேர்ந்தெடுத்த பாதிக்கப்பட்ட process ஆகும். Kernel எப்போதும் மிகப்பெரிய process-ஐயே தேர்ந்தெடுக்கும், ஆனால் அது நினைவகப் பற்றாக்குறைக்குக் காரணமான process-ஆக இருக்க வேண்டிய அவசியமில்லை.

Cgroup limit-ஆல் செய்யப்படும் kill வேறு முன்னொட்டைக் (prefix) கொண்டிருக்கும், மேலும் அதற்கு மேலே அச்சிடப்பட்ட அறிக்கை அதன் சொந்த எல்லையைத் தொட்ட cgroup-ன் பெயரைக் குறிப்பிடும்:

Memory cgroup out of memory: Killed process 8811 (python3) total-vm:1044320kB, anon-rss:769112kB, file-rss:0kB, shmem-rss:0kB, UID:998 pgtables:1720kB oom_score_adj:0

அந்த முன்னொட்டே நோயறிதலில் பெரும்பகுதியாகும். Memory cgroup out of memory என்பது ஒரு குறிப்பிட்ட unit நீங்கள் வழங்கிய MemoryMax= எல்லையைத் தொட்டுவிட்டது என்பதையும், கணினியின் மற்ற பகுதிகள் சரியாக உள்ளன என்பதையும் குறிக்கிறது. ஒரு சாதாரண Out of memory என்பது கணினி முழுவதுமாக நினைவகம் தீர்ந்துவிட்டது என்பதைக் குறிக்கிறது, எனவே உங்கள் வரம்புகள் (caps) விடுபட்டிருக்கலாம் அல்லது மிகத் தாராளமாக அமைக்கப்பட்டிருக்கலாம்.

பிறகு, systemd என்ன கண்டது என்று கேட்கவும்:

systemctl status myapp.service
journalctl -u myapp.service -n 50
myapp.service: A process of this unit has been killed by the OOM killer.
myapp.service: Main process exited, code=killed, status=9/KILL
myapp.service: Failed with result 'oom-kill'.

systemctl status அதே விஷயத்தை ஒரே வரியில் Active: failed (Result: oom-kill) போலக் கூறுகிறது.

Cgroup counters மூன்றாவது ஆதாரமாகும், இது மட்டுமே throttling-ஐப் பதிவு செய்கிறது. இது எந்த log வரியையும் உருவாக்காது:

cat /sys/fs/cgroup/system.slice/myapp.service/memory.events
cat /sys/fs/cgroup/system.slice/myapp.service/memory.peak
low 0
high 4213
max 118
oom 12
oom_kill 12

high என்பது அந்த unit எத்தனை முறை MemoryHigh=-ஐத் தாண்டி throttling-க்கு உள்ளானது என்பதைக் கணக்கிடுகிறது. max என்பது அது எத்தனை முறை hard cap-ஐ அடைந்தது என்பதையும், oom_kill என்பது எத்தனை process-கள் உண்மையில் கொல்லப்பட்டன என்பதையும் கணக்கிடுகிறது. oom_kill 0 உடன் கூடிய பெரிய high என்பது முன்னரே குறிப்பிட்ட அமைதியான சூழலாகும்: service இயங்கிக்கொண்டிருக்கும், மிக மெதுவாகச் செயல்படும், ஆனால் யாருக்கும் எந்தப் பிழையையும் தெரிவிக்காது. memory.peak (Linux 5.19 மற்றும் புதிய பதிப்புகள்) அந்த cgroup அடைந்த அதிகபட்ச பயன்பாட்டைக் கொண்டுள்ளது, இதுவே MemoryMax=-ஐ அளவிடப் பயன்படுத்த வேண்டிய எண்ணாகும். Unit restart ஆகும்போது இந்த இரண்டு கோப்புகளும் reset ஆகிவிடும், ஏனெனில் systemd அந்த cgroup-ஐ மீண்டும் உருவாக்குகிறது.

இதற்கெல்லாம் அடிப்படையாக ஒரு முன்நிபந்தனை உள்ளது. /var/log/journal இல்லையென்றால், journal RAM-ல் மட்டுமே இருக்கும், கணினியை மீட்டெடுக்க நீங்கள் செய்த reboot-க்குப் பிறகு அனைத்து வரிகளும் அழிந்துவிடும்.

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
journalctl --list-boots

journalctl --list-boots தற்போதைய boot-ஐ விட அதிகமாகக் காட்டினால், வரலாறு இப்போது பாதுகாக்கப்படுகிறது என்று அர்த்தம், எனவே journalctl -k -b -1 மூலம் செயலிழந்த boot-ன் kernel செய்திகளை உங்களால் பார்க்க முடியும்.

சிறிய VPS-க்கான தொடக்கப்புள்ளி

2 GB திட்டத்தில், kernel மற்றும் page cache-க்காக 300 முதல் 400 MB வரை ஒதுக்கி வைக்கவும். அனைத்து unit-களின் உச்சகட்ட பயன்பாடும் ஒரே நேரத்தில் நிகழக்கூடும் என்பதால், அவற்றின் மொத்த அளவை 2 GB-க்கு மிகாமல் பார்த்துக்கொள்ளவும். முக்கியமான service-க்கு அதிகப்படியான வளங்களை ஒதுக்கிவிட்டு, மற்ற தேவையற்ற service-களுக்குக் கட்டுப்பாடுகளை விதிக்கவும்.

[Service]
MemoryHigh=256M
MemoryMax=384M
MemorySwapMax=0
CPUWeight=20
TasksMax=64
Restart=on-failure
RestartSec=5s

server-க்குள் நுழைய ஒரு வழியை வைத்திருப்பது கூடுதல் முக்கியத்துவம் வாய்ந்தது. ssh.service-க்கான drop-in கோப்பில் OOMScoreAdjust=-500-ஐ அமைப்பதன் மூலம், global OOM killer உங்கள் SSH daemon-ஐ இலக்காகக் கொள்வதற்கான வாய்ப்பு குறைகிறது. இது server-ஐ சரிசெய்வதற்கும், control panel மூலம் reboot செய்வதற்கும் இடையிலான வித்தியாசமாகும். இது kernel தேர்ந்தெடுக்கும் இலக்கை மட்டுமே மாற்றும்; system முடங்கும் நேரத்தைக் குறைக்காது.

Containers ஒவ்வொன்றும் தனித்தனி cgroups-ல் இயங்குகின்றன. இவை உங்கள் unit கோப்புகளால் உருவாக்கப்படாமல், container runtime-ஆல் உருவாக்கப்படுகின்றன. எனவே, docker.service-ல் விதிக்கப்படும் கட்டுப்பாடு ஒரு container-க்கு மட்டும் பொருந்தாது. MemoryMax= மற்றும் CPUQuota= ஆகியவற்றிற்கு இணையான container அமைப்புகள் Docker Compose-ல் memory மற்றும் CPU வரம்புகளை அமைத்தல் பகுதியில் விளக்கப்பட்டுள்ளன.

FAQ

runaway process-ஐ நிறுத்துவதற்குப் பதிலாக எனது VPS ஏன் உறைந்து (freeze) போனது?

ஏனெனில், reclaim செயல்முறை பக்கங்களை (pages) திரும்பப் பெறுகிறதா என்பதை வைத்தே kernel முன்னேற்றத்தை மதிப்பிடுகிறது, அது எவ்வளவு நேரம் எடுக்கிறது என்பதை வைத்தல்ல. நினைவகம் குறைவாக இருக்கும்போது, அது page cache-ஐ வெளியேற்றும்; இதில் இயங்கும் நிரல்களின் executable பக்கங்களும் அடங்கும். அடுத்த கட்டளையின்போது அவை மீண்டும் படிக்கப்படும். அனைத்தும் storage-க்காகக் காத்திருக்கும், தொழில்நுட்ப ரீதியாக எந்த ஒதுக்கீடும் (allocation) தோல்வியடையாததால், OOM killer அழைக்கப்படாது. இது நடக்கும்போது /proc/pressure/memory-ஐச் சரிபார்க்கவும்: full avg10 40-க்கு மேல் இருந்தால், கடந்த பத்து வினாடிகளில் எந்தப் பணியும் இயங்கவில்லை என்று அர்த்தம். earlyoom போன்ற ஒரு userspace daemon, கணினி அந்த நிலையை அடைவதற்கு முன்பே process-ஐ நிறுத்திவிடும்.

MemoryHigh மற்றும் MemoryMax ஆகியவற்றுக்கு இடையே உள்ள வேறுபாடு என்ன?

MemoryHigh= என்பது வேகத்தைக் கட்டுப்படுத்தும் (throttle) ஒரு soft cap ஆகும். Kernel அந்த unit-லிருந்து தீவிரமாக நினைவகத்தை மீட்டெடுத்து, அதன் ஒதுக்கீடுகளை மெதுவாக்கும், ஆனால் பயன்பாடு அந்த அளவைத் தாண்டினாலும் எதுவும் நிறுத்தப்படாது. MemoryMax= என்பது ஒரு hard cap: இதற்குள் ஒரு ஒதுக்கீட்டைப் பூர்த்தி செய்ய முடியாவிட்டால், அந்த unit-ன் சொந்த cgroup-க்குள் OOM killer தூண்டப்படும். இதனால், கணினியில் உள்ள மிகப்பெரிய process-க்கு பதிலாக, சிக்கலை ஏற்படுத்திய process மட்டுமே நிறுத்தப்படும். MemoryHigh=-ஐ MemoryMax=-க்குக் கீழே அமைக்கவும், அவற்றுக்கு இடைப்பட்ட பகுதியை எச்சரிக்கை மண்டலமாகக் கருதவும்.

OOM killer எந்த service-ஐத் தாக்கியது என்பதை எப்படிக் கண்டறிவது?

journalctl -k --grep "Killed process" --since "2 hours ago" கட்டளையை இயக்கவும். Memory cgroup out of memory என்று தொடங்கும் வரி, ஒரு unit அதன் சொந்த MemoryMax=-ஐத் தாக்கியதைக் குறிக்கிறது. வெறும் Out of memory என்பது முழு கணினியிலும் நினைவகம் தீர்ந்துவிட்டதைக் குறிக்கிறது. பிறகு journalctl -u <unit> -n 50-ஐ இயக்கி Failed with result 'oom-kill'-ஐத் தேடவும். உங்கள் server-ல் /var/log/journal இல்லை என்றால், journal RAM-ல் சேமிக்கப்பட்டிருக்கும், reboot-ன் போது அந்தத் தரவுகள் அழிந்திருக்கும். எனவே, அடுத்த முறை நிகழ்வதற்கு முன்பே அந்த directory-ஐ உருவாக்கவும்.

சிறிய VPS-ல் swap சேர்க்க வேண்டுமா?

ஒரு சிறிய swap file, ஒருமுறை ஒதுக்கப்பட்டு மீண்டும் பயன்படுத்தப்படாத cold pages-க்கு உதவும். இது runaway process-க்கு உதவாது: இது நிறுத்தப்படுவதைத் தாமதப்படுத்தும், மேலும் குறுகிய கால செயலிழப்பை, நீங்கள் லாக்-இன் செய்து சரிசெய்ய முடியாத நீண்ட கால முடக்கமாக மாற்றும். Swap-ஐக் குறைவாக வைத்திருங்கள், நீங்கள் இழக்கத் தயாராக இருக்கும் unit-களில் MemorySwapMax=0-ஐ அமைக்கவும். இதனால் அவை அவற்றின் உச்சத்தை அடைந்து விரைவாக restart ஆகும், அதே நேரத்தில் முக்கியமான services அவற்றின் swap-ஐத் தக்கவைத்துக் கொள்ளும்.

unit file எழுதாமல் ஒரு கட்டளையை என்னால் கட்டுப்படுத்த முடியுமா?

ஆம். sudo systemd-run --scope -p MemoryMax=1G -p CPUQuota=50% ./script.sh அந்த வரம்புகளுடன் உங்கள் terminal-ல் ஒரு transient scope-க்குள் கட்டளையை இயக்கும், அது வெளியேறியதும் வரம்புகள் மறைந்துவிடும். systemd.resource-control-ல் உள்ள ஒவ்வொரு property-யும் -p-க்குப் பிறகு கிடைக்கும், எனவே MemorySwapMax=, TasksMax= மற்றும் CPUWeight= ஆகியவையும் அங்கு வேலை செய்யும். --scope-ஐ நீக்கிவிட்டு, --unit=name-ஐச் சேர்ப்பதன் மூலம் அந்த வேலையை background-ல் இயக்கலாம், அதன் வெளியீடு journal-ல் பதிவாகும்.