পাঠ ৩৬ · ৫৭-এর মধ্যে · মডিউল ৮

GitOps ও ডিক্লারেটিভ ডিপ্লয়মেন্ট

GitOps & declarative deployment
৮ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

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

  • GitOps কী এবং এটি কীভাবে L17-এর IaC দর্শনকে সম্পূর্ণ ডিপ্লয়মেন্ট প্রক্রিয়ায় প্রসারিত করে
  • reconciliation loop প্যাটার্ন কীভাবে GitOps-এর মূল চালিকাশক্তি (L27/L28-এর একই ধারণা পুনরায় প্রয়োগ)
  • GitOps-এর সুবিধা — অডিট ট্রেইল, সহজ রোলব্যাক, সরলীকৃত অ্যাক্সেস কন্ট্রোল
  • Python দিয়ে একটি GitOps sync সিমুলেট করা — যা ম্যানুয়াল আউট-অফ-ব্যান্ড পরিবর্তন স্বয়ংক্রিয়ভাবে রিভার্ট করে দেয়

১ · GitOps কী

GitOpsGitOpsএকটি নির্দিষ্ট CI/CD প্যাটার্ন যেখানে একটি Git রিপোজিটরি ইনফ্রাস্ট্রাকচার/অ্যাপ্লিকেশনের কাঙ্ক্ষিত অবস্থার একমাত্র সোর্স-অফ-ট্রুথ, এবং একটি স্বয়ংক্রিয় কন্ট্রোলার লাইভ সিস্টেমকে ক্রমাগত সেই অবস্থার সাথে মিলিয়ে রাখে। হলো একটি নির্দিষ্ট CI/CD প্যাটার্ন যেখানে একটি Git রিপোজিটরি আপনার ইনফ্রাস্ট্রাকচার ও অ্যাপ্লিকেশনের কাঙ্ক্ষিত অবস্থার একমাত্র সোর্স-অফ-ট্রুথ হিসেবে কাজ করে — L17-এ আমরা যে ডিক্লারেটিভ IaC দর্শন শিখেছিলাম (কাঙ্ক্ষিত END STATE বর্ণনা করো, টুল বাকিটা বের করে নেবে), GitOps সেই একই দর্শনকে পুরো ডিপ্লয়মেন্ট প্রক্রিয়ার জন্য প্রয়োগ করে।

২ · একই reconciliation loop, এবার পুরো ডিপ্লয়মেন্টের জন্য

একটি স্বয়ংক্রিয় এজেন্ট/কন্ট্রোলার ক্রমাগত Git রিপোজিটরি পর্যবেক্ষণ করে এবং লাইভ সিস্টেমকে যা-ই কমিট করা হোক না কেন তার সাথে মিলিয়ে দেয় — এটি হুবহু L27/L28-এর reconciliation loop ধারণা (এবং L32-এর অপারেটর প্যাটার্ন), শুধু এবার Kubernetes পডের বদলে পুরো ডিপ্লয়মেন্ট প্রক্রিয়ার জন্য প্রয়োগ করা হয়েছে।

অডিট ট্রেইল
সম্পূর্ণ ডিপ্লয়মেন্ট ইতিহাস = Git কমিট ইতিহাস, কে কী কখন পরিবর্তন করেছে তার স্পষ্ট রেকর্ড।
সহজ রোলব্যাক
আগের অবস্থায় ফিরতে চাইলে শুধু git revert — কোনো আলাদা রোলব্যাক টুল দরকার নেই।
সরলীকৃত অ্যাক্সেস
"কে ডিপ্লয় কমান্ড চালাতে পারবে" প্রশ্নের উত্তর শুধু Git রিপোজিটরির পারমিশন — আলাদা কোনো অ্যাক্সেস সারফেস নেই।
GitOps কেন ম্যানুয়াল আউট-অফ-ব্যান্ড পরিবর্তন সহ্য করে না

যেহেতু GitOps-এর পুরো নিরাপত্তা মডেলটাই দাঁড়িয়ে আছে এই ধারণার উপর যে Git-ই একমাত্র সত্য, তাই যদি কেউ লাইভ সিস্টেমে সরাসরি একটি ম্যানুয়াল পরিবর্তন করে (Git-এ কমিট না করেই), পরবর্তী নিয়মিত sync-এ কন্ট্রোলার সেই পরিবর্তনকে "ড্রিফট" হিসেবে দেখবে এবং স্বয়ংক্রিয়ভাবে রিভার্ট করে দেবে — L20-এর ড্রিফট-ডিটেকশন ধারণার একটি স্বয়ংক্রিয়-সংশোধনকারী সংস্করণ।

Python
# একটি টয় GitOps reconciler — Git-কে সোর্স-অফ-ট্রুথ ধরে লাইভ স্টেট সিঙ্ক করা
# (বাস্তব কোনো Git রিপো বা ক্লাস্টারে কিছুই ঘটছে না — এটি একটি ধারণাগত সিমুলেশন)

git_repo_state = {
    "replicas": 3,
    "image_tag": "v1.9.0",
    "feature_flag_new_ui": True,
}

live_cluster_state = {
    "replicas": 3,
    "image_tag": "v1.9.0",
    "feature_flag_new_ui": True,
}


def gitops_sync(desired, live):
    """desired (Git-এ কমিট করা অবস্থা) ও live (বর্তমান রানিং অবস্থা) তুলনা করে,
    যেকোনো পার্থক্য পেলে live-কে desired-এর সাথে মিলিয়ে দেয়।"""
    changes = []
    for key, desired_value in desired.items():
        if live.get(key) != desired_value:
            changes.append((key, live.get(key), desired_value))
            live[key] = desired_value
    return changes


print("===== ধাপ ১: প্রথম sync (কোনো ড্রিফট নেই) =====")
changes = gitops_sync(git_repo_state, live_cluster_state)
print("প্রয়োগ হওয়া পরিবর্তন:", changes if changes else "কোনোটিই না — ইতিমধ্যে Git-এর সাথে মিলছে")

print("\n===== ধাপ ২: একজন ইঞ্জিনিয়ার Git-এর বাইরে সরাসরি লাইভ ক্লাস্টার পরিবর্তন করলেন =====")
live_cluster_state["replicas"] = 10  # ম্যানুয়াল স্কেল-আপ, Git-এ কমিট না করেই
print("লাইভ ক্লাস্টার এখন:", live_cluster_state)
print("কিন্তু git_repo_state অপরিবর্তিত:", git_repo_state)

print("\n===== ধাপ ৩: GitOps কন্ট্রোলারের পরবর্তী নিয়মিত sync =====")
changes = gitops_sync(git_repo_state, live_cluster_state)
print("প্রয়োগ হওয়া পরিবর্তন:", changes)
print("লাইভ ক্লাস্টার আবার Git-এর সাথে মিলে গেছে:", live_cluster_state)

    
লক্ষ্য করুন ধাপ ৩-এ gitops_sync replicas-এর মান ১০ পেয়ে সেটিকে "ভুল" ধরে নিচ্ছে না — বরং git_repo_state-এ যা কমিট করা আছে (৩) সেটাকেই একমাত্র সঠিক ধরে নিয়ে live_cluster_state["replicas"]-কে জোর করে আবার ৩-এ ফিরিয়ে আনছে। ম্যানুয়াল পরিবর্তনটি সম্পূর্ণ নীরবে ও স্বয়ংক্রিয়ভাবে রিভার্ট হয়ে গেছে — এটাই GitOps-এর মূল নিরাপত্তা গ্যারান্টি।
মূল কথা · Key takeaway

GitOps হলো L17-এর IaC দর্শন ও L27/L28-এর reconciliation loop প্যাটার্নের সংমিশ্রণ, প্রয়োগ করা হয়েছে পুরো ডিপ্লয়মেন্ট প্রক্রিয়ার উপর — Git-ই একমাত্র সত্য, এবং একটি স্বয়ংক্রিয় কন্ট্রোলার সবসময় লাইভ সিস্টেমকে সেই সত্যের সাথে মিলিয়ে রাখে। M8 (CI/CD পাইপলাইন) মডিউল এখন প্রায় সম্পূর্ণ — পরবর্তী পাঠ (L37) সর্বশেষ টুকরো যোগ করবে: ব্লু-গ্রিন, ক্যানারি ও রোলিং ডিপ্লয়মেন্ট স্ট্র্যাটেজি — কীভাবে একটি নতুন ভার্সন প্রকৃতপক্ষে নিরাপদে ট্রাফিকে চালু করা হয়।

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

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

প্র ০১ GitOps-এ "রোলব্যাক" করা মানে git revert করা কেন এত সহজ ও নির্ভরযোগ্য একটি প্রক্রিয়া?

যেহেতু কাঙ্ক্ষিত অবস্থা সম্পূর্ণভাবে Git ইতিহাসে ধারাবাহিকভাবে সংরক্ষিত, একটি খারাপ পরিবর্তনের কমিট রিভার্ট করা মানেই স্বয়ংক্রিয়ভাবে "কাঙ্ক্ষিত অবস্থা" আবার আগের ভালো অবস্থায় ফিরে যাওয়া — এরপর reconciliation loop নিজে থেকেই লাইভ সিস্টেমকে সেই পুনরুদ্ধার হওয়া অবস্থার সাথে মিলিয়ে দেবে। কোনো আলাদা "কীভাবে রোলব্যাক করব" টুল বা প্রক্রিয়া শিখতে হয় না — এটি ঠিক নতুন পরিবর্তন ডিপ্লয় করার মতোই একই মেকানিজম ব্যবহার করে।

প্র ০২ একজন ইঞ্জিনিয়ার যদি একটি জরুরি প্রোডাকশন সমস্যা সমাধানের জন্য দ্রুত ম্যানুয়ালি লাইভ ক্লাস্টার পরিবর্তন করেন (Git-এ কমিট না করে), GitOps পরিবেশে এর দীর্ঘমেয়াদী ঝুঁকি কী?

পরবর্তী নিয়মিত sync-এ কন্ট্রোলার সেই জরুরি ফিক্সটিকে "ড্রিফট" হিসেবে দেখবে এবং স্বয়ংক্রিয়ভাবে রিভার্ট করে দেবে — সমস্যাটি ফিরে আসবে, প্রায়ই ইঞ্জিনিয়ারের কাছে কোনো স্পষ্ট ব্যাখ্যা ছাড়াই। সঠিক পদ্ধতি হলো এমনকি জরুরি ফিক্সও Git-এ কমিট করা (দ্রুত হলেও), যাতে GitOps-এর সোর্স-অফ-ট্রুথ গ্যারান্টি ভেঙে না যায়।

প্র ০৩ GitOps কীভাবে "কে ডিপ্লয় করার অনুমতি পাবে" এই অ্যাক্সেস-কন্ট্রোল প্রশ্নকে সরলীকৃত করে?

ঐতিহ্যবাহী পদ্ধতিতে প্রায়ই একটি পৃথক ডিপ্লয়মেন্ট টুল/সিস্টেমে অ্যাক্সেস ম্যানেজ করতে হয় (কে ডিপ্লয় কমান্ড চালাতে পারবে তার নিজস্ব পারমিশন সিস্টেম)। GitOps-এ যেহেতু ডিপ্লয় করার একমাত্র উপায় হলো Git রিপোজিটরিতে একটি পরিবর্তন কমিট/মার্জ করা, তাই অ্যাক্সেস কন্ট্রোল প্রশ্নটি একটিমাত্র, ইতিমধ্যে সুপরিচিত সারফেসে (Git-এর নিজস্ব ব্রাঞ্চ পারমিশন ও পুল রিকোয়েস্ট রিভিউ প্রক্রিয়া) নেমে আসে — আলাদা কোনো অ্যাক্সেস সিস্টেম শেখা বা রক্ষণাবেক্ষণ করার দরকার নেই।

অনুশীলন

  1. চিন্তা করুন: উপরের কোড সেলে যদি ধাপ ২-এ ম্যানুয়াল পরিবর্তনের বদলে git_repo_state["image_tag"] = "v2.0.0" (অর্থাৎ Git-এই একটি বৈধ নতুন কমিট) করা হতো, তাহলে ধাপ ৩-এ কী ঘটতো এবং এটি ম্যানুয়াল লাইভ পরিবর্তনের দৃশ্য থেকে কীভাবে আলাদা হতো?

    এই ক্ষেত্রে gitops_sync ঠিক একইভাবে পার্থক্য শনাক্ত করে live_cluster_state ["image_tag"]-কে "v2.0.0"-এ আপডেট করে দিত — কিন্তু এবার এটি "রিভার্ট" নয়, বরং একটি বৈধ, ইচ্ছাকৃত ডিপ্লয়মেন্ট, কারণ পরিবর্তনটি সঠিক সোর্স-অফ-ট্রুথে (Git) এসেছিল। এটি দেখায় gitops_sync ফাংশন নিজে "ভালো" বা "খারাপ" পরিবর্তনের মধ্যে পার্থক্য করে না — এটি শুধু Git-কে অন্ধভাবে অনুসরণ করে, তাই সব শৃঙ্খলা নির্ভর করে পরিবর্তনগুলো সঠিকভাবে Git-এর মধ্য দিয়েই যাচ্ছে কি না তার উপর।

  2. পরীক্ষা করুন: gitops_sync ফাংশনকে পরিবর্তন করুন যাতে এটি শুধু কী পরিবর্তন হলো তা রিটার্ন না করে, প্রতিটি পরিবর্তনের জন্য একটি স্পষ্ট লগ লাইনও প্রিন্ট করে (যেমন "সংশোধন করা হলো: replicas বর্তমানে 10 ছিল, Git অনুযায়ী 3-এ ফিরিয়ে আনা হলো")। কোড আবার চালিয়ে যাচাই করুন লগ বার্তাগুলো প্রত্যাশিতভাবে দেখাচ্ছে কি না।

    gitops_sync-এর লুপের ভেতরে, changes.append(...)-এর ঠিক পরে print(f"সংশোধন করা হলো: {key} বর্তমানে {live.get(key)} ছিল, Git অনুযায়ী {desired_value}-এ ফিরিয়ে আনা হলো") যোগ করলে (মান আপডেট করার আগে live.get(key) পড়ে নিয়ে), প্রতিটি sync চালানোর সময় ঠিক কোন কী-এর মান কীভাবে পরিবর্তিত হলো তার একটি স্পষ্ট, মানুষ-পাঠযোগ্য অডিট লগ পাবেন — বাস্তব GitOps টুল যেভাবে তাদের sync ইতিহাস দেখায় তার একটি সরলীকৃত সংস্করণ।

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

আগের পাঠ
L35 · পাইপলাইন ডিজাইন — বিল্ড, টেস্ট, ডিপ্লয় স্টেজ