Skip to content
← অর্কেস্ট্রেশন · প্রাথমিক · 10 মিনিট · 01 / 06 EN

Kubernetes Fundamentals

Pods, deployments, services, আর control loop — Kubernetes আসলে কী করে এবং যে primitive-গুলোর উপর বাকি সবকিছু দাঁড়িয়ে।

Kubernetespodsdeploymentsservicescontrol loopkubectl

গল্পে বুঝি

ফাতিমা আল-ফিহরি একটা নাচের প্রোডাকশনের ডিরেক্টর। তার হাতে একটা বাঁধা স্ক্রিপ্ট, আর সেই স্ক্রিপ্টে লেখা একটাই কড়া নিয়ম — “মঞ্চে সবসময় ঠিক তিনজন নাচিয়ে থাকবে, একটাও কম নয়।” ফাতিমা কখনো নিজে দৌড়ে গিয়ে কাকে মঞ্চে পাঠাবে সেটা ঠিক করে না; সে শুধু স্ক্রিপ্টটা মঞ্চের সামনে ধরে রাখে আর ক্রমাগত মিলিয়ে দেখে — মঞ্চের বাস্তব অবস্থা স্ক্রিপ্টের সাথে মিলছে তো? এক শো-তে এক নাচিয়ে হঠাৎ অজ্ঞান হয়ে পড়ে গেল, মঞ্চে রইল দুজন। মুহূর্তের মধ্যে উইংসে দাঁড়িয়ে থাকা একজন আন্ডারস্টাডি ছুটে এসে জায়গা নিয়ে নিল, আবার তিনজন। ফাতিমাকে কিছুই আলাদা করে বলতে হয়নি — স্ক্রিপ্ট আর বাস্তবের ফাঁকটা সে নিজেই মিটিয়ে দিয়েছে।

এই প্রোডাকশনে পারফর্মাররা একা নড়াচড়া করে না। প্রতিটা নাচিয়ের সাথে বাঁধা থাকে তার নিজের একজন আলো-ধরা সহকারী আর একজন মেকআপ আর্টিস্ট — এই ছোট দলটা সবসময় একসাথে মঞ্চে ঢোকে, একসাথে বেরোয়। আর দর্শকদের কথা ভাবুন: হলের সামনে একজন আশার (usher) দাঁড়িয়ে আছে। কোন নাচিয়ে আজ রাতে পারফর্ম করছে সেটা কোনো দর্শককে জানতে হয় না — তারা শুধু আশারকে বলে “নাচিয়েদের কাছে যাব”, আর আশার তাদের ঠিক জায়গায় পাঠিয়ে দেয়। কাল যদি পুরো তিনজন বদলে যায়, দর্শকের কিছুই বদলায় না; আশার একই ঠিকানা।

গল্পটা হুবহু Kubernetes। স্ক্রিপ্টের “তিনজন নাচিয়ে” হলো আপনার desired state, আর ফাতিমার বারবার মিলিয়ে দেখে ফাঁক মেটানোটাই controller-এর reconciliation (control loop)। নাচিয়ে + তার সহকারী + মেকআপ আর্টিস্ট — একসাথে ঢোকা এই ছোট দলটা একটা pod (একসাথে চলা container-দের গুচ্ছ)। “সবসময় ঠিক তিনজন” নিয়মটা ধরে রাখা, আর অজ্ঞান হওয়া নাচিয়ের জায়গায় আন্ডারস্টাডি বসানো — এটাই একটা deployment, যা নির্দিষ্ট সংখ্যক replica বজায় রাখে আর নিজে থেকে self-healing করে। আর আশার হলো service — বদলাতে থাকা pod-দের সামনে একটা স্থিতিশীল ঠিকানা, যাতে ক্লায়েন্টকে কখনো জানতে না হয় ঠিক কোন pod এখন সাড়া দিচ্ছে। বাস্তবে ঠিক এভাবেই একটা pod ক্র্যাশ করলে deployment নতুন pod তুলে দেয় আর service-এর IP অপরিবর্তিত থাকে — তাই আপনার অ্যাপ চলতেই থাকে, কেউ টেরও পায় না।

বাস্তব জীবনের উদাহরণ

একটা সেল্‌ফ-কারেক্টিং ফ্যাক্টরি ফ্লোর: আপনি ফ্যাক্টরি ম্যানেজারকে বলেন “সবসময় ৩টা welding robot চালু থাকা চাই।” কোন রোবটগুলো বা ভাঙলে কীভাবে রিস্টার্ট করতে হবে সেটা আপনি বলে দেন না — ম্যানেজার সেটা সামলায়। কোনো রোবট ফেইল করলে সেটা অটোমেটিক রিপ্লেস হয়ে যায়। ৫টা লাগলে আপনি সংখ্যাটা আপডেট করেন, বাকিটা ম্যানেজার বুঝে নেয়। container-এর জন্য Kubernetes হলো সেই ফ্যাক্টরি ম্যানেজার।

The Control Loop

Kubernetes-এর সবকিছু একই প্যাটার্ন অনুসরণ করে:

Desired state (what you declared) → Controller watches → Actual state
                    ↑                                          |
                    └── Controller reconciles ←────────────────┘

আপনি যা চান সেটা declare করেন (order-service-এর ৩টা replica)। Controller-রা ক্রমাগত desired state আর actual state তুলনা করে এবং ফাঁকটা মিটিয়ে দিতে পরিবর্তন আনে। একটা pod ক্র্যাশ করলো → actual state নেমে ২ হলো → controller নতুন একটা pod তৈরি করলো → actual state আবার ৩-এ ফিরে এলো।

এটাই declarative: আপনি ফলাফল বর্ণনা করেন, ধাপগুলো নয়।

Core Objects

Pod: সবচেয়ে ছোট deployable unit। এক বা একাধিক container যারা network আর storage শেয়ার করে। একটা pod-এর ভেতরের container-রা localhost দিয়ে যোগাযোগ করে।

# Pods are rarely created directly — use Deployments
apiVersion: v1
kind: Pod
metadata:
  name: order-service
  labels:
    app: order-service
spec:
  containers:
    - name: order-service
      image: myorg/order-service:1.2.0
      ports:
        - containerPort: 3000
      env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: order-service-secrets
              key: database_url
      resources:
        requests:
          memory: '128Mi'
          cpu: '100m'
        limits:
          memory: '256Mi'
          cpu: '500m'

Deployment: একটা ReplicaSet ম্যানেজ করে যা আবার Pod-গুলো ম্যানেজ করে। rolling update আর rollback সামলায়।

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1 # create 1 extra pod before killing old
      maxUnavailable: 0 # never go below desired replicas during update
  template:
    metadata:
      labels:
        app: order-service
        version: '1.2.0'
    spec:
      containers:
        - name: order-service
          image: myorg/order-service:1.2.0
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 5
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /health/live
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10
          resources:
            requests:
              memory: '256Mi'
              cpu: '250m'
            limits:
              memory: '512Mi'
              cpu: '1000m'
          lifecycle:
            preStop:
              exec:
                command: ['sleep', '5']
      terminationGracePeriodSeconds: 35

Service: একদল pod-এর জন্য একটা স্থিতিশীল network endpoint। Pod আসে-যায় নতুন IP নিয়ে; কিন্তু Service IP অপরিবর্তিত থাকে।

apiVersion: v1
kind: Service
metadata:
  name: order-service
  namespace: production
spec:
  selector:
    app: order-service # routes to pods with this label
  ports:
    - port: 80
      targetPort: 3000
  type: ClusterIP # internal only

Service type-গুলো:

  • ClusterIP — শুধু cluster-এর ভেতরের IP (default)
  • NodePort — প্রতিটা node-এ একটা static port-এ expose করে
  • LoadBalancer — cloud load balancer provision করে (AWS ALB, GCP LB)

Namespaces

Namespace ক্লাস্টারকে ভার্চুয়াল সাব-ক্লাস্টারে ভাগ করে। ভিন্ন namespace-এর resource-গুলো একে অপর থেকে isolated (আলাদা RBAC, resource quota, network policy)।

kubectl create namespace production
kubectl create namespace staging

# Deploy to a specific namespace
kubectl apply -f deployment.yml -n production

Essential kubectl

# Context and cluster
kubectl config get-contexts
kubectl config use-context k3s-production

# Get resources
kubectl get pods -n production
kubectl get deployments -n production
kubectl get services -n production
kubectl get all -n production   # everything

# Inspect
kubectl describe pod order-service-7d4b5-xyz -n production
kubectl logs order-service-7d4b5-xyz -n production --tail=100 -f
kubectl exec -it order-service-7d4b5-xyz -n production -- sh

# Apply and delete
kubectl apply -f deployment.yml
kubectl delete -f deployment.yml

# Rollouts
kubectl rollout status deployment/order-service -n production
kubectl rollout history deployment/order-service -n production
kubectl rollout undo deployment/order-service -n production        # rollback
kubectl rollout undo deployment/order-service --to-revision=3 -n production

# Scale
kubectl scale deployment order-service --replicas=5 -n production

# Port-forward for debugging
kubectl port-forward pod/order-service-7d4b5-xyz 3000:3000 -n production

ConfigMaps and Secrets

apiVersion: v1
kind: ConfigMap
metadata:
  name: order-service-config
  namespace: production
data:
  LOG_LEVEL: 'info'
  QUEUE_CONCURRENCY: '10'
  FEATURE_NEW_CHECKOUT: 'true'
apiVersion: v1
kind: Secret
metadata:
  name: order-service-secrets
  namespace: production
type: Opaque
data:
  # base64-encoded values (echo -n "value" | base64)
  database_url: cG9zdGdyZXM6Ly8...
  jwt_secret: c2VjcmV0...

pod-এ reference করা:

spec:
  containers:
    - name: order-service
      envFrom:
        - configMapRef:
            name: order-service-config
      env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: order-service-secrets
              key: database_url

Secret কখনো git-এ commit করবেন না। এগুলো ম্যানেজ করতে Sealed Secrets, External Secrets Operator, বা Vault ব্যবহার করুন। Base64 কোনো encryption নয়।

Resource Requests and Limits

requests — pod-কে যা guaranteed দেওয়া হয়। Scheduler এটা দিয়ে যথেষ্ট capacity আছে এমন একটা node খুঁজে নেয়। limits — একটা pod সর্বোচ্চ যতটা ব্যবহার করতে পারবে। memory limit ছাড়িয়ে গেলে container OOMKilled হয়।

resources:
  requests:
    memory: '256Mi'
    cpu: '250m' # 250 millicores = 0.25 CPU cores
  limits:
    memory: '512Mi'
    cpu: '1000m' # 1 full core

Memory: সবসময় limit সেট করুন। OOM-killed pod রিস্টার্ট হয়; কিন্তু OOM node সবকিছু evict করে দেয়।

CPU: limit ছাড়িয়ে গেলে container throttle হয় (kill হয় না)। CPU limit বেশি নিচে রাখলে latency বাড়ে। অনেক টিম CPU request সেট করে কিন্তু limit করে না — এতে pod সঠিকভাবে schedule হওয়ার পরও burst করতে পারে।

Ingress

external traffic-কে service-এর দিকে route করে:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: '10m'
    cert-manager.io/cluster-issuer: 'letsencrypt-prod'
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls-cert
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /api/orders
            pathType: Prefix
            backend:
              service:
                name: order-service
                port:
                  number: 80
          - path: /api/products
            pathType: Prefix
            backend:
              service:
                name: product-service
                port:
                  number: 80

ক্লাস্টারে একটা ingress controller (nginx-ingress) ইনস্টল থাকা লাগে। cert-manager অটোমেটিক Let’s Encrypt সার্টিফিকেট provision আর renew করে।

Labels and Selectors

Label হলো যেকোনো resource-এর উপর key-value pair। Selector label দিয়ে resource ফিল্টার করে। Kubernetes-এর পুরো scheduling আর routing মডেল label-এর উপর নির্ভরশীল।

# Find pods by label
kubectl get pods -l app=order-service -n production
kubectl get pods -l app=order-service,version=1.2.0 -n production

# Add a label to a running pod (for debugging)
kubectl label pod order-service-7d4b5-xyz debug=true -n production

# Remove a pod from a Service (stop routing to it without killing)
kubectl label pod order-service-7d4b5-xyz app=order-service-debug --overwrite -n production
# Service selector no longer matches — this pod gets no traffic
# Use this to debug a single instance under real conditions