🐳 ডকার এবং কুবারনেটস
সম্পূর্ণ বাংলা গাইড - প্রযুক্তিগত বিস্তারিত সহ
📑 বিষয়বস্তু
- অংশ ১: সমস্যা এবং সমাধান
- অংশ ২: ইতিহাস - কীভাবে আমরা এখানে এলাম
- অংশ ৩: ডকার - সম্পূর্ণ বোঝাপড়া
- অংশ ৪: কুবারনেটস - আর্কিটেকচার
- অংশ ৫: কম্পোনেন্ট ডিটেইলস
- অংশ ৬: কর্মপ্রবাহ এবং উদাহরণ
- অংশ ৭: ব্যবহারিক কমান্ড
🤔 অংশ ১: সমস্যা এবং সমাধান
বাস্তব গল্প: তামিম ও জয়
দৃশ্য ১: একটি স্টার্টআপ অফিস
তামিম: "আমি একটি দারুণ ওয়েব অ্যাপ্লিকেশন তৈরি করেছি। এটি আমার ল্যাপটপে একদম নিখুঁতভাবে কাজ
করছে।" ✅
জয়: "তামিম ভাই, আমাকে কোডটা দিন। আমি আমার মেশিনে পরীক্ষা করে দেখি।"
(এক ঘণ্টা পরে)
জয়: "তামিম ভাই, এটা তো কাজ করছে না! সার্ভার ক্র্যাশ করছে।" 💥
তামিম: "কী বলছেন! আমার মেশিনে তো একদম ঠিকঠাক কাজ করছে... তাহলে সমস্যা কোথায়?" 😕
আসল সমস্যা কোথায়?
মূল সমস্যা হলো—দুইটি মেশিনের পরিবেশ এক নয়।
তামিমের মেশিনে:
• 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।