পাঠ ৫৪ · ৫৭-এর মধ্যে · মডিউল ১৩
Home / Courses / Cloud Computing & DevOps / কেস স্টাডি: CI/CD পাইপলাইন

কেস স্টাডি: একটি সম্পূর্ণ CI/CD পাইপলাইন তৈরি করা

Case study: building a full CI/CD pipeline
১০ মিনিট পড়া উন্নত · Advanced কেস স্টাডি Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • একটি বাস্তব এন্ড-টু-এন্ড CI/CD পাইপলাইনের প্রতিটি ধাপ কোন লেসনের কৌশল থেকে আসে
  • কেন প্রতিটি ধাপ শুধুমাত্র আগের ধাপ পাস করলেই চলে (fail-fast চেইনিং)
  • একাধিক আলাদা লেসনের সিমুলেটেড ফাংশন কীভাবে একটি একক পাইপলাইনে চেইন করা যায়
  • ডেলিভারি-গেট ও ক্যানারি রোলআউট একসাথে কীভাবে কাজ করে একটি বাস্তব রিলিজে

১ · কনটেক্সট — সমস্যা

একটি নতুন সার্ভিস তৈরি হয়েছে, কিন্তু এখনও এর কোনো স্বয়ংক্রিয় ডেলিভারি পথ নেই — ডেভেলপাররা ম্যানুয়ালি বিল্ড করে, ম্যানুয়ালি সার্ভারে কপি করে ডিপ্লয় করছে। লক্ষ্য: একটি একক, স্বয়ংক্রিয় পাইপলাইন তৈরি করা যা একটি কোড কমিট থেকে শুরু করে নিরাপদে প্রোডাকশন পর্যন্ত পৌঁছায় — কোনো ম্যানুয়াল, ভুল-প্রবণ ধাপ ছাড়াই।

২ · অ্যাপ্রোচ — ধাপে ধাপে, প্রতিটি আগের লেসনের প্রয়োগ

সোর্স কমিট একটি CI রান ট্রিগার করে (M8/L33) — লিন্ট → ইউনিট টেস্ট → ইমেজ বিল্ড (M6/L23) → ইমেজ স্ক্যান (M6/L26), প্রতিটি ধাপ ফেল-ফাস্ট নিয়মে চলে। CI পাস করলে, প্রয়োজনীয় ইনফ্রাস্ট্রাকচার পরিবর্তন একটি রিভিউ করা IaC প্ল্যান দিয়ে অ্যাপ্লাই হয় (M5/L18) — কখনো ব্লাইন্ডলি নয়, সবসময় আগে প্ল্যান দেখে। এরপর GitOps সিঙ্ক (M8/L36) স্টেজিং এনভায়রনমেন্টে ডিপ্লয় করে — Git-ই একমাত্র সোর্স অফ ট্রুথ। স্টেজিং-এ স্বয়ংক্রিয় স্মোক টেস্ট চলে, তারপর প্রোডাকশন ডিপ্লয়মেন্ট একটি গেটেড সিদ্ধান্ত (M8/L34 — ডেলিভারি নাকি ডিপ্লয়মেন্ট মোড) হিসেবে একটি ক্যানারি স্ট্র্যাটেজি (M8/L37) ব্যবহার করে হয়। পোস্ট-ডিপ্লয়, মনিটরিং (M10/L41) গোল্ডেন সিগনাল দেখে এবং এরর-রেট বাড়লে স্বয়ংক্রিয় রোলব্যাক ট্রিগার করার জন্য অ্যালার্টিং কনফিগার করা থাকে।

কমিট Source Commit CI (L33): লিন্ট/টেস্ট/বিল্ড/স্ক্যান CI Pipeline IaC প্ল্যান/অ্যাপ্লাই (L18) IaC Apply GitOps সিঙ্ক → স্টেজিং (L36) Staging Sync ক্যানারি প্রোড ডিপ্লয় (L37) Canary Deploy মনিটরিং ও অ্যালার্ট (L41) Monitor / Auto-rollback
প্রতিটি বক্স আগের কোনো লেসনের সরাসরি প্রয়োগ — পাইপলাইন এই টুকরোগুলোর একটি সুশৃঙ্খল চেইন মাত্র।

৩ · মূল সিদ্ধান্ত ও ট্রেড-অফ

গেটেড ডিপ্লয়মেন্ট + ক্যানারি — কেন দুটোই একসাথে

L34-এর "ডেলিভারি বনাম ডিপ্লয়মেন্ট" সিদ্ধান্ত এখানে একটি ম্যানুয়াল গেট বেছে নেয় — একজন মানুষ প্রোডাকশনে যাওয়ার চূড়ান্ত অনুমোদন দেয়, কারণ এই সার্ভিসের ব্যবসায়িক ঝুঁকি বেশি (নতুন, এখনো প্রমাণিত না)। কিন্তু অনুমোদনের পরও পুরো ট্রাফিক একসাথে না পাঠিয়ে L37-এর ক্যানারি স্ট্র্যাটেজি ব্যবহার করা হয় — কারণ একজন মানুষের অনুমোদনও একটি অপ্রত্যাশিত বাগ ধরতে পারে না যা শুধু বাস্তব প্রোডাকশন ট্রাফিকেই প্রকাশ পায়। দুটো গার্ডরেইল স্বাধীন এবং একে অপরের পরিপূরক।

৪ · কোড — এন্ড-টু-এন্ড পাইপলাইন চেইন করা

নিচের কোড তিনটি আলাদা লেসনের প্যাটার্ন — L33-এর ফেইল-ফাস্ট CI রানার, L18-এর IaC প্ল্যান/অ্যাপ্লাই, ও L37-এর ক্যানারি ট্রাফিক-স্প্লিটার — একটি একক, ক্রমিক পাইপলাইন রানে চেইন করে, একটি সফল রানের সম্পূর্ণ কনসোলিডেটেড লগ প্রিন্ট করে।

Python
import random

# --- ধাপ ১: CI পাইপলাইন (L33-এর ফেইল-ফাস্ট প্যাটার্ন) ---
def run_ci_pipeline(stages):
    for name, stage_fn in stages:
        passed = stage_fn()
        print(f"[CI] {name:12}-> {'PASS' if passed else 'FAIL'}")
        if not passed:
            return False
    return True

ci_stages = [
    ("lint",        lambda: True),
    ("unit_test",   lambda: True),
    ("build_image", lambda: True),
    ("scan_image",  lambda: True),
]
ci_passed = run_ci_pipeline(ci_stages)

if not ci_passed:
    print("\nপাইপলাইন CI ধাপে থেমে গেছে — বাকি ধাপ চলবে না।")
else:
    # --- ধাপ ২: IaC প্ল্যান/অ্যাপ্লাই (L18-এর প্যাটার্ন) ---
    desired_config = {"web_replicas": 3, "db_tier": "managed-small"}
    current_state  = {"web_replicas": 2, "db_tier": "managed-small"}

    def plan(desired, current):
        return {k: (current.get(k), v) for k, v in desired.items() if current.get(k) != v}

    changes = plan(desired_config, current_state)
    print(f"\n[IaC Plan]  পরিবর্তন প্রয়োজন: {changes if changes else 'কোনো পরিবর্তন নেই'}")
    if changes:
        current_state.update(desired_config)
        print(f"[IaC Apply] প্রয়োগ সম্পন্ন -> {current_state}")

    # --- ধাপ ৩: GitOps সিঙ্ক (L36-এর প্যাটার্ন, সংক্ষিপ্ত) ---
    print("\n[GitOps]    স্টেজিং এনভায়রনমেন্ট Git-এর কমিটেড স্টেটের সাথে সিঙ্ক সম্পন্ন")

    # --- ধাপ ৪: ক্যানারি প্রোড রোলআউট (L37-এর প্যাটার্ন) ---
    def route_traffic(canary_pct, rng):
        return "new_version" if rng.random() * 100 < canary_pct else "old_version"

    rng = random.Random(42)   # ফিক্সড সিড — পুনরুৎপাদনযোগ্য সিমুলেশন
    total_requests = 1000
    canary_pct = 10
    routed = [route_traffic(canary_pct, rng) for _ in range(total_requests)]
    new_version_count = routed.count("new_version")

    print(f"\n[Canary]    কনফিগার করা: {canary_pct}% | প্রকৃত: "
          f"{new_version_count}/{total_requests} ({new_version_count/total_requests*100:.1f}%) নতুন ভার্সনে")

    # --- ধাপ ৫: পোস্ট-ডিপ্লয় মনিটরিং (L41-এর প্যাটার্ন, সংক্ষিপ্ত) ---
    print("[Monitor]   গোল্ডেন সিগনাল স্বাভাবিক -> কোনো অটো-রোলব্যাক ট্রিগার হয়নি")
    print("\n=== পাইপলাইন রান সম্পন্ন: সফল ===")

    
লক্ষ্য করুন — ক্যানারি স্প্লিটের প্রকৃত ফলাফল কনফিগার করা ১০%-এর কাছাকাছি (কিন্তু ঠিক ১০% নয়, কারণ এটি র‍্যান্ডম স্যাম্পলিং) — ঠিক যেমন L37-এ দেখেছিলাম। এই পুরো লগটি একটি একক পাইপলাইন রান, কিন্তু প্রতিটি লাইন আগের একটি ভিন্ন লেসনের একটি নির্দিষ্ট, ইতিমধ্যে-শেখা কৌশল।

৫ · ফলাফল

নতুন সার্ভিসের প্রতিটি কমিট এখন স্বয়ংক্রিয়ভাবে, নিরাপদে, ও দ্রুত প্রোডাকশনে পৌঁছাতে পারে — প্রতিটি ধাপে একটি স্বয়ংক্রিয় গার্ডরেইল আছে (ফেইল-ফাস্ট CI, রিভিউ করা IaC প্ল্যান, স্মোক টেস্ট, গেটেড অনুমোদন, ক্যানারি ব্লাস্ট রেডিয়াস সীমাবদ্ধতা, ও মনিটরিং-ভিত্তিক অটো-রোলব্যাক) যা L01-এর DORA মেট্রিক্সে ফিরে গেলে — এই টিম এখন উচ্চতর ডিপ্লয়মেন্ট ফ্রিকোয়েন্সি ও কম চেঞ্জ ফেইলিওর রেট দুটোই একসাথে অর্জন করতে পারবে।

মূল কথা · Key takeaway

একটি "সম্পূর্ণ CI/CD পাইপলাইন" আসলে কোনো একক জাদুকরী টুল নয় — এটি এই কোর্সের ইতিমধ্যে শেখা অনেকগুলো ছোট, স্বাধীন কৌশলের একটি সুশৃঙ্খল, ক্রমিক চেইন, যেখানে প্রতিটি ধাপ শুধু আগেরটি পাস করলেই চলে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ কেন IaC অ্যাপ্লাই (L18) ধাপটি CI পাস হওয়ার পরে, কিন্তু GitOps স্টেজিং সিঙ্কের আগে বসানো হয়েছে?

অ্যাপ্লিকেশন কোড নিরাপদ প্রমাণিত হওয়ার আগে (CI পাস) কোনো ইনফ্রাস্ট্রাকচার পরিবর্তন করা অপ্রয়োজনীয় ঝুঁকি, আবার অ্যাপ্লিকেশন ডিপ্লয় করার আগে প্রয়োজনীয় ইনফ্রাস্ট্রাকচার (যেমন নতুন রিসোর্স) প্রস্তুত থাকা দরকার — তাই এই ক্রমটি নিশ্চিত করে প্রতিটি পরবর্তী ধাপ তার নির্ভরতাগুলো ইতিমধ্যে সন্তুষ্ট পায়।

প্র ০২ যদি এই টিম L34-এর "Continuous Deployment" মোড বেছে নিত (কোনো ম্যানুয়াল গেট ছাড়া), পাইপলাইনে কী পরিবর্তন হতো?

স্মোক টেস্ট পাসের পর প্রোডাকশন ক্যানারি ডিপ্লয় স্বয়ংক্রিয়ভাবেই শুরু হয়ে যেত, কোনো মানুষের অপেক্ষা ছাড়াই। এর জন্য টিমের কাছে অত্যন্ত উচ্চ আস্থাসম্পন্ন স্বয়ংক্রিয় টেস্টিং, মনিটরিং ও রোলব্যাক ক্ষমতা থাকা জরুরি — কারণ কোনো মানুষ চূড়ান্ত সেফটি-নেট হিসেবে থাকবে না।

প্র ০৩ মনিটরিং ধাপ (L41) যদি পাইপলাইন থেকে সম্পূর্ণ বাদ দেওয়া হতো, ক্যানারি রোলআউটের প্রকৃত মূল্য কতটা কমে যেত?

অনেকটাই — ক্যানারির পুরো মূল্য এই ধারণায় নির্ভরশীল যে সমস্যা হলে তা দ্রুত ধরা পড়বে এবং রোলব্যাক ট্রিগার হবে। মনিটরিং ছাড়া একটি ক্যানারি রোলআউট শুধু ট্রাফিক ভাগ করে দেয়, কিন্তু কোনো সমস্যা সৃষ্টি হলে তা শনাক্ত করার কোনো উপায় থাকে না — অর্থাৎ ক্যানারি ও মনিটরিং একে অপরকে ছাড়া কার্যত অকার্যকর।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোডে ci_stages-এর "scan_image" ধাপটি lambda: False করে দিন এবং কোড আবার চালান — পুরো পাইপলাইন কোথায় থেমে যায় দেখুন।

    CI রানার "scan_image"-এ FAIL রিপোর্ট করবে এবং সাথে সাথে False রিটার্ন করবে — এর ফলে বাকি সব ধাপ (IaC apply, GitOps sync, canary, monitor) সম্পূর্ণ এড়িয়ে যাবে এবং কোড শুধু "পাইপলাইন CI ধাপে থেমে গেছে" প্রিন্ট করবে — ফেইল-ফাস্টের বাস্তব প্রদর্শন।

  2. পরীক্ষা করুন: canary_pct-এর মান ১০ থেকে ৫০-এ পাল্টে কোড আবার চালান — নতুন ভার্সনে যাওয়া রিকোয়েস্টের প্রকৃত শতাংশ কতটা পাল্টায়?

    প্রকৃত ফলাফল ৫০%-এর কাছাকাছি হবে (একই ফিক্সড সিড ব্যবহার করলেও, কারণ থ্রেশহোল্ড নিজেই বদলে গেছে) — দেখাচ্ছে canary_pct সরাসরি কতটা ট্রাফিক নতুন ভার্সনে যাবে তা নিয়ন্ত্রণ করে, র‍্যান্ডম স্যাম্পলিং সত্ত্বেও বড় নমুনায় কনফিগার করা মানের কাছাকাছিই থাকে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
কেস স্টাডি: মনোলিথ থেকে কন্টেইনারে মাইগ্রেশন