🐳 ডকার এবং কুবারনেটস

সম্পূর্ণ বাংলা গাইড - প্রযুক্তিগত বিস্তারিত সহ

📑 বিষয়বস্তু

🤔 অংশ ১: সমস্যা এবং সমাধান

বাস্তব গল্প: তামিম ও জয়

দৃশ্য ১: একটি স্টার্টআপ অফিস

তামিম: "আমি একটি দারুণ ওয়েব অ্যাপ্লিকেশন তৈরি করেছি। এটি আমার ল্যাপটপে একদম নিখুঁতভাবে কাজ করছে।" ✅

জয়: "তামিম ভাই, আমাকে কোডটা দিন। আমি আমার মেশিনে পরীক্ষা করে দেখি।"

(এক ঘণ্টা পরে)

জয়: "তামিম ভাই, এটা তো কাজ করছে না! সার্ভার ক্র্যাশ করছে।" 💥

তামিম: "কী বলছেন! আমার মেশিনে তো একদম ঠিকঠাক কাজ করছে... তাহলে সমস্যা কোথায়?" 😕

আসল সমস্যা কোথায়?

মূল সমস্যা হলো—দুইটি মেশিনের পরিবেশ এক নয়।

তামিমের মেশিনে:
• Python ৩.৯
• PostgreSQL ১২
• Redis ৬.০
• প্রয়োজনীয় সব লাইব্রেরি ইনস্টল করা আছে
• সঠিক সিস্টেম কনফিগারেশন রয়েছে

জয়ের মেশিনে:
• Python ৩.৮ — সংস্করণ ভিন্ন!
• PostgreSQL ১৩ — সংস্করণ ভিন্ন!
• Redis ৫.০ — সংস্করণ ভিন্ন!
• কিছু প্রয়োজনীয় লাইব্রেরি অনুপস্থিত
• সিস্টেম কনফিগারেশনও ভিন্ন

প্রোডাকশন সার্ভারে:
• Ubuntu ১৮.০৪ — পুরোনো সংস্করণ
• Python ২.৭ — অত্যন্ত পুরোনো সংস্করণ!
• সম্পূর্ণ ভিন্ন সিস্টেম সেটআপ
তামিমের মেশিন, জয়ের মেশিন এবং প্রোডাকশন সার্ভারের পরিবেশের পার্থক্য

তাহলে যদি এমন একটি সমাধান থাকত...

প্রশ্ন: আমরা যদি অ্যাপ্লিকেশনের জন্য প্রয়োজনীয় পুরো রানটাইম পরিবেশটাকেই একটি প্যাকেজের মধ্যে নিয়ে যেতে পারি, তাহলে কেমন হয়?

সেই প্যাকেজের মধ্যে থাকতে পারে:
✓ আপনার সম্পূর্ণ অ্যাপ্লিকেশন কোড
✓ Python ৩.৯ — নির্দিষ্ট সংস্করণ
✓ প্রয়োজনীয় লাইব্রেরি ও ডিপেন্ডেন্সি
✓ প্রয়োজনীয় সিস্টেম টুল ও কনফিগারেশন
✓ অ্যাপ্লিকেশন চালানোর জন্য প্রয়োজনীয় অন্যান্য উপাদান

তাহলে ফলাফল কী হবে?
• তামিমের মেশিনে → ✅ একই পরিবেশে চলবে
• জয়ের মেশিনে → ✅ একই পরিবেশে চলবে
• প্রোডাকশন সার্ভারে → ✅ একই পরিবেশে চলবে
• অন্য যেকোনো মেশিনে → ✅ একইভাবে চালানো যাবে

এই সমস্যার সমাধানের ধারণা থেকেই ডকার-এর মূল উদ্দেশ্যটি বোঝা যায়।

অংশ ২: ইতিহাস — কীভাবে আমরা এখানে এসে পৌঁছালাম

Server Technology-এর বিবর্তন

                📚 CONTAINER TECHNOLOGY — HISTORY & EVOLUTION
                │
                │
                ├── 🖥️ ১. Physical Server Era
                │   │   ১৯৭০s – ১৯৯০s
                │   │
                │   ├── কী ছিল?
                │   │   └── একটি application চালাতে একটি physical server ব্যবহার করা হতো।
                │   │
                │   ├── কীভাবে কাজ করত?
                │   │   └── Server → Operating System → Application
                │   │
                │   ├── সমস্যা কী ছিল?
                │   │   ├── Hardware অনেক expensive ছিল
                │   │   ├── Server setup করতে অনেক সময় লাগত
                │   │   ├── CPU ও RAM-এর বড় অংশ খালি পড়ে থাকত
                │   │   └── প্রতিটি workload-এর জন্য আলাদা server লাগতে পারত
                │   │
                │   └── সহজ উদাহরণ:
                │       └── ১০০% capacity-এর server কিনলাম,
                │           কিন্তু application ব্যবহার করছে মাত্র ১০%।
                │           বাকি ৯০% resource unused!
                │
                │
                ├── 🖥️ ২. Virtual Machine Era
                │   │   ২০০১ সালের দিকে
                │   │
                │   ├── কেন এলো?
                │   │   └── একটি physical server-এর resource আরও ভালোভাবে
                │   │       ব্যবহার করার প্রয়োজন ছিল।
                │   │
                │   ├── কী এলো?
                │   │   └── Virtual Machine (VM)
                │   │
                │   ├── কীভাবে কাজ করে?
                │   │   │
                │   │   └── Physical Server
                │   │          ↓
                │   │       Hypervisor
                │   │          ↓
                │   │       ┌────────┬────────┬────────┐
                │   │       │  VM 1  │  VM 2  │  VM 3  │
                │   │       │ Guest OS│Guest OS│Guest OS│
                │   │       │   App  │   App  │   App  │
                │   │       └────────┴────────┴────────┘
                │   │
                │   ├── সুবিধা
                │   │   ├── একটি server-এ একাধিক workload
                │   │   ├── Hardware utilization ভালো হলো
                │   │   └── Workload-এর মধ্যে isolation পাওয়া গেল
                │   │
                │   └── নতুন সমস্যা
                │       ├── প্রতিটি VM-এর আলাদা Guest OS প্রয়োজন
                │       ├── বেশি RAM লাগে
                │       ├── বেশি disk space লাগে
                │       └── Container-এর তুলনায় startup ধীর
                │
                │
                ├── 🔬 ৩. Linux Process Isolation
                │   │   ২০০৬ সালের দিকে
                │   │
                │   ├── নতুন চিন্তা:
                │   │   └── Application আলাদা করার জন্য কি
                │   │       প্রতিবার সম্পূর্ণ Operating System চালাতে হবে?
                │   │
                │   ├── উত্তর:
                │   │   └── না।
                │   │       Linux Kernel-এর isolation feature ব্যবহার করা যায়।
                │   │
                │   ├── Google-এর Process Containers
                │   │   └── Resource accounting ও process isolation-এর
                │   │       development-এ গুরুত্বপূর্ণ ভূমিকা রাখে।
                │   │
                │   └── এখান থেকেই container technology-এর
                │       ভিত্তি আরও শক্তিশালী হতে থাকে।
                │
                │
                ├── 🐧 ৪. Linux Namespaces
                │   │   ২০০৬ সালের পর
                │   │
                │   ├── মূল প্রশ্ন:
                │   │   └── "একটি process অন্য process বা system-এর
                │   │       কোন অংশ দেখতে পারবে?"
                │   │
                │   ├── Namespaces-এর কাজ:
                │   │   └── Process-এর জন্য আলাদা system view তৈরি করা।
                │   │
                │   ├── উদাহরণ
                │   │   ├── PID Namespace
                │   │   │   └── আলাদা process view
                │   │   │
                │   │   ├── Network Namespace
                │   │   │   └── আলাদা network environment
                │   │   │
                │   │   ├── Mount Namespace
                │   │   │   └── আলাদা filesystem mount view
                │   │   │
                │   │   ├── UTS Namespace
                │   │   │   └── আলাদা hostname
                │   │   │
                │   │   ├── IPC Namespace
                │   │   │   └── আলাদা IPC resources
                │   │   │
                │   │   └── User Namespace
                │   │       └── আলাদা user/UID mapping
                │   │
                │   └── সহজভাবে:
                │       └── Namespaces = "তুমি কী দেখতে পারবে?"
                │
                │
                ├── ⚙️ ৫. Linux cgroups
                │   │   ২০০৭–২০০৮ সালের দিকে
                │   │
                │   ├── নতুন সমস্যা:
                │   │   └── একটি application যেন পুরো server-এর
                │   │       CPU বা RAM ব্যবহার করতে না পারে।
                │   │
                │   ├── সমাধান:
                │   │   └── cgroups (Control Groups)
                │   │
                │   ├── cgroups কী করে?
                │   │   ├── CPU usage control
                │   │   ├── Memory limit
                │   │   ├── Block I/O control
                │   │   └── Resource usage accounting
                │   │
                │   └── সহজভাবে:
                │       └── cgroups = "তুমি কতটুকু resource ব্যবহার করতে পারবে?"
                │
                │
                ├── 🧩 ৬. Namespaces + cgroups
                │   │
                │   ├── Namespaces
                │   │   └── Isolation
                │   │
                │   ├── cgroups
                │   │   └── Resource Control
                │   │
                │   └── একসাথে:
                │       │
                │       ├── Namespaces → Process-কে আলাদা environment দেয়
                │       │
                │       └── cgroups → Process-এর resource সীমাবদ্ধ করে
                │
                │       ↓
                │
                │       এই Linux kernel capabilities
                │       container technology-এর foundation তৈরি করে।
                │
                │
                ├── 📦 ৭. LXC — Linux Containers
                │   │   ২০০৮ সালের দিকে
                │   │
                │   ├── কেন এলো?
                │   │   └── Linux-এর isolation ও resource-control
                │   │       capabilities ব্যবহার করে container
                │   │       তৈরি ও manage করার practical tooling দরকার ছিল।
                │   │
                │   ├── LXC কী?
                │   │   └── Linux Containers
                │   │
                │   ├── LXC কী ব্যবহার করে?
                │   │   ├── Linux Namespaces
                │   │   ├── Linux cgroups
                │   │   └── অন্যান্য Linux kernel features
                │   │
                │   ├── সুবিধা
                │   │   ├── Full Guest OS ছাড়াই isolated environment
                │   │   ├── Lightweight
                │   │   └── Linux kernel share করে
                │   │
                │   └── সহজভাবে:
                │       └── Linux Kernel আমাদের building blocks দিল,
                │           LXC সেগুলো ব্যবহার করে container manage করার
                │           practical system দিল।
                │
                │
                ├── 🐳 ৮. Docker
                │   │   ২০১৩
                │   │
                │   ├── Docker কী?
                │   │   └── Container technology-কে developer-friendly
                │   │       করার একটি platform/tooling ecosystem।
                │   │
                │   ├── Docker আসার আগে
                │   │   └── Container technology ছিল,
                │   │       কিন্তু developer experience তুলনামূলকভাবে জটিল ছিল।
                │   │
                │   ├── Docker কী সহজ করল?
                │   │   ├── Dockerfile
                │   │   ├── Docker Image
                │   │   ├── Docker CLI
                │   │   ├── Image Registry
                │   │   └── Application Packaging
                │   │
                │   ├── Docker-এর early architecture
                │   │   │
                │   │   └── Docker
                │   │       ↓
                │   │       LXC
                │   │       ↓
                │   │       Linux Kernel
                │   │       ↓
                │   │       Namespaces + cgroups
                │   │
                │   ├── সবচেয়ে বড় পরিবর্তন:
                │   │   └── Developer সহজে application + dependencies
                │   │       একটি image-এর মধ্যে package করতে পারল।
                │   │
                │   └── সহজভাবে:
                │       └── "আমার machine-এ কাজ করে,
                │           তোমার machine-এও একইভাবে চলবে।"
                │
                │
                ├── 🐳 ৯. Docker 1.0
                │   │   ২০১৪
                │   │
                │   ├── Docker আরও stable ও production-ready হয়।
                │   │
                │   ├── Docker ecosystem দ্রুত grow করতে থাকে।
                │   │
                │   └── Container technology developers-এর মধ্যে
                │       mainstream হতে শুরু করে।
                │
                │
                ├── ⚙️ ১০. libcontainer
                │   │   ২০১৪–২০১৫
                │   │
                │   ├── Early Docker
                │   │   └── LXC-এর ওপর নির্ভর করত।
                │   │
                │   ├── পরে Docker
                │   │   └── নিজস্ব container execution library তৈরি করে।
                │   │
                │   ├── নাম:
                │   │   └── libcontainer
                │   │
                │   └── ধারণাটি:
                │       └── Docker যেন LXC-এর ওপর সরাসরি নির্ভর না করে
                │           Linux container primitives ব্যবহার করতে পারে।
                │
                │
                ├── 📜 ১১. Open Container Initiative (OCI)
                │   │   ২০১৫
                │   │
                │   ├── সমস্যা:
                │   │   └── Container ecosystem-এ standard দরকার।
                │   │
                │   ├── সমাধান:
                │   │   └── OCI
                │   │
                │   ├── OCI-এর লক্ষ্য:
                │   │   └── Open container standards তৈরি করা।
                │   │
                │   ├── গুরুত্বপূর্ণ specification
                │   │   ├── Image Specification
                │   │   └── Runtime Specification
                │   │
                │   └── ফলাফল:
                │       └── Container ecosystem একটি নির্দিষ্ট
                │           vendor-এর technology-তে আটকে থাকল না।
                │
                │
                ├── ⚙️ ১২. runc
                │   │
                │   ├── কী?
                │   │   └── একটি low-level OCI container runtime।
                │   │
                │   ├── কাজ:
                │   │   └── Container তৈরি ও চালানোর জন্য
                │   │       Linux kernel-এর প্রয়োজনীয় functionality ব্যবহার করা।
                │   │
                │   └── সহজভাবে:
                │       └── Docker/Kubernetes-এর অনেক উপরের abstraction-এর
                │           নিচে runc-এর মতো runtime container চালানোর
                │           low-level কাজ করে।
                │
                │
                ├── 🔧 ১৩. containerd
                │   │
                │   ├── কী?
                │   │   └── Container lifecycle management-এর জন্য
                │   │       একটি container runtime component।
                │   │
                │   ├── কাজ
                │   │   ├── Image management
                │   │   ├── Container lifecycle
                │   │   ├── Runtime-এর সঙ্গে integration
                │   │   └── Container execution management
                │   │
                │   └── সহজভাবে:
                │       └── containerd = Container চালানো ও manage করার
                │           মাঝের গুরুত্বপূর্ণ management layer।
                │
                │
                └── ☸️ ১৪. Kubernetes — Container Orchestration Era
                    │
                    ├── নতুন সমস্যা:
                    │   └── একটি container manage করা সহজ,
                    │       কিন্তু ১০০/১০০০ container?
                    │
                    ├── তখন কী দরকার?
                    │   ├── Container কোথায় চলবে?
                    │   ├── Container crash করলে কে restart করবে?
                    │   ├── Traffic কীভাবে distribute হবে?
                    │   ├── Application কীভাবে scale করবে?
                    │   ├── Server নষ্ট হলে workload কোথায় যাবে?
                    │   └── নতুন version কীভাবে deploy হবে?
                    │
                    ├── সমাধান:
                    │   └── Container Orchestration
                    │
                    ├── Kubernetes কী করে?
                    │   ├── Scheduling
                    │   ├── Scaling
                    │   ├── Service Discovery
                    │   ├── Load Balancing
                    │   ├── Self-Healing
                    │   ├── Rolling Updates
                    │   └── Container Management
                    │
                    └── 🎯 পুরো Evolution
                        │
                        ├── Physical Server
                        │       ↓
                        │   Resource অপচয়
                        │
                        ├── Virtual Machine
                        │       ↓
                        │   Better utilization
                        │   কিন্তু Full Guest OS দরকার
                        │
                        ├── Linux Namespaces
                        │       ↓
                        │   Isolation
                        │
                        ├── Linux cgroups
                        │       ↓
                        │   Resource Control
                        │
                        ├── LXC
                        │       ↓
                        │   Linux Container Management
                        │
                        ├── Docker
                        │       ↓
                        │   Developer-friendly Containers
                        │
                        ├── OCI + runc
                        │       ↓
                        │   Standardized Container Runtime
                        │
                        ├── containerd
                        │       ↓
                        │   Container Lifecycle Management
                        │
                        └── Kubernetes
                                ↓
                            Container Orchestration
            

প্রতিটি পর্যায়ের বিস্তারিত

১. Physical Server-এর যুগ

কীভাবে কাজ করত:
একটি কোম্পানিকে প্রতিটি Application বা Service-এর জন্য আলাদা Physical Server কিনতে হতো।

খরচের একটি ধারণা:
• Server Hardware: $৫,০০০–$১৫,০০০
• Data Center Space: প্রতি মাসে প্রায় $৫০০
• Power Consumption: প্রতি মাসে প্রায় $২০০
• Administration ও Maintenance: প্রতি মাসে প্রায় $৩০০

প্রধান সমস্যা:
একটি Physical Server-এর CPU, RAM এবং অন্যান্য Resource-এর বড় একটি অংশ অব্যবহৃত পড়ে থাকত। অনেক ক্ষেত্রে Server-এর মোট Capacity-এর মাত্র ১০–১৫% ব্যবহার হতো। অর্থাৎ প্রায় ৮৫–৯০% Resource অব্যবহৃত থাকার সম্ভাবনা ছিল।

Scaling-এর সমস্যা:
নতুন কোনো Application বা Service চালু করতে হলে নতুন Server কিনতে হতো। এরপর Data Center-এ Server সেটআপ, Operating System ইনস্টল, Network Configuration এবং অন্যান্য Setup সম্পন্ন করতে হতো। ফলে নতুন Service চালু করতে অনেক সময় এবং বিপুল অর্থের প্রয়োজন হতো।

২. Virtual Machine-এর যুগ — ২০০৬-এর পর

নতুন ধারণা:
Hypervisor Technology-এর মাধ্যমে একটি শক্তিশালী Physical Server-এর মধ্যে একাধিক Virtual Machine (VM) চালানো সম্ভব হলো।

Hypervisor-এর উদাহরণ:
VMware, VirtualBox, KVM

কীভাবে কাজ করত:
একটি Physical Server-এর CPU, RAM এবং Storage-এর Resource ভাগ করে তার মধ্যে একাধিক স্বাধীন Virtual Machine চালানো হতো।

সুবিধা:
✓ একই Physical Server-এ একাধিক Server চালানো যায়
✓ Hardware Resource তুলনামূলকভাবে ভালোভাবে ব্যবহার করা যায়
✓ নতুন VM তুলনামূলকভাবে দ্রুত তৈরি করা যায়
✓ প্রতিটি VM-এর জন্য আলাদা Environment তৈরি করা যায়
✓ Application-গুলো একে অপরের থেকে Isolation-এর মধ্যে থাকে

তবে সমস্যা থেকেই গেল:
✗ প্রতিটি VM-এর নিজস্ব পূর্ণাঙ্গ OS থাকে
✗ প্রতিটি VM চালু হতে তুলনামূলকভাবে বেশি সময় লাগে
✗ প্রতিটি VM-এর জন্য আলাদা Disk Space প্রয়োজন
✗ প্রতিটি VM-এর জন্য আলাদা Memory বরাদ্দ করতে হয়
✗ Guest OS-এর কারণে অতিরিক্ত Resource Overhead তৈরি হয়

৩. Linux Namespaces এবং cgroups — Container-এর ভিত্তি

Linux Kernel-এর গুরুত্বপূর্ণ সুবিধা:

Linux Kernel-এ এমন কিছু গুরুত্বপূর্ণ Feature তৈরি ও উন্নত হয়, যেগুলো পরবর্তীতে আধুনিক Container Technology-এর ভিত্তি হয়ে ওঠে। এর মধ্যে সবচেয়ে গুরুত্বপূর্ণ দুটি হলো Namespaces এবং cgroups

Namespaces — Isolation তৈরি করে:
Namespaces একটি Process বা Container-কে System-এর অন্যান্য Process ও Resource থেকে আলাদা একটি Environment হিসেবে দেখতে সাহায্য করে।

├─ PID Namespace — Process-গুলোকে আলাদা Process Tree-এর মধ্যে রাখে
├─ Network Namespace — Network Interface ও Network Stack আলাদা করে
├─ IPC Namespace — Inter-Process Communication Resource আলাদা করে
├─ Mount Namespace — File System Mount আলাদা করে
├─ UTS Namespace — Hostname ও Domain Name আলাদা করে
└─ User Namespace — User ID ও Group ID আলাদাভাবে Map করতে দেয়

cgroups — Resource Control করে:
cgroups নির্ধারণ করে একটি Process বা Process Group কতটুকু CPU, Memory, I/O এবং অন্যান্য Resource ব্যবহার করতে পারবে।

├─ CPU Limit — CPU ব্যবহারের সীমা নির্ধারণ করা যায়
├─ Memory Limit — সর্বোচ্চ Memory ব্যবহারের সীমা নির্ধারণ করা যায়
├─ I/O Control — Disk Read/Write-এর ব্যবহার নিয়ন্ত্রণ করা যায়
├─ PID Limit — সর্বোচ্চ কতগুলো Process চলতে পারবে তা নির্ধারণ করা যায়
└─ Device Control — নির্দিষ্ট Hardware Device-এ Access নিয়ন্ত্রণ করা যায়

৪. LXC — Linux Containers — ২০০৮-এর দিকে

Container Technology-এর একটি গুরুত্বপূর্ণ ধাপ:

LXC (Linux Containers) হলো Linux-এর একটি Container Technology, যা Namespaces এবং cgroups-এর মতো Linux Kernel Feature ব্যবহার করে Lightweight এবং Isolated Environment তৈরি করে।

কীভাবে কাজ করত:
LXC Linux Kernel-এর Isolation এবং Resource Control সুবিধাগুলো ব্যবহার করে একটি আলাদা Environment তৈরি করত, যেখানে Application-গুলো তুলনামূলকভাবে কম Overhead-এর মধ্যে চালানো যেত।

সুবিধা:
✓ Virtual Machine-এর তুলনায় অনেক Lightweight
✓ প্রতিটি Container-এর জন্য সম্পূর্ণ আলাদা OS চালানোর প্রয়োজন নেই
✓ VM-এর তুলনায় দ্রুত Start করা যায়
✓ Resource Overhead তুলনামূলকভাবে কম

তবে কিছু সীমাবদ্ধতা ছিল:
✗ Setup ও Management তুলনামূলকভাবে জটিল
✗ Developer-এর জন্য ব্যবহার করা সহজ ছিল না
✗ Application Packaging-এর জন্য সহজ Standard Workflow ছিল না
✗ Container Image তৈরি ও Share করার জন্য Docker-এর মতো সহজ Ecosystem ছিল না

৫. Docker — ২০১৩

Docker-এর আসল অবদান কী?

একটি বিষয় শুরুতেই পরিষ্কার করা গুরুত্বপূর্ণ—Docker Container আবিষ্কার করেনি।

Docker আসার আগেই Linux-এ Namespaces, cgroups এবং LXC-এর মতো Container Technology ছিল। Docker মূলত এই বিদ্যমান Technology-গুলোর ওপর ভিত্তি করে Container-কে আরও সহজ, Standardized এবং Developer-Friendly করে তুলেছিল।

Docker যেসব গুরুত্বপূর্ণ ধারণা ও Tool জনপ্রিয় করে তোলে:

১. Docker Image — Application এবং তার Dependencies-কে একটি Portable Package হিসেবে তৈরি করার পদ্ধতি

২. Dockerfile — Image কীভাবে তৈরি হবে, তা নির্ধারণ করার জন্য সহজ ও Reproducible Instruction File

৩. Docker Hub — Container Image Share ও Distribute করার জন্য একটি কেন্দ্রীয় Registry

৪. Docker CLI — Container তৈরি, চালানো, বন্ধ করা এবং পরিচালনার জন্য সহজ Command-Line Interface

৫. Layered Filesystem — Image-কে একাধিক Layer-এ ভাগ করে Layer Reuse-এর মাধ্যমে Storage ও Build Process আরও Efficient করা

ফলাফল:
Container Technology আর শুধু Infrastructure Expert-দের মধ্যে সীমাবদ্ধ থাকল না। একজন সাধারণ Developer-ও সহজে Application Package করে Container হিসেবে চালাতে, Share করতে এবং অন্য Environment-এ একইভাবে Deploy করতে পারল।

এভাবেই Docker Container-কে আধুনিক Software Development ও Deployment-এর একটি গুরুত্বপূর্ণ অংশে পরিণত করতে বড় ভূমিকা রাখে।

🐳 অংশ ৩: Docker — সম্পূর্ণ ধারণা

Docker কী?

একটি সহজ উদাহরণ দিয়ে শুরু করি:

ধরুন, আপনাকে একটি Package এক শহর থেকে অন্য শহরে পাঠাতে হবে। Package-এর ভেতরে কী আছে, সেটি গুরুত্বপূর্ণ। কিন্তু তার পাশাপাশি এটাও গুরুত্বপূর্ণ— যেখানেই Package পাঠানো হোক, সেটি যেন একই অবস্থায় পৌঁছায়।

একটি Shipping Service-এর সাধারণ ধারণা:

১. প্রয়োজনীয় জিনিস সংগ্রহ করুন
২. Standard Box-এর মধ্যে রাখুন
৩. Box Seal করুন
৪. Shipping Label লাগান
৫. যেকোনো জায়গায় পাঠান
৬. গন্তব্যে পৌঁছানোর পরও ভেতরের জিনিস একই থাকে

Docker-এর ধারণাটাও অনেকটা একই:

১. Application নিন
২. Application, Runtime এবং Dependencies-কে Image-এ Package করুন
৩. Image Registry-তে Push করুন
৪. অন্য Machine থেকে Image Pull করুন
৫. Image থেকে Container চালান
৬. একই Image ব্যবহার করে Application চালান

সহজভাবে বললে:
Docker Application-কে তার প্রয়োজনীয় Environment এবং Dependencies-সহ Package করার একটি Standard পদ্ধতি দেয়, যাতে Application-টি বিভিন্ন Environment-এ একইভাবে চালানো সহজ হয়।

Docker-এর তিনটি মূল ধারণা

① Image — Application-এর Blueprint

Image কী?

Docker Image হলো একটি Read-Only Template। এর মধ্যে Application চালানোর জন্য প্রয়োজনীয় File, Runtime, Library, Dependency এবং Configuration-এর সংজ্ঞা থাকে।

সহজভাবে মনে রাখুন:

Image = Blueprint

যেমন একটি Blueprint দেখে একটি বাড়ি তৈরি করা যায়, তেমনি একটি Image থেকে Container তৈরি করা যায়।

একটি Image-এ থাকতে পারে:

├─ Base Image
├─ Runtime — Python, Node.js, Java ইত্যাদি
├─ Application Dependencies
├─ Application Code
├─ System Libraries
├─ Configuration Files
└─ প্রয়োজনীয় Metadata

উদাহরণ:
একটি Python Application-এর Image-এর মধ্যে থাকতে পারে— Python Runtime, pip Package, Application Code এবং প্রয়োজনীয় Dependencies।

গুরুত্বপূর্ণ:
Image নিজে Application চালায় না। Image হলো Container তৈরি করার Template।

② Container — Image-এর Running Instance

Container কী?

Container হলো একটি Docker Image-এর Running Instance

সহজভাবে মনে রাখুন:

Image = Blueprint
Container = সেই Blueprint থেকে তৈরি Running Instance

একটি Image থেকে একাধিক Container তৈরি করা যায়।

Container-এর বৈশিষ্ট্য:

├─ আলাদা Process Environment
├─ আলাদা File System View
├─ আলাদা Network Namespace
├─ আলাদা Mount Namespace
├─ Resource Limit প্রয়োগ করা যায়
└─ Host-এর অন্যান্য Process থেকে Isolation পাওয়া যায়

সবচেয়ে গুরুত্বপূর্ণ বিষয়:
Container কোনো Virtual Machine নয়। Container Host-এর Linux Kernel ব্যবহার করে। তাই VM-এর তুলনায় Container সাধারণত অনেক Lightweight এবং দ্রুত Start হয়।

③ Registry — Image-এর Warehouse

Registry কী?

Docker Registry হলো এমন একটি Service যেখানে Docker Image সংরক্ষণ, Upload এবং Download করা যায়।

সহজভাবে মনে রাখুন:

Registry = Docker Image-এর Warehouse

আপনি Local Machine-এ Image তৈরি করার পর সেটি Registry-তে Push করতে পারেন। অন্য Machine সেই Image Pull করে Container চালাতে পারে।

জনপ্রিয় Registry:

১. Docker Hub — বহুল ব্যবহৃত Public Registry
২. GitHub Container Registry (GHCR) — GitHub-এর সঙ্গে Integration
৩. AWS ECR — AWS-এর Managed Container Registry
৪. Google Artifact Registry — Google Cloud-এর Registry Service
৫. Private Registry — প্রতিষ্ঠানের নিজস্ব Registry

Image, Registry এবং Container-এর সম্পর্ক

Docker Image-এর Layer

Layer কী?

Docker Image সাধারণত একটি বিশাল File নয়। এটি একাধিক Layer নিয়ে গঠিত।

Dockerfile-এর বিভিন্ন Instruction-এর মাধ্যমে Image Build করার সময় এই Layer-গুলো তৈরি হয়। প্রতিটি Layer আগের Layer-এর ওপর একটি পরিবর্তন যোগ করে।

উদাহরণ:
Layer-এর সুবিধা:

├─ Layer Cache করা যায়
├─ একই Layer একাধিক Image-এ Reuse করা যায়
├─ Build Process দ্রুত করা যায়
└─ Disk Space সাশ্রয় করা যায়

উদাহরণ:
দুটি Image যদি একই Base Image ব্যবহার করে, তাহলে Docker একই Base Layer পুনরায় ব্যবহার করতে পারে। ফলে একই Data বারবার সংরক্ষণ করার প্রয়োজন হয় না।

Dockerfile — Image তৈরির Recipe

Dockerfile কী?

Dockerfile হলো একটি সাধারণ Text File যেখানে Docker Image কীভাবে তৈরি হবে, তার ধারাবাহিক Instruction লেখা থাকে।

সহজভাবে মনে রাখুন:

Dockerfile = Image তৈরির Recipe

Dockerfile → Docker Build → Docker Image

একটি বাস্তব Dockerfile

# Base Image নির্বাচন

FROM python:3.9-slim

# Image Metadata

LABEL maintainer="[tamim@example.com](mailto:tamim@example.com)"
LABEL version="1.0"
LABEL description="A Bangla Web Application"

# Environment Variables

ENV APP_HOME=/app
ENV PYTHONUNBUFFERED=1

# Working Directory

WORKDIR $APP_HOME

# System Dependencies

RUN apt-get update &&
apt-get install -y --no-install-recommends
gcc
postgresql-client
curl &&
apt-get clean &&
rm -rf /var/lib/apt/lists/*

# Python Dependencies

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Application Code

COPY . .

# Application Port

EXPOSE 5000

# Health Check

HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3
CMD curl -f http://localhost:5000/health || exit 1

# Container Start Command

CMD ["python", "app.py"]

Dockerfile-এর গুরুত্বপূর্ণ Instruction

FROM
Image তৈরির জন্য Base Image নির্ধারণ করে।
FROM python:3.9-slim

RUN
Image Build হওয়ার সময় কোনো Command চালায়।
RUN pip install -r requirements.txt

COPY
Host Machine থেকে File বা Directory Image-এর মধ্যে কপি করে।
COPY . .

WORKDIR
পরবর্তী Instruction-এর জন্য Working Directory নির্ধারণ করে।
WORKDIR /app

ENV
Environment Variable নির্ধারণ করে।
ENV PORT=5000

EXPOSE
Container-এর কোন Port-এ Application Listen করবে তা ঘোষণা করে।
এটি নিজে থেকে Port Publish করে না।
EXPOSE 5000

CMD
Container চালু হলে Default হিসেবে যে Command চলবে তা নির্ধারণ করে।
CMD ["python", "app.py"]

ENTRYPOINT
Container-এর মূল Executable বা Application নির্ধারণ করতে ব্যবহৃত হয়।
ENTRYPOINT ["python"]

HEALTHCHECK
Container-এর Application সঠিকভাবে কাজ করছে কি না তা পরীক্ষা করে।
HEALTHCHECK CMD curl -f http://localhost:5000/health

USER
Container-এর Process কোন User হিসেবে চলবে তা নির্ধারণ করে। Security-এর জন্য Non-Root User ব্যবহার করা ভালো।
USER appuser

VOLUME
Persistent Data সংরক্ষণের জন্য Mount Point ঘোষণা করতে ব্যবহৃত হয়।
VOLUME ["/data"]

Docker-এর সম্পূর্ণ Flow এক নজরে

মনে রাখার সবচেয়ে সহজ উপায়:

Dockerfile → কীভাবে Image তৈরি হবে তার Recipe

Image → Application-এর Blueprint

Registry → Image রাখার ও Share করার জায়গা

Container → Image-এর Running Instance

সম্পূর্ণ Flow:

Dockerfile → Image → Registry → Container

🎯 অংশ ৪: Kubernetes — Architecture ও মূল ধারণা

Docker-এর পর নতুন সমস্যা: Container অনেক হয়ে গেলে কী হবে?

তামিম এবং জয়ের Startup এখন দ্রুত বড় হচ্ছে।

শুরুতে তারা মাত্র একটি Container চালাচ্ছিল। তখন সবকিছু হাতে হাতে পরিচালনা করা সহজ ছিল।

দিন ১:
১টি Container → সহজেই ম্যানেজ করা যায় ✅

সপ্তাহ ২:
৫টি Container → এখনও ম্যানুয়ালি পরিচালনা করা সম্ভব ✅

মাস ১:
১০০টি Container → ম্যানুয়াল Management কঠিন হয়ে গেল 😅

মাস ৩:
১,০০০টি Container → ৫০টি Machine-এ ছড়িয়ে আছে।

তামিম:
"কোন Container কোন Machine-এ চালাব?
কোনো Container বন্ধ হয়ে গেলে কে আবার চালাবে?
কোনো Machine নষ্ট হলে সেখানে থাকা Container-গুলোর কী হবে?
Traffic বেড়ে গেলে কীভাবে নতুন Container চালাব?" 😭

Docker এখানে কোথায় থেমে যায়?

Docker একটি Container তৈরি ও চালানোর জন্য অসাধারণ একটি Technology।

কিন্তু যখন আপনার কাছে শত শত বা হাজার হাজার Container এবং অনেকগুলো Machine থাকে, তখন শুধু Container চালাতে পারলেই সমস্যা সমাধান হয় না।

তখন আমাদের দরকার এমন একটি System, যা স্বয়ংক্রিয়ভাবে সিদ্ধান্ত নেবে—

কোন Machine-এ কোন Container চলবে, কোন Container ব্যর্থ হলে কী করতে হবে, কতগুলো Container চালু রাখতে হবে, কীভাবে Traffic বিতরণ হবে, কীভাবে নতুন Version Deploy হবে, এবং কোনো Machine ব্যর্থ হলে কীভাবে Application সচল রাখা যাবে।

হাজার হাজার Container পরিচালনার প্রধান সমস্যা

❓ Scheduling
১,০০০টি Container ৫০টি Machine-এর মধ্যে কীভাবে সঠিকভাবে বিতরণ করা হবে?

❓ Self-Healing
কোনো Container Crash করলে কীভাবে স্বয়ংক্রিয়ভাবে নতুন Container চালু হবে?

❓ Scaling
Application-এর Traffic বেড়ে গেলে কীভাবে নতুন Container যোগ হবে?

❓ Load Balancing
ব্যবহারকারীদের Request কীভাবে একাধিক Application Instance-এর মধ্যে বিতরণ হবে?

❓ Rolling Update
পুরোনো Version বন্ধ না করেই কীভাবে নতুন Version Deploy করা হবে?

❓ Rollback
নতুন Version-এ সমস্যা হলে কীভাবে দ্রুত আগের Version-এ ফিরে যাওয়া হবে?

❓ Networking
হাজার হাজার Container এবং Service কীভাবে একে অপরের সঙ্গে যোগাযোগ করবে?

❓ Storage
Container মুছে গেলেও গুরুত্বপূর্ণ Data কীভাবে সংরক্ষিত থাকবে?

❓ Monitoring
কোন Application বা Machine সুস্থ আছে এবং কোনটি সমস্যায় আছে—তা কীভাবে জানা যাবে?

❓ Machine Failure
কোনো Worker Machine সম্পূর্ণভাবে নষ্ট হয়ে গেলে সেখানে চলমান Application কীভাবে সচল থাকবে?

সমাধান: Kubernetes

Kubernetes কী?

Kubernetes হলো একটি Container Orchestration Platform। এটি অনেকগুলো Machine জুড়ে Containerized Application Deploy, Manage, Scale এবং Maintain করতে সাহায্য করে।

সহজভাবে বললে—

Docker আপনাকে Container চালাতে সাহায্য করে।
Kubernetes অনেকগুলো Container এবং Machine-কে একসঙ্গে পরিচালনা করতে সাহায্য করে।

আপনি Kubernetes-কে বলতে পারেন:

"আমি চাই আমার Application-এর ১০টি Instance সবসময় চালু থাকুক।"

এরপর Kubernetes চেষ্টা করবে সেই Desired State বজায় রাখতে।

কোনো Container বন্ধ হয়ে গেলে → নতুন Container চালানোর ব্যবস্থা করবে।
কোনো Machine ব্যর্থ হলে → সম্ভব হলে Workload অন্য Machine-এ চালাবে।
Traffic বাড়লে → অতিরিক্ত Instance চালানোর ব্যবস্থা করা যাবে।
নতুন Version Deploy করতে → Rolling Update ব্যবহার করা যাবে।
নতুন Version-এ সমস্যা হলে → Rollback করা যাবে।

Kubernetes-এর সবচেয়ে গুরুত্বপূর্ণ ধারণা: Desired State

Kubernetes বোঝার জন্য Desired State ধারণাটি খুবই গুরুত্বপূর্ণ।

ধরুন আপনি Kubernetes-কে বললেন:

"আমার Application-এর ৫টি Pod সবসময় Running অবস্থায় থাকতে হবে।"

এটিই হলো আপনার Desired State

এখন যদি কোনো কারণে ১টি Pod Crash করে এবং মাত্র ৪টি Pod Running থাকে, তাহলে Kubernetes বুঝবে—

Desired State = ৫টি Pod
Current State = ৪টি Pod

তাই Kubernetes-এর Controller প্রয়োজনীয় ব্যবস্থা নিয়ে আবার ৫টি Pod করার চেষ্টা করবে।

অর্থাৎ Kubernetes বারবার চেষ্টা করে— Current State যেন Desired State-এর সঙ্গে মিলে যায়।

Kubernetes Cluster কী?

Kubernetes-এ একাধিক Machine একসঙ্গে মিলে একটি Cluster তৈরি করে।

একটি Kubernetes Cluster-এর প্রধান দুটি অংশ হলো:

১. Control Plane
Cluster-এর Management এবং Decision-Making অংশ।

২. Worker Node
যেখানে বাস্তবে Application-এর Pod এবং Container চলে।

সহজভাবে মনে রাখুন:

Control Plane = সিদ্ধান্ত নেয়
Worker Node = কাজ সম্পন্ন করে

Kubernetes Architecture — পুরো ছবিটি একসঙ্গে

Control Plane — Kubernetes-এর মস্তিষ্ক

Control Plane হলো Kubernetes Cluster-এর Management Layer।

এটি নিজে সাধারণত আপনার Application-এর মূল Workload চালানোর জায়গা নয়। বরং এটি পুরো Cluster-এর অবস্থা পর্যবেক্ষণ করে, সিদ্ধান্ত নেয় এবং Worker Node-গুলোকে পরিচালনা করে।

Control Plane-এর প্রধান Component হলো:

├─ kube-apiserver — Cluster-এর API Gateway
├─ etcd — Cluster State-এর Data Store
├─ kube-scheduler — Pod-এর জন্য Node নির্বাচন করে
└─ Controller Manager — Desired State বজায় রাখে

Control Plane-এর প্রতিটি Component

① API Server — Kubernetes-এর Front Door

মূল ধারণা:

Kubernetes Cluster-এর সঙ্গে যোগাযোগের প্রধান দরজা হলো kube-apiserver

আপনি যখন kubectl ব্যবহার করেন, তখন আপনার Command সরাসরি Scheduler বা Controller-এর কাছে যায় না। সাধারণত Request প্রথমে API Server-এর কাছে যায়।

API Server-এর কাজ:

├─ Client-এর Request গ্রহণ করা
├─ Authentication করা
├─ Authorization পরীক্ষা করা
├─ Request-এর Validation করা
├─ Cluster State পড়া বা পরিবর্তনের Request পরিচালনা করা
└─ Client-কে Response পাঠানো

উদাহরণ:

আপনি যদি বলেন— kubectl get pods

তাহলে kubectl API Server-এর কাছে Pod-এর তথ্য চায়। API Server প্রয়োজনীয় তথ্য সংগ্রহ করে Response পাঠায়।

Default Secure API Port:
6443

② etcd — Cluster-এর Persistent State Store

মূল ধারণা:

etcd হলো একটি Distributed Key-Value Store। Kubernetes Cluster-এর গুরুত্বপূর্ণ State এবং Configuration এখানে সংরক্ষিত থাকে।

সহজভাবে মনে রাখুন:

etcd = Kubernetes-এর Persistent Memory

Kubernetes-এর কাছে গুরুত্বপূর্ণ হলো— "Cluster এখন কেমন আছে?" এবং "Cluster কেমন থাকা উচিত?"

এই State-এর একটি গুরুত্বপূর্ণ অংশ etcd-তে সংরক্ষিত থাকে।

etcd-তে সংরক্ষিত হতে পারে:

├─ Kubernetes Object-এর State ও Metadata
├─ Pod সম্পর্কিত তথ্য
├─ Service সম্পর্কিত তথ্য
├─ Deployment ও ReplicaSet-এর State
├─ ConfigMap ও Secret-এর Data
├─ Cluster Configuration
└─ অন্যান্য Kubernetes Resource-এর State

গুরুত্বপূর্ণ:
etcd সাধারণ কোনো Application Database নয়। এটি Kubernetes-এর নিজস্ব Cluster State সংরক্ষণের জন্য ব্যবহৃত একটি Distributed Data Store।

Production Cluster-এ etcd-এর High Availability এবং Backup অত্যন্ত গুরুত্বপূর্ণ।

③ Scheduler — Pod-এর জন্য সঠিক Node নির্বাচন করে

মূল ধারণা:

Kubernetes-এ নতুন Pod তৈরি করার সময় সেটি কোন Worker Node-এ চলবে, সেই সিদ্ধান্ত নেওয়ার দায়িত্ব হলো kube-scheduler-এর।

সহজভাবে মনে রাখুন:

Scheduler = Pod-এর জন্য সঠিক জায়গা নির্বাচনকারী

Scheduler-এর সাধারণ কাজ:

১. নতুন একটি Unscheduled Pod শনাক্ত করে
২. কোন Node-গুলো Pod চালাতে পারবে তা পরীক্ষা করে
৩. Resource Requirement বিবেচনা করে
৪. Constraint এবং Scheduling Rule বিবেচনা করে
৫. উপযুক্ত Node-গুলোর মধ্যে নির্বাচন করে
৬. নির্বাচিত Node-এ Pod Assign করার সিদ্ধান্ত জানায়

Scheduler যে বিষয়গুলো বিবেচনা করতে পারে:

├─ CPU ও Memory-এর Availability
├─ Resource Requests ও Limits
├─ Node Selector
├─ Node Affinity / Anti-Affinity
├─ Taints ও Tolerations
├─ Pod Affinity / Anti-Affinity
├─ Storage Requirements
└─ Zone বা Topology সম্পর্কিত Constraint

④ Controllers — Desired State বজায় রাখে

মূল ধারণা:

Kubernetes-এর সবচেয়ে গুরুত্বপূর্ণ ধারণাগুলোর একটি হলো Control Loop

Controller বারবার দেখে—

Desired State কী?
Current State কী?

যদি দুটির মধ্যে পার্থক্য থাকে, Controller প্রয়োজনীয় Action নেওয়ার চেষ্টা করে।

উদাহরণ:

Desired State → ৫টি Pod
Current State → ৪টি Pod

Controller বুঝবে একটি Pod কম আছে এবং প্রয়োজনীয় ব্যবস্থা নিয়ে আবার ৫টি Pod চালু রাখার চেষ্টা করবে।

প্রধান Controller-এর উদাহরণ:

Deployment Controller
└─ Deployment-এর Desired State বজায় রাখতে সাহায্য করে।

ReplicaSet Controller
└─ নির্দিষ্ট সংখ্যক Pod-এর Replica বজায় রাখে।

Node Controller
└─ Node-এর স্বাস্থ্য ও Availability পর্যবেক্ষণ করে এবং Node Failure শনাক্ত করতে সাহায্য করে।

StatefulSet Controller
└─ Stateful Application-এর Pod-এর Identity, Ordering এবং Lifecycle পরিচালনা করে।

Job Controller
└─ নির্দিষ্ট কাজ সফলভাবে সম্পন্ন হওয়া পর্যন্ত Pod পরিচালনা করে।

Controller Manager
└─ Kubernetes-এর বিভিন্ন Controller-কে পরিচালনা করে।

Worker Node — যেখানে Application চলে

Worker Node হলো সেই Machine যেখানে Kubernetes-এর Application Workload বাস্তবে চলে।

একটি Worker Node-এ সাধারণত থাকে:

├─ kubelet
├─ Container Runtime যেমন containerd
├─ kube-proxy বা সংশ্লিষ্ট Networking Component
└─ Application-এর Pod ও Container

সহজভাবে মনে রাখুন:

Control Plane সিদ্ধান্ত নেয়।
Worker Node সেই সিদ্ধান্ত অনুযায়ী Application চালায়।

① kubelet — Node-এর Agent

kubelet কী?

kubelet হলো প্রতিটি Worker Node-এ চলমান একটি Agent। এটি Control Plane-এর সঙ্গে যোগাযোগ করে এবং Node-এ নির্ধারিত Pod চালু ও সচল রাখতে কাজ করে।

মূল কাজ:

├─ Pod-এর Specification গ্রহণ করা
├─ Container Runtime-এর মাধ্যমে Container চালানোর ব্যবস্থা করা
├─ Container ও Pod-এর Health পর্যবেক্ষণ করা
├─ Pod-এর বর্তমান অবস্থা API Server-কে জানানো
└─ নির্ধারিত Workload চালু রাখার জন্য প্রয়োজনীয় ব্যবস্থা নেওয়া

② Container Runtime — Container চালানোর Engine

Container Runtime কী?

Container Runtime হলো সেই Software Layer যা বাস্তবে Container চালানোর কাজ করে।

Kubernetes সরাসরি Container-এর Process তৈরি করার কাজ করে না। kubelet Container Runtime-এর সঙ্গে যোগাযোগ করে।

Kubernetes Ecosystem-এ বহুল ব্যবহৃত Runtime-এর একটি হলো containerd

containerd Container-এর Lifecycle পরিচালনা করে এবং নিচের স্তরে OCI-compatible Runtime-এর মাধ্যমে Container Process চালানো হয়।

③ runc — Container চালানোর নিম্নস্তরের Runtime

runc কী?

runc হলো একটি Lightweight OCI Runtime। এটি Linux-এর Namespace, cgroups এবং অন্যান্য Kernel Feature ব্যবহার করে Container Process তৈরি ও চালাতে সাহায্য করে।

সহজভাবে Layer-টি এমনভাবে ভাবতে পারেন:

একটি Pod কী?

Kubernetes-এ Container-কে সাধারণত সরাসরি পরিচালনা করা হয় না। Container-গুলোকে Pod-এর মধ্যে চালানো হয়।

Pod হলো Kubernetes-এর সবচেয়ে ছোট Deployable Unit।

একটি Pod-এর মধ্যে একটি বা একাধিক Container থাকতে পারে।

একই Pod-এর Container-গুলো সাধারণত কিছু Resource Share করে, যেমন—

├─ Network Namespace
├─ Pod IP Address
└─ Shared Volumes

সাধারণ Application-এর ক্ষেত্রে একটি Pod-এ একটি প্রধান Application Container থাকা খুবই স্বাভাবিক।

একটি Request-এর সম্পূর্ণ যাত্রা

কিন্তু Pod তৈরি বা পরিবর্তনের সিদ্ধান্ত কীভাবে হয়?

ধরুন আপনি Kubernetes-কে বললেন— "আমার Application-এর ৩টি Replica চাই।"

তখন সাধারণ Flow হবে:

ধাপ ১:
আপনি Kubernetes API Server-এর কাছে Desired State পাঠাবেন।

ধাপ ২:
API Server Request Validate করে Cluster State-এর প্রয়োজনীয় তথ্য পরিচালনা করবে।

ধাপ ৩:
Scheduler নতুন Pod-এর জন্য উপযুক্ত Worker Node নির্বাচন করবে।

ধাপ ৪:
সংশ্লিষ্ট Worker Node-এর kubelet সেই Pod-এর জন্য প্রয়োজনীয় Container চালানোর ব্যবস্থা করবে।

ধাপ ৫:
Container Runtime Container চালু করবে।

ধাপ ৬:
Controller এবং kubelet ক্রমাগত অবস্থা পর্যবেক্ষণ করবে।

ধাপ ৭:
কোনো Pod ব্যর্থ হলে Kubernetes আবার Desired State পূরণ করার চেষ্টা করবে।

Kubernetes Architecture — এক লাইনে প্রতিটি Component

API Server → Cluster-এর সঙ্গে যোগাযোগের প্রধান দরজা

etcd → Cluster State-এর Persistent Data Store

Scheduler → Pod কোন Node-এ চলবে তা নির্বাচন করে

Controller → Desired State বজায় রাখে

kubelet → Worker Node-এ Pod চালু ও পর্যবেক্ষণ করে

containerd → Container Lifecycle পরিচালনা করে

runc → Linux-এর সাহায্যে Container Process চালায়

Pod → Kubernetes-এর সবচেয়ে ছোট Deployable Unit

Worker Node → যেখানে Application Workload চলে

Control Plane → পুরো Cluster পরিচালনা ও নিয়ন্ত্রণ করে
সবচেয়ে গুরুত্বপূর্ণ ধারণাটি মনে রাখুন:

Docker মূলত আপনাকে Container তৈরি ও চালানোর পদ্ধতি দেয়।

Kubernetes সেই Container-গুলোকে অনেকগুলো Machine-এর মধ্যে Deploy, Schedule, Scale, Monitor এবং Recover করার জন্য একটি সম্পূর্ণ Orchestration System দেয়।

Control Plane → সিদ্ধান্ত নেয়
Scheduler → Pod-এর জন্য Node নির্বাচন করে
Controller → Desired State বজায় রাখে
Worker Node → Application চালায়
kubelet → Node-এর Pod পরিচালনা করে
containerd → Container পরিচালনা করে
runc → Container Process চালায়

Kubernetes-এর মূল দর্শন: "আপনি কী চান তা বলুন; Kubernetes সেই অবস্থা বজায় রাখার চেষ্টা করবে।"

⚙️ অংশ 5: Kubernetes Components — বিস্তারিত পরিচয়

আগের অংশে আমরা কী শিখেছি?

Kubernetes Cluster-এ মূলত 2 ধরনের জায়গা আছে—

Control Plane → সিদ্ধান্ত নেয়, Cluster পরিচালনা করে
Worker Node → সেই সিদ্ধান্ত অনুযায়ী Application চালায়

এবার প্রশ্ন হলো—

"Control Plane বলল যে একটি Pod চালাতে হবে। কিন্তু Worker Node-এ আসলে কে সেই কাজটা করবে?"

এখানেই আমাদের পরিচয় হবে— kubelet, containerd, runc এবং Pod-এর সঙ্গে।

Worker Node-এর ভেতরে কী আছে?

1. kubelet — Worker Node-এর দায়িত্বশীল কর্মচারী

ভাবুন kubelet হলো অফিসের সেই কর্মচারী,
যাকে Manager বলেছে—

"ভাই, এই Application-এর 3টা Instance চালু রাখতে হবে। ঠিকমতো চলছে কি না দেখবেন। সমস্যা হলে আমাকে জানাবেন।"

kubelet তখন বলে—

"ঠিক আছে Boss, Node আমার। চিন্তা নাই!" 😎
kubelet কী?

kubelet হলো প্রতিটি Worker Node-এ চলমান একটি Agent। এটি Control Plane-এর নির্দেশ অনুযায়ী Node-এ নির্ধারিত Pod চালু ও সচল রাখতে কাজ করে।

সহজভাবে মনে রাখুন:

kubelet = Worker Node-এর Local Manager

kubelet নিজে Container Runtime নয়। বরং এটি Container Runtime-এর সঙ্গে যোগাযোগ করে Container চালানোর ব্যবস্থা করে।

kubelet-এর প্রধান কাজ:

1. API Server-এর মাধ্যমে Pod-এর Desired State সম্পর্কে তথ্য পাওয়া
2. Pod-এর Specification অনুযায়ী Container চালানোর ব্যবস্থা করা
3. Container Runtime-এর সঙ্গে যোগাযোগ করা
4. Pod ও Container-এর বর্তমান অবস্থা পর্যবেক্ষণ করা
5. Container ব্যর্থ হলে Pod-এর Desired State অনুযায়ী Runtime-কে ব্যবস্থা নিতে বলা
6. Pod-এর Status API Server-এর মাধ্যমে Control Plane-কে জানানো
7. Node-এর Health ও Resource সম্পর্কিত তথ্য পর্যবেক্ষণ করা

kubelet কার সঙ্গে কথা বলে?

মনে রাখুন:
kubelet সাধারণত API Server-এর সঙ্গে HTTPS-এর মাধ্যমে যোগাযোগ করে। Container Runtime-এর সঙ্গে যোগাযোগের ক্ষেত্রে Kubernetes-এর Container Runtime Interface (CRI) ব্যবহৃত হয়, যা gRPC ভিত্তিক।

kubelet-এর একটি বাস্তব উদাহরণ

ধরুন আপনি Kubernetes-কে বললেন:

replicas: 3

অর্থাৎ আপনি চান Application-এর 3টি Pod চলুক।

Scheduler Pod-গুলোর জন্য Node নির্বাচন করবে। এরপর সংশ্লিষ্ট Worker Node-এর kubelet কাজ শুরু করবে।

kubelet বলবে:

"আমার Node-এ এই Pod চালানোর কথা। ঠিক আছে, Runtime ভাই, Container তৈরি করে দাও!"

এরপর kubelet Container Runtime-এর মাধ্যমে Container চালানোর ব্যবস্থা করবে।

যদি Container ঠিকমতো চলে → kubelet Status রিপোর্ট করবে।

যদি Container Crash করে → kubelet এবং Runtime Pod-এর নির্ধারিত আচরণ অনুযায়ী Container পুনরায় চালানোর ব্যবস্থা করবে।

অর্থাৎ kubelet-এর কাজ হলো— "Pod যা হওয়ার কথা, Node-এ সেটি বাস্তবে আছে কি না নিশ্চিত করতে সাহায্য করা।"

2. containerd — Container-এর Manager

এবার kubelet containerd-এর কাছে গেল।

kubelet:
"ভাই containerd, এই Pod-এর Container চালাতে হবে।"

containerd:
"Image কোথায়?"

kubelet:
"Registry-তে আছে।"

containerd:
"ঠিক আছে। Image নিয়ে আসছি, Filesystem তৈরি করছি, তারপর Container চালানোর ব্যবস্থা করছি।"

runc পাশ থেকে:
"শেষে Process চালানোর কাজটা আমার!" 😎
containerd কী?

containerd হলো একটি Container Runtime। এটি Container-এর Lifecycle পরিচালনার জন্য ব্যবহৃত হয়।

সহজভাবে মনে রাখুন:

containerd = Container-এর Manager

এটি Image সংগ্রহ করা থেকে শুরু করে Container-এর Lifecycle পরিচালনা পর্যন্ত বিভিন্ন কাজ করে এবং নিচের স্তরের Runtime-এর সঙ্গে সমন্বয় করে।

containerd-এর প্রধান কাজ:

1. Registry থেকে Image Pull করা
2. Image-এর Content সংরক্ষণ ও পরিচালনা করা
3. Image-এর Filesystem Snapshot প্রস্তুত করা
4. Container-এর Root Filesystem প্রস্তুত করা
5. Container Configuration প্রস্তুত করা
6. OCI Runtime যেমন runc-এর মাধ্যমে Container Process চালানোর ব্যবস্থা করা
7. Container Lifecycle পরিচালনা করা
8. Container-এর State ও Resource সম্পর্কিত Runtime তথ্য পরিচালনা করা

containerd-এর কাজ এক নজরে

Container Lifecycle

একটি Container সাধারণত বিভিন্ন অবস্থার মধ্য দিয়ে যায়।
Creating
Container-এর জন্য প্রয়োজনীয় Configuration এবং Filesystem প্রস্তুত হচ্ছে।

Running
Container-এর মূল Process চলছে। Application কাজ করছে।

Stopped
Container-এর Process আর চলছে না।

Removed
Container-এর Runtime Resources পরিষ্কার করা হয়েছে।

3. runc — Container চালানোর নিম্নস্তরের Runtime

এখন আসল মাঠের খেলোয়াড়!

containerd অনেক কাজের Manager। কিন্তু শেষ পর্যন্ত Linux-এ Container-এর Process তৈরি করবে কে?

runc:
"এই কাজটা আমার!" 💪

containerd বলবে:
"ঠিক আছে ভাই, এই Container-এর Specification নাও। চালু করে দাও।"

runc Linux Kernel-এর বিভিন্ন Feature ব্যবহার করে Container-এর Process তৈরি করে।
runc কী?

runc হলো একটি OCI-compatible low-level Container Runtime। এটি Container-এর জন্য নির্ধারিত Configuration অনুসরণ করে Linux-এ Container Process তৈরি ও চালাতে সাহায্য করে।

সহজভাবে মনে রাখুন:

containerd = Container-এর Manager
runc = Container Process চালানোর Low-Level Runtime


runc-এর প্রধান কাজ:

1. Container-এর OCI Specification গ্রহণ করা
2. Linux Namespace তৈরি ও Configure করা
3. cgroups-এর মাধ্যমে Resource Control প্রয়োগ করা
4. Root Filesystem প্রস্তুত করা
5. প্রয়োজনীয় Mount Configure করা
6. Security-related Configuration প্রয়োগ করা
7. Container-এর মূল Process শুরু করা

runc এবং Linux Namespace

Container-কে Host System থেকে আলাদা অনুভব করানোর জন্য Linux Namespace গুরুত্বপূর্ণ ভূমিকা পালন করে।

PID Namespace
Container-এর Process-এর জন্য আলাদা Process View তৈরি করে।

Network Namespace
Container-এর জন্য আলাদা Network Environment তৈরি করে।

Mount Namespace
Container-এর Filesystem Mount-এর আলাদা View তৈরি করে।

User Namespace
User এবং Group ID Mapping-এর মাধ্যমে User Isolation করতে সাহায্য করে।

IPC Namespace
Inter-Process Communication Resource আলাদা করতে সাহায্য করে।

runc এবং cgroups

Namespace মূলত বলে— "তুমি কী কী দেখতে পারবে?"

আর cgroups বলে— "তুমি কতটুকু Resource ব্যবহার করতে পারবে?"

উদাহরণ হিসেবে একটি Container-এর জন্য নির্ধারণ করা যেতে পারে:

├─ CPU Limit
├─ Memory Limit
├─ Process/PID Limit
└─ I/O সম্পর্কিত Resource Control

উদাহরণ:

cpu: 500m
অর্থাৎ Kubernetes CPU Resource-এর হিসেবে 0.5 CPU-এর সমপরিমাণ Limit/Request বোঝাতে পারে, Configuration-এর প্রেক্ষাপট অনুযায়ী।

memory: 2Gi
অর্থাৎ 2 GiB Memory।

মনে রাখুন:
Kubernetes Resource Configuration → kubelet → Container Runtime → Linux cgroups—এই বিভিন্ন স্তরের মাধ্যমে Resource Control বাস্তবায়িত হয়।

4. Pod — Kubernetes-এর সবচেয়ে ছোট Deployable Unit

এবার আসি Pod-এ।

Kubernetes-এ আপনি সাধারণত বলেন না— "এই Container-টা চালাও।"

আপনি বলেন— "এই Pod চালাও।"

Pod-এর মধ্যে 1টি বা একাধিক Container থাকতে পারে।

Pod-কে ভাবতে পারেন একটি ছোট্ট Apartment হিসেবে। 🏠

Apartment-এর মধ্যে একাধিক মানুষ থাকতে পারে। তারা কিছু Resource Share করতে পারে, কিন্তু প্রত্যেকের নিজের কাজ আলাদা।

একইভাবে একটি Pod-এর মধ্যে একাধিক Container থাকতে পারে এবং তারা কিছু Resource Share করে।
Pod কী?

Pod হলো Kubernetes-এর সবচেয়ে ছোট Deployable Unit। একটি Pod-এর মধ্যে 1টি বা একাধিক Container থাকতে পারে।

একই Pod-এর Container-গুলো কিছু গুরুত্বপূর্ণ Resource Share করে।

Pod-এর Shared Resources:

1. Network Namespace
একই Pod-এর Container-গুলো সাধারণত একই Network Namespace ব্যবহার করে।

এর ফলে তারা একই Pod IP ব্যবহার করে এবং একে অপরের সঙ্গে localhost ব্যবহার করে যোগাযোগ করতে পারে।

2. Storage Volume
একই Volume একটি Pod-এর একাধিক Container-এর মধ্যে Mount করা যেতে পারে।

এর মাধ্যমে Container-গুলো প্রয়োজন অনুযায়ী File বা Data Share করতে পারে।

3. কিছু Security Context
Pod-level Security Context-এর মাধ্যমে কিছু Security-related Configuration একসঙ্গে নির্ধারণ করা যায়।

4. একই Lifecycle
Pod-এর মধ্যে থাকা Container-গুলো একই Pod-এর Lifecycle-এর অংশ। Kubernetes Pod-কে একটি Unit হিসেবে Schedule করে।

একটি Pod-এর ভেতরের চিত্র

Pod-এ একাধিক Container কেন?

সাধারণ Application-এর ক্ষেত্রে একটি Pod-এ 1টি প্রধান Application Container থাকাই সবচেয়ে সাধারণ Pattern।

তবে কিছু ক্ষেত্রে Application-এর পাশে Helper বা Sidecar Container চালানো হয়।

উদাহরণ:

1. Main Application + Logging Sidecar
Main Application কাজ করবে, আর Sidecar Log সংগ্রহ বা Forward করতে সাহায্য করবে।

2. Main Application + Proxy
Proxy Container Network বা Security-related কাজ করতে পারে।

3. Main Application + Monitoring Agent
অতিরিক্ত Container Metrics বা Monitoring-এর কাজে সহায়তা করতে পারে।

গুরুত্বপূর্ণ:
শুধু "দুটি Container দরকার" বলেই তাদের একই Pod-এ রাখতে হবে এমন নয়। তাদের যদি একই Lifecycle, Network এবং Storage Context Share করার প্রয়োজন থাকে, তখন একই Pod ব্যবহার করা অর্থপূর্ণ।

একটি Container চালু হওয়ার সম্পূর্ণ গল্প

সবাইকে এক লাইনে চিনে রাখুন

kubelet
→ "এই Node-এ যে Pod চালানোর কথা, সেটি ঠিকমতো চলছে কি না আমি দেখছি।"

containerd
→ "Container-এর Lifecycle এবং Image Management আমি সামলাই।"

runc
→ "Linux-এ আসল Container Process চালানোর Low-Level কাজটা আমি করি।"

Pod
→ "আমি Kubernetes-এর সবচেয়ে ছোট Deployable Unit। আমার মধ্যে 1টি বা একাধিক Container থাকতে পারে।"

একটি মজার উদাহরণ — Kubernetes Restaurant

ধরুন Kubernetes একটি বিশাল Restaurant। 🍽️

Control Plane = Restaurant Manager
কে কোথায় কাজ করবে, কতজন কর্মী দরকার—সব সিদ্ধান্ত নেয়।

Scheduler = Staff Coordinator
কোন Worker Node-এ নতুন Pod যাবে, সে সিদ্ধান্ত নেয়।

Worker Node = Kitchen
আসল রান্না এখানে হয়।

kubelet = Kitchen Supervisor
Manager যা বলেছে, Kitchen-এ ঠিকমতো হচ্ছে কি না দেখে।

containerd = Kitchen Operations Manager
কোন রান্নার Process কীভাবে চলবে, তার Runtime Management করে।

runc = Chef
"Recipe দাও, আমি রান্না করে দিচ্ছি!" 😎

Pod = একটি Kitchen Station
একই Station-এ থাকা Container-গুলো কিছু Resource Share করতে পারে।

Container = আসল রান্নার কাজ
শেষ পর্যন্ত Application-এর Process এখানেই চলছে।
শেষবারের মতো পুরো বিষয়টি মনে রাখুন:

Control Plane

সিদ্ধান্ত নেয় — "এই Pod কোথায় চলবে?"

Scheduler

Worker Node নির্বাচন করে

kubelet

Node-এ Pod চালানোর ব্যবস্থা করে

containerd

Container Lifecycle পরিচালনা করে

runc

Linux-এর সাহায্যে Container Process চালায়

Pod

Container-কে Kubernetes-এর Deployable Unit হিসেবে ধারণ করে

Container

আপনার Application-এর Process চালায়

Kubernetes-এর ভেতরের এই Layered Flow বুঝে ফেলতে পারলে Kubernetes আর "জাদুর বাক্স" মনে হবে না।

🔄 অংশ 6: কর্মপ্রবাহ এবং বাস্তব উদাহরণ

সম্পূর্ণ Workflow: Tamim-এর Web API Kubernetes-এ

Scenario:

Tamim একটি Web API তৈরি করেছে। তার Application Docker Container-এর মধ্যে ভালোভাবেই চলছে। এখন সে চায় Kubernetes ব্যবহার করে Application-টিকে Production Environment-এ চালাতে।

কিন্তু Tamim শুধু একটি Container চালাতে চায় না। সে চায়—

✓ Application-এর একাধিক Replica থাকবে
✓ কোনো Container বন্ধ হয়ে গেলে সেটি আবার চালু হবে
✓ কোনো Node নষ্ট হলেও Application সচল থাকবে
✓ প্রয়োজন হলে Replica সংখ্যা বাড়ানো যাবে
✓ নতুন Version ধীরে ধীরে Deploy করা যাবে

এখন দেখা যাক, Tamim শুধু একটি কমান্ড চালানোর পর Kubernetes-এর ভেতরে আসলে কতগুলো মানুষ... মানে Component কাজ শুরু করে! 😄

ধাপ 1: Dockerfile তৈরি

Tamim প্রথমে Application-এর জন্য Dockerfile তৈরি করে।

Dockerfile-এর মাধ্যমে সে বলে দেয় Application চালানোর জন্য কী কী প্রয়োজন।

যেমন—

• Python-এর নির্দিষ্ট Base Image ব্যবহার করা
• প্রয়োজনীয় Dependency ইনস্টল করা
• Application Code Container-এর মধ্যে কপি করা
• Working Directory নির্ধারণ করা
• Application কীভাবে চালু হবে তা নির্ধারণ করা
• প্রয়োজনীয় Port Document করা

উদাহরণ:

FROM python:3.9-slim
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]

ধাপ 2: Docker Image তৈরি

Tamim এখন Dockerfile ব্যবহার করে একটি Image তৈরি করে।

docker build -t tamim/api:v1.0 .

এখানে—

docker build → Docker Image তৈরি করার নির্দেশ
-t → Image-এর নাম ও Tag নির্ধারণ
tamim/api → Image-এর নাম
v1.0 → Version Tag
. → বর্তমান Directory-কে Build Context হিসেবে ব্যবহার করা

Build শেষ হলে Tamim-এর কাছে একটি Docker Image তৈরি হলো।

ধাপ 3: Image Registry-তে Push করা

Kubernetes-এর Worker Node-গুলো যেন Image-টি সংগ্রহ করতে পারে, তাই Tamim Image-টি একটি Container Registry-তে Push করে।

docker push tamim/api:v1.0

এখন Image-টি Registry-তে রয়েছে।

Worker Node যখন এই Image-এর প্রয়োজন অনুভব করবে, Container Runtime Registry থেকে Image Pull করতে পারবে।

অর্থাৎ—

Local Machine → Build
Registry → Store & Share
Worker Node → Pull & Run

ধাপ 4: Kubernetes Deployment তৈরি

এখন Tamim Kubernetes-কে বলে দিতে চায়— "আমি আমার Application-এর 3টি Replica চালু রাখতে চাই।"

এজন্য সে একটি Deployment তৈরি করে।
apiVersion: apps/v1
kind: Deployment

metadata:
  name: tamim-api

spec:
  replicas: 3

  selector:
    matchLabels:
      app: tamim-api

  template:
    metadata:
      labels:
        app: tamim-api

    spec:
      containers:
        - name: api
          image: tamim/api:v1.0

          ports:
            - containerPort: 5000

          resources:
            requests:
              cpu: 250m
              memory: 512Mi

            limits:
              cpu: 500m
              memory: 1Gi

          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: url

Deployment YAML-টি কী বলছে?

apiVersion: apps/v1
Kubernetes-এর কোন API Version ব্যবহার করা হচ্ছে তা নির্দেশ করে।

kind: Deployment
আমরা একটি Deployment Resource তৈরি করছি।

metadata.name: tamim-api
Deployment-এর নাম tamim-api

replicas: 3
Kubernetes-এর কাছে Desired State হলো— 3টি Pod চালু থাকা উচিত।

selector
Deployment কোন Pod-গুলোকে পরিচালনা করবে তা Label-এর মাধ্যমে নির্ধারণ করে।

template
নতুন Pod তৈরি করার Blueprint বা Template।

image: tamim/api:v1.0
Pod-এর Container কোন Docker Image ব্যবহার করবে তা নির্ধারণ করে।

containerPort: 5000
Application Container-এর ভিতরে 5000 Port ব্যবহার করছে—এটি Document করে।

resources.requests
Container-এর জন্য Kubernetes-কে নির্দিষ্ট পরিমাণ Resource প্রয়োজন বলে জানায়। Scheduler Node নির্বাচন করার সময় এই তথ্য ব্যবহার করতে পারে।

resources.limits
Container-এর Resource ব্যবহারের সর্বোচ্চ সীমা নির্ধারণ করে।

env + secretKeyRef
Sensitive Configuration সরাসরি YAML-এ না লিখে Kubernetes Secret থেকে Environment Variable হিসেবে নেওয়া হচ্ছে।

ধাপ 5: Deployment Kubernetes-এ পাঠানো

Tamim এখন চালাল—

kubectl apply -f deployment.yaml

এই একটি ছোট্ট কমান্ড দেখে মনে হতে পারে— "ব্যস! কাজ শেষ!" 😎

কিন্তু আসলে Kubernetes-এর ভেতরে তখন বিশাল কর্মযজ্ঞ শুরু হয়!

Deployment Apply করার পর ভিতরে কী ঘটে?

ধাপ 6: API Server অনুরোধ গ্রহণ করে

kubectl সরাসরি etcd-এর সঙ্গে কথা বলে না।

প্রথমে Request যায় Kubernetes-এর API Server-এর কাছে।

API Server তখন বিভিন্ন বিষয় যাচাই করে—

1. Request-এর Authentication
2. Authorization বা Permission
3. Resource-এর Configuration
4. YAML থেকে তৈরি Resource-এর বৈধতা

এরপর Kubernetes-এর Desired State সংরক্ষণের জন্য সংশ্লিষ্ট তথ্য etcd-তে রাখা হয়।

ধাপ 7: Deployment Controller কাজ শুরু করে

Deployment Controller দেখে—

"আচ্ছা! নতুন একটি Deployment এসেছে। এখানে বলা হয়েছে 3টি Replica দরকার।"

Controller তখন একটি ReplicaSet তৈরি বা আপডেট করার মাধ্যমে Desired Replica সংখ্যা বজায় রাখার ব্যবস্থা করে।

ধাপ 8: ReplicaSet 3টি Pod তৈরি করে

ReplicaSet দেখে—

Desired = 3
Current = 0

তাই সে বলে—

"আমার 3টা Pod দরকার। এখনই!" 😤

Kubernetes তখন 3টি Pod তৈরি করার জন্য API Server-এ Resource Object তৈরি করে।

ধাপ 9: Scheduler Pod-এর জন্য Node নির্বাচন করে

Pod তৈরি হয়েছে, কিন্তু এখনো Pod-এর জন্য নির্দিষ্ট Worker Node নির্বাচন করা হয়নি।

Scheduler তখন দেখে—

• কোন Node-এ পর্যাপ্ত CPU আছে?
• কোন Node-এ পর্যাপ্ত Memory আছে?
• Node-এর Taints ও Pod-এর Tolerations কী বলছে?
• Affinity বা Anti-Affinity Rule আছে কি?
• অন্যান্য Scheduling Constraint কী আছে?

তারপর Scheduler উপযুক্ত Node নির্বাচন করে।
Scheduler-এর সিদ্ধান্ত: Pod 1 → Worker Node 1 Pod 2 → Worker Node 2 Pod 3 → Worker Node 1 কারণ: Node 1 → পর্যাপ্ত Resource আছে Node 2 → পর্যাপ্ত Resource আছে Kubernetes চেষ্টা করতে পারে Pod-গুলোকে বিভিন্ন Node-এ ছড়িয়ে দিতে, যাতে একটি Node ব্যর্থ হলে সব Replica একসঙ্গে হারিয়ে না যায়।

ধাপ 10: kubelet কাজ শুরু করে

Scheduler সিদ্ধান্ত নেওয়ার পর সংশ্লিষ্ট Worker Node-এর kubelet বুঝতে পারে যে তার Node-এ নতুন Pod চালানোর দায়িত্ব এসেছে।

kubelet তখন Container Runtime-এর সঙ্গে যোগাযোগ করে।

kubelet:
"containerd ভাই, tamim/api:v1.0 Image দিয়ে এই Pod-এর Container চালাতে হবে।"

containerd:
"ঠিক আছে, Image আছে কি না দেখি!" 😎

ধাপ 11: containerd Image Pull করে

Worker Node-এ Image আগে থেকেই থাকলে containerd সেটি পুনরায় Download না করে বিদ্যমান Image ব্যবহার করতে পারে।

Image না থাকলে Registry থেকে Image Pull করা হয়।

তারপর containerd Image-এর Layer এবং Filesystem প্রস্তুত করে Container চালানোর জন্য প্রয়োজনীয় Runtime Configuration তৈরি করে।

ধাপ 12: containerd → runc

Container-এর জন্য Runtime Configuration প্রস্তুত হলে containerd OCI-compatible Runtime যেমন runc-এর মাধ্যমে Container Process চালানোর ব্যবস্থা করে।

runc তখন Linux Kernel-এর বিভিন্ন Feature ব্যবহার করে—

• Namespace
• cgroups
• Mounts
• Root Filesystem
• Security Configuration

সব প্রস্তুত করে Container-এর মূল Process চালু করে।

শেষ ফলাফল

এখন Kubernetes-এর কাছে—

Desired State: 3টি Pod
Actual State: 3টি Pod

এবং Tamim-এর Application চলছে—

Pod 1 → tamim/api:v1.0
Pod 2 → tamim/api:v1.0
Pod 3 → tamim/api:v1.0

Tamim তখন নিশ্চিন্তে চা খেতে যেতে পারে। ☕😎

যদি কোনো Container Crash করে?

পরিস্থিতি 1: Container Process Crash

ধরুন Pod 2-এর Application-এ Bug ছিল।

Application হঠাৎ Crash করল। 💥

তখন kubelet লক্ষ্য করবে যে Container-এর Process প্রত্যাশিত অবস্থায় নেই।

Pod-এর Restart Policy এবং Container-এর বর্তমান অবস্থার ভিত্তিতে kubelet Container Runtime-এর মাধ্যমে Container পুনরায় চালানোর ব্যবস্থা করতে পারে।

ফলে সাধারণ ক্ষেত্রে—

Pod 2 একই Pod হিসেবেই থাকতে পারে, কিন্তু তার Container পুনরায় চালু হয়।

পরিস্থিতি 2: পুরো Pod হারিয়ে গেলে

এবার ধরুন Pod 2 শুধু Crash করেনি— পুরো Pod-টাই আর নেই।

ReplicaSet Controller দেখে—

Desired = 3
Actual = 2

"এই যে! একটা Pod কম!"
😱

তখন ReplicaSet একটি নতুন Pod তৈরি করার ব্যবস্থা করবে। Scheduler নতুন Pod-এর জন্য উপযুক্ত Node নির্বাচন করবে এবং সেই Node-এর kubelet নতুন Container চালানোর ব্যবস্থা করবে।

পরিস্থিতি 3: একটি Worker Node ব্যর্থ হয়

এবার আরও বড় বিপদ। 😐

ধরুন Pod 1 এবং Pod 3 Worker Node 1-এ চলছে। হঠাৎ Worker Node 1 সম্পূর্ণ Offline হয়ে গেল।

Server Hardware Failure! Power Failure! Network Failure! যেকোনো কিছু হতে পারে।

Kubernetes তখন Node-এর Health Status পর্যবেক্ষণ করে এবং Node-টি Ready অবস্থায় নেই বলে চিহ্নিত করতে পারে।

এরপর Kubernetes-এর বিভিন্ন Controller ও Scheduling Mechanism-এর মাধ্যমে হারিয়ে যাওয়া Workload পুনরায় চালানোর ব্যবস্থা করা হয়, যদি সংশ্লিষ্ট Workload-এর Desired State তা নির্দেশ করে।

একটি গুরুত্বপূর্ণ বিষয়: Desired State বনাম Actual State

Kubernetes বোঝার জন্য এই ধারণাটি অত্যন্ত গুরুত্বপূর্ণ।

Tamim বলেছে:

Desired State = 3 Replicas

Kubernetes ক্রমাগত চেষ্টা করে—

Actual State ≈ Desired State

যদি কোনো সময়—

Desired = 3
Actual = 2

তাহলে Kubernetes-এর Controller বলবে—

"একটা কম আছে। ঠিক করতে হবে।"

আবার যদি—

Desired = 3
Actual = 4

তাহলে Controller অতিরিক্ত Resource সরিয়ে Desired State-এর দিকে নিয়ে যাওয়ার ব্যবস্থা করবে।

এটাই Kubernetes-এর অন্যতম গুরুত্বপূর্ণ ধারণা: Declarative Desired State এবং Reconciliation.

📝 অংশ 7: ব্যবহারিক কমান্ড — হাতে-কলমে Kubernetes ও Docker

এতক্ষণ আমরা তত্ত্ব শিখলাম।

এখন সময় এসেছে Keyboard-এ হাত দেওয়ার। 😎

কারণ Kubernetes সম্পর্কে 500 পৃষ্ঠা পড়ে যদি শেষ পর্যন্ত kubectl get pods লিখতে না পারেন, তাহলে Kubernetes আপনাকে দেখে বলবে— "ভাই, আগে আমাকে চালিয়ে দেখেন!" 😄

Docker-এর প্রয়োজনীয় কমান্ড

কমান্ড কাজ উদাহরণ
docker build Docker Image তৈরি docker build -t tamim/api:v1.0 .
docker run Container চালু docker run -p 5000:5000 tamim/api:v1.0
docker ps চলমান Container দেখা docker ps
docker ps -a সব Container দেখা docker ps -a
docker images স্থানীয় Image দেখা docker images
docker logs Container-এর Log দেখা docker logs container-id
docker stop Container বন্ধ করা docker stop container-id
docker start বন্ধ Container আবার চালু করা docker start container-id
docker rm Container মুছে ফেলা docker rm container-id
docker pull Registry থেকে Image নামানো docker pull python:3.9
docker push Registry-তে Image পাঠানো docker push tamim/api:v1.0

Kubernetes-এর প্রয়োজনীয় কমান্ড

কমান্ড কাজ উদাহরণ
kubectl apply -f Manifest তৈরি বা আপডেট kubectl apply -f deployment.yaml
kubectl get pods Pod-এর তালিকা দেখা kubectl get pods
kubectl get pods -o wide Pod কোন Node-এ চলছে দেখা kubectl get pods -o wide
kubectl get nodes Cluster-এর Node দেখা kubectl get nodes
kubectl get deployments Deployment দেখা kubectl get deployments
kubectl get replicasets ReplicaSet দেখা kubectl get replicasets
kubectl describe pod Pod-এর বিস্তারিত তথ্য kubectl describe pod pod-name
kubectl logs Pod-এর Container Log দেখা kubectl logs pod-name
kubectl exec -it Container-এর ভিতরে Command চালানো kubectl exec -it pod-name -- bash
kubectl scale Replica সংখ্যা পরিবর্তন kubectl scale deployment tamim-api --replicas=5
kubectl delete Resource মুছে ফেলা kubectl delete -f deployment.yaml

সবচেয়ে গুরুত্বপূর্ণ Debugging কমান্ড

Pod চলছে না?

প্রথমে দেখুন:
kubectl get pods

তারপর বিস্তারিত দেখুন:
kubectl describe pod pod-name

Log দেখুন:
kubectl logs pod-name

একাধিক Container থাকলে নির্দিষ্ট Container-এর Log দেখুন:
kubectl logs pod-name -c container-name

Container-এর ভিতরে ঢুকতে চাইলে:
kubectl exec -it pod-name -- bash

Kubernetes Debugging-এর সহজ সূত্র:

get → describe → logs → exec

একটি ছোট্ট বাস্তব অনুশীলন

1. Deployment তৈরি করুন:
kubectl apply -f deployment.yaml

2. Pod দেখুন:
kubectl get pods

3. Pod কোন Node-এ চলছে দেখুন:
kubectl get pods -o wide

4. Deployment দেখুন:
kubectl get deployment

5. Replica সংখ্যা বাড়ান:
kubectl scale deployment tamim-api --replicas=5

6. আবার Pod দেখুন:
kubectl get pods

এবার আপনি নিজেই দেখতে পাবেন Kubernetes কীভাবে নতুন Pod তৈরি করছে।
এই অংশের মূল শিক্ষা:

Docker আমাদের Application-কে Package করে।

Registry সেই Image সংরক্ষণ ও বিতরণ করে।

Kubernetes সেই Containerized Application-কে বৃহৎ পরিসরে চালানো ও পরিচালনা করে।

আর ভিতরে ভিতরে—

API Server → Controller → ReplicaSet → Scheduler → kubelet → containerd → runc → Container

এই পুরো Workflow বুঝে গেলে Kubernetes-এর "জাদু" আসলে আর জাদু থাকে না। এটি হয়ে যায় একটি সুসংগঠিত Reconciliation System।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.