Kubernetes Service ও Ingress
এই পাঠে যা শিখবেন
- Pod-এর ক্রমাগত-পরিবর্তনশীল IP ঠিকানার সমস্যা এবং Service কীভাবে তা সমাধান করে
- label selector দিয়ে Service কীভাবে সঠিক পড-গুলো খুঁজে পায় — একটি Python সিমুলেশনের মাধ্যমে
- ClusterIP, NodePort ও LoadBalancer — তিনটি Service টাইপের পার্থক্য
- Ingress কীভাবে একটি একক এন্ট্রি পয়েন্ট থেকে অনেকগুলো Service-এ রাউট করে
১ · সমস্যা — পড-এর ঠিকানা ক্রমাগত পরিবর্তিত হয়
L28-এ আমরা দেখেছি Pod-গুলো ephemeral — একটি পড ক্র্যাশ করলে ReplicaSet একটি সম্পূর্ণ নতুন পড তৈরি করে, যেটি একটি সম্পূর্ণ নতুন IP ঠিকানা পায়। তাহলে অন্য একটি পড বা বাইরের একজন ক্লায়েন্ট কীভাবে নির্ভরযোগ্যভাবে এই ক্রমাগত-পরিবর্তনশীল পড-সেটের সাথে যোগাযোগ করবে? সরাসরি IP হার্ডকোড করা কাজ করবে না — সেই IP যেকোনো মুহূর্তে অকেজো হয়ে যেতে পারে।
২ · Service — একটি স্থিতিশীল ঠিকানা
ServiceKubernetes Serviceএকটি স্থিতিশীল ভার্চুয়াল IP/DNS নাম যা একটি label selector-এর সাথে মিলে যাওয়া বর্তমান পড-গুলোর মধ্যে স্বয়ংক্রিয়ভাবে ট্রাফিক লোড-ব্যালেন্স করে। এই সমস্যার সমাধান দেয় — এটি একটি স্থিতিশীল ভার্চুয়াল IP ঠিকানা (এবং একটি DNS নাম) প্রদান করে যা কখনও পরিবর্তন হয় না, এবং label selectorLabel Selectorএক বা একাধিক key-value জোড়া যা দিয়ে একটি Service ঠিক করে কোন পড-গুলো তার ট্রাফিকের লক্ষ্য — শুধু যেসব পডের লেবেল সব শর্ত মেলে সেগুলোই অন্তর্ভুক্ত হয়। দিয়ে বর্তমানে কোন পড-গুলো ম্যাচ করে তা ক্রমাগত পুনর্গণনা করে। এটি সরাসরি L15-এর সার্ভিস-ডিসকভারি ধারণার একটি অভ্যন্তরীণ, ক্লাস্টার-নেটিভ বাস্তবায়ন — পড আসুক বা যাক, Service-এর ঠিকানা কখনও বদলায় না।
শুধু ক্লাস্টারের ভেতর থেকেই অ্যাক্সেসযোগ্য — অভ্যন্তরীণ মাইক্রোসার্ভিস যোগাযোগের জন্য।
প্রতিটি ওয়ার্কার নোডের নিজস্ব IP-তে একটি নির্দিষ্ট পোর্ট খুলে দেয় — সহজ কিন্তু কম ব্যবহৃত প্রোডাকশনে।
একটি আসল ক্লাউড লোড ব্যালেন্সার প্রভিশন করে (L14-এর ধারণা) — বাইরের ট্রাফিকের জন্য সবচেয়ে সাধারণ।
৩ · Ingress — একটি একক প্রবেশপথ, অনেক Service
IngressIngressক্লাস্টারে বাইরের HTTP(S) ট্রাফিক প্রবেশের ব্যবস্থাপনা — পাথ বা হোস্টনেম অনুযায়ী ভিন্ন ভিন্ন Service-এ রাউট করে, একটি একক এন্ট্রি পয়েন্ট থেকে।
প্রতিটি Service-এর জন্য আলাদা LoadBalancer ব্যবহার করা ব্যয়বহুল ও ব্যবস্থাপনা-জটিল হতে পারে। Ingress একটি একক
প্রবেশপথ দেয় যা পাথ (যেমন /api বনাম /images) বা হোস্টনেম অনুযায়ী ভিন্ন ভিন্ন
Service-এ ট্রাফিক রাউট করে — ধারণাগতভাবে system-design কোর্সের API gateway-এর সাথে মিল রয়েছে। এটি অনেকগুলো
ব্যাকএন্ড Service-কে একটি একক, সুসংগঠিত বাইরের ঠিকানার পেছনে সাজিয়ে রাখে।
# Label-selector-ভিত্তিক Service রাউটিং সিমুলেশন
# (fake in-memory ডেটা — বাস্তব kubectl/cluster-এর বিরুদ্ধে চলছে না)
pods = [
{"id": "pod-1", "labels": {"app": "web", "version": "v1"}},
{"id": "pod-2", "labels": {"app": "web", "version": "v2"}},
{"id": "pod-3", "labels": {"app": "web", "version": "v2"}},
{"id": "pod-4", "labels": {"app": "worker", "version": "v2"}},
]
def get_matching_pods(pods, selector):
"""selector-এর সবগুলো key-value শর্ত মেলে এমন পড-গুলোর id ফেরত দেয়।"""
matches = []
for pod in pods:
if all(pod["labels"].get(k) == v for k, v in selector.items()):
matches.append(pod["id"])
return matches
service_selector = {"app": "web", "version": "v2"}
print("Service selector:", service_selector)
print("বর্তমান ম্যাচিং পড:", get_matching_pods(pods, service_selector))
# pod-2 রোলিং-আপডেটে সরে গেল, নতুন pod-5 (v2) যোগ হলো — L28-এর মতোই একটি স্বাভাবিক পরিবর্তন
pods = [p for p in pods if p["id"] != "pod-2"]
pods.append({"id": "pod-5", "labels": {"app": "web", "version": "v2"}})
print("\nপড-সেট পরিবর্তনের পরে (pod-2 সরে গেছে, pod-5 যোগ হয়েছে):")
print("নতুন ম্যাচিং পড:", get_matching_pods(pods, service_selector))
print("Service-এর ঠিকানা কিন্তু এই পুরো সময়ে একটুও বদলায়নি")
get_matching_pods() প্রতিবার নতুন করে চালানো হয়েছে, কিন্তু কোনো পরিবর্তন
Service-এর নিজের ঠিকানায় প্রভাব ফেলেনি। বাস্তবে Kubernetes এই ম্যাচিং প্রক্রিয়া ক্রমাগত, স্বয়ংক্রিয়ভাবে চালায় —
একটি পড যোগ/অপসারণ/রিলেবেল হওয়া মাত্র Service-এর লক্ষ্য-তালিকা আপডেট হয়ে যায়, কোনো ম্যানুয়াল হস্তক্ষেপ ছাড়াই।
Service ও Ingress একসাথে Pod-এর অস্থিরতাকে অন্য সবার কাছে অদৃশ্য করে দেয় — Service ভেতরের জন্য একটি স্থিতিশীল ঠিকানা দেয়, Ingress বাইরের জন্য একটি সুসংগঠিত প্রবেশপথ দেয়। পরবর্তী পাঠে আমরা দেখব কীভাবে অ্যাপ্লিকেশনের কনফিগারেশন ও সংবেদনশীল ডেটা (পাসওয়ার্ড, API কী) একইভাবে ইমেজ থেকে বাইরে রাখা যায়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ Service-এর ঠিকানা পড-এর ঠিকানার চেয়ে "স্থিতিশীল" — এই স্থিতিশীলতা ছাড়া বাস্তবে কী সমস্যা হতো?
Service ছাড়া, একটি অ্যাপ্লিকেশনকে অন্য মাইক্রোসার্ভিসের সাথে যোগাযোগ করতে হলে প্রতিবার পড-এর IP পরিবর্তন হওয়ার সাথে সাথে নিজেই ট্র্যাক করে রাখতে হতো — যেটি Pod-এর ephemeral প্রকৃতির কারণে ক্রমাগত ঘটে (L28)। প্রতিটি ক্লায়েন্টকে নিজে থেকে এই আপডেট ট্র্যাক করতে হলে সিস্টেম ভঙ্গুর ও জটিল হয়ে যেত — Service এই পুরো সমস্যা একটি স্থিতিশীল ঠিকানার পেছনে লুকিয়ে ফেলে।
প্র ০২ ClusterIP, NodePort ও LoadBalancer-এর মধ্যে কখন কোনটা বেছে নেবেন?
অভ্যন্তরীণ মাইক্রোসার্ভিস যোগাযোগের জন্য (যেমন একটি ব্যাকএন্ড সার্ভিস অন্য একটি ইন্টারনাল সার্ভিসকে কল করছে) ClusterIP যথেষ্ট ও সবচেয়ে নিরাপদ (least-privilege ধারণা, L16)। বাইরের ব্যবহারকারীদের জন্য প্রোডাকশনে সাধারণত LoadBalancer (বা তার উপরে Ingress) ব্যবহৃত হয়। NodePort মূলত ডেভেলপমেন্ট/টেস্টিং বা এমন পরিবেশে ব্যবহৃত হয় যেখানে একটি সম্পূর্ণ ক্লাউড লোড ব্যালেন্সার প্রভিশন করার সুবিধা নেই।
প্র ০৩ Ingress আর একটি Service-এর মধ্যে পার্থক্য কী — একটির বদলে শুধু আরেকটি ব্যবহার করলেই কি চলে না?
একটি একক LoadBalancer Service একটি একক ব্যাকএন্ডের দিকে ট্রাফিক পাঠায়, কিন্তু বাস্তব অ্যাপ্লিকেশনে
প্রায়ই একাধিক ব্যাকএন্ড Service থাকে (যেমন /api এক Service-এ, /images আরেক
Service-এ)। Ingress একটি একক এন্ট্রি পয়েন্ট থেকে পাথ/হোস্ট দেখে সঠিক Service বেছে নেওয়ার এই "রাউটিং
লজিক" যোগ করে — প্রতিটি ব্যাকএন্ডের জন্য আলাদা, ব্যয়বহুল LoadBalancer তৈরি না করেই।
অনুশীলন
-
চিন্তা করুন: যদি
service_selector-এ শুধু{"app": "web"}থাকত (version না থাকত), তাহলেpodsতালিকায় কোন কোন পড ম্যাচ করত?তখন
pod-1(v1) এবংpod-2/pod-3(v2) সবগুলোই ম্যাচ করত, কারণ selector-এ শুধুappকী-এর শর্ত আছে। এটি দেখায় কেন একটি Service-এর selector-এ কতগুলো কী রাখা হয়েছে তা সরাসরি নির্ধারণ করে কতটা "সংকীর্ণ" বা "বিস্তৃত" তার লক্ষ্য-গোষ্ঠী — উদাহরণস্বরূপversionবাদ দিলে v1 ও v2 উভয় ভার্সনই একসাথে ট্রাফিক পেত, যা একটি ক্যানারি রোলআউটের (M8/L37) সময় অনিচ্ছাকৃতভাবে ঘটলে সমস্যা তৈরি করতে পারে। -
পরীক্ষা করুন:
podsতালিকায় একটি নতুন পড যোগ করুন যার লেবেল{"app": "web", "version": "v3"}— নিশ্চিত করুন এটিservice_selector = {"app": "web", "version": "v2"}-এর সাথে ম্যাচ করে না।v3 পড
get_matching_pods()-এর ফলাফলে আসবে না, কারণversionকী-এর মান ("v3") selector-এর প্রত্যাশিত মানের ("v2") সাথে মেলে না —all()শর্তটি একটি key-value-ও না মিললে পুরো পড বাদ দেয়। এটিই একটি Service-কে নির্দিষ্ট একটি ভার্সনের দিকেই ট্রাফিক পাঠাতে সাহায্য করে, বাকি ভার্সনের পড থাকলেও।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ পরবর্তী পাঠ — ConfigMap, Secret ও Volume — অ্যাপ্লিকেশনের কনফিগারেশন ও সংবেদনশীল ডেটা কীভাবে ম্যানেজ করবেন তা দেখাবে।
- System Design & Software Architecture কোর্স সঙ্গী কোর্স API gateway ও লোড ব্যালেন্সিং প্যাটার্ন আরও গভীরভাবে দেখুন।
- Cybersecurity & Ethical Hacking কোর্স সঙ্গী কোর্স ক্লাস্টারের নেটওয়ার্ক এক্সপোজার নিরাপদ রাখার কৌশল শিখতে দেখুন।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity ও Cloud Computing & DevOps — সব এক জায়গায়।