SSD Nodes Learn 🎉 VPS $5.50/महिन्यापासून
मार्गदर्शक Matt Connorद्वारे Matt Connor · अपडेटेड 2026-08-13

systemd मध्ये प्रक्रियेची memory आणि CPU मर्यादा कशी ठेवाल

systemd unit वर MemoryHigh, MemoryMax, CPUQuota आणि TasksMax सेट करा. cgroup v2 वापरूनही VPS का अडखळते आणि OOM kill नंतर काय तपासायचे ते जाणून घ्या.

systemd drop-in वापरून प्रक्रियेची memory आणि CPU मर्यादित करा

प्रक्रिया चालवणाऱ्या unit मध्ये काही ओळी जोडून Linux VPS वर तिची memory आणि CPU मर्यादित करता येतात. MemoryMax= ही memory ची कठोर कमाल मर्यादा आहे. CPUQuota= ही processor time ची कमाल मर्यादा आहे. या दोन्ही मर्यादा cgroup v2 (control groups, version 2) द्वारे लागू केल्या जातात. प्रत्येक सेवेचा वापर मोजण्यासाठी systemd आधीपासून याच kernel वैशिष्ट्याचा वापर करते.

sudo systemctl edit myapp.service

यामुळे comments मधील सूचनांसह drop-in file उघडते. त्या सूचनांच्या वर हे जोडा:

[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 च्या स्वतःच्या units मध्ये पुन्हा दाखवले पाहिजेत: MemoryMax=805306368 आणि CPUQuotaPerSecUSec=800ms. ते MemoryMax=infinity दाखवत असेल, तर drop-in load झालेले नाही. File /etc/systemd/system/myapp.service.d/override.conf येथे तयार झाली आहे का ते तपासा. तसेच ती [Service] header ने सुरू होते का ते तपासा. कारण section शिवाय settings line असल्यास systemd Assignment outside of section. Ignoring. log करते आणि सेवा कोणत्याही मर्यादेशिवाय सुरू करते.

ही मर्यादा निश्चित केल्यानंतर योग्य आकडे कसे निवडायचे आणि तरीही कोणत्या अडचणी येऊ शकतात, हे या मार्गदर्शकाच्या उर्वरित भागात सांगितले आहे.

वेगाने संसाधने वापरणारी प्रक्रिया स्वतःची मेमरी पूर्णपणे भरत नसतानाही VPS का गोठवते

कठोर मेमरी मर्यादा गाठणारी प्रक्रिया साधारण एका सेकंदात बंद होते आणि सेवा पुन्हा सुरू होते. ही चांगली परिस्थिती आहे. वाईट परिस्थितीत काहीही बंद होत नाही: मशीन ping ला उत्तर देते, SSH connection स्वीकारते, पण shell prompt कधीच दिसत नाही. मशीन सुरू असते आणि व्यस्त असते; मात्र त्यातील कोणतेही काम उपयुक्त नसते.

हे असे का घडते ते पाहूया. कारण ही यंत्रणा लगेच स्पष्ट होत नाही. मोकळी मेमरी कमी झाल्यावर kernel नवीन मेमरी देण्याऐवजी pages परत मिळवतो. परत मिळवण्यासाठी सर्वात कमी खर्चिक pages म्हणजे file-backed pages. चालू असलेल्या प्रत्येक गोष्टीचा executable code page cache मध्ये असतो. त्यामुळे kernel sshd चे text pages बाहेर काढतो. त्यानंतर चालणारी पुढील instruction sshd storage मधून ते bytes पुन्हा वाचावे लागणारा page fault ठरते. परिणामी प्रत्येक प्रक्रिया चालण्याऐवजी disk ची वाट पाहत राहते. तेच pages सतत बाहेर जातात आणि पुन्हा येतात. या स्थितीला thrashing म्हणतात.

Laptop पेक्षा VPS मध्ये ही समस्या अधिक गंभीर होण्याची दोन कारणे आहेत. Storage अनेकदा network-attached किंवा shared असते. त्यामुळे प्रत्येक page fault साठी local NVMe device पेक्षा अधिक milliseconds लागतात. तसेच kernel वेळ मोजत नाही; तो failure मोजतो. Reclaim हळूहळू का होईना, एखादा page परत देत असेपर्यंत kernel ला प्रगती होत आहे असे वाटते आणि तो out of memory (OOM) killer सुरू करत नाही. काहीही kill होण्यापूर्वी मशीन अनेक मिनिटे या स्थितीत राहू शकते.

ही स्थिती घडताना तुम्ही ती पाहू शकता. 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 याचा अर्थ असा की मागील दहा सेकंदांपैकी 48% वेळ मशीनवरील प्रत्येक runnable task मेमरीशी संबंधित कामासाठी थांबले होते. त्यामुळे कोणतेही task चालले नाही. निरोगी server मध्ये full चे मूल्य जवळपास शून्य असते. 10 पेक्षा जास्त मूल्य मानवाला जाणवेल इतकी गती कमी करते. 40 किंवा त्याहून अधिक मूल्याला लोक frozen स्थिती म्हणतात.

म्हणूनच केवळ मर्यादा लावणे म्हणजे हमी देणे नव्हे. MemoryHigh= अंतर्गत ठेवलेल्या unit ला kill करण्याऐवजी throttle केले जाते. त्यामुळे ती unit सुरू राहते, पण संथ राहते. systemd च्या दृष्टीने ती कधीही अपयशी झालेली नसल्याने systemd तिला पुन्हा सुरू करत नाही. Swap करण्यास परवानगी असलेल्या capped unit कडून होणारे reads आणि writes त्या unit वर charge केले जातात; मात्र ते एका shared device द्वारे हाताळले जातात. त्यामुळे त्या मशीनवरील इतर प्रत्येक सेवेसाठी /proc/pressure/io चे मूल्य वाढू शकते. मर्यादा कमतरतेचा खर्च कोण भरेल हे ठरवतात; त्या अतिरिक्त क्षमता निर्माण करू शकत नाहीत.

तुमचा VPS cgroup v2 चालवत आहे का ते तपासा

stat -fc %T /sys/fs/cgroup

cgroup2fs ही unified hierarchy आहे. खालील प्रत्येक setting साठी ती आवश्यक आहे. tmpfs याचा अर्थ सर्व्हर जुन्या v1 layout सह boot झाला आहे. अशा layout मध्ये MemoryHigh= आणि MemorySwapMax= उपलब्ध नसतात आणि प्रत्येक unit चे OOM वर्तन वेगळे असते. Ubuntu 22.04 आणि त्यानंतरच्या आवृत्त्या तसेच Debian 11 आणि त्यानंतरच्या आवृत्त्या default ने v2 वापरतात. जुनी image किंवा systemd.unified_cgroup_hierarchy=0 सह boot केलेला kernel v2 वापरत नाही.

cgroup v2 वर systemd प्रत्येक unit साठी memory accounting default ने सुरू करते. त्यामुळे आवश्यक आकडे आधीपासून उपलब्ध असतात:

systemd-cgtop -m

यामुळे memory वापरानुसार cgroups ची क्रमवारी लावलेली यादी मिळते. सर्व्हर प्रतिसाद देत असतानाच "या सर्व्हरची memory कोणती प्रक्रिया वापरत आहे" या प्रश्नाचे उत्तर मिळवण्याचा हा सर्वात जलद मार्ग आहे. सर्व्हर नवीन असल्यास, नवीन VPS वरील पहिल्या दहा मिनिटांतील खाते आणि firewall चे काम यापूर्वी करा.

MemoryHigh throttles. MemoryMax kills.

या दोन memory settings मधील फरक failure कसा दिसेल हे ठरवतो.

  • MemoryHigh= ही soft cap आहे. तिच्यापेक्षा जास्त वापर झाल्यास kernel त्या cgroup मधून memory आक्रमकपणे reclaim करतो आणि त्याच्या allocations जाणूनबुजून धीम्या करतो. वापर ही मर्यादा ओलांडू शकतो आणि कोणतीही process kill केली जात नाही.
  • MemoryMax= ही hard cap आहे. तिच्या मर्यादेत allocation पूर्ण करता आली नाही, तर OOM killer त्याच cgroup मध्ये चालतो आणि त्या unit मधील स्वतःच्या processes पैकी एक process kill करतो.

तुम्ही पूर्णपणे विश्वास ठेवत नसलेल्या कोणत्याही गोष्टीवर MemoryMax= सेट करण्याचे खरे कारण या दुसऱ्या भागात आहे. कोणतीही cap नसल्यास memory shortage ही संपूर्ण मशीनची समस्या बनते. Global OOM killer आपला victim oom_score नुसार निवडतो. याचा अर्थ बहुतेक वेळा सर्वात मोठी process निवडली जाते. सर्वात मोठी process सामान्यतः तुमचा database असतो, leak करणारी script नाही. Cap असल्यास kill त्या समस्येला कारणीभूत असलेल्या unit मध्येच होतो.

दोन्ही सेट करा आणि MemoryHigh= ही MemoryMax= पेक्षा सुमारे 20 ते 30 percent कमी ठेवा. हा फरक warning zone म्हणून काम करतो. हळूहळू होणारा leak High ओलांडतो आणि service धीमी झाल्याचे दिसते. अचानक झालेली spike Max मधून थेट जाते आणि process बंद होते.

Percentage values installed physical memory च्या आधारावर मोजली जातात. त्यामुळे 4 GB plan वर MemoryMax=25% म्हणजे 1 GB असते आणि plan resize केल्यानंतरही ती संपूर्ण मशीनच्या memory ची एक चतुर्थांश राहते. MemorySwapMax=0 मुळे त्या unit ला swap पूर्णपणे वापरता येत नाही. त्यामुळे दीर्घकाळ चालणारी अत्यंत धीमी स्थिती टाळली जाते आणि process जलद, स्पष्टपणे बंद होते.

Cap सोबत restart policy देखील सेट करा. अन्यथा kill झाल्यानंतर फक्त stopped service उरते.

[Unit]
StartLimitIntervalSec=300
StartLimitBurst=5

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

StartLimit* हे [Unit] मध्ये आणि Restart= हे [Service] मध्ये असते. यापैकी कोणतेही चुकीच्या section मध्ये ठेवल्यास systemd ते दुर्लक्षित करतो. पाच मिनिटांत पाच restarts झाल्यास ती तात्पुरती blip नसून leak असते. त्यानंतर systemd प्रयत्न थांबवतो आणि unit failed स्थितीत ठेवतो. नंतर शोधण्यासाठी हीच स्थिती योग्य आहे; समस्या लपवणारा crash loop नाही.

CPUQuota ने CPU मर्यादा ठेवा किंवा CPUWeight ने CPU वाटा द्या

CPUQuota= एका CPU वर उपलब्ध असलेल्या वेळेच्या टक्केवारीइतका CPU वेळ वापरते. CPUQuota=50% म्हणजे एका core च्या निम्मा वाटा. CPUQuota=200% म्हणजे दोन cores इतका CPU वेळ. Unit हा वेळ त्याला आवश्यक तितक्या threads मध्ये वाटू शकते. 2 vCPU plan वर CPUQuota=200% म्हणजे पूर्ण मशीन.

बहुतेक services साठी CPUWeight= हा अधिक योग्य default आहे. हा 1 ते 10000 मधील सापेक्ष वाटा असतो आणि kernel चा default 100 असतो. CPU साठी स्पर्धा सुरू झाल्यावरच त्याचा परिणाम दिसतो: load असताना CPUWeight=20 असलेले backup job 100 असलेल्या web server ला CPU वेळ देऊन मागे राहते. मात्र मशीन idle असताना ते पूर्ण CPU वापरू शकते. कठोर quota लावल्यास idle असलेली क्षमता वाया जाते.

CPU मर्यादा लावल्याने नेमका काय फायदा होतो, हे वास्तववादी पद्धतीने समजून घ्या. CPU-bound process मुळे Linux सहसा पूर्णपणे थांबत नाही, कारण scheduler सर्व processes ना वेळ देत राहतो. मशीन बंद पाडण्याचे मुख्य कारण memory असते. Predictable ceiling हवी असल्यास CPUQuota= वापरा. उदाहरणार्थ, build किंवा agent एखाद्या तासासाठी अन्यथा सतत पूर्ण CPU वापरत राहणार असल्यास ते उपयुक्त ठरते. अशा workload साठी योग्य आकार ठरवणे हा स्वतंत्र विषय आहे. तो coding agent VPS साठी किती RAM आणि CPU आवश्यक आहे येथे पाहिला आहे.

तुमच्या कोणत्याही process कडून फारसा CPU वापर होत नसताना CPU busy दिसत असेल, तर कारण hypervisor च्या दुसऱ्या बाजूला असू शकते. याला noisy neighbour मुळे होणारा CPU steal time म्हणतात. तुम्ही सेट केलेली कोणतीही quota ते बदलू शकत नाही.

TasksMax fork loop थांबवते

TasksMax= म्हणजे एखाद्या unit मध्ये ठेवता येणाऱ्या processes आणि threads ची संख्या. Threads चीही गणना होते. त्यामुळे Java किंवा Go सेवेला process list वरून दिसते त्यापेक्षा अधिक headroom आवश्यक असतो. loop मध्ये fork करणाऱ्या script विरुद्ध हे सर्वात कमी खर्चाचे संरक्षण आहे, कारण संपूर्ण प्रणालीतील process IDs संपण्याऐवजी fork unit मध्येच अपयशी ठरतो.

TasksMax=128

एखादी unit ही मर्यादा गाठल्यावर kernel cgroup चे नाव देणारी नोंद log करतो:

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

प्रोग्राम स्वतः सहसा fork: retry: Resource temporarily unavailable दाखवतो. manager default ने काय लागू करतो ते systemctl show -p DefaultTasksMax वापरून तपासा.

systemd-run ने एकदाच चालणाऱ्या job वर मर्यादा लावा

यापैकी काहीही वापरण्यासाठी unit file आवश्यक नाही. systemd-run एका command भोवती transient unit तयार करते.

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

--scope तुमच्या terminal मध्ये command चालवते आणि त्यानंतर Running scope as unit: run-r7c1a....scope प्रदर्शित करते. Output तुमच्या screen वरच दिसतो आणि command पूर्ण झाल्यावर मर्यादा काढून टाकल्या जातात. systemd.resource-control मधील कोणतीही property -p नंतर कार्य करते.

मोठ्या कालावधीच्या job साठी --scope काढून टाका आणि तिला नाव द्या. त्यानंतर ती background मध्ये transient service म्हणून चालते आणि logs journal मध्ये लिहिले जातात:

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

तुम्ही root नसताना --user सोबतही तेच options वापरू शकता. मात्र तुमच्या user manager कडे फक्त त्याला delegate केलेले controllers असतात. त्यामुळे एखादी property तेथे नाकारली जाऊ शकते. तसे झाल्यास sudo वापरून command चालवा. एखाद्या job साठी कायमस्वरूपी unit आवश्यक झाल्यावर settings मध्ये कोणताही बदल न करता त्या real unit मध्ये हलवा: script systemd service आणि timer म्हणून चालवणे.

प्रामाणिक उत्तर: swap बाबतचा प्रश्न

swap अपयश टाळत नाही; तो अपयशाचे स्वरूप बदलतो.

swap नसल्यास memory leak मर्यादेपर्यंत पोहोचतो आणि काहीतरी काही सेकंदांत बंद पडते. Outage मोठा, अल्पकाळाचा आणि नंतर journal मध्ये समजण्यास सोपा असतो. swap असल्यास kernel कमी वापरली जाणारी anonymous pages disk वर लिहितो आणि वेळ मिळवतो. प्रक्रिया स्थिर होणार असेल, तर swap मदत करते. पण ती सतत memory वापरत राहणारी प्रक्रिया असेल, तर swap पाच सेकंदांचा outage वीस मिनिटांच्या stall मध्ये बदलतो. हा stall अधिक वाईट असतो, कारण बंद पडलेली प्रक्रिया असतानाही shell वापरता येतो; पण सतत swapping करणारा server वापरता येत नाही.

swapon --show
free -h

लहान VPS साठी व्यावहारिक मध्यम मार्ग असा आहे: एकदा allocate होऊन पुन्हा कधीही वापरल्या न जाणाऱ्या pages साठी मर्यादित swap file ठेवा आणि ज्या units बंद पडल्या तरी चालतील त्यांच्यावर MemorySwapMax=0 सेट करा. महत्त्वाच्या services साठी swap उपलब्ध ठेवा. अनिश्चित वर्तन करणाऱ्या services ना मर्यादा लवकर गाठू द्या आणि restart करा.

vm.swappiness कमी करणे हा कमकुवत उपाय आहे, आणि त्यामागचे कारण समजून घेणे उपयुक्त आहे. यामुळे page cache हटवणे आणि anonymous pages swap करणे यांच्यातील संतुलनच बदलते. दोन्ही प्रकरणांत नंतर disk read करावा लागतो. त्यामुळे कोणती pages thrash होतील हे बदलते; server thrash करेल की नाही हे बदलत नाही.

अडथळा येण्यापूर्वी early OOM daemon प्रक्रिया बंद करतो

Kernel reclaim पूर्णपणे अपयशी होईपर्यंत प्रतीक्षा करतो. लहान VPS वर हीच प्रतीक्षा म्हणजे मशीन गमावण्याची अचूक वेळ असते. Userspace मधील दोन daemon स्वतः memory वर लक्ष ठेवून आणि लवकर प्रक्रिया बंद करून ही समस्या टाळतात.

earlyoom उपलब्ध memory आणि free swap वर लक्ष ठेवतो. यापैकी कोणतीही मात्रा threshold पेक्षा कमी झाल्यावर तो सर्वाधिक score असलेली प्रक्रिया बंद करतो.

sudo apt install earlyoom
systemctl status earlyoom

Debian आणि Ubuntu package install होताच service सुरू करतो. त्याचे options /etc/default/earlyoom मध्ये असतात:

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

-m PERCENT उपलब्ध memory ची किमान मर्यादा ठरवतो आणि -s PERCENT free swap ची किमान मर्यादा ठरवतो. दोन्हींचे default मूल्य 10 percent आहे. प्रत्येक जोडीतील दुसरी संख्या म्हणजे SIGKILL ची मर्यादा आहे. पहिल्या मूल्यापेक्षा कमी झाल्यावर earlyoom SIGTERM पाठवतो. दुसऱ्या मूल्यापेक्षा कमी झाल्यावर तो SIGKILL पाठवतो. हे मूल्य default नुसार पहिल्या मूल्याच्या निम्मे असते. बदल लागू करण्यासाठी sudo systemctl restart earlyoom वापरा. कोणती प्रक्रिया बंद केली आणि त्या प्रक्रियेकडे किती memory होती हे पाहण्यासाठी journalctl -u earlyoom वाचा.

systemd-oomd हा दुसरा पर्याय आहे. त्याच्या manual page मध्ये त्याचे वर्णन असे केले आहे: "a system service that uses cgroups-v2 and pressure stall information (PSI) to monitor and take corrective action before an OOM occurs in the kernel space". हे single process ऐवजी संपूर्ण cgroup वर काम करते. त्यामुळे एखादे stray child बंद करण्याऐवजी ते संपूर्ण unit बंद करते. Units ManagedOOMMemoryPressure=kill किंवा ManagedOOMSwap=kill वापरून opt in करतात. Thresholds /etc/systemd/oomd.conf मध्ये असतात.

systemctl status systemd-oomd
oomctl

oomctl सध्या कोणत्या गोष्टींवर लक्ष ठेवले जात आहे ते दाखवतो. Server image वर हे बहुतेक वेळा काहीही दाखवत नाही, कारण ही setting प्रत्येक unit साठी opt in असते. एक daemon निवडा आणि त्यावरच थांबा. दोन्ही चालवल्यास victim निवडण्यासाठी दोन प्रक्रिया एकमेकींशी स्पर्धा करतात. त्यामुळे एखादी प्रक्रिया का बंद झाली हे नंतर शोधणे अधिक कठीण होते.

कोणते unit जबाबदार होते?

सुरुवात kernel पासून करा, कारण 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 मध्ये त्याने धरलेली memory. येथे ती सुमारे 1.8 GB आहे. चौकोनी कंसातील नाव सावधगिरीने वाचा. kernel ने निवडलेला victim तोच असतो. kernel सर्वात मोठा process निवडतो. मात्र shortage निर्माण करणारा process नेहमी तोच असेल असे नाही.

cgroup limit मुळे झालेल्या kill ला वेगळा prefix असतो. त्याच्या वर छापलेला report स्वतःची कमाल मर्यादा गाठलेल्या 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

तो prefix निदानासाठी बहुतेक माहिती देतो. Memory cgroup out of memory म्हणजे एका unit ने तुम्ही दिलेला MemoryMax= गाठला, आणि उर्वरित system मध्ये समस्या नव्हती. साधा Out of memory म्हणजे संपूर्ण machine ची 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 ची नोंद करणारा हा एकमेव स्रोत आहे. throttling मुळे log line कधीही तयार होत नाही:

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= पेक्षा किती वेळा वर ढकलून throttle केले गेले ते मोजले जाते. max मध्ये hard cap किती वेळा गाठली ते मोजले जाते. oom_kill मध्ये प्रत्यक्ष kill केलेल्या processes ची संख्या मोजली जाते. oom_kill 0 सोबत मोठे high दिसणे म्हणजे आधीचे silent प्रकरण. सेवा चालू असते, तिचा वेग अत्यंत कमी झालेला असतो आणि तिने कोणत्याही ठिकाणी failure कळवलेले नसते. memory.peak (Linux 5.19 आणि त्यानंतरच्या आवृत्त्यांमध्ये) cgroup ने गाठलेला सर्वाधिक usage ठेवते. MemoryMax= चे sizing करण्यासाठी हीच संख्या वापरा. Unit restart झाल्यावर दोन्ही files reset होतात, कारण systemd cgroup पुन्हा तयार करते.

या सर्वांच्या खाली एक prerequisite आहे. /var/log/journal अस्तित्वात नसेल, तर journal RAM मध्ये राहते. त्यामुळे system recover करण्यासाठी आवश्यक असलेल्या reboot नंतर प्रत्येक line नष्ट होते.

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 मध्ये current boot पेक्षा अधिक boots दिसत असतील, तर history आता टिकून राहते. त्यामुळे journalctl -k -b -1 वापरून बंद पडलेल्या boot मधील kernel messages पाहता येतात.

लहान VPS साठी प्रारंभिक मांडणी

2 GB प्लॅनवर kernel आणि page cache साठी 300 ते 400 MB राखून ठेवा. सर्व caps मिळून पूर्ण 2 GB होतील असे करू नका, कारण प्रत्येक unit एकाच वेळी peak वर जाऊ शकते. महत्त्वाच्या सेवेला सर्वाधिक हिस्सा द्या. त्याभोवतीच्या अनिश्चित सेवांवर मर्यादा घाला.

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

प्रवेशाचा पर्याय उपलब्ध ठेवण्यासाठी आणखी एक setting उपयुक्त ठरते. OOMScoreAdjust=-500 ला ssh.service च्या drop-in मध्ये सेट केल्यास global OOM killer तुमच्या SSH daemon ला बळी म्हणून निवडण्याची शक्यता लक्षणीयरीत्या कमी होते. त्यामुळे control panel मधून सर्व्हर reboot करण्याऐवजी समस्या दुरुस्त करता येते. यामुळे kernel केवळ कोणता process बळी निवडेल, हा निर्णय बदलतो. stall चा कालावधी कमी होत नाही.

Containers त्यांच्या स्वतःच्या cgroups मध्ये चालतात. हे cgroups तुमच्या unit files ऐवजी container runtime तयार करते. त्यामुळे docker.service वरील मर्यादा एखाद्या container वरील मर्यादा ठरत नाही. MemoryMax= आणि CPUQuota= चे container-निहाय equivalent Docker Compose मध्ये memory आणि CPU मर्यादा सेट करणे येथे स्पष्ट केले आहेत.

वारंवार विचारले जाणारे प्रश्न (FAQ)

माझ्या VPS ने runaway process बंद करण्याऐवजी काम करणे का थांबवले?

कारण kernel प्रगतीचे मूल्यांकन reclaim मुळे pages परत मिळतात का यावर करतो; त्यासाठी किती वेळ लागतो यावर नाही. Memory कमी असताना तो page cache मधील pages काढून टाकतो. यात चालू programs चे executable pages देखील येतात. त्यानंतर पुढील instruction वेळी तो ते pages पुन्हा वाचतो. सर्व प्रक्रिया storage वर थांबतात आणि allocation तांत्रिकदृष्ट्या अपयशी ठरलेले नसते. त्यामुळे OOM killer कधीही invoke होत नाही. ही स्थिती सुरू असताना /proc/pressure/memory तपासा. full avg10 चे मूल्य 40 पेक्षा जास्त असल्यास मागील दहा सेकंदांत जवळजवळ कोणत्याही task ला चालण्याची संधी मिळालेली नसते. earlyoom सारखा userspace daemon system त्या स्थितीपर्यंत पोहोचण्यापूर्वी process बंद करतो.

MemoryHigh आणि MemoryMax मध्ये काय फरक आहे?

MemoryHigh= ही throttling करणारी soft cap आहे. kernel त्या unit मधून pages कठोरपणे reclaim करतो आणि तिच्या allocations चा वेग कमी करतो. मात्र usage त्या संख्येपेक्षा जास्त जाऊ शकतो आणि कोणतीही प्रक्रिया बंद केली जात नाही. MemoryMax= ही hard cap आहे. तिच्या मर्यादेत allocation पूर्ण करता न आल्यास त्या unit च्या स्वतःच्या cgroup मध्ये OOM killer invoke होतो. त्यामुळे समस्या निर्माण करणारी process बंद होते; संपूर्ण box वरील सर्वात मोठी process नाही. MemoryHigh= हे MemoryMax= पेक्षा कमी ठेवा आणि त्यांच्यातील अंतर warning zone म्हणून वापरा.

OOM killer ने कोणती service बंद केली हे कसे शोधू?

journalctl -k --grep "Killed process" --since "2 hours ago" चालवा. Memory cgroup out of memory ने सुरू होणारी line म्हणजे एखाद्या unit ने स्वतःचे MemoryMax= गाठले. साधी Out of memory म्हणजे संपूर्ण machine ची memory संपली. त्यानंतर journalctl -u <unit> -n 50 चालवा आणि Failed with result 'oom-kill' शोधा. तुमच्या server वर /var/log/journal अस्तित्वात नसल्यास journal RAM मध्ये ठेवला गेला होता आणि reboot सोबत पुरावा नष्ट झाला. त्यामुळे पुढील incident पूर्वी ती directory तयार करा.

लहान VPS मध्ये swap जोडावे का?

एकदाच allocate होणाऱ्या आणि त्यानंतर पुन्हा न वापरल्या जाणाऱ्या cold pages साठी लहान swap file उपयुक्त ठरते. runaway process साठी ती उपयुक्त ठरत नाही. ती process बंद होण्यास विलंब करते आणि login करून समस्या दुरुस्त करता न येणारा दीर्घ stall निर्माण करते; त्याऐवजी अल्प outage होत नाही. swap माफक ठेवा. ज्या units बंद झाल्या तरी चालतील त्यांच्यावर MemorySwapMax=0 सेट करा. त्यामुळे त्या त्यांची मर्यादा गाठून त्वरीत restart होतील आणि महत्त्वाच्या services त्यांचा swap वापरत राहतील.

unit file न लिहिता एखाद्या command वर मर्यादा घालता येते का?

होय. sudo systemd-run --scope -p MemoryMax=1G -p CPUQuota=50% ./script.sh तुमच्या terminal मध्ये त्या limits सह transient scope अंतर्गत command चालवतो. command बंद झाल्यावर त्या limits नाहीशा होतात. systemd.resource-control मधील प्रत्येक property -p नंतर उपलब्ध असते. त्यामुळे MemorySwapMax=, TasksMax= आणि CPUWeight= देखील तेथे काम करतात. --scope काढून --unit=name जोडा. यामुळे job background मध्ये चालेल आणि त्याचे output journal मध्ये जाईल.