5 पॉइंट द्वारा GN⁺ 2023-06-29 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • Docker जिन कंटेनरों को abstract करके आसान बनाता है, उनकी बुनियाद Linux namespaces, cgroups और chroot कमांड से खुद जोड़कर यह देखा जाता है कि isolation और execution environment कैसे बनते हैं
  • लक्ष्य Docker का विकल्प बनाना नहीं, बल्कि उसके सिद्धांत को समझना है; इसलिए layered images, networking, orchestration और व्यापक operations tools को इसमें लागू नहीं किया गया है
  • isolation की शुरुआत unshare --uts --pid --net --mount --ipc --fork से होती है, जो UTS, PID, network, mount और IPC namespaces को अलग करता है
  • resource control के लिए /sys/fs/cgroup/cpu/container1 में cgroup बनाया जाता है और cpu.cfs_quota_us तथा tasks सेट करके मौजूदा shell और child processes को CPU limit के दायरे में रखा जाता है
  • debootstrap से Ubuntu 20.04 Focal Fossa root file system बनाया जाता है, फिर /proc, /sys, /dev को mount करके chroot के अंदर Nginx install और run किया जाता है

इस प्रैक्टिस का उद्देश्य और दायरा

  • Docker, Linux namespaces, cgroups और chroot का उपयोग करके isolation, resource management और security देता है
  • यह प्रैक्टिस theory से ज़्यादा वास्तविक command flow पर फोकस करती है और Docker जैसे एक बुनियादी container environment को हाथ से बनाती है
  • लक्ष्य Docker की पूरी functionality को दोहराना नहीं, बल्कि यह समझना है कि containerization की core foundational technologies आपस में कैसे काम करती हैं
  • Docker की निम्नलिखित features इस प्रैक्टिस के दायरे में शामिल नहीं हैं
    • layered images
    • networking
    • container orchestration
    • व्यापक deployment और operations tools

चरण 1: namespaces से isolation environment बनाना

  • नया isolated environment unshare कमांड से शुरू होता है
unshare --uts --pid --net --mount --ipc --fork
  • दिए गए namespaces कंटेनर को अलग system identifiers और resource instances देते हैं
    • --uts
    • --pid
    • --net
    • --mount
    • --ipc
  • unshare कमांड के बारे में विस्तार से man page में देखा जा सकता है

चरण 2: cgroups से CPU usage सीमित करना

  • cgroups containerized processes के लिए system resources के allocation और usage को नियंत्रित करते हैं
  • उदाहरण में container1 नाम का नया cgroup बनाकर CPU quota limit सेट की जाती है
mkdir /sys/fs/cgroup/cpu/container1
echo 100000 > /sys/fs/cgroup/cpu/container1/cpu.cfs_quota_us
echo 0 > /sys/fs/cgroup/cpu/container1/tasks
echo $$ > /sys/fs/cgroup/cpu/container1/tasks
  • पहली पंक्ति /sys/fs/cgroup/cpu/ के नीचे container1 directory बनाती है, जिसे कंटेनर के cgroup के रूप में इस्तेमाल किया जाता है
  • दूसरी पंक्ति /sys/fs/cgroup/cpu/container1/cpu.cfs_quota_us में 100000 लिखकर CPU quota limit तय करती है
  • तीसरी पंक्ति tasks फ़ाइल में 0 लिखकर पहले से assigned processes को हटाती है
  • चौथी पंक्ति $$, जो मौजूदा shell या script का PID है, उसे tasks फ़ाइल में लिखती है
    • मौजूदा process container1 cgroup में assign हो जाती है
    • इसके बाद shell या script द्वारा बनाए गए child processes भी उसी cgroup में रहते हैं
    • उन processes का resource usage तय की गई CPU quota limit के अधीन रहता है

चरण 3: root file system बनाना

  • कंटेनर का file system debootstrap से ubuntu-rootfs directory में एक minimal Ubuntu environment install करके बनाया जाता है
debootstrap focal ./ubuntu-rootfs http://archive.ubuntu.com/ubuntu/
  • पहला argument focal install की जाने वाली Ubuntu release को बताता है
  • दूसरा argument ./ubuntu-rootfs वह directory है जहाँ Ubuntu environment install होगा
  • तीसरा argument http://archive.ubuntu.com/ubuntu/ installation के लिए इस्तेमाल होने वाला Ubuntu repository URL है
  • debootstrap के बारे में विस्तार से man page में देखा जा सकता है

चरण 4: ज़रूरी file systems mount करना और chroot में प्रवेश

  • कंटेनर root file system के अंदर /proc, /sys, /dev जैसे ज़रूरी file systems mount किए जाते हैं
  • इसके बाद chroot से root directory को कंटेनर file system में बदला जाता है
mount -t proc none ./ubuntu-rootfs/proc
mount -t sysfs none ./ubuntu-rootfs/sys
mount -o bind /dev ./ubuntu-rootfs/dev
chroot ./ubuntu-rootfs /bin/bash
  • proc file system को ./ubuntu-rootfs/proc पर mount किया जाता है
    • यह processes और system resources की जानकारी virtual files के रूप में देता है
    • ./ubuntu-rootfs/ environment के अंदर के processes process-related system information तक पहुँच सकते हैं
  • sysfs file system को ./ubuntu-rootfs/sys पर mount किया जाता है
    • यह devices, drivers और kernel से जुड़ी जानकारी hierarchical structure में देता है
    • अंदर के processes sysfs interface के ज़रिए system-related information तक पहुँच सकते हैं
  • /dev को ./ubuntu-rootfs/dev पर bind mount किया जाता है
    • /dev में physical और virtual devices को दर्शाने वाली device files होती हैं
    • अंदर के environment से access की गई device files host system के संबंधित devices से जुड़ती हैं
    • अंदर के processes ज़रूरी devices को ऐसे इस्तेमाल कर सकते हैं जैसे वे host पर सीधे उपलब्ध हों
  • chroot ./ubuntu-rootfs /bin/bash root directory को ./ubuntu-rootfs/ में बदल देता है, जिसे Docker कंटेनर में docker exec से प्रवेश करने जैसा समझा जा सकता है

चरण 5: कंटेनर के अंदर application चलाना

  • कंटेनर environment तैयार हो जाने पर उसके अंदर applications install और run की जा सकती हैं
  • उदाहरण में Nginx web server install करके यह देखा जाता है कि application कंटेनर के अंदर कैसे चलती है
(container) $ apt update
(container) $ apt install nginx
(container) $ service nginx start
  • पूरी प्रैक्टिस Linux namespaces, cgroups और chroot को मिलाकर एक बुनियादी container environment बनाने का command flow दिखाती है

2 टिप्पणियां

 
GN⁺ 2023-06-29
Hacker News की राय
  • जब भी मैं देखता हूँ कि container इतनी सरल तकनीक है, तो एक बात मन में आती है: अगर मकसद सिर्फ एक single binary चलाना है, तो container के अंदर अभी भी पूरा OS filesystem क्यों चाहिए?
    dependencies या dynamic libraries इसके लिए ठीक कारण हो सकते हैं, लेकिन क्या खाली filesystem से शुरू करके binary को चलाने के लिए जो फाइलें सचमुच ज़रूरी हों उन्हें धीरे-धीरे जोड़ने वाला bottom-up approach ज़्यादा समझदारी भरा नहीं होगा? अभी तो तरीका लगभग उलटा है: एक पूरे OS filesystem से शुरू करो और फिर गैर-ज़रूरी चीजें हटाओ

    • ज़रूरी नहीं कि ऐसा ही हो। ज़्यादातर container builds में यह बस सबसे कम रुकावट वाला रास्ता है, और कई applications को ठीक से चलने के लिए तरह-तरह की support files चाहिए होती हैं। मेरे ज़्यादातर Go containers में सिर्फ दो फाइलें होती हैं: Go binary और CA certificate
      सिद्धांत में bottom-up सही है, लेकिन जैसे ही dynamic loading, plugins और runtime loading support आ जाता है, व्यवहार में इसे करना लगभग नामुमकिन हो जाता है। इसलिए आम तौर पर लोग ऐसे base image से शुरू करते हैं जिसमें ज़रूरी चीजें पहले से हों। BSD jail या chroot भी इसी तरह काम करते हैं, लेकिन complex applications में configuration सचमुच दर्दनाक हो जाती है
    • यह भी ज़रूरी नहीं है। systemd-nspawn में --directory=/ --volatile=yes देने पर ऐसा container बनाया जा सकता है जो अपना root filesystem होस्ट से ही लेता है
      इसमें container root पर tmpfs mount होता है, और host का /usr container के /usr पर read-only mount किया जाता है। container मशीन में इंस्टॉल किए गए सारे software चला सकता है, और writes को tmpfs की ओर redirect कर दिया जाता है
      या --directory=/ की जगह /var/lib/machines/debian-bookworm या /var/lib/machines/fedora-38 जैसी किसी दूसरी directory को दे सकते हैं जिसमें OS image हो। writes हर container के tmpfs में जाती हैं, इसलिए कई containers एक ही image को पारदर्शी तरीके से share कर सकते हैं
      https://0pointer.net/blog/running-an-container-off-the-host-...
    • आजकल ज़्यादातर container build तरीक़े इससे बहुत दूर भी नहीं हैं। आम तौर पर Alpine या slim Debian image इस्तेमाल की जाती है। ऐसे distro images का फ़ायदा यह है कि वे shell जैसी काफ़ी utilities देती हैं, जिनकी container के अंदर कभी ज़रूरत पड़ सकती है
      और हाँ, आपने जो approach बताई वह Nix के काम करने के तरीके से मिलती-जुलती है, और Nix से OCI images भी बनाई जा सकती हैं
    • “पूरा” distro लेकर शुरू न करने वाले छोटे container images बनाने के कई तरीके हैं, लेकिन वे किसी खास उपयोग में काम करेंगे या नहीं, यह application की ज़रूरतों पर निर्भर करता है
      FROM Scratch पूरी तरह खाली image से शुरू करता है, इसलिए यह सबसे छोटा होता है, लेकिन application को support files के बिना चलना आना चाहिए। उदाहरण के लिए, वह statically compiled binary होना चाहिए
      Distroless में standard OS support files थोड़ी मात्रा में होती हैं, लेकिन package manager नहीं होता, इसलिए यह उन मामलों के लिए ठीक है जहाँ बहुत सारे OS packages इंस्टॉल करने की ज़रूरत नहीं होती
      Wolfi अपेक्षाकृत नया है, और खास उद्देश्यों के लिए minimal image ecosystem बना रहा है
    • Docker का मूल विचार यह है कि program को उसके अपने OS के भीतर चलाया जा सके। यह self-contained न होने वाले आम Linux software, यानी ऐसे software जिनकी system dependencies बहुत हों और जो filesystem में इधर-उधर फैले हों, उन्हें deploy करने के तरीके के रूप में लोकप्रिय हुआ
      अगर आपका program ऐसा नहीं है, जैसे ज़्यादातर Rust या Go programs जो statically linked single binary होते हैं, तो शुरू से ही Docker इस्तेमाल करने की बहुत कम वजह है
      आप कह सकते हैं, “फिर भी containerize तो करना है” या “orchestration का क्या?”, और अब ये side effects भी मौजूद हैं, लेकिन अंततः यह ज़्यादा उस स्थिति जैसा है जहाँ सबको app चलाने के लिए लगभग Docker इस्तेमाल करने पर मजबूर कर दिया गया। Docker खराब software के लिए एक workaround है
  • यह लेख ChatGPT से जनरेट किया हुआ लगता है

    • हाँ, इसकी शैली ChatGPT जैसी लगती है। दूसरे लेख के निष्कर्ष भी ChatGPT वाले conclusion style से मेल खाते हैं:

      Remember, namespaces are a powerful feature that requires careful configuration and management. With proper knowledge and implementation, you can harness the full potential of Linux namespaces to create robust and secure systems.
      इस लेख में एक और संकेत यह दिखता है कि सारे links introduction में ही ठूँस दिए गए हैं। GPT आम तौर पर लेख के बीच-बीच में links को स्वाभाविक ढंग से पिरो नहीं पाता
      संपादन: पक्का जानने का कोई तरीका नहीं है, और ChatGPT भी काफ़ी स्मार्ट है, इसलिए मैं अपनी भाषा थोड़ी नरम कर रहा हूँ। आख़िरकार बेहतर यही है कि बात को उसकी अपनी खूबियों और कमियों के आधार पर आँका जाए

    • हाँ, मैं अपने workflow में GPT को एक tool की तरह इस्तेमाल करता हूँ। मैं लोकल में Markdown में ब्लॉग लिखता हूँ, और एक सहायक script इस्तेमाल करता हूँ जो मूल पाठ लेकर prompt के साथ title, summary, intro और conclusion बनाती है, और पूरे मूल पाठ को proofread भी करती है। अब इसने Grammarly को पूरी तरह replace कर दिया है
      मैं इस workflow से काफ़ी संतुष्ट हूँ। कच्चे रूप में विचार उँडेलने के अलावा मुझे ज़्यादा चिंता नहीं करनी पड़ती, इसलिए मैं ज़्यादा बार लिख पाता हूँ
      इसे ऐसे समझिए जैसे Markdown files से static pages बनाकर वेब पर आसानी से deploy करने के लिए Astro या TailwindCSS जैसे tools का इस्तेमाल करना
      https://media.tenor.com/1PMq-CFZno4AAAAC/avengers-endgame-hu...
    • यह लेख पढ़ते समय मुझे काफ़ी झुंझलाहट हुई। ज़्यादातर वाक्य यह नहीं समझाते कि आखिर ये खास commands क्यों ज़रूरी हैं, और सब कुछ सिर्फ जगह भरने जैसा लगा। यह सचमुच LLM output जैसा दिखा
    • सिर्फ इस ब्लॉग पोस्ट में ही नहीं, दूसरी पोस्टों में भी ChatGPT वाली भावना बहुत ज़ोर से आती है
    • संभव है कि इसे जनरेट करने के बाद एडिट किया गया हो
  • Linux kernel-स्तर की सुविधाओं से Docker isolation को दोहराने वाले लेख Docker जितने ही पुराने हैं, और मेरे अनुभव में वे लगभग हमेशा Docker ecosystem के सबसे महत्वपूर्ण हिस्सों में से एक को छोड़ देते हैं। वह है आसानी से hack और extend किए जा सकने वाला container image format
    container-आधारित architecture की लोकप्रियता सिर्फ namespace, cgroup, और chroot का चतुराई से उपयोग करके “मजबूत isolation, resource management, security” बनाने की वजह से नहीं है, बल्कि image format को आसानी से extend कर पाने की वजह से भी है। image format के बिना Docker बहुत कम दिलचस्प होता, और यह कहना भी मुश्किल होता कि “मैंने खुद Docker बना लिया”

    • बिल्कुल यही बात है
      Docker में कई शानदार features हैं, लेकिन इसका killer feature बिना किसी शक के app packaging और deployment है। chroot जैसी सुविधाएँ बहुत पहले से मौजूद थीं, लेकिन वे Docker जितनी लोकप्रिय नहीं हो सकीं, और इसकी वजह है। वे उस समस्या को हल नहीं कर सकीं जिसे ज़्यादातर लोगों को अपने app को containerize करने से पहले पहले सुलझाना पड़ता है
    • इस लेख में हर Docker को containerd से बदल दें, तो बात बिल्कुल फिट बैठती है
  • Bocker की याद आ गई
    [0]: https://github.com/p8952/bocker

  • लेखक ने माना कि उसने यह लेख लिखने में ChatGPT का इस्तेमाल किया, इसे कैसे लेना चाहिए, मैं समझ नहीं पा रहा हूँ
    विषय मेरी दिलचस्पी से बिल्कुल मेल खाता है, लेकिन आगे से मैं संभव हो तो ChatGPT-लिखे लेख नहीं पढ़ना चाहूँगा

    • फिर से समझाऊँ तो, GPT का उपयोग शीर्षक, सारांश, परिचय और निष्कर्ष लिखने में मदद के लिए किया गया। मैं जो सीख रहा था उससे आने वाले विचारों को Markdown फ़ाइल में उँडेलने पर ध्यान देता हूँ, और script के ज़रिए थोड़ा GPT magic छिड़ककर वाक्यों को छोटे और स्पष्ट लेख के रूप में निखारता हूँ, साथ ही व्याकरण और अर्थ-संबंधी गलतियाँ ठीक करता हूँ
      इस साल मैं Linux को सीधे explore कर रहा हूँ, इसलिए इन दिनों उसी तरफ के content पर ज़्यादा ध्यान दे रहा हूँ
      फिर भी, मैं उस भावना को पूरी तरह समझता हूँ। अगर पसंद न आए तो छोड़ सकते हैं, कोई बुरा मानना नहीं। बस, जब तक मुझे इस तरीके को और बेहतर बनाने का कोई बेहतर उपाय नहीं मिल जाता, मैं इसे इस्तेमाल करता रहूँगा :)
    • कम से कम उसने ईमानदारी से यह बताया, यह ठीक है। निजी तौर पर, अगर बनाने वाले को लगता है कि वह इसे खुद इससे बेहतर नहीं लिख सकता, तो कुछ हद तक ChatGPT-assisted लेखन मुझे ठीक लगता है
      लेकिन शर्त यह है कि उसमें काफ़ी चयन और संपादन हुआ हो। ऐसा नहीं होना चाहिए कि “Linux namespace को manually इस्तेमाल करने पर एक लेख लिखो...” कहकर उसे सीधे blog में paste कर दिया जाए
  • मैंने कई सालों से ऐसे बहुत से लेख देखे हैं। फिर भी Docker बना हुआ है। शायद container ecosystem बनाने में Linux internals से निपटना सबसे कठिन हिस्सा नहीं है

    • सरल मामलों में यह निश्चित रूप से कठिन हिस्सा नहीं है
      हाथ से करके सीखने वाली practice के रूप में यह दिलचस्प है, लेकिन मुझे ठीक से समझ नहीं आता कि ऐसे लेख बार-बार नए होकर क्यों घूमते रहते हैं
  • यह विषय Docker developer Jérôme Petazzoni की Dockercon 2015 प्रस्तुति में बहुत अच्छी तरह समेटा गया है। यह एक प्रस्तुति है जो समझाती है कि containerization कैसे काम करती है
    वीडियो देखने के बाद ही मुझे साफ़ तौर पर समझ आया कि बहुत से लोग शुरू में जैसा सोचते हैं, उसके विपरीत यह virtualization बिल्कुल नहीं है
    https://www.youtube.com/watch?v=sK5i-N34im8

  • क्या यह असल में नीचे दिया गया चलाने जैसा काफ़ी नहीं है?
    debootstrap focal ./ubuntu-rootfs http://archive.ubuntu.com/ubuntu/
    systemd-nspawn -D ./ubuntu-rootfs

  • मुझे यह concept पसंद है, लेकिन मैं हमेशा इसे बस ऐसे सरल तरीके से संभालता आया हूँ कि सभी dependencies को application के उसी folder root में compile करके डाल देता हूँ। इससे ज़्यादा जटिलता की कभी ज़रूरत नहीं पड़ी। application developers ने सिर्फ package manager इस्तेमाल करने की ज़िद में इसे बेवजह जटिल बनाया है
    nginx, Apache, PHP, Perl, Python आदि को भी application के उसी root में isolate किया जा सकता है, और configuration के path parameter के साथ compile करें तो हर application के लिए कई instances रखे जा सकते हैं

  • लेख में बताए गए बुनियादी container की तुलना में Docker अतिरिक्त रूप से कौन-सी सुविधाएँ देता है?

    • Docker डिफ़ॉल्ट रूप से [1] के अनुसार seccomp system call allowlist लागू करता है, और [2] के अनुसार capability को सीमित करता है। इसके अलावा कई डिफ़ॉल्ट security hardening practices भी लागू होती हैं। अगर किसी Docker container को सच में reboot system call करना हो, तो यह permission स्पष्ट रूप से जोड़ी जा सकती है
      और अधिक जटिल sandboxing तकनीकों में sockets, pipes, files आदि के handles पहले से खोलकर रखना, फिर उन पर seccomp filter को और सख्त करके नए handles खोलने से रोक देना शामिल है। इस तरह कोई container volume के तयशुदा files को पढ़ और लिख तो सकता है, लेकिन नए files खोलने जैसी filesystem interaction की क्षमता बिल्कुल नहीं रखेगा। क्योंकि filesystem से जुड़े system calls को पूरी तरह disable किया जा सकता है
      [1] https://github.com/moby/moby/blob/master/profiles/seccomp/de...
      [2] https://docs.docker.com/engine/security/#linux-kernel-capabi...
    • लेख में कहा गया है कि Docker layered images, networking, container orchestration, और व्यापक tooling जैसी सुविधाएँ देता है, इसलिए यह शक्तिशाली और बहुउपयोगी है
    • मेरी राय में सबसे बड़ी चीज़ Dockerfile और “marketplace”, यानी Hub था। Dockerfile syntax शुरुआती दिनों में बेतरतीब था, लेकिन सिर्फ base image निर्दिष्ट कर पाने और कुछ commands लिख पाने से ही usability काफ़ी बेहतर हो गई थी
      उसके बाद build और push चलाकर image को व्यापक रूप से उपयोग योग्य बनाने वाला workflow था। Linux jail, jailer, debootstrap, lxc जैसे विकल्पों की तुलना में collaboration बहुत आसान था
    • दूसरे जवाबों में बताई गई सुविधाओं के अलावा, Docker जो देता है वह है simplicity। किसी application को container में चलाने के लिए namespaces, capability, cgroup जैसी बारीकियों को समझना ज़रूरी नहीं है :)
    • “Docker” शब्द या product name इतना dilute हो चुका है कि इस पर बात करना मुश्किल है। कई सुविधाओं वाले कई products के लिए यह नाम अलग-अलग तरह से इस्तेमाल होता है, और अब ऐसा कोई product भी नहीं है जिसे बस “Docker” कहा जाए। अलग-अलग operating systems के लिए virtualization से जुड़ी सुविधाएँ, orchestration से जुड़ी सुविधाएँ वगैरह बहुत हैं
      वैसे, लेख भी किसी specific product की ओर link नहीं करता, सिर्फ Docker company के first page पर link करता है। मुझे उस first page पर जो link सबसे पहले दिखता है वह “Docker Desktop for Linux” है, और यह शायद virtualization-based system लगता है
 
cosine20 2023-06-29

कुछ तो सूक्ष्म सा...?!