நான் கன்டெய்னர்களைப் புரிந்து கொண்டதாக நினைத்தேன். பின்னர் நானே ஒன்றை உருவாக்க முயன்றேன்.

நான் கன்டெய்னர்களைப் புரிந்து கொண்டதாக நினைத்தேன். பின்னர் நானே ஒன்றை உருவாக்க முயன்றேன்.

பூஜ்ஜியத்திலிருந்து உருவாக்குவது பாடப்புத்தகங்கள் தவிர்க்கும் விஷயங்களை எவ்வாறு வெளிப்படுத்துகிறது

தெரிந்துகொள்வதற்கும் உருவாக்குவதற்கும் இடையிலான இடைவெளி

நீங்கள் Docker தேர்வில் தேர்ச்சி பெறலாம், சரியான சொற்களை மனப்பாடமாகச் சொல்லலாம்—namespaces, cgroups, images, layers, PID 1, Kubernetes Pods—ஆனாலும், ஒரு கன்டெய்னரை உருவாக்க முயலும் போது நீங்கள் என்ன செய்கிறீர்கள் என்பதில் எந்த அறிவும் இல்லாமல் இருக்கலாம். DEV Community-யில் சமீபத்தில் தனது கதையைப் பகிர்ந்த ஒரு உருவாக்காளரிடமிருந்து கிடைத்த பாடம் இதுவாகும்; மேலும் இது கோட்பாடும் நடைமுறையும் வெவ்வேறு உலகங்களில் வாழ்கின்றன என்பதை நினைவூட்டுகிறது. கன்டெய்னராக்கம் (containerization) இப்போது எங்கும் நிறைந்துள்ளது என்பதால் இது முக்கியமானது—Docker, Kubernetes மற்றும் ஆயிரம் பயன்பாட்டு அமைப்புகள் (deployment systems) நீங்கள் நிகழ்நேரத்தில் அவற்றை எதிர்கொள்ளும் வரை அருவமாக (abstract) தோன்றும் கருத்துக்களை அடிப்படையாகக் கொண்டுள்ளன.

முதல் கட்டளை: ஒரு அடக்கமான தொடக்கம்

இது எளிமையாகத் தொடங்கியது: புதிய namespace-இல் ஒரு செயல்முறையை (process) பின்வரும் unshare கட்டளையைப் பயன்படுத்தி இயக்க முயற்சிப்பது. முதல் முயற்சி:

bash sudo unshare -p 1 test

பிழை: unshare: failed to execute 1: No such file or directory

flags தவறாக இருந்தன. கட்டளையானது "1" என்ற பெயருடைய நிரலை இயக்குமாறு கணினியைக் கேட்டது, ஆனால் அப்படி ஒன்று இல்லை. எதையும் உருவாக்குவதற்கு முன், உண்மையான சிக்கல்களை அடைவதற்கு முன்பே, என்ன நடக்க வேண்டும் என்பதில் விசைப்பலகைக்கும் ஆவணங்களுக்கும் இடையே வெவ்வேறு கருத்துக்கள் இருந்தன.

பகுதி 1: Namespaces மற்றும் PID 1

முதல் உண்மையான முயற்சி என்னவென்றால், ஒரு செயல்முறையை புதிய PID (process ID) namespace-இல் இயக்கி, அது தன்னை PID 1—செயல்முறை மரத்தின் (process tree) வேராகப் பார்ப்பதை நிரூபிப்பதாகும். எனவே கட்டளை இயக்கப்பட்டது:

bash sudo unshare --pid bash

பின்னர் அந்த shell-க்குள்:

bash echo $$

எதிர்பார்க்கப்பட்ட வெளியீடு: 1. உண்மையான வெளியீடு: 25184.

இது வேலை செய்யவில்லை. அது PID 1 அல்ல; அது host-இலிருந்து வந்த தாய் செயல்முறை ID (parent process ID) மட்டுமே. விதி எளிமையானது ஆனால் இயல்புக்கு மாறானது: PID namespaces குழந்தை செயல்முறைகளுக்குப் (child processes) பொருந்தும், மாறாக பின்வரும் கட்டளையை அழைக்கும் செயல்முறைக்கு அல்ல unshare. நீங்கள் fork செய்ய வேண்டும். புதிய namespace-க்குள் பிறக்கும் முதல் குழந்தை PID 1 ஆகிறது.

எனவே வேலை செய்யும் பதிப்பு:

bash sudo unshare --pid --fork bash echo $$

இப்போது வெளியீடு 1 ஆக இருந்தது. shell தன்னை செயல்முறை மரத்தின் வேராக நினைத்தது. உள்ளிருந்து பார்க்கும்போது எல்லாமே வித்தியாசமாகத் தோன்றியது.

அடுத்து எதிர்பாராத ஆச்சரியம் வந்தது. உள்ளிருந்து பின்வருவனவற்றை இயக்குவது ps காட்டியது:

PID PPID COMMAND 25310 25304 bash 25344 25310 ps

ஆனால் shell தான் PID 1 என்று கூறியது. அதில் எந்த அர்த்தமும் இல்லை. உண்மை வெளிப்பட்டது: ps kernel-இடம் "என்னென்ன செயல்முறைகள் உள்ளன?" என்ற தூய கேள்வியைக் கேட்பதில்லை. அது கோப்புகளைப் படிக்கிறது. ஒருவேளை /proc இன்னும் host-இன் செயல்முறை கோப்புமுறைமையைச் சுட்டிக்காட்டினால், உங்கள் கருவிகள் உங்களிடம் பொய் சொல்லும். அவை host-இன் எண் முறையைக் காட்டும்.

இதற்கான தீர்வு மீண்டும் mount செய்வதாகும் /proc namespace-க்கு உள்ளிருந்து:

bash mount -t proc proc /proc ps -o pid,ppid,comm

இப்போது அது காட்டியது:

PID PPID COMMAND 1 0 bash 7 1 ps

அந்த தருணத்தில்தான் விஷயம் புரிந்தது. namespace உண்மையான தனிமைப்படுத்தலை வழங்கியது, ஆனால் கோப்புமுறைமைக் காட்சி மாறும் வரை கருவிகளால் அதைப் பார்க்க முடியவில்லை. தனிமைப்படுத்தலும் (isolation) தெளிவுத்தன்மையும் (visibility) வெவ்வேறு விஷயங்கள்.

hostname-ஐக் கட்டுப்படுத்தும் UTS namespace—புரிந்துகொள்ள எளிதாக இருந்தது. Host-இல் பின்வருவனவற்றை இயக்குவது hostname ஒரு பெயரைக் காட்டியது. புதிய UTS namespace-க்குள் (பின்வருவனவற்றுடன் உருவாக்கப்பட்டது sudo unshare --uts bash), அதை மாற்றுவது வேறு ஒன்றைக் காட்டியது. மீண்டும் host-க்கு வந்ததும், அது மூலப் பெயருக்கே மாறியது. ஒரு கணினி, ஒரு kernel, மூன்று வெவ்வேறு காட்சிகள்.

பகுதி 2: கோப்புமுறைமை கையளிப்பு (Filesystem Handoff)

namespaces-க்கு பிறகு, அடுத்த பதிப்பு செயல்முறைக்கு அதன் சொந்த கோப்புமுறைமையை வழங்க வேண்டியிருந்தது: BusyBox மற்றும் ஒரு shell கொண்ட rootfs (root filesystem). இது மிகவும் கன்டெய்னர் போன்றது.

முதல் பிழை எளிமையானது:

exec /bin/sh: no such file or directory

நிரல் குறிப்பிட்ட இடத்தில் shell இருக்கவில்லை. அது சரி செய்யப்பட்டது. ஆனால் அதன் பிறகு:

./rootfs/bin/busybox: cannot execute: required file not found

இந்த பிழை மிகவும் கொடூரமானது, ஏனெனில் கோப்பு அங்கேயே உள்ளது. உங்களால் அதை பட்டியலிட முடியும். பார்க்க முடியும். ஆனாலும் kernel அதை இயக்க மறுக்கிறது. பின்வரும் file கட்டளையைப் பயன்படுத்தியபோது உண்மை தெரியவந்தது:

ELF 64-bit LSB pie executable, ARM aarch64, dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, stripped

binary அங்கேயே இருந்தது. அதற்குத் தேவையான interpreter—dynamic linker—பழைய உலகத்திலிருந்து கிடைக்கவில்லை. கோப்பு இல்லை என்று Linux சொல்லவில்லை. "இங்கிருந்து, இந்த ELF-க்கு தேவையான interpreter-ஐ என்னால் ஏற்ற முடியாது" என்று அது கூறியது.

BusyBox-ஐ static ஆக மாற்றுவது தீர்வாக இருக்கவில்லை. Alpine-ஐ புதிய root கோப்புமுறைமையாக மாற்றுவதே தீர்வாக இருந்தது, இதனால் interpreter சரியான பாதையில் இருக்கும். ஆனால் முதலில், இந்த மாற்றத்திற்கு ஒரு பாலம் தேவைப்பட்டது—கோப்புமுறைமை மாற்றத்திற்கு முன்பும் மாற்றத்தின் போதும் இயங்கக்கூடிய ஒரு கருவி. BusyBox இரண்டு வடிவங்களில் வந்தது: Alpine-க்குள் பயன்படுத்துவதற்கு ஒன்று dynamic, மற்றொன்று கையளிப்பிற்கான (handoff) static வடிவம்:

bash /bin/busybox pivot_root . put_old

static BusyBox இயக்கக்கூடிய முக்கிய காரணியாக இருந்தது pivot_root கணினி உலகங்களை முழுமையாக மாற்றுவதற்கு முன்பு.

Alpine புதிய root ஆக மாறிய பிறகு, மேலும் பல ஆச்சரியங்கள் தோன்றின. பழைய கோப்புமுறைமையின் கட்டளைப் பாதைகளை Bash இன்னும் நினைவில் வைத்திருந்தது. அது பின்வருவனவற்றை இயக்க முயன்றபோது mount, அது பின்வரும் இடத்தைத் தேடியது /usr/bin/mount சமீபத்தில்தான் வெளியேற்றப்பட்ட ஒரு உலகில்:

bash: /usr/bin/mount: No such file or directory

இதற்கான தீர்வு hash -r, இது கட்டளை சேமிப்பகத்தை (command cache) அழிக்கிறது. Bash பழைய உலகில் ஒரு முடிவை எடுத்தது, அதிலிருந்து மீள முடியவில்லை.

பகுதி 3: Mac சிக்கல்

இந்த அமைப்பு ஒரு சாதாரண Linux மடிக்கணினி அல்ல. அது Apple Silicon Mac → சலுகை பெற்ற (privileged) Ubuntu container → macOS-இலிருந்து mount செய்யப்பட்ட repo. யாராவது விரும்பினாலும் விரும்பாவிட்டாலும், virtiofs (மெய்நிகராக்கத்திற்கான கோப்புமுறைமை பாஸ்த்ரூ) இதில் ஈடுபட்டிருந்தது என்று அர்த்தம்.

இப்போது root கோப்புமுறைமையாக இருந்த Alpine-க்குள், symlinks வழியாக இயக்குவது Mac-பகிரப்பட்ட mount-இல் "Permission denied" உடன் தோற்கக்கூடும், அதே வேளையில் BusyBox-ஐ நேரடியாக அழைப்பது வேலை செய்தது:

bash ls

sh: ls: Permission denied

/bin/busybox ls

(வேலை செய்கிறது)

கோப்புகள் அங்கேயே இருந்தன. அந்த symlinks வழியாக இயக்குவதுதான் விசித்திரமான பகுதியாக இருந்தது. இதற்கான தீர்வு சலிப்பான ஆனால் சரியான ஒன்று: rootfs-ஐ ஒரு கன்டெய்னர்-சார்ந்த சொந்தப் பாதைக்கு (container-native path) நகர்த்தி அங்கிருந்து முயற்சிக்கவும். ஒரு Mac-பகிரப்பட்ட mount-ஐ சாதாரண Linux போல செயல்படுமாறு நிர்ப்பந்திக்க வேண்டாம்.

பகுதி 4: pivot_root-இன் கடுமையான நிபந்தனைகள்

இவ்வளவு விஷயங்களுக்குப் பிறகும், pivot_root கற்பிப்பதை நிறுத்தவில்லை. பிழை:

pivot_root: invalid argument

புதிய root ஒரு mount point ஆக இருக்க வேண்டும். பழைய root செல்வதற்கு ஒரு இடம் தேவைப்பட்டது. எனவே பின்வரும் சடங்கு பின்பற்றப்பட்டது:

  1. புதிய root-ஐ அதன் மீதே Bind-mount செய்யவும்
  2. ஒரு oldroot கோப்பகத்தை (directory) உருவாக்கவும்
  3. பின்வருவனவற்றை அழைக்கவும் pivot_root(newroot, oldroot)
  4. கோப்பகத்தை (directory) புதிய root-க்கு மாற்றவும்
  5. பழைய root-ஐ Unmount செய்யவும்

இறுதியில் அது வேலை செய்தபோது, அதற்கான வெகுமதி சிறியதாகவும் முழுமையாகவும் இருந்தது:

bash cat /etc/os-release NAME="Alpine Linux" ID=alpine VERSION_ID=3.24.1

வெறும் ஒரு உரைக்கோப்பு. ஆனால் இப்போது அது கன்டெய்னர் வேலை செய்தது என்பதற்கான சான்றாக இருந்தது.

முடிவுரை

பூஜ்ஜியத்திலிருந்து ஒரு கன்டெய்னரை உருவாக்குவது ஒரு பயிற்சிநெறி ஒருபோதும் கற்றுத்தர முடியாத ஒன்றைக் கற்றுத் தருகிறது: கோட்பாட்டை அறிவதற்கும் அது நிகழ்நேரத்தில் தோற்பதைப் பார்ப்பதற்கும் இடையே உள்ள தூரம். Namespaces, cgroups மற்றும் பிற விஷயங்கள் உண்மையானவை. ஆவணப்படுத்தப்பட்டபடியே அவை சரியாக வேலை செய்கின்றன. ஆனால் "நான் இதைப் புரிந்துகொள்கிறேன்" என்பதிலிருந்து "என்னால் இதை வேலை செய்ய வைக்க முடியும்" என்பதற்கான பாதை பிழைச் செய்திகள், Bash caches, கோப்புமுறைமை அனுமதிகள், மற்றும் கோப்புமுறைமை சரியாக இல்லாவிட்டால் உங்கள் கருவிகள் உங்களிடம் பொய் சொல்லும் என்ற புரிதல் வழியே செல்கிறது.

நன்மைகள்

  • நேரடி அனுபவக் கற்றல் (hands-on learning), வெறும் படிப்பால் பெற முடியாத புரிதலை ஆழமாகப் பதிக்கிறது
  • உண்மையான பிழைகள் ஆவணங்கள் பெரும்பாலும் தவிர்க்கும் வரம்புகளைக் (constraints) கற்றுத் தருகின்றன
  • பூஜ்ஜியத்திலிருந்து உருவாக்குவது நவீன கன்டெய்னர் கருவிகள் சிக்கலான தன்மையை எவ்வாறு மறைக்கின்றன என்பதை வெளிப்படுத்துகிறது
  • Namespaces, கோப்புமுறைமைகள் மற்றும் interpreters ஆகியவற்றைப் புரிந்துகொள்வது Docker மற்றும் Kubernetes பற்றிய புதிர் தன்மையைக் குறைக்கிறது

குறைபாடுகள்

  • கற்றல் வளைவு (learning curve) செங்குத்தானது மற்றும் பல சிறிய, குழப்பமான பிழைகளை உள்ளடக்கியது
  • சூழ்நிலை காரணிகள் (macOS-இல் உள்ள virtiofs போன்றவை) கணிக்க முடியாத சிக்கல்களைச் சேர்க்கின்றன
  • Docker-ஐ நேரடியாகப் பயன்படுத்துவதுடன் ஒப்பிடும்போது இந்த செயல்முறை மெதுவானது
  • பல விளிம்பு நிலைகள் (Bash hash caching, symlink permissions) ஆவணங்களிலிருந்து தெளிவாகத் தெரிவதில்லை

எச்சரிக்கை

இந்தக் கட்டுரை கல்வி நோக்கத்திலானது மற்றும் அடிப்படை விதிகளிலிருந்து (first principles) கன்டெய்னர்களை உருவாக்குவதில் உள்ள உண்மையான கற்றலை விவரிக்கிறது. காட்டப்பட்டுள்ள கட்டளைகளும் கருத்துகளும் மூலப் பொருளுக்குத் துல்லியமாக உள்ளன. இது உற்பத்தி நிலைக் (production-grade) கன்டெய்னர் ரன்டைம் அல்ல; கன்டெய்னர்கள் எவ்வாறு செயல்படுகின்றன என்பதைப் புரிந்துகொள்வதற்கான ஒரு கற்பித்தல் கருவியாகும். உற்பத்தியில் எந்தவொரு கன்டெய்னர் அமைப்பையும் நம்புவதற்கு முன், அதிகாரப்பூர்வ ஆவணங்கள் மற்றும் சிறந்த நடைமுறைகளைக் கலந்தாலோசிக்கவும். உங்கள் சூழலில் எதையும் செயல்படுத்துவதற்கு முன் அனைத்துக் கூற்றுகளையும் மூல ஆதாரத்துடன் சரிபார்க்கவும்.

அடிக்கடி கேட்கப்படும் கேள்விகள்

  • PID namespace என்றால் என்ன மற்றும் கன்டெய்னர்களில் இது ஏன் முக்கியமானது?
  • unshare-ஐ அழைக்கும் செயல்முறை ஏன் தானாகவே PID 1 ஆக மாறாது?
  • /proc கோப்புமுறைமைக்கும் கன்டெய்னர்களுக்கும் என்ன தொடர்பு?
  • pivot_root எவ்வாறு chroot-லிருந்து வேறுபடுகிறது?
  • /proc-ஐ மீண்டும் mount செய்வது ps காட்டியதை ஏன் மாற்றியது?
  • கன்டெய்னர் உருவாக்கத்தில் BusyBox-இன் பங்கு என்ன?
  • புதிய root கோப்புமுறைமைக்கு மாறும்போது dynamic interpreters ஏன் முக்கியம்?
  • macOS-இல் கன்டெய்னர் அமைப்பை virtiofs எவ்வாறு சிக்கலாக்குகிறது?

டேகுகள்

#containers #linux #docker #devops #namespaces #cgroups #filesystem #learning

Free field guide

API Security Testing Checklist

A practical workflow for testing authentication, authorization, input handling, business logic, and evidence without losing track of scope.