Բոլոր դասերը
Linux և սերվերներՄիջին12 րոպե ընթերցումԻմ ստեկում

Փաթեթներ, log-եր, cron և սկավառակներ

Սերվերը պահիր թարմացված, իմացիր, թե որտեղ են log-երը, պլանավորիր job-եր և երբեք մի մնա առանց սկավառակի տեղի։

  • apt
  • Logs
  • cron
  • Disks & df / du
  • logrotate
Քայլ 1/5
App-ը լոգ է գրում։ Ու գրում։ Ու գրում։ Ոչ ոք դրանք չի ռոտացնում, և դիսկը 60%-ից կամաց հասնում է 100%-ի։

30 վայրկյանում

Սերվերի սպասարկման մեծ մասը հանգում է չորս բանի՝ package manager-ով ծրագրերի տեղադրում և թարմացում, log-երի ընթերցում և rotation, կրկնվող job-երի պլանավորում և սկավառակի ու հիշողության հսկում։ Միայն լցված սկավառակը կարող է միանգամից շարքից հանել տվյալների բազան, վեբ սերվերը և deploy-ը։ Այս դասը տալիս է հրամաններն ու սովորությունները, որոնք սերվերը առողջ են պահում։

Ինչու եմ օգտագործում

  • unattended-upgrades-ը յուրաքանչյուր սերվերի իմ baseline-ի մասն է, որովհետև չթարմացված փաթեթները ներս մտնելու ամենահեշտ ճանապարհներից են։
  • Մեկ production սերվերի սկավառակի զբաղվածությունը 91%-ից իջեցրի 66%-ի՝ գտնելով հին log-երը, հին build-երը և չափազանց մեծ node_modules-ները։
  • Սկավառակի, load-ի և uptime-ի monitoring-ը իմ ստանդարտ ցուցակում է, որովհետև լցված սկավառակը լուռ ձախողում է, մինչև ամեն ինչ միանգամից կոտրվի։

Ինչպես է աշխատում

01apt՝ ծրագրերի տեղադրում և թարմացում

Debian-ում և Ubuntu-ում apt-ը ծրագրեր է տեղադրում վստահելի repository-ներից, լուծում է dependency-ները և ստուգում է փաթեթների ստորագրությունները։ apt update-ը թարմացնում է հասանելի տարբերակների ցուցակը․ այն ոչինչ չի տեղադրում։ apt upgrade-ը տեղադրում է արդեն եղածի նոր տարբերակները, իսկ apt full-upgrade-ը կարող է նաև փաթեթներ ավելացնել կամ հեռացնել, երբ dependency-ները փոխվում են, ինչը պետք է kernel-ի թարմացումների համար։ RHEL ընտանիքի համակարգերում նույն աշխատանքներն արվում են dnf-ով (dnf check-update, dnf upgrade)։ Նախընտրիր դիստրիբուտիվի repository-ների փաթեթները․ third-party repository-ներ ավելացրու միայն վստահելի vendor-ներից՝ օգտագործելով նրանց signed-by keyring-ները։ Kernel-ի կամ core գրադարանի թարմացումից հետո ստուգիր՝ արդյոք reboot է պահանջվում։

bash
sudo apt update                    # refresh package lists
apt list --upgradable              # what would change
sudo apt upgrade                   # install updates
sudo apt full-upgrade              # also handle changed dependencies
sudo apt install nginx htop        # install packages
sudo apt remove --purge apache2    # remove, including config
sudo apt autoremove                # remove unused dependencies
apt show nginx; apt policy nginx   # details and versions
[ -f /var/run/reboot-required ] && cat /var/run/reboot-required

02Անվտանգության ավտոմատ թարմացումներ

unattended-upgrades-ը ամեն օր ավտոմատ տեղադրում է անվտանգության թարմացումները, այնպես որ հայտնի անցքերը փակվում են, նույնիսկ երբ ոչ ոք մուտք չի գործում։ Այն լռելյայն տեղադրված է Ubuntu Server-ում․ կարող ես ստուգել և միացնել այն dpkg-reconfigure-ով։ Լռելյայն այն կիրառում է միայն security pocket-ի թարմացումները, ինչը խելամիտ հավասարակշռություն է անվտանգության և կայունության միջև։ Կարող ես կարգավորել այն ավտոմատ reboot անելու հանգիստ ժամին, երբ kernel-ի թարմացումը դա պահանջում է, և հին kernel-ները մաքրելու։ RHEL-ում համարժեքը dnf-automatic-ն է։ Դրա log-ը՝ /var/log/unattended-upgrades/-ում, ցույց է տալիս, թե ինչ և երբ է տեղադրվել։ Ավտոմատ թարմացումները չեն փոխարինում major տարբերակների միջև պլանավորված upgrade-ներին, որոնք պետք է նախ փորձարկես։

bash
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades   # enable
cat /etc/apt/apt.conf.d/20auto-upgrades
# In /etc/apt/apt.conf.d/50unattended-upgrades you can set:
#   Unattended-Upgrade::Automatic-Reboot "true";
#   Unattended-Upgrade::Automatic-Reboot-Time "04:00";
#   Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
sudo unattended-upgrade --dry-run --debug         # test it

03Log-եր՝ /var/log, journald և logrotate

Ժամանակակից սերվերի վրա log-երի երկու համակարգ կա։ systemd-ի journal-ը հավաքում է ծառայությունների և kernel-ի output-ը․ այն կարդում ես journalctl-ով։ /var/log-ի դասական տեքստային ֆայլերը գալիս են rsyslog-ից և nginx-ի նման հավելվածներից։ Ubuntu-ում օգտակար ֆայլերն են /var/log/syslog-ը՝ ընդհանուր հաղորդագրությունների համար, /var/log/auth.log-ը՝ login-ների և sudo-ի համար, և /var/log/nginx/-ը՝ վեբ traffic-ի և սխալների համար (RHEL-ն օգտագործում է /var/log/messages և /var/log/secure)։ Log-երը անվերջ աճում են, եթե ինչ-որ բան դրանք չկրճատի։ logrotate-ը դա անում է տեքստային ֆայլերի համար․ այն վերանվանում է ընթացիկ ֆայլը, սեղմում է հները և պահում միայն որոշակի քանակ։ Journal-ի համար սահմանիր չափի սահմանափակում journald-ի config-ում կամ մաքրիր այն vacuum-ով։

bash
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}
# Test without changing anything:  sudo logrotate -d /etc/logrotate.d/myapp
# Journal size:  journalctl --disk-usage
#                sudo journalctl --vacuum-size=500M
# Permanent cap: SystemMaxUse=500M in /etc/systemd/journald.conf

04Պլանավորում cron-ով

cron-ը հրամաններ է գործարկում ժամանակացույցով։ Յուրաքանչյուր օգտատեր ունի crontab (խմբագրիր այն crontab -e-ով), իսկ համակարգային job-երը գտնվում են /etc/crontab-ում և /etc/cron.d-ում։ Տողն ունի հինգ ժամանակային դաշտ՝ րոպե, ժամ, ամսվա օր, ամիս և շաբաթվա օր, որոնց հաջորդում է հրամանը։ Աստղանիշը նշանակում է «ամեն», */5-ը՝ «ամեն հինգը», իսկ 1-5-ի նման միջակայքերը՝ երկուշաբթիից ուրբաթ։ Cron-ն աշխատում է նվազագույն environment-ով․ PATH-ը կարճ է, և shell profile-դ չի բեռնվում, ուստի օգտագործիր բացարձակ ճանապարհներ և output-ը վերաուղղորդիր log, այլապես սխալներն անհետանում են։ Cron-ն օգտագործում է սերվերի ժամային գոտին, որը cloud սերվերներում հաճախ UTC է։ crontab.guru-ի նման կայքը օգնում է ստուգել արտահայտությունը։

bash
# m  h  dom mon dow  command
*/5  *  *   *   *    /usr/local/bin/healthcheck.sh >> /var/log/healthcheck.log 2>&1
0    3  *   *   *    /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
30   2  *   *   1    /usr/local/bin/weekly-report.sh
# Laravel scheduler: run every minute as the app user
*    *  *   *   *    cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1
# Prevent overlapping runs with flock
0    *  *   *   *    flock -n /tmp/sync.lock /usr/local/bin/sync.sh

05Սկավառակներ՝ df, du, lsblk և mount

df-ը ցույց է տալիս, թե որքան է լցված յուրաքանչյուր mount արված ֆայլային համակարգ, du-ն՝ որքան տեղ են զբաղեցնում ֆայլերն ու դիրեկտորիաները։ lsblk-ը ցուցակում է block սարքերը, այնպես որ կարող ես տեսնել սկավառակներն ու partition-ները, ներառյալ նոր միացրած volume-ը։ Նոր volume օգտագործելու համար մեկ անգամ ստեղծիր ֆայլային համակարգ դրա վրա (ext4-ը անվտանգ լռելյայն է), mount արա այն և ավելացրու /etc/fstab-ում ըստ UUID-ի, որպեսզի reboot-ից հետո վերադառնա։ fstab-ը ստուգիր mount -a-ով մինչև reboot անելը, որովհետև կոտրված գրառումը կարող է խանգարել սերվերի boot-ին։ Հետևիր նաև inode-ներին df -i-ով․ սկավառակը կարող է «լցված» լինել ազատ տեղով, եթե միլիոնավոր փոքր ֆայլեր (session-ներ, cache) սպառել են բոլոր inode-ները։

bash
df -h                        # space per filesystem
df -i                        # inodes per filesystem
lsblk -f                     # disks, partitions, filesystems, UUIDs
sudo mkfs.ext4 /dev/sdb      # format a NEW empty volume (destroys data!)
sudo mkdir -p /mnt/data
sudo mount /dev/sdb /mnt/data
# /etc/fstab line (use the UUID from lsblk -f):
# UUID=your-uuid  /mnt/data  ext4  defaults,nofail  0  2
sudo mount -a                # test fstab before rebooting

06Ինչն է լցնում սկավառակը

Երբ df-ը ցույց է տալիս սկավառակ 90% կամ ավելի, աշխատիր վերևից ներքև։ du-ն խորության սահմանափակմամբ ցույց է տալիս ամենամեծ դիրեկտորիաները․ կրկնիր ամենամեծի ներսում։ ncdu-ն ինտերակտիվ տարբերակ է, որը սա արագ է դարձնում։ Սովորական կասկածյալներն են հին log-երը և rotate արված արխիվները, systemd journal-ը, Docker image-ները և build cache-ը, deploy-ների հին release թղթապանակները, node_modules և vendor դիրեկտորիաները, home դիրեկտորիաներում մոռացված տվյալների բազայի dump-երը և apt-ի փաթեթների cache-ը։ Մեկ թակարդ՝ եթե ջնջում ես log ֆայլ, որը պրոցեսը դեռ բաց է պահում, տեղը չի ազատվում, մինչև այդ պրոցեսը restart չանի կամ ֆայլը նորից չբացի։ lsof +L1-ը ցուցակում է այդ ջնջված, բայց բաց ֆայլերը։ Կենդանի log-ը truncate անելն ավելի անվտանգ է, քան ջնջելը։

bash
sudo du -xh --max-depth=1 / | sort -h | tail
sudo du -xh --max-depth=1 /var | sort -h | tail
sudo ncdu -x /                         # interactive (apt install ncdu)
sudo find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null
journalctl --disk-usage
docker system df                       # images, containers, cache
sudo apt clean                         # apt package cache
sudo lsof +L1                          # deleted files still held open
sudo truncate -s 0 /var/log/myapp/huge.log   # empty a live log safely

07Հիշողություն և swap

free -h-ը ցույց է տալիս հիշողությունը։ Մի խուճապի մատնվիր փոքր «free» թվից․ Linux-ը ազատ հիշողությունն օգտագործում է որպես disk cache և վերադարձնում է այն, երբ հավելվածներին պետք է։ Կարդալու սյունը available-ն է։ Երբ available հիշողությունը սպառվում է, kernel-ի OOM (out of memory) killer-ը ավարտում է պրոցեսներից մեկը, հաճախ ամենամեծը, որը հաճախ քո տվյալների բազան է։ Swap-ը սկավառակի տեղ է, որն օգտագործվում է որպես լրացուցիչ հիշողություն։ Այն շատ ավելի դանդաղ է, քան RAM-ը, բայց փոքր VPS-ի վրա համեստ swap ֆայլը (1-ից 2 GB) հանկարծակի crash-ը վերածում է դանդաղման, որը կարող ես նկատել և շտկել։ Եթե սերվերը անընդհատ swap է անում, քեզ պետք է ավելի շատ RAM կամ քիչ ագահ հավելված, ոչ թե ավելի շատ swap։

bash
free -h                          # read the "available" column
sudo journalctl -k | grep -i "out of memory"   # OOM kills
# Create a 2 GB swap file
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab
swapon --show

Օգտագործեք, երբ

  • Քո յուրաքանչյուր սերվեր․ թարմացումները, log rotation-ը և սկավառակի monitoring-ը հիմնական հիգիենա են։
  • Լցված սկավառակի incident-ներ, ձախողվող deploy-ներ կամ գրելը մերժող տվյալների բազաներ։
  • Կրկնվող առաջադրանքներ, ինչպես backup-ներ, հաշվետվություններ, մաքրումներ և framework-ների scheduler-ներ։
  • Փոքր VPS instance-ներ, որտեղ swap ֆայլը և journal-ի սահմանափակումները կանխում են խուսափելի crash-երը։

Մի՛ օգտագործեք, երբ

  • Production-ում մի գործարկիր apt full-upgrade կամ major release upgrade առանց snapshot-ի և maintenance window-ի։
  • Ծանրաբեռնված տվյալների բազայի սերվերի վրա swap-ը մի օգտագործիր որպես բավարար RAM-ի փոխարինող։
  • Միայն տեղ ազատելու համար մի ջնջիր ֆայլեր, որոնք չես հասկանում․ նախ ստուգիր, թե ինչն է դրանք գրում։

Այլընտրանքներ

  • dnf / dnf-automatic

    apt-ի և unattended-upgrades-ի համարժեքները RHEL-ում, Rocky-ում և Alma-ում։

  • systemd timer-ներ

    cron-ի ավելի դիտարկելի այլընտրանք՝ journal-ի log-երով և բաց թողածի լրացմամբ։

  • Կենտրոնացված logging (Loki, ELK, hosted)

    Log-երը տեղափոխիր սերվերից դուրս, որպեսզի կարողանաս որոնել բոլոր մեքենաներում և պահել դրանք սկավառակի մահից հետո էլ։

  • Object storage

    Օգտատերերի upload-ները և backup-ները տեղափոխիր S3-համատեղելի storage, որպեսզի սերվերի սկավառակը մնա փոքր և փոխարինելի։

Լավագույն պրակտիկաներ

  1. Միացրու unattended-upgrades-ը անվտանգության թարմացումների համար և ստուգիր պահանջվող reboot-ները։
  2. Մեծ upgrade-ներից առաջ snapshot արա և նախ upgrade արա staging-ը։
  3. Հավելվածի յուրաքանչյուր log-ի համար logrotate կանոն տուր և սահմանափակիր journal-ի չափը։
  4. Alert սահմանիր սկավառակի զբաղվածության վրա շատ ավելի վաղ, քան այն կլցվի, օրինակ՝ 80%-ում։
  5. Cron-ում օգտագործիր բացարձակ ճանապարհներ, output-ը վերաուղղորդիր log և flock-ով կանխիր իրար վրա ընկնելը։
  6. Լրացուցիչ volume-ները mount արա ըստ UUID-ի nofail տարբերակով և fstab-ը ստուգիր mount -a-ով։
  7. Release-ները, Docker image-ները և build cache-երը մաքրիր որպես deploy գործընթացի մաս։

Տարածված սխալներ

  • apt upgrade գործարկել առանց նախապես apt update-ի, ուստի ոչ մի նոր բան չի տեղադրվում։
  • Կենդանի log-ը ջնջել rm-ով և տեսնել, որ տեղ չի ազատվել, որովհետև պրոցեսը դեռ բաց է պահում այն։
  • Cron job-եր, որոնք աշխատում են տերմինալում, բայց աննկատ ձախողվում են PATH-ի կամ բացակայող վերաուղղորդման պատճառով։
  • Տառասխալ /etc/fstab-ում, որը խանգարում է սերվերի boot-ին։
  • Կարդալ «free» հիշողությունը «available»-ի փոխարեն և ավելացնել RAM, որը պետք չէր։

Խորը վերլուծություն

08apt-ի տակ․ dpkg, source-եր, pinning և phased updates

apt-ը պլանավորողն է, տեղադրումն անում է dpkg-ն։ dpkg-ն բացում է .deb արխիվները, գործարկում է դրանց maintainer script-երը և վիճակը գրանցում /var/lib/dpkg-ում։ Եթե upgrade-ն ընդհատվում է, փաթեթները մնում են կիսակարգավորված, մինչև գործարկես dpkg --configure -a։ Ubuntu 24.04-ից repository-ները նկարագրվում են deb822 ֆորմատով, այնպիսի ֆայլերում, ինչպես /etc/apt/sources.list.d/ubuntu.sources-ն է, իսկ երրորդ կողմի repository-ները պետք է իրենց key-ը նշեն Signed-By-ով, որպեսզի այդ key-ը չկարողանա երաշխավորել այլ repository-ներ։ Pinning-ը /etc/apt/preferences.d-ում սահմանում է repository-ների միջև առաջնահերթություններ, իսկ apt-mark hold-ը սառեցնում է փաթեթի տարբերակը, երբ upgrade անելուց առաջ պետք է սպասել։ Ubuntu-ն օգտագործում է նաև phased updates․ ոչ անվտանգային թարմացումները մի քանի օրվա ընթացքում տարածվում են մեքենաների աճող տոկոսի վրա, ուստի apt-ը կարող է որոշ upgrade-ներ ցույց տալ որպես «deferred due to phasing»։ Դա սպասելի է, ոչ թե կոտրված mirror։

bash
# /etc/apt/sources.list.d/vendor.sources (deb822 format)
Types: deb
URIs: https://packages.example.com/apt
Suites: stable
Components: main
Signed-By: /etc/apt/keyrings/vendor.gpg
 
# Useful commands:
#   sudo dpkg --configure -a        # finish interrupted installs
#   sudo apt-mark hold nginx        # freeze a version (unhold to undo)
#   apt-cache policy nginx          # which repo and priority wins
#   dpkg -S /usr/sbin/nginx         # which package owns a file
#   zgrep ' install ' /var/log/dpkg.log*   # install history

09Ֆայլային համակարգեր․ reserved block-եր, volume-ների մեծացում և LVM

ext4-ը լռելյայն պահում է բլոկների 5%-ը root-ի համար, որպեսզի root-ով աշխատող ծառայությունները շարունակեն աշխատել, երբ օգտատերերը լցնում են սկավառակը։ 500 GB data volume-ի վրա դա 25 GB է․ tune2fs -m 1-ը նվազեցնում է այն, բայց root ֆայլային համակարգի վրա պահիր լռելյայնը։ ext4-ը կարելի է մեծացնել online և փոքրացնել միայն offline, իսկ XFS-ը՝ RHEL-ի լռելյայնը, կարելի է մեծացնել online, բայց երբեք չի փոքրացվում։ Երբ provider-ի մոտ մեծացնում ես սկավառակը, ֆայլային համակարգն ինքնուրույն չի մեծանում․ եթե սկավառակն ունի partition-ներ, նախ մեծացրու partition-ը growpart-ով, հետո ֆայլային համակարգը resize2fs-ով (ext4) կամ xfs_growfs-ով (XFS)։ Շատ cloud image-ներ դա ավտոմատ անում են root սկավառակի համար boot-ի ժամանակ cloud-init-ի միջոցով, բայց միացված volume-ները սովորաբար ձեռքով են պահանջում։ LVM-ն ավելացնում է շերտ, որը թույլ է տալիս միավորել սկավառակներ, մեծացնել logical volume-ներ և snapshot-ներ անել՝ ավելի շատ շարժվող մասերի գնով։

bash
lsblk                                  # disk vs partition sizes
sudo growpart /dev/vda 1               # grow partition 1 to fill the disk
sudo resize2fs /dev/vda1               # grow ext4 online
sudo xfs_growfs /                      # grow XFS (by mount point)
sudo resize2fs /dev/sdb                # unpartitioned volume: grow directly
sudo tune2fs -l /dev/sdb | grep -i 'reserved block count'
sudo tune2fs -m 1 /dev/sdb             # 1% reserved on a data volume
sudo lvextend -r -l +100%FREE /dev/vg0/data   # LVM: grow LV and filesystem

10I/O-ի և հիշողության ճնշման ախտորոշում

Երբ սերվերը դանդաղ է, բայց CPU-ն պարապ է, չափիր սկավառակը։ vmstat 1-ը ամեն վայրկյան ցույց է տալիս I/O-ի վրա արգելափակված պրոցեսները (b), swap-in-ը և swap-out-ը (si, so) և I/O-ի սպասման CPU ժամանակը (wa)։ iostat -x 1-ը (sysstat փաթեթ) ցույց է տալիս ըստ սարքի latency-ն r_await-ում և w_await-ում և utilization-ը․ SSD-ների և ցանցային volume-ների վրա latency-ն և provider-ի IOPS սահմանն ավելի կարևոր են, քան %util-ը։ iotop-ը կամ pidstat -d 1-ը ցույց են տալիս, թե որ պրոցեսն է I/O անում։ Գրառումները նախ գնում են page cache, իսկ ավելի ուշ flush են արվում, ուստի մեծ գրառումը կարող է արագ թվալ, իսկ հետո writeback-ի ժամանակ ամեն ինչ կանգնեցնել։ /proc/pressure/io-ում և /proc/pressure/memory-ում Pressure Stall Information-ը ցույց է տալիս, թե ժամանակի որ մասն են task-երը կանգնած եղել, ինչը շատ ավելի լավ ազդանշան է, քան ազատ հիշողությունը։ vm.swappiness-ը կառավարում է, թե որքան պատրաստակամ է kernel-ը swap անում․ լռելյայն 60-ը նորմալ է սերվերների մեծ մասի համար։

bash
vmstat 1 5                     # b, si/so, wa columns
iostat -x 1 3                  # r_await, w_await, %util per device
sudo iotop -oPa                # processes doing I/O (accumulated)
pidstat -d 1 5                 # per-process disk reads/writes
cat /proc/pressure/io          # some/full stall percentages
grep -E 'Dirty|Writeback' /proc/meminfo
sysctl vm.swappiness

11Log pipeline-ի նախագծում

Մեկ սերվերի վրա journald-ը logrotate-ի հետ բավարար է, եթե չափերը սահմանափակես։ journald-ը log-երը պահում է /var/log/journal-ում, երբ այդ դիրեկտորիան գոյություն ունի կամ դրված է Storage=persistent, հակառակ դեպքում՝ միայն հիշողության մեջ /run-ի տակ, և դրանք անհետանում են reboot-ի ժամանակ։ Այն նաև rate limit է կիրառում աղմկոտ ծառայությունների վրա (RateLimitIntervalSec և RateLimitBurst), ուստի ցիկլով կրկնվող սխալը կարող է թաքցնել իր կրկնությունները․ journal-ը գրանցում է, թե քանի հաղորդագրություն է ճնշվել։ Մեկ սերվերից այն կողմ log-երը պետք է լքեն մեքենան․ agent-ը, ինչպես Grafana Alloy-ն (Promtail-ի հաջորդը), Vector-ը կամ Fluent Bit-ը, կարդում է journal-ը և ֆայլերը և ուղարկում Loki, Elasticsearch կամ hosted ծառայություն։ Նախընտրիր կառուցվածքային JSON log-եր համաձայնեցված դաշտերով, ինչպես level-ը, request ID-ն և user ID-ն, որպեսզի կարողանաս ֆիլտրել grep-ի փոխարեն։ Retention-ը որոշիր ըստ տիպի՝ debug log-երը օրերով, access log-երը շաբաթներով, audit log-երը այնքան, որքան պահանջում է policy-ն։

ini
# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
SystemKeepFree=2G
MaxRetentionSec=30day
RateLimitIntervalSec=30s
RateLimitBurst=10000
 
# Apply: sudo systemctl restart systemd-journald
# Check: journalctl --disk-usage; journalctl --verify

Իրական իրավիճակներ

01

apt-ը կողպված է կամ կիսատ է մնացել

Խնդիր

apt install-ը ձախողվում է «Could not get lock /var/lib/dpkg/lock-frontend» սխալով, իսկ upgrade-ի ժամանակ SSH session-ի կտրվելուց հետո apt-ը բողոքում է, որ dpkg-ն ընդհատվել է։

Ինչպես լուծել

Նախ ստուգիր՝ արդյոք մեկ այլ apt իսկապես աշխատում է․ ps aux | grep -E 'apt|dpkg|unattended' և systemctl status unattended-upgrades apt-daily-upgrade.service։ Նոր սերվերներում unattended-upgrades-ը հաճախ աշխատում է boot-ից անմիջապես հետո, ուստի սպասիր դրան՝ lock ֆայլերը ջնջելու փոխարեն, ինչը կարող է վնասել dpkg-ի բազան։ Եթե ոչինչ չի աշխատում, և նախորդ upgrade-ն ընդհատվել է, գործարկիր sudo dpkg --configure -a, հետո sudo apt -f install՝ կոտրված կախվածությունները շտկելու համար, հետո նորից apt update և upgrade։ Կարդա /var/log/apt/term.log-ը՝ ձախողվող maintainer script-ը գտնելու համար։ Հետագայում երկար upgrade-ները գործարկիր tmux-ի ներսում, որպեսզի կտրված connection-ը դրանք չսպանի։

02

Provider-ի սկավառակը մեծացվել է, բայց df-ը ցույց է տալիս հին չափը

Խնդիր

Provider-ի panel-ում միացված volume-ը մեծացրիր 100 GB-ից 200 GB։ lsblk-ը ցույց է տալիս 200 GB, բայց df -h-ը դեռ 100 GB է հաղորդում, և սկավառակը դեռ գրեթե լիքն է։

Ինչպես լուծել

Block device-ը մեծացել է, բայց partition-ը և ֆայլային համակարգը՝ ոչ։ Գործարկիր lsblk -f՝ դասավորությունը և ֆայլային համակարգի տիպը տեսնելու համար։ Եթե ֆայլային համակարգն անմիջապես սարքի վրա է (առանց partition-ի, ինչը տարածված է volume-ների համար), մեծացրու այն online՝ sudo resize2fs /dev/sdb ext4-ի համար կամ sudo xfs_growfs /mnt/data XFS-ի համար։ Եթե կա partition, նախ sudo growpart /dev/sdb 1, հետո resize արա partition-ի ֆայլային համակարգը։ LVM-ի դեպքում օգտագործիր pvresize, հետո lvextend -r։ Սկսելուց առաջ snapshot արա։ Հետո շտկիր նաև աճի արմատական պատճառը, քանի որ ավելի մեծ սկավառակը միայն ժամանակ է շահում, եթե log-երը կամ upload-ները անսահմանափակ են աճում։

03

«No space left on device»՝ գիգաբայթներով ազատ տեղով

Խնդիր

Upload-ները և PHP session-ները ձախողվում են «No space left on device» սխալով, բայց df -h-ը ցույց է տալիս սկավառակը 60%-ով։ Ծառայությունների restart-ը չի օգնում։

Ինչպես լուծել

Ստուգիր inode-ները df -i-ով․ եթե IUse%-ը 100% է, ֆայլային համակարգին վերջացել են ֆայլերի գրառումները, սովորաբար միլիոնավոր փոքրիկ ֆայլերի պատճառով։ Ամենաշատ ֆայլերով դիրեկտորիան գտիր sudo find / -xdev -type f | cut -d/ -f2-4 | sort | uniq -c | sort -rn | head-ով։ Տիպիկ մեղավորներն են PHP session ֆայլերն առանց garbage collection-ի, cache դիրեկտորիաները կամ mail queue-երը։ Հիները ջնջիր find -mtime +2 -delete-ով ճիշտ դիրեկտորիայում։ Հետո շտկիր պատճառը․ միացրու session-ների garbage collection-ը կամ session-ները տեղափոխիր Redis, ավելացրու մաքրման timer և alert դիր inode-ների օգտագործման վրա՝ տեղի հետ մեկտեղ։ Նոր ֆայլային համակարգերի համար, որոնք պահելու են հսկայական քանակությամբ փոքր ֆայլեր, inode ratio-ն ընտրիր mkfs-ի ժամանակ։

Արագ ուղեցույց

Ավարտել ընդհատված փաթեթի տեղադրումը
sudo dpkg --configure -a && sudo apt -f install
Որ փաթեթին է պատկանում ֆայլը
dpkg -S /usr/bin/curl
Սառեցնել / ապասառեցնել փաթեթի տարբերակը
sudo apt-mark hold nginx / sudo apt-mark unhold nginx
Մեծացնել partition-ը և ext4 ֆայլային համակարգը
sudo growpart /dev/vda 1 && sudo resize2fs /dev/vda1
Ամենաշատ ֆայլերով դիրեկտորիաները (inode-ներ)
sudo du --inodes -x -d 2 / | sort -n | tail
Սկավառակի latency ըստ սարքի
iostat -x 1 3
I/O անող պրոցեսները
sudo iotop -oPa
Նախորդ boot-ի log-երը
journalctl -b -1 -p warning
Հիմա փոքրացնել journal-ը
sudo journalctl --vacuum-time=14d
Ստիպողաբար գործարկել logrotate-ը կանոնը փորձարկելու համար
sudo logrotate -vf /etc/logrotate.d/myapp

Իմ իրական նախագծերում

  • Մեկ սերվերի սկավառակի զբաղվածությունը 91%-ից իջեցրի 66%-ի՝ մաքրելով հին log-երը, հին build-երը և չափազանց մեծ node_modules-ները, և դրանից հետո ստուգեցի դրա backup-ները։
  • unattended-upgrades-ը և սկավառակի, load-ի ու uptime-ի monitoring-ը այն baseline-ի մեջ են, որը կիրառում եմ բոլոր սերվերների վրա։
  • Սերվերներիս վրա cron-ով եմ գործարկում Laravel-ի scheduler-ը։
  • POS SaaS սերվերի վրա log-երը կենտրոնացված հավաքվում են Loki-ով և վիզուալացվում Grafana-ում՝ Prometheus-ի մետրիկաների կողքին։

Հարցեր և պատասխաններ

Q1Ո՞րն է տարբերությունը apt update-ի և apt upgrade-ի միջև։

apt update-ը միայն ներբեռնում է փաթեթների թարմ ցուցակները կարգավորված repository-ներից, որպեսզի apt-ն իմանա, թե որ տարբերակներն են գոյություն ունեն։ Այն ոչ մի ծրագիր չի փոխում։ apt upgrade-ը հետո տեղադրում է արդեն տեղադրված փաթեթների նոր տարբերակները՝ ոչինչ չհեռացնելով։ apt full-upgrade-ը գնում է ավելի հեռու և կարող է տեղադրել նոր dependency-ներ կամ հեռացնել փաթեթներ upgrade-ն ավարտելու համար, ինչը պետք է kernel-ի և որոշ գրադարանների թարմացումներին։ Այնպես որ նորմալ հաջորդականությունն է՝ update, հետո upgrade։ Production-ում նախ դիտում եմ apt list --upgradable-ը, մեծ փոփոխություններից առաջ snapshot եմ անում և թողնում եմ, որ unattended-upgrades-ը ամեն օր մշակի սովորական անվտանգության շտկումները։ Ubuntu-ի թողարկումների միջև անցումը առանձին, պլանավորված do-release-upgrade է։

Q2Production սերվերի սկավառակը լցված է։ Ի՞նչ կանես։

Նախ կայունացնում եմ․ df -h՝ տեսնելու, թե որ ֆայլային համակարգն է լցված, և df -i՝ inode-ների սպառումը բացառելու համար։ Հետո պատճառը գտնում եմ du -xh --max-depth=1-ով՝ դասավորված ըստ չափի, խորանալով ամենամեծ դիրեկտորիաների մեջ, կամ ncdu-ով։ Սովորական մեղավորներն են առանց rotation-ի log-երը, journal-ը, Docker image-ները և build cache-ը, հին release դիրեկտորիաները և մոռացված տվյալների բազայի dump-երը։ Տեղն ազատում եմ անվտանգ․ կենդանի log-երը truncate եմ անում ջնջելու փոխարեն, vacuum եմ անում journal-ը, prune եմ անում Docker-ը, հեռացնում եմ հին release-ները։ Եթե տեղը չի վերադառնում, lsof +L1-ը ցույց է տալիս ջնջված ֆայլերը, որոնք պրոցեսը դեռ բաց է պահում։ Դրանից հետո շտկում եմ արմատական պատճառը logrotate կանոններով, journal-ի սահմանափակումներով և սկավառակի alert-ով։

Q3Ինչո՞ւ է իմ cron job-ը աշխատում տերմինալում, բայց ոչ cron-ից։

Cron-ը հրամանները գործարկում է նվազագույն environment-ով։ PATH-ը պարունակում է միայն մի քանի համակարգային դիրեկտորիա, քո .bashrc-ն կամ .profile-ը չի բեռնվում, աշխատանքային դիրեկտորիան օգտատիրոջ home-ն է, և այն օգտագործում է /bin/sh, ոչ թե bash, եթե այլ բան չնշես։ Այդ պատճառով այլ տեղերում տեղադրված node-ի կամ php-ի նման հրամանները չեն գտնվում, հարաբերական ճանապարհները կոտրվում են, և environment փոփոխականները բացակայում են։ Շտկիր բինար ֆայլերի և ֆայլերի բացարձակ ճանապարհներով, cd արա ճիշտ դիրեկտորիա, անհրաժեշտ փոփոխականները սահմանիր crontab-ում կամ wrapper script-ում և output-ը միշտ վերաուղղորդիր log >> file 2>&1-ով, որպեսզի տեսնես սխալները։ Ստուգիր նաև ժամային գոտին։

Q4Ինչպե՞ս կանխել, որ log-երը լցնեն սկավառակը։

Տեքստային log ֆայլերի համար յուրաքանչյուր հավելվածի համար ավելացնում եմ logrotate կանոն՝ rotation ամեն օր կամ ամեն շաբաթ, ֆայլերի ֆիքսված քանակ, հների սեղմում, և copytruncate կամ postrotate signal, որպեսզի հավելվածը շարունակի գրել նոր ֆայլում։ systemd journal-ի համար journald.conf-ում սահմանում եմ SystemMaxUse, որպեսզի այն մնա չափի սահմանի տակ։ Հավելվածները production-ում պետք է խուսափեն debug մակարդակի logging-ից։ Երկարաժամկետ կարևոր ամեն ինչի համար log-երը պետք է ուղարկվեն կենտրոնական համակարգ, ինչպես Loki-ն կամ hosted ծառայություն, որպեսզի սերվերը լոկալ պահի միայն կարճ պատուհան։ Իսկ սկավառակի զբաղվածության alert-ը բռնում է այն, ինչ կանոնները բաց են թողնում։

Q5free-ը ցույց է տալիս գրեթե զրո ազատ հիշողություն։ Սերվերը խնդրի մե՞ջ է։

Սովորաբար՝ ոչ։ Linux-ը այլապես պարապ RAM-ն օգտագործում է որպես ֆայլերի page cache, ինչը արագացնում է սկավառակից կարդալը, և անմիջապես ազատում է այն, երբ հավելվածներին հիշողություն է պետք։ Այդ cache-ը երևում է որպես used, ուստի առողջ մեքենայի վրա free սյունը փոքր է թվում։ Հետևելու թիվը available-ն է, որը գնահատում է, թե որքան հիշողություն կարելի է տալ նոր աշխատանքին առանց swap-ի։ Իրական խնդիրը նման է ցածր available հիշողության, կայուն swap ակտիվության, բարձր I/O wait-ով աճող load-ի կամ OOM killer-ի հաղորդագրությունների journalctl -k-ում։ Այդ դեպքում փնտրում եմ աճած պրոցեսը, օրինակ՝ leak կամ չկարգավորված տվյալների բազա, մինչև պարզապես ավելի շատ RAM գնելը։

Q6Սերվերը պե՞տք է swap ունենա։

Փոքր և միջին VPS instance-ների մեծ մասում՝ այո, համեստ քանակով, սովորաբար մոտ 1-ից 2 GB։ Այն գործում է որպես անվտանգության buffer․ հիշողության կարճ պոռթկումը սերվերը դանդաղեցնում է OOM killer-ին trigger անելու փոխարեն, որը կարող էր սպանել տվյալների բազան։ Այն նաև թույլ է տալիս kernel-ին հազվադեպ օգտագործվող էջերը RAM-ից դուրս տեղափոխել։ Բայց swap-ը լրացուցիչ հիշողություն չէ․ սկավառակը շատ ավելի դանդաղ է, քան RAM-ը։ Եթե սերվերը անընդհատ swap է անում, այն թույլ է կամ հավելվածը leak ունի, և լուծումն ավելի շատ RAM-ն է կամ կարգավորումը։ Որոշ setup-ներ, ինչպես Kubernetes node-երը կամ latency-ի նկատմամբ կրիտիկական տվյալների բազաները, միտումնավոր աշխատում են առանց swap-ի կամ շատ ցածր swappiness-ով։

Սենիոր մակարդակի հարցեր

S1Ինչպե՞ս ես հավասարակշռում ավտոմատ թարմացումները և կայունությունը production սերվերներում։

Ես առանձնացնում եմ ռիսկի մակարդակները։ Դիստրիբուտիվի security pocket-ի անվտանգային թարմացումները կիրառվում են ավտոմատ ամեն օր unattended-upgrades-ով, քանի որ բաց թողնված հայտնի խոցելիությունն ավելի մեծ ռիսկ է, քան լավ փորձարկված security patch-ը։ Feature և point թարմացումները, երրորդ կողմի repository-ները, ինչպես database-ները կամ runtime-ները, և այն ամենը, ինչ պահանջում է կրիտիկական ծառայության restart, անցնում են պլանավորված պատուհանով՝ նախ staging, snapshot, հետո production։ Փաթեթները, որոնք պետք է շարժվեն հավելվածի հետ համաքայլ, օրինակ՝ database-ի major տարբերակը, pin կամ hold են արվում։ Kernel-ի թարմացումների համար ես կամ թույլ եմ տալիս ավտոմատ reboot հանգիստ ժամին, եթե հավելվածը հանդուրժում է կարճ restart, կամ հետևում եմ /var/run/reboot-required-ին և reboot անում գիտակցաբար։ Ամբողջ fleet-ի մակարդակով թարմացումները սերվերների միջև աստիճանաբար եմ անում, որպեսզի վատ թարմացումը երբեք միանգամից ամեն ինչին չհարվածի։

S2Database սերվերը դանդաղ է, և iowait-ը բարձր է։ Ինչպե՞ս ես պարզում՝ արդյոք storage-ն է bottleneck-ը։

Ես հաստատում եմ դա թվերով՝ մինչև որևէ բան tune անելը։ vmstat-ը ցույց է տալիս արգելափակված պրոցեսները և wa-ն, iostat -x-ը՝ ըստ սարքի կարդալու և գրելու latency-ն և հերթի չափը։ Ցանցով միացված cloud volume-ների վրա համեմատիր դիտարկված IOPS-ը և throughput-ը plan-ի փաստաթղթավորված սահմանների հետ, քանի որ provider-ի cap-ին հասնելը ճիշտ դանդաղ սկավառակի տեսք ունի։ pidstat -d-ն կամ iotop-ը հաստատում են, որ I/O անողը database-ն է, իսկ /proc/pressure/io-ն ցույց է տալիս, թե որքան ժամանակ են task-երը կանգնած։ Հետո ստուգում եմ պատճառը database-ի կողմից․ բացակայող index-ներ, որոնք full scan են առաջացնում, working set-ի համար չափազանց փոքր buffer pool, ուստի կարդալը գնում է սկավառակ, կամ checkpoint կամ backup job, որը հագեցնում է գրառումները։ Լուծումները տատանվում են query-ների և հիշողության tuning-ից մինչև տեղական NVMe կամ ավելի բարձր IOPS tier։

S3Ի՞նչ կպահես սերվերի սկավառակի վրա, և ի՞նչ կտեղափոխես դրանից դուրս։

Սերվերի սկավառակը համարում եմ փոխարինելի։ Այն պահում է օպերացիոն համակարգը, հավելվածի release-ը, կարճաժամկետ cache-երը, տեղական log-երի կարճ պատուհանը և database-ի ֆայլերը, եթե database-ը self-hosted է։ Այն ամենը, ինչի կորուստը ցավոտ կլինի, գնում է այլ տեղ՝ օգտատերերի upload-ները S3-համատեղելի object storage, database-ի backup-ները object storage այլ provider-ի կամ տարածաշրջանի մոտ, իսկ log-երը ուղարկվում են կենտրոնական համակարգ։ Դա սկավառակը դարձնում է փոքր և կանխատեսելի, ուստի այն հազվադեպ է լցվում, և սերվերի վերակառուցումը դառնում է provisioning-ի և տվյալների վերականգնման հարց, ոչ թե «ընտանի կենդանու» մեքենան փրկելու։ Գինը object storage-ի լրացուցիչ latency-ն և egress-ն է, ավելի շատ շարժվող մասերը և այդ ծառայությունների credential-ները անվտանգ կառավարելու անհրաժեշտությունը։

Բառարան

dpkg
Debian-ի ցածր մակարդակի փաթեթային գործիքը, որը տեղադրում է .deb ֆայլերը և հետևում դրանց վիճակին։ apt-ը կանչում է այն։
deb822 sources
apt repository ֆայլերի (.sources) կառուցվածքային key-value ֆորմատը, Ubuntu-ում լռելյայն՝ 24.04-ից։
Pinning
apt preference-ներ, որոնք առաջնահերթություններ են տալիս repository-ներին կամ տարբերակներին՝ կառավարելով, թե որ տարբերակն է տեղադրվում։
Phased updates
Ubuntu-ի ոչ անվտանգային թարմացումների աստիճանական տարածումը մեքենաների աճող մասի վրա՝ regression-ները շուտ բռնելու համար։
Reserved blocks
ext4-ի տեղ, լռելյայն 5%, որը միայն root-ը կարող է օգտագործել՝ համակարգը օգտագործելի պահելով, երբ սկավառակը լցվում է։
Inode exhaustion
Ֆայլային համակարգում ֆայլերի գրառումների վերջանալը, մինչդեռ ազատ տեղ դեռ կա, սովորաբար միլիոնավոր փոքրիկ ֆայլերի պատճառով։
LVM
Logical Volume Manager․ շերտ, որը սկավառակները միավորում է volume-ների մեջ, որոնք կարելի է resize անել, տարածել և snapshot անել։
Page cache
RAM, որը kernel-ն օգտագործում է ֆայլերի տվյալները cache անելու և գրառումները բուֆերացնելու համար․ ազատվում է, երբ հավելվածներին հիշողություն է պետք։
I/O wait
CPU-ի պարապ ժամանակ, մինչ պրոցեսները սպասում են սկավառակին։ Բարձր արժեքները ցույց են տալիս, որ bottleneck-ը storage-ն է, ոչ թե CPU-ն։
Log shipping
Log-երի ուղարկումը սերվերներից կենտրոնական պահոց agent-ի միջոցով, որպեսզի դրանք որոնելի լինեն և դիմանան սերվերի կորստին։

Պրոդուկտի գաղափար ունե՞ք։Եկեք ստեղծենք այն։

Պատմեք ձեր գաղափարի, պրոդուկտի կամ թիմի մասին։ Սովորաբար պատասխանում եմ մեկ աշխատանքային օրվա ընթացքում։