সরাসরি পর্বে যান
পর্ব ৫৯ · ৭০-এর মধ্যে · মডিউল ১০

Continuous delivery আর DevOps — deployment pipeline, environment আর DORA metric

Continuous Delivery and DevOps — Deployment Pipelines, Environments and DORA Metrics

Taught in Bangla, this lesson separates continuous integration, delivery and deployment, and walks through a deployment pipeline from commit stage to production. It covers build once, deploy many with environment promotion and config, deploy versus release, rollback versus roll forward, DevOps culture with CALMS and the three ways, computing the four DORA metrics from logs, infrastructure as code, GitOps and DevSecOps.

এই পর্বে যা শিখবেন

  • Continuous integration, continuous delivery আর continuous deployment-এর সূক্ষ্ম পার্থক্য, আর Humble ও Farley-র (২০১০) deployment pipeline
  • “Build একবার, deploy বহুবার”, environment promotion আর config-কে artifact থেকে আলাদা রাখা — চালানো যায় এমন মডেলে
  • Deploy বনাম release, rollback বনাম roll forward, আর release management-এর মূল প্রশ্ন
  • DevOps-এর জন্মকথা, CALMS, তিন পথ, আর DORA-র চারটি metric — log থেকে হিসাব, batch-এর আকারের প্রভাব আর অপব্যবহার
  • Infrastructure as code, GitOps-এর reconciliation loop, আর DevSecOps-এর সংক্ষিপ্ত পরিচয়

১ · সবুজ build থেকে ব্যবহারকারীর হাত — continuous delivery কী

পর্ব ৫৮-এ (Continuous integration) দেখেছেন, দল সারাদিন ছোট ছোট পরিবর্তন mainline-এ মেলায় আর প্রতিটিতে স্বয়ংক্রিয় build ও test চলে। কিন্তু সবুজ build মানেই ব্যবহারকারী নতুন সুবিধা পেলেন, তা নয়। অনেক দলে সবুজ কোড সপ্তাহের পর সপ্তাহ বসে থাকে — “মাসের শেষ শুক্রবার রাতে release”, সাথে হাতে লেখা পঁচিশ ধাপের নির্দেশিকা, আর ভয়। এই মডিউলের (মডিউল ১০) প্রশ্ন এখান থেকে শুরু: কোড থেকে ব্যবহারকারী পর্যন্ত পথটি কীভাবে নিরাপদ, দ্রুত আর মাপা যায় এমন করবেন, আর তার চারপাশের পেশাদার কাজ — estimation, পরিকল্পনা, ঝুঁকি, দলগত কাজ আর নৈতিকতা — কীভাবে সামলাবেন।

পাড়ার একটি মিষ্টির দোকান ভাবুন। এক রকম দোকানে কারিগর সারা সপ্তাহ মিষ্টি বানিয়ে গুদামে রাখেন, আর বৃহস্পতিবার একবার পাঠান। কোনো ব্যাচে চিনি বেশি হলে খবর আসে সাত দিন পরে — ততক্ষণে পাঁচশো কেজি একই ভুলে বানানো। আরেক রকম দোকানে প্রতিটি ছোট ব্যাচ বানানোর সাথে সাথে চেখে দেখা হয়, আর মালিক যখন চান, তখনই এক ট্রে পাঠাতে পারেন। দ্বিতীয়টি continuous delivery — প্রতিটি ব্যাচ বিক্রির যোগ্য, কখন পাঠাবেন তা শুধু সিদ্ধান্ত।

শব্দগুলো কাছাকাছি, তাই একবারে পরিষ্কার করে নিই। Continuous integration (CI) মেলানো আর যাচাইয়ের অনুশীলন। Continuous delivery (CD) তার পরের ধাপ: software-কে সবসময় release-যোগ্য অবস্থায় রাখা, যাতে যেকোনো সবুজ version একটি বোতাম চেপে নিরাপদে production-এ পাঠানো যায়। Continuous deployment আরও এক ধাপ: বোতামটিও নেই — pipeline-এর সব ধাপ পার হওয়া প্রতিটি পরিবর্তন নিজে থেকেই production-এ যায়।

অনুশীলনস্বয়ংক্রিয় কতদূরProduction-এ কে পাঠায়মূল প্রতিশ্রুতি
Continuous integrationbuild আর testপ্রশ্নই ওঠে নাmainline সবসময় সবুজ
Continuous deliveryproduction-এর আগের সব ধাপ, আর deploy-এর কাজটিওএকজন মানুষ, ব্যবসার সিদ্ধান্তে — একটি বোতামযেকোনো সময় release করা যায়
Continuous deploymentproduction পর্যন্ত সবpipeline নিজেপ্রতিটি সবুজ পরিবর্তন release হয়

একটু ইতিহাস। Agile Manifesto-র (২০০১) প্রথম নীতিতেই আছে “early and continuous delivery of valuable software”. ধারণাটিকে পূর্ণ রূপ দেয় Jez Humble ও David Farley-র বই Continuous Delivery (২০১০), যেখানে deployment pipeline-এর নকশা বিস্তারিত বর্ণিত। “Continuous deployment” শব্দটির জন্য প্রায়ই Timothy Fitz-এর ২০০৯ সালের একটি blog লেখা উদ্ধৃত হয়। অনেক জায়গায় “CD” দুটির যেকোনোটি বোঝায়, তাই প্রসঙ্গ দেখে পড়ুন।

Continuous delivery-র কেন্দ্রীয় ফল হলো release on demand: কবে release হবে, সেটি আর প্রযুক্তিগত বাধা নয়, শুধু ব্যবসার সিদ্ধান্ত। ঈদের আগে নতুন অফার আজ বিকেলেই চালু করতে চাইলে করা যায়। এর জন্য লাগে একটি deployment pipeline (অংশ ২), একই artifact-এর environment থেকে environment-এ যাত্রা (অংশ ৩), আর deploy থেকে release আলাদা করার কৌশল (অংশ ৪); তারপর সংস্কৃতি আর মাপ — DevOps, DORA metric আর GitOps (অংশ ৫–৮)।

এই মডিউলের পথ

পর্ব ৫৯ (এটি) delivery-র পথ। তারপর কাজের পরিকল্পনা আর পরিচালনা: পর্ব ৬০-এ Software estimation — story point, planning poker, function point আর COCOMO II; পর্ব ৬১-এ Project planning — WBS, Gantt chart, CPM আর PERT; পর্ব ৬২-এ Risk আর quality management; পর্ব ৬৩-এ দলগত কাজ আর open source; পর্ব ৬৪-এ পেশাগত নৈতিকতা; আর পর্ব ৬৫-এ ক্যাপস্টোন — requirement থেকে release পর্যন্ত একটি পূর্ণ project, যেখানে এই পর্বের pipeline-ও কাজে লাগবে।

২ · Deployment pipeline — commit stage থেকে production

Humble ও Farley-র মূল ভাবনা: প্রতিটি commit একটি release candidate, যতক্ষণ না কোনো ধাপ প্রমাণ করে যে সেটি ভালো নয়। Pipeline একটি আস্থার সিঁড়ি। নিচের ধাপগুলো দ্রুত আর সস্তা, ওপরের ধাপগুলো ধীর কিন্তু production-এর কাছাকাছি। একটি ধাপ পার হলে আস্থা বাড়ে; ব্যর্থ হলে পরিবর্তনটি সেখানেই থামে, আর খবর ফেরে লেখকের কাছে। বইয়ে বর্ণিত সাধারণ ধাপগুলো (দলভেদে নাম আর সংখ্যা আলাদা):

  • Commit stage: compile, unit test, static analysis — পর্ব ৫৮-এর CI pipeline-এর মতোই, কয়েক মিনিটে। এখানেই artifact (package, container image) একবার তৈরি হয় আর একটি artifact repository-তে জমা পড়ে।
  • Acceptance stage: artifact একটি test environment-এ বসিয়ে স্বয়ংক্রিয় acceptance test — ব্যবহারকারীর চোখে কাজ ঠিক হয় কি না (পর্ব ৫১-এ test pyramid).
  • Capacity আর অন্যান্য non-functional test: চাপে গতি (performance testing), নিরাপত্তা scan, কখনো দীর্ঘ সময়ের স্থিরতা।
  • Manual ধাপ: staging environment-এ exploratory testing বা ব্যবহারকারীর গ্রহণযোগ্যতা যাচাই — যন্ত্র যা ধরতে পারে না, মানুষের চোখ তা দেখে।
  • Release: production environment-এ deployment — continuous delivery-তে একটি বোতাম, continuous deployment-এ স্বয়ংক্রিয়।

Deployment pipeline — ধাপ, environment, একই artifact আর feedback

Solid arrow = promote on success · orange dashed = the same artifact pulled from the repository · grey dashed = feedback on failure

Deployment pipeline-এর পাঁচটি ধাপ, environment, একই artifact আর feedback loop ডেভেলপার · commit ১ · Commit stage ২ · Acceptance ৩ · Capacity ৪ · Manual · UAT ৫ · Production artifact ব্যবহারকারী · flag-এ release build · unit · analysis env: test · স্বয়ংক্রিয় env: perf · load test env: staging · অনুমোদন env: prod · বোতাম 611809b3 একই artifact ব্যর্থ হলে feedback
ছবি ৫৯.১ — Commit stage artifact একবার বানিয়ে repository-তে রাখে (digest 611809b3); পরের প্রতিটি environment সেই একই artifact নামায় (কমলা ভাঙা রেখা), শুধু config আলাদা। যেকোনো ধাপ ব্যর্থ হলে পরিবর্তন সেখানেই থামে আর খবর লেখকের কাছে ফেরে (ধূসর)। ছবিতে সবার ওপরের ধাপ সবচেয়ে দ্রুত আর সস্তা; যত নিচে নামছেন, ধাপ তত ধীর কিন্তু production-এর তত কাছের।

এবার একটি পরিবর্তনের পুরো যাত্রা দেখুন। কাল্পনিক অনলাইন বাজার অ্যাপ bazar-cart-এর দলে তানভীর নতুন এক-পাতার checkout লিখেছেন, যা একটি feature flag-এর আড়ালে আছে। সময় আর সংখ্যা উদাহরণের জন্য ধরা:

  1. Commitmain
  2. Commit stage৭ মিনিট
  3. Acceptancetest
  4. Capacityperf
  5. Stagingঅনুমোদন
  6. Proddeploy
  7. Releaseflag
bazar-cart · নতুন checkout (কাল্পনিক দল)
ঘড়ি
কোথায় চলছে
Artifact digest
Config (NEW_CHECKOUT)
ফল
Lead time (commit থেকে prod)
  1. Commit. সোমবার ১০:০২-এ তানভীরের ছোট commit main-এ মিশল। Pipeline-এর কাছে এটি একটি release candidate — যতক্ষণ না কোনো ধাপ উল্টো প্রমাণ করে।
  2. Commit stage. সাত মিনিটে compile, ১,২৪০টি unit test আর static analysis সবুজ। এখানেই একবারমাত্র artifact তৈরি হলো, digest 611809b3, আর জমা পড়ল artifact repository-তে।
  3. Acceptance stage. Test environment-এ সেই artifact বসানো হলো, test-এর config দিয়ে (flag on). ৮৬টি স্বয়ংক্রিয় acceptance test সবুজ। কোনো test লাল হলে এখানেই থামত, আর তানভীর মিনিট কয়েকের মধ্যে খবর পেতেন।
  4. Capacity stage. Perf environment-এ সেকেন্ডে ৩০০ অনুরোধের চাপে p95 latency ১৮০ ms, লক্ষ্য ৩০০ ms-এর মধ্যে। Digest এখনো 611809b3.
  5. Staging আর অনুমোদন. Production-এর মতো সাজানো staging-এ smoke test, QA-র exploratory testing, আর product owner-এর অনুমোদন। এখন পরিবর্তনটি release-যোগ্য — continuous deployment হলে এই মুহূর্তেই নিজে থেকে prod-এ যেত।
  6. Production deploy. দুপুর দুটোয় দল একটি বোতাম চাপল। একই digest prod-এ চলছে, কিন্তু prod-এর config-এ flag বন্ধ — কোড আছে, ব্যবহারকারী এখনো পুরোনো checkout দেখেন। Lead time for changes = ১০:০২ থেকে ১৪:০০ = ৩ ঘণ্টা ৫৮ মিনিট।
  7. Release. পরের তিন দিনে flag ধাপে ধাপে ৫%, ৫০%, ১০০% ব্যবহারকারীর জন্য চালু হলো। কোনো নতুন build বা deploy লাগেনি — deploy আর release দুটি আলাদা ঘটনা (অংশ ৪)।

Pipeline-এর নকশার একটি নিয়ম: ব্যর্থতা যত আগে ধরা যায়, তত সস্তা। তাই দ্রুত test commit stage-এ, ধীর test পরের ধাপে। আরেকটি নিয়ম: pipeline-এর বাইরে দিয়ে কোনো পরিবর্তন production-এ যাবে না — “জরুরি” hotfix-ও নয়; জরুরি পথ হলো একই pipeline-এর দ্রুত সংস্করণ, হাতে server-এ file কপি নয়।

৩ · Build একবার, deploy বহুবার — environment promotion আর config

Pipeline-এর সবচেয়ে গুরুত্বপূর্ণ নিয়মগুলোর একটি: build একবার, deploy বহুবার। Commit stage যে artifact বানায়, সেই হুবহু artifact test, perf, staging আর prod-এ যায় — একে বলে environment promotion. কেন এত জোর? কারণ staging-এ যা test হলো, prod-এ যদি অন্য কিছু চলে, তাহলে test-এর প্রমাণ prod-এর জন্য খাটে না।

পরীক্ষার খাতার খসড়া আর ফেয়ার কপির কথা ভাবুন। শিক্ষক খসড়া দেখে বললেন “ঠিক আছে”। এখন আপনি ফেয়ার কপি আবার নতুন করে লিখলেন — আর লেখার সময় দুটি সংখ্যা অজান্তে বদলে গেল। শিক্ষকের “ঠিক আছে” এখন কোন খাতার জন্য? Prod-এর জন্য আবার build করা ঠিক এই ভুল। ভালো উপায় হলো খসড়াটিরই ফটোকপি জমা দেওয়া — যা দেখা হয়েছে, সেটিই জমা।

আবার build করলে কী বদলাতে পারে? Dependency-র version range (^2.1) আজ ২.১.৩ আর তিন দিন পরে ২.২.০ ধরতে পারে; compiler-এর version বা build-এর তারিখ বদলাতে পারে। Lockfile আর reproducible build ঝুঁকি কমায়, কিন্তু সবচেয়ে সরল প্রতিরক্ষা আবার build-ই না করা। Artifact চেনা হয় তার digest দিয়ে — artifact-এর সব byte-এর hash (container image-এ সাধারণত sha256:…)। দুই environment-এ একই digest মানে হুবহু একই artifact; পর্ব ৫২-এ (Git-এর ভেতরে) Git-এর content-addressed storage-এও এই ধারণাই দেখেছেন।

Config থাকে artifact-এর বাইরে

একই artifact সব environment-এ চললে test আর prod-এর database আলাদা হবে কীভাবে? উত্তর: config artifact-এর অংশ নয়। Database-এর ঠিকানা, flag-এর মান, বাইরের URL আর secret deploy-এর সময় environment থেকে আসে, সাধারণত environment variable বা একটি config service দিয়ে। Heroku-র প্রকৌশলীদের (Adam Wiggins-এর নাম প্রায়ই উল্লেখ হয়) মোটামুটি ২০১১ সালে প্রকাশিত The Twelve-Factor App নির্দেশিকার তৃতীয় নীতি এটিই — config environment-এ রাখুন; আর পঞ্চম নীতি বলে build, release আর run তিনটি ধাপ আলাদা রাখতে। এটি একটি প্রভাবশালী নির্দেশিকা, কোনো আনুষ্ঠানিক মান নয়; সব নীতি সব ধরনের software-এ সমান খাটে না।

একটি সহজ পরীক্ষা: আপনার repository কি এখনই open source করে দেওয়া যায়, কোনো password ফাঁস না করে? উত্তর “না” হলে config বা secret কোডের ভেতরে ঢুকে আছে (secret রাখার নিয়ম পর্ব ৫৭-এ, Git-এ নিরাপত্তা)। Secret-এর মান কখনো Git-এ নয় — একটি secret manager-এ, আর deploy-এর সময় শুধু সেই environment-এর জন্য।

নিচের মডেলে দুটি pipeline. Pipeline A artifact একবার বানিয়ে চারটি environment-এ এগিয়ে দেয়। Pipeline B প্রতিটি environment-এ আবার build করে, আর prod-এর build তিন দিন পরে হওয়ায় একটি library-র নতুন minor version ধরে ফেলে। Hash হিসেবে FNV-1a 32-bit ব্যবহার করা হয়েছে — আসল artifact repository-র SHA-256 digest-এর জায়গায় একটি ছোট বিকল্প:

// Build once, deploy many: the SAME artifact moves dev -> test -> staging -> prod;
// only the config differs. FNV-1a 32-bit stands in for a real SHA-256 digest.
const fnv1a = s => { let h = 0x811c9dc5; for (const ch of s) { h ^= ch.charCodeAt(0);
  h = Math.imul(h, 0x01000193) >>> 0; } return h.toString(16).padStart(8, "0"); };
// A "build" = source + the dependency versions resolved at build time.
const build = (src, resolved) => fnv1a(src + JSON.stringify(resolved));
const SRC = "bazar-cart@a1c9e40";
const CONFIG = {
  dev:     { DB_URL: "db.dev.internal",  NEW_CHECKOUT: "on"  },
  test:    { DB_URL: "db.test.internal", NEW_CHECKOUT: "on"  },
  staging: { DB_URL: "db.stg.internal",  NEW_CHECKOUT: "on"  },
  prod:    { DB_URL: "db.prod.internal", NEW_CHECKOUT: "off" },
};
// Pipeline A: build once, promote the digest.  Pipeline B: rebuild in every environment;
// "^2.1" resolved again on day 4 picks a newer minor release of a library.
const once = build(SRC, { pay: "2.1.3" });
const A = { dev: once, test: once, staging: once, prod: once };
const B = { dev: build(SRC, { pay: "2.1.3" }), test: build(SRC, { pay: "2.1.3" }),
            staging: build(SRC, { pay: "2.1.3" }), prod: build(SRC, { pay: "2.2.0" }) };
function check(name, deployed) {
  const envs = Object.keys(deployed), digests = new Set(Object.values(deployed));
  console.log(`${name}: ` + envs.map(e => `${e}=${deployed[e]}`).join(" "));
  if (digests.size === 1) console.log("  OK: one artifact everywhere; what prod runs was tested");
  else envs.slice(1).forEach((e, i) => { if (deployed[e] !== deployed[envs[i]])
    console.log(`  ANTI-PATTERN: ${e} runs ${deployed[e]}, but ${envs[i]} tested ${deployed[envs[i]]}`); });
  const diff = Object.keys(CONFIG.prod).filter(k => CONFIG.staging[k] !== CONFIG.prod[k]);
  console.log(`  config keys that differ staging->prod: ${diff.join(", ")}`);
}
check("Pipeline A", A);
check("Pipeline B", B);

আউটপুট:

Pipeline A: dev=611809b3 test=611809b3 staging=611809b3 prod=611809b3
  OK: one artifact everywhere; what prod runs was tested
  config keys that differ staging->prod: DB_URL, NEW_CHECKOUT
Pipeline B: dev=611809b3 test=611809b3 staging=611809b3 prod=460181f7
  ANTI-PATTERN: prod runs 460181f7, but staging tested 611809b3
  config keys that differ staging->prod: DB_URL, NEW_CHECKOUT

Pipeline A-তে চারটি environment-এই একই digest 611809b3 — prod যা চালাচ্ছে, ঠিক সেটিই staging-এ test হয়েছিল। Pipeline B-তে dev, test আর staging একই, কিন্তু prod-এর digest 460181f7: source একই (a1c9e40), শুধু pay library ২.১.৩-এর বদলে ২.২.০ — এক byte বদলালেই hash বদলায়। এই prod artifact কোনো environment-এ কখনো test হয়নি। দুটি pipeline-এই config-এর দুটি key আলাদা (DB_URL, NEW_CHECKOUT) — এটি স্বাভাবিক আর কাঙ্ক্ষিত: artifact একই, config আলাদা. বাস্তবে এই check-টি deploy-এর ধাপে বসানো যায়: “prod-এ যে digest যাচ্ছে, staging-এ কি ঠিক সেটিই সবুজ হয়েছিল?” না হলে deploy থামুক।

Environment branch-এর ফাঁদ। কিছু দল প্রতিটি environment-এর জন্য আলাদা branch রাখে (staging, production) আর merge হলে সেখান থেকে আবার build করে। এতে branch-গুলো ধীরে ধীরে আলাদা হয় (পর্ব ১৭-এ environment branch-এর বিতর্ক), আর প্রতিটি environment-এ নতুন build. একই artifact-এর promotion অনেক বেশি নির্ভরযোগ্য।

৪ · Deploy বনাম release — rollback, roll forward আর release management

অংশ ২-এর stepper-এ সোমবার দুপুরে deploy হলো, কিন্তু release হলো মঙ্গল থেকে বৃহস্পতিবারে। দুটি শব্দ প্রায়ই একসাথে বলা হয়, কিন্তু আলাদা ঘটনা:

  • Deploy: নতুন version production-এর যন্ত্রে বসানো আর চালানো — একটি প্রযুক্তিগত ঘটনা।
  • Release: ব্যবহারকারীকে নতুন আচরণ দেখানো — একটি ব্যবসার ঘটনা।

দুটি আলাদা করলে deploy নিরাপদ আর একঘেয়ে হয়ে যায়: দিনে পাঁচবার deploy হলেও ব্যবহারকারী কিছুই টের পান না, আর release হয় flag ঘুরিয়ে, ঠিক যখন ব্যবসা চায়। এর প্রধান হাতিয়ার feature flag — trunk-based development-এর সাথে তার ব্যবহার, flag-এর ধরন আর flag-এর debt পর্ব ১৭-এ (Branching strategy) দেখেছেন। আরেকটি কৌশল dark launch: নতুন কোড prod-এ আসল অনুরোধের ওপর চালানো, কিন্তু ফল ব্যবহারকারীকে না দেখানো — শুধু আচরণ আর চাপ মাপা।

Deploy-এর নিজস্ব কৌশলগুলো — blue-green, canary, rolling update, Kubernetes-এর rollout, graceful shutdown, আর database migration-এর expand/contract — System Design কোর্সের Deployment আর release পর্বে বিস্তারিত আছে; এখানে আর পুনরাবৃত্তি করছি না। এই কোর্সের জন্য মূল কথা: কৌশল যা-ই হোক, সবই একই artifact আর একই pipeline-এর ওপর দাঁড়ায়।

সমস্যা হলে — rollback না roll forward?

Production-এ নতুন version-এর পরে error বাড়ল। দুটি পথ:

Rollback

আগের ভালো artifact আবার deploy করা, বা flag বন্ধ করা। আগের digest repository-তে আছে বলে মিনিটের কাজ। সমস্যা: database-এর schema বা data ইতিমধ্যে বদলে গেলে আগের কোড তার সাথে না-ও মিলতে পারে।

Roll forward

দ্রুত একটি সংশোধিত নতুন version পাঠানো। কারণ স্পষ্ট, fix ছোট আর pipeline দ্রুত হলে ভালো। ঝুঁকি: চাপের মধ্যে লেখা fix নিজেই নতুন ভুল আনতে পারে।

প্রচলিত পরামর্শ: আগে ব্যবহারকারীর ক্ষতি থামান, তারপর কারণ খুঁজুন — অর্থাৎ নিশ্চিত না হলে rollback বা flag বন্ধ। এটি পর্ব ৫৮-এর “লাল main-এ আগে revert” নিয়মেরই production-রূপ। Git-এর দিক থেকে rollback সাধারণত git revert (পর্ব ১১-এ ভুল শোধরানো) — ইতিহাস না মুছে নতুন commit, যা pipeline দিয়েই prod-এ যায়। আর rollback কাজ করবে কি না, তা আগের প্রস্তুতির ওপর নির্ভর করে: ফেরা যায় এমন migration, হাতের কাছে আগের artifact, আর নিয়মিত মহড়া।

Release management — continuous delivery-তেও দরকার

Release management মানে কোন পরিবর্তন কবে, কাদের কাছে, কোন ঝুঁকি আর ফেরার পরিকল্পনাসহ যাবে, তার সমন্বয়। Continuous delivery এই কাজকে বাদ দেয় না, ছোট করে: পঁচিশ ধাপের হাতের নির্দেশিকার বদলে pipeline-এ লেখা ধাপ, মাসিক release meeting-এর বদলে প্রতিটি পরিবর্তনের ছোট ঝুঁকি-যাচাই। তবু কিছু প্রশ্ন সবসময় থাকে: database migration আছে কি? কোনো public API ভাঙছে কি (তাহলে SemVer-এ MAJOR — পর্ব ১৮-এ ভালো commit, tag আর release)? Release notes কে লিখবেন? ঈদের আগের ভিড়ের সপ্তাহে deploy কমাবেন কি না? যেখানে app store-এর অনুমোদন বা আইনি নিয়ন্ত্রণ আছে, সেখানে continuous deployment সম্ভব না-ও হতে পারে — কিন্তু continuous delivery তখনো সম্ভব।

৫ · DevOps — দেয়াল ভাঙার সংস্কৃতি

ধরুন একটি প্রতিষ্ঠানে দুটি দল। Development-এর লক্ষ্য দ্রুত নতুন feature; operations-এর দায় system চালু রাখা, তাই তাদের লক্ষ্য কম পরিবর্তন। মাঝে একটি দেয়াল: development কোড “দেয়ালের ওপারে ছুড়ে দেয়”, operations রাত তিনটায় ফোন পায়। দুই দলই নিজের লক্ষ্যে ঠিক, কিন্তু প্রতিষ্ঠান মিলে ধীর আর ঝুঁকিপূর্ণ। DevOps এই দেয়াল ভাঙার আন্দোলন।

জন্মকথা। প্রকাশিত বিবরণ অনুযায়ী, ২০০৮ সালে Toronto-র একটি Agile সম্মেলনে Andrew Shafer আর Patrick Debois “agile infrastructure” নিয়ে কথা বলেন। ২০০৯ সালের জুনে O’Reilly-র Velocity সম্মেলনে John Allspaw আর Paul Hammond “10+ Deploys Per Day: Dev and Ops Cooperation at Flickr” বক্তৃতায় দেখান, development আর operations একসাথে কাজ করলে দিনে দশবারের বেশি deploy সম্ভব। সেটি অনলাইনে দেখে অনুপ্রাণিত হয়ে Patrick Debois ২০০৯ সালের অক্টোবরে বেলজিয়ামের Ghent-এ প্রথম DevOpsDays আয়োজন করেন, আর Twitter-এ ছোট করার প্রয়োজনে “DevOps” শব্দটি ছড়ায়। (তারিখ আর ক্রম প্রচলিত বর্ণনা অনুযায়ী; সূত্রভেদে খুঁটিনাটি একটু আলাদা।)

CALMS — DevOps মাপার পাঁচটি দিক

DevOps-এর কোনো আনুষ্ঠানিক সংজ্ঞা বা মান নেই; একটি প্রচলিত কাঠামো CALMS. প্রচলিত বর্ণনা অনুযায়ী John Willis আর Damon Edwards প্রথমে CAMS বলেন (মোটামুটি ২০১০), পরে Jez Humble Lean-এর L যোগ করেন:

অক্ষরঅর্থদলে কেমন দেখায়
C · Cultureযৌথ দায়, দোষারোপহীনতাincident-এর পরে blameless postmortem; dev আর ops একই লক্ষ্যে
A · Automationবারবারের কাজ যন্ত্রেdeployment pipeline, infrastructure as code, স্বয়ংক্রিয় test
L · Leanছোট batch, অপচয় কমানোছোট PR, WIP limit, value stream-এ অপেক্ষা খোঁজা (পর্ব ৬)
M · Measurementঅনুমান নয়, মাপDORA metric, error rate, latency — অংশ ৬
S · Sharingজ্ঞান আর tool ভাগএকই dashboard, একই runbook, খোলা postmortem

“You build it, you run it”

২০০৬ সালে ACM Queue-এর একটি সাক্ষাৎকারে Amazon-এর CTO Werner Vogels যে কথাটি বলেছিলেন বলে বহুল-উদ্ধৃত, তার সারকথা: you build it, you run it — যে দল service বানায়, সেই দলই production-এ সেটি চালায়। এতে ডেভেলপার নিজের কোডের রাতের আচরণ দেখেন, তাই log আর monitoring-এর দিকে মনোযোগ আপনা-আপনি বাড়ে। খরচও আছে: on-call-এর চাপ আর সব দলে ops-এর দক্ষতার দরকার। তাই অনেক প্রতিষ্ঠান একটি platform দল রাখে, যারা pipeline আর পরিকাঠামো “স্ব-সেবা” হিসেবে দেয়; আর SRE reliability-কে আলাদা প্রকৌশল হিসেবে দেখে। SLO আর error budget দিয়ে গতি আর স্থিতির ভারসাম্য রাখার পদ্ধতি System Design-এর Observability পর্বে।

তিন পথ — The Three Ways

Gene Kim, Kevin Behr ও George Spafford-এর উপন্যাস The Phoenix Project (২০১৩) আর পরে Kim, Humble, Debois ও Willis-এর The DevOps Handbook (২০১৬; দ্বিতীয় সংস্করণ ২০২১) DevOps-কে তিনটি পথে সাজায়:

  1. প্রথম পথ — flow: development থেকে production পর্যন্ত কাজ বাঁ থেকে ডানে দ্রুত আর মসৃণ চলুক। ছোট batch, কম WIP, ধাপে ধাপে অপেক্ষা কমানো (পর্ব ৬-এ Kanban আর lean-এর flow আর Little-এর সূত্র)।
  2. দ্বিতীয় পথ — feedback: ডান থেকে বাঁয়ে দ্রুত খবর ফিরুক — pipeline-এর লাল, production-এর alert, ব্যবহারকারীর অভিযোগ — যাতে সমস্যা ছোট থাকতেই ধরা পড়ে।
  3. তৃতীয় পথ — ধারাবাহিক শেখা আর পরীক্ষা: ব্যর্থতা থেকে দোষারোপহীনভাবে শেখা, ছোট পরীক্ষা চালানো, আর দৈনন্দিন কাজের উন্নতির জন্য সময় রাখা।

DevOps পদ বা tool নয়। “আমাদের DevOps দল আছে” — কিন্তু সেই দল যদি শুধু development আর operations-এর মাঝখানে নতুন একটি দেয়াল হয়, তাহলে দেয়াল দুটি হলো, একটি নয়। একইভাবে Jenkins, Docker বা Kubernetes কিনলে DevOps হয় না, ঠিক যেমন CI tool থাকলেই CI হয় না (পর্ব ৫৮)। প্রশ্ন একটিই: পরিবর্তন কি দ্রুত, নিরাপদে আর যৌথ দায়ে ব্যবহারকারীর কাছে যাচ্ছে?

৬ · DORA-র চারটি metric — সংজ্ঞা আর হিসাব

“আমাদের delivery কি ভালো হচ্ছে?” — এই প্রশ্নের উত্তর অনুভূতিতে দিলে তর্ক শেষ হয় না। DORA (DevOps Research and Assessment) দল বছরের পর বছর হাজারো পেশাজীবীর জরিপ থেকে চারটি মাপ বেছে নেয়, যেগুলো একসাথে delivery-র গতি আর স্থিতি দেখায়। ফলাফল সংকলিত হয় Nicole Forsgren, Jez Humble ও Gene Kim-এর বই Accelerate (২০১৮)-এ; DORA ২০১৮ সালের শেষে Google-এর অংশ হয়। এই চারটিকে একসাথে বলে DORA metric:

Metricপ্রশ্নহিসাব (এই পর্বের নিয়মে)ধরন
Deployment frequencyকত ঘন ঘন production-এ deploy?সফল prod deploy ÷ দিনগতি
Lead time for changescommit থেকে production পর্যন্ত কত সময়?প্রতিটি commit-এর (deploy-এর সময় − commit-এর সময়), তার medianগতি
Change failure rateকত শতাংশ deploy সমস্যা ঘটায়?যে deploy-এ rollback, hotfix বা incident লেগেছে ÷ মোট deployস্থিতি
Time to restore serviceসমস্যা থেকে কত দ্রুত ফেরা যায়?প্রতিটি incident-এর (স্বাভাবিক হওয়ার সময় − শুরু), তার medianস্থিতি

খেয়াল করুন, DORA-র lead time পর্ব ৬-এর Kanban-এর lead time-এর চেয়ে সরু: অনুরোধ আসা থেকে নয়, commit থেকে production পর্যন্ত — অর্থাৎ শুধু delivery-র পথ। শেষ metric-টিকে পুরোনো লেখায় প্রায়ই MTTR বলা হয়। পরের report-গুলোতে নাম আর সংখ্যা কিছু বদলেছে: ২০২১ নাগাদ operational performance-এর জন্য reliability নামে একটি পঞ্চম মাপ যোগ হয়; আর ২০২৩ নাগাদ “time to restore service”-এর বদলে আসে failed deployment recovery time — শুধু deploy-এর কারণে ঘটা ব্যর্থতা থেকে ফেরার সময়। পরে rework rate-এর মতো আরও মাপের কথাও এসেছে বলে আমরা জানি। Performance-এর band (elite, high, medium, low)-এর সীমাও বছরভেদে বদলেছে, আর এগুলো জরিপের গুচ্ছ (cluster) থেকে আসে, আইনি মান নয়। সর্বশেষ সংজ্ঞা DORA-র নিজের প্রকাশনায় দেখে নিন।

Git আর deploy log থেকে কীভাবে মাপবেন

চারটি metric-এর কাঁচামাল দুটি জায়গায়: Git জানে প্রতিটি commit-এর সময়, আর deploy-এর tool জানে কোন commit কখন production-এ গেল। অনেক দল প্রতিটি prod deploy-এ একটি annotated tag বসায় (tag পর্ব ১৮-এ) — তাহলে Git থেকেই দুটি deploy-এর মাঝের commit-গুলো পাওয়া যায়। নিচের transcript একটি scratch repository-তে Git ২.৫৩-এ তৈরি; কাল্পনিক দল, সময় নির্দিষ্ট করে দেওয়া:

$ git tag --list "deploy-*" --format="%(refname:short) %(taggerdate:iso-strict)"
deploy-0041 2026-03-02T17:00:00+06:00
deploy-0042 2026-03-03T16:00:00+06:00
$ git log --reverse --format="%h %cI %s" deploy-0041..deploy-0042
96c783e 2026-03-03T09:10:00+06:00 feat(pay): add cash on delivery
4ec747c 2026-03-03T11:45:00+06:00 test(pay): cover COD limit
97b188e 2026-03-03T14:20:00+06:00 fix(cart): empty cart crash

প্রথম command প্রতিটি deploy tag আর তার সময় দেখায় (%(taggerdate:iso-strict)). দ্বিতীয়টি deploy-0041..deploy-0042 range দিয়ে দেখায় কোন commit-গুলো দ্বিতীয় deploy-এ নতুন গেছে (range-এর মানে পর্ব ৯-এ, History আর পার্থক্য দেখা), প্রতিটির commit-এর সময়সহ (%cI). ১৬:০০-এর deploy থেকে বিয়োগ করলে তিনটি lead time: ৬ ঘণ্টা ৫০ মিনিট, ৪ ঘণ্টা ১৫ মিনিট আর ১ ঘণ্টা ৪০ মিনিট; median ৪ ঘণ্টা ১৫ মিনিট। সতর্কতা: rebase বা squash-এ commit-এর সময় বদলাতে পারে — কোন বিন্দু থেকে মাপছেন, লিখে রাখুন আর বদলাবেন না।

Change failure rate-এর জন্য দরকার deploy-এর সাথে incident বা rollback-এর যোগসূত্র — incident-এর রেকর্ডে “কোন deploy-এর পরে” লেখা থাকলে সহজ। ফেরার সময়ের জন্য incident খোলা আর বন্ধের সময়। এবার একটি ছোট সপ্তাহের log থেকে হাতে হিসাব করি। কাল্পনিক bazar-cart-এর সাত দিনে ছয়টি deploy:

Deployদিনপ্রতিটি commit-এর lead time (ঘণ্টা)সমস্যা?ফিরতে সময়
D1রবি২, ৫না—
D2সোম৩হ্যাঁ (checkout-এ error)৪৫ মিনিট
D3মঙ্গল১, ৪, ২০না—
D4বুধ৬না—
D5বৃহস্পতি২, ৮হ্যাঁ (ভুল দাম)১৮০ মিনিট
D6বৃহস্পতি১না—
bazar-cart · ৭ দিন, ৬টি deploy, ১০টি commit, ২টি incident
এখন যা হিসাব হচ্ছে
হিসাব
ফল
সাবধানতা
  1. কাঁচা তথ্য. সাত দিনে ছয়টি deploy, মোট দশটি commit, দুটি সমস্যা। আগে সংজ্ঞা ঠিক করুন — কোন deploy গোনা হবে আর “সমস্যা” মানে কী।
  2. Deployment frequency. ৬ ÷ ৭ = দিনে ০.৮৬, অর্থাৎ সপ্তাহে ছয়বার — “দিনে একবারের কম, সপ্তাহে একবারের বেশি”।
  3. Lead time. প্রতিটি commit একটি মান: দশটি সাজিয়ে nearest-rank median = ⌈০.৫ × ১০⌉ = ৫ম মান = ৩ ঘণ্টা। গড় হতো ৫.২ — ২০ ঘণ্টার একটি commit গড়কে টানে, median-কে নয়।
  4. Change failure rate. D2 আর D5, তাই ২ ÷ ৬ = ৩৩.৩%. ছোট নমুনায় একটি deploy এদিক-ওদিক হলেই সংখ্যা ১৬.৭ শতাংশ-বিন্দু বদলায়।
  5. Time to restore. ৪৫ আর ১৮০ মিনিট; median = ⌈০.৫ × ২⌉ = ১ম মান = ৪৫ মিনিট, গড় ১১২.৫. দুটি incident-এ কোনো একক সংখ্যা বিশ্বাসযোগ্য নয় — incident-এর সংখ্যাও পাশে লিখুন।
  6. একসাথে পড়া. গতি ভালো, কিন্তু প্রতি তিনটি deploy-এর একটি সমস্যা ঘটাচ্ছে। পরের কাজ গতি বাড়ানো নয় — দাম আর checkout-এর acceptance test জোরদার করা।

এবার বড় একটি log — ২৮ দিনের, seeded PRNG দিয়ে তৈরি, যাতে প্রত্যেক পাঠক একই সংখ্যা দেখেন। প্রতিদিন ০ থেকে ৩টি deploy, প্রতিটিতে ১–৩টি commit, যা deploy-এর ১ থেকে ৩১ ঘণ্টা আগে লেখা; প্রতিটি deploy-এর প্রায় ১৫% সম্ভাবনায় সমস্যা, আর ফিরতে ১০ থেকে ১৮০ মিনিট। Band-এর সীমা এখানে দেওয়া মান — মোটামুটি ২০১৯ সালের দিকের report-এর ধাঁচে সরল করা; আসল report-এর সীমা বছরভেদে আলাদা:

// DORA's four key metrics from a SIMULATED 28-day deploy + incident log.
// mulberry32 = small seeded PRNG, so every reader sees the same log.
function mulberry32(a) { return function () { a |= 0; a = a + 0x6D2B79F5 | 0;
  let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
  return ((t ^ t >>> 14) >>> 0) / 4294967296; }; }
const rnd = mulberry32(59), H = 3600e3, MIN = 60e3, DAYS = 28;
const deploys = [], incidents = [];
for (let d = 0; d < DAYS; d++) {
  const n = Math.floor(rnd() * 4);                    // 0..3 deploys that day
  for (let k = 0; k < n; k++) {
    const at = d * 24 * H + (10 + 3 * k) * H;         // 10:00, 13:00, 16:00
    const commits = Array.from({ length: 1 + Math.floor(rnd() * 3) },
                               () => at - (1 + rnd() * 30) * H);   // committed 1-31 h earlier
    const failed = rnd() < 0.15;                      // caused a user-facing problem?
    deploys.push({ at, commits, failed });
    if (failed) incidents.push({ minutes: Math.round(10 + rnd() * 170) }); // detect -> restored
  }
}
const median = xs => { const s = [...xs].sort((a, b) => a - b);
  return s[Math.ceil(0.5 * s.length) - 1]; };          // nearest-rank median
const perDay = deploys.length / DAYS;
const leadH = median(deploys.flatMap(dp => dp.commits.map(c => dp.at - c))) / H;
const cfr = deploys.filter(dp => dp.failed).length / deploys.length;
const restoreMin = median(incidents.map(i => i.minutes));
// STATED, simplified bands (roughly the 2019-era report style; reports change them).
const band = (v, cuts, up, other = "low") =>   // up: bigger is better
  (cuts.find(([lim]) => up ? v >= lim : v <= lim) || [0, other])[1];
console.log(`deploys: ${deploys.length} in ${DAYS} days, commits: ${deploys.reduce((a, d) => a + d.commits.length, 0)}`);
console.log(`deployment frequency: ${perDay.toFixed(2)}/day -> ${band(perDay, [[1, "elite"], [1 / 7, "high"], [1 / 30, "medium"]], true)}`);
console.log(`lead time for changes (median): ${leadH.toFixed(1)} h -> ${band(leadH, [[24, "elite"], [168, "high"], [720, "medium"]])}`);
console.log(`change failure rate: ${(100 * cfr).toFixed(1)}% -> ${band(cfr, [[0.15, "0-15% band"]], false, "above 15%")}`);
console.log(`time to restore (median): ${restoreMin} min over ${incidents.length} incidents -> ${band(restoreMin, [[60, "elite"], [1440, "high"], [10080, "medium"]])}`);

আউটপুট:

deploys: 35 in 28 days, commits: 68
deployment frequency: 1.25/day -> elite
lead time for changes (median): 15.9 h -> elite
change failure rate: 25.7% -> above 15%
time to restore (median): 63 min over 9 incidents -> high

২৮ দিনে ৩৫টি deploy মানে দিনে ১.২৫ — দিনে একবারের বেশি, তাই এই সরল band-এ “elite”. ৬৮টি commit-এর lead time-এর median ১৫.৯ ঘণ্টা, এক দিনের নিচে — এটিও “elite” (তবে খেয়াল করুন, কোনো কোনো বছরের report-এ elite-এর সীমা ছিল এক ঘণ্টারও কম; band কোন বছরের, তা না বললে লেবেল অর্থহীন)। কিন্তু ৩৫টির মধ্যে ৯টি deploy সমস্যা ঘটিয়েছে: ৯ ÷ ৩৫ = ২৫.৭%, ১৫%-এর ওপরে। ফেরার median ৬৩ মিনিট — এক ঘণ্টার সীমা থেকে মাত্র তিন মিনিট বেশি, তাই “high”. সীমার কাছে একটি incident এদিক-ওদিক হলেই লেবেল লাফায়; লেবেলের চেয়ে সংখ্যা আর তার প্রবণতা বেশি তথ্য দেয়। চারটি একসাথে পড়লে গল্পটি ওপরের সপ্তাহের মতোই: দল দ্রুত, কিন্তু পরিবর্তন যথেষ্ট যাচাই হচ্ছে না।

৭ · ছোট batch, কম অপেক্ষা — আর metric-এর অপব্যবহার

DORA-র একটি প্রধান দাবি — Accelerate-এর ভাষায় — গতি আর স্থিতি পরস্পরবিরোধী নয়: জরিপে যে দলগুলো বেশি ঘন ঘন deploy করে, তাদের change failure rate-ও গড়ে কম। কেন হতে পারে? একটি বড় কারণ batch-এর আকার। সপ্তাহে একবার deploy মানে প্রতিটি deploy-এ এক সপ্তাহের সব পরিবর্তন — ভাঙলে কোনটির জন্য, খুঁজতে সময় লাগে, আর rollback-এ ভালো পরিবর্তনগুলোও ফিরে যায়। আর অপেক্ষা: সোমবারের commit বৃহস্পতিবারের deploy-এর জন্য বসে থাকে। ঈদের আগে বাসের টিকিটের কাউন্টারের কথা ভাবুন — সপ্তাহে একদিন কাউন্টার খুললে সবাই সেদিন লাইনে, আর কেউ রবিবারে এলেও বৃহস্পতিবার পর্যন্ত অপেক্ষা।

নিচের Python program একই ৪০টি commit (দুই সপ্তাহ, রবি থেকে বৃহস্পতি, প্রতিদিন ১০, ১২, ২ আর ৪টায়) তিনটি নিয়মে deploy করে: সপ্তাহে একবার বৃহস্পতিবার বিকেল ৫টায়, প্রতিদিন বিকেল ৫টায়, আর প্রতিটি commit-এর পরে (৪০ মিনিটের pipeline). প্রতিটি commit-এর lead time = তার পরের প্রথম deploy − commit:

# Lead time for changes under three deploy policies, same commits.
# Commits: 4 per working day (Sun-Thu) at 10:00, 12:00, 14:00, 16:00 for 2 weeks.
from datetime import datetime, timedelta
from math import ceil

start = datetime(2026, 3, 1)                       # a Sunday
commits = [start + timedelta(days=d, hours=h)
           for d in range(14) if (start + timedelta(days=d)).weekday() not in (4, 5)
           for h in (10, 12, 14, 16)]              # Friday(4), Saturday(5) off

def deploy_times(policy):
    if policy == "weekly (Thu 17:00)":
        return [start + timedelta(days=d, hours=17) for d in (4, 11)]
    if policy == "daily (17:00)":
        return sorted({c.replace(hour=17) for c in commits})
    return [c + timedelta(minutes=40) for c in commits]   # every commit, 40-min pipeline

def pct(xs, p):                                    # nearest-rank percentile
    s = sorted(xs)
    return s[ceil(p / 100 * len(s)) - 1]

print(f"{len(commits)} commits")
for policy in ("weekly (Thu 17:00)", "daily (17:00)", "every change (+40 min)"):
    deps = deploy_times(policy)
    lead = [(min(t for t in deps if t >= c) - c).total_seconds() / 3600 for c in commits]
    batch = len(commits) / len(deps)
    print(f"{policy:24} deploys={len(deps):2} batch={batch:4.1f} "
          f"median={pct(lead, 50):6.1f} h  p90={pct(lead, 90):6.1f} h  max={max(lead):6.1f} h")

আউটপুট:

40 commits
weekly (Thu 17:00)       deploys= 2 batch=20.0 median=  51.0 h  p90=  99.0 h  max= 103.0 h
daily (17:00)            deploys=10 batch= 4.0 median=   3.0 h  p90=   7.0 h  max=   7.0 h
every change (+40 min)   deploys=40 batch= 1.0 median=   0.7 h  p90=   0.7 h  max=   0.7 h

একই কাজ, শুধু deploy-এর নিয়ম বদল। সাপ্তাহিক deploy-এ প্রতিটি deploy-এ ২০টি commit, median lead time ৫১ ঘণ্টা, আর রবিবার সকাল ১০টার commit বৃহস্পতিবার বিকেল ৫টা পর্যন্ত — ১০৩ ঘণ্টা — অপেক্ষা করে। দৈনিক deploy-এ batch ৪, median ৩ ঘণ্টা, সর্বোচ্চ ৭ ঘণ্টা (সকাল ১০টা থেকে বিকেল ৫টা)। প্রতিটি পরিবর্তনে deploy করলে batch ১, আর lead time শুধু pipeline-এর ৪০ মিনিট (০.৭ ঘণ্টা)। Lead time-এর বড় অংশ কাজ নয়, অপেক্ষা — পর্ব ৬-এর flow efficiency সংখ্যায়। আর batch ১ হলে কোনো deploy ভাঙলে সন্দেহের তালিকায় ২০টির বদলে একটি commit.

যখন metric লক্ষ্য হয়ে যায়

পর্ব ৬-এ Goodhart-এর সূত্র দেখেছেন: কোনো মাপ লক্ষ্য হলে মানুষ মাপটিকেই সাজায়, ব্যবস্থাকে নয়। DORA metric এর ব্যতিক্রম নয়। কয়েকটি পরিচিত বিকৃতি:

  • ফাঁপা deploy: deploy frequency-র লক্ষ্য পূরণে খালি বা শুধু comment-বদলের deploy. সংখ্যা বাড়ে, ব্যবহারকারী কিছু পান না।
  • Failure-এর সংজ্ঞা সরু করা: “এটি config-এর ভুল, deploy-এর নয়” বা “মাত্র দশ মিনিট, incident নয়” — change failure rate কমে কাগজে।
  • ঘড়ি দেরিতে চালু: lead time-এর শুরু commit থেকে নয়, PR approve থেকে — অপেক্ষার সবচেয়ে বড় অংশ চোখের আড়ালে।
  • Incident তাড়াতাড়ি বন্ধ: দ্রুত “resolved” চিহ্ন দিয়ে পরে নতুন ticket — ফেরার সময় সুন্দর দেখায়।
  • দল বা ব্যক্তির তুলনা আর পুরস্কার: ভিন্ন ঝুঁকির দলকে এক মাপে সাজানো, ব্যক্তির deploy গোনা। DORA-র নিজের নির্দেশনাও metric-কে দলের নিজের উন্নতির জন্য ব্যবহারের কথা বলে, র‍্যাংকিংয়ের জন্য নয়।

প্রতিরক্ষা: চারটি metric জোড়ায় দেখুন (গতির পাশে স্থিতি), সংজ্ঞা লিখে স্থির রাখুন, নিজের প্রবণতার সাথে তুলনা করুন, আর সংখ্যার পাশে গল্প রাখুন — postmortem, ব্যবহারকারীর অভিযোগ, দলের ক্লান্তি। আর মনে রাখুন, DORA-র ফলাফল জরিপভিত্তিক সম্পর্ক (correlation); প্রতিটি দলে কারণ-ফল নিশ্চিত নয়।

৮ · Infrastructure as code আর GitOps — কাঙ্ক্ষিত অবস্থা Git-এ

Artifact একই, config আলাদা — কিন্তু যে server, network আর database-এ সেগুলো চলে, সেগুলো কে বানায়? পুরোনো পথে একজন admin হাতে server সাজান। ছয় মাস পরে কেউ জানেন না staging আর prod ঠিক কোথায় আলাদা; কেউ হাতে একটি setting বদলেছিলেন, যা কোথাও লেখা নেই — একে বলে configuration drift.

Infrastructure as code (IaC) এর উত্তর: পরিকাঠামোর বর্ণনা file-এ লিখুন, file রাখুন Git-এ, আর tool সেই বর্ণনা থেকে পরিকাঠামো বানাক। তাহলে পরিকাঠামোর পরিবর্তনও PR-এ review হয়, history থাকে, আর একই file থেকে নতুন environment মিনিটে তৈরি হয়। Tool-এর উদাহরণ (লেখার সময়ে প্রচলিত): Terraform বা OpenTofu, Ansible, Puppet, Chef. বেশিরভাগ tool declarative: আপনি লেখেন কী চাই (“এই image-এর ৩টি copy”), tool ঠিক করে কীভাবে — রান্নার ধাপ নয়, প্লেটে কী থাকবে তার ছবি।

GitOps এই ভাবনাকে আরেক ধাপ নেয়। শব্দটি ২০১৭ সালে Weaveworks প্রতিষ্ঠানের (Alexis Richardson-এর লেখায়) জনপ্রিয় হয় বলে প্রচলিত; পরে CNCF-এর OpenGitOps প্রকল্প চারটি নীতি লেখে (মোটামুটি এই অর্থে): system-এর desired state declarative ভাবে বর্ণিত; সেই বর্ণনা version-সহ অপরিবর্তনীয় ভাবে রাখা (সাধারণত Git); একটি agent নিজে থেকে সেটি টেনে নেয় (pull); আর agent অবিরাম আসল অবস্থাকে বর্ণনার সাথে মিলিয়ে রাখে। শেষ নীতিটির নাম reconciliation loop — ঘরের থার্মোস্ট্যাটের মতো: আপনি তাপমাত্রা ঠিক করে দেন, যন্ত্র বারবার মাপে আর পার্থক্য দেখলে চালু-বন্ধ করে। Kubernetes-এর মতো system-এ Argo CD বা Flux-এর মতো tool এই agent-এর কাজ করে (Kubernetes-এর মূল ধারণা System Design-এর Deployment আর release পর্বে)।

নিচের খেলনা reconciler একটি loop-এ desired আর actual মেলায়: যা Git-এ আছে কিন্তু চলছে না, তা create; যা আলাদা, তা update; আর যা চলছে কিন্তু Git-এ নেই — prune বন্ধ থাকলে শুধু সতর্কবার্তা, চালু থাকলে delete. শুরুতে দুটি drift আছে: কেউ হাতে worker-কে ৫টি copy-তে বাড়িয়েছেন, আর একটি debug service হাতে বানিয়েছেন:

// A toy GitOps reconciler: desired state (read from Git) vs actual state (the cluster).
// Each loop: diff -> actions -> apply. Running it again must change nothing (converged).
const desired = {                                   // what the main branch of the config repo says
  web:    { image: "bazar-cart:1.8.0", replicas: 3 },
  worker: { image: "bazar-jobs:2.4.1", replicas: 2 },
  redis:  { image: "redis:7.4",        replicas: 1 },
};
const actual = {                                    // what is really running
  web:    { image: "bazar-cart:1.7.2", replicas: 3 },
  worker: { image: "bazar-jobs:2.4.1", replicas: 5 },   // someone scaled it by hand
  debug:  { image: "busybox:1.36",     replicas: 1 },   // created by hand, not in Git
};
function diff(want, have, prune) {
  const acts = [];
  for (const [n, spec] of Object.entries(want)) {
    if (!(n in have)) { acts.push(["create", n, spec]); continue; }
    const changed = Object.keys(spec).filter(k => spec[k] !== have[n][k]);
    if (changed.length) acts.push(["update", n, spec,
      changed.map(k => `${k} ${have[n][k]} -> ${spec[k]}`).join(", ")]);
  }
  for (const n of Object.keys(have))
    if (!(n in want)) acts.push(prune ? ["delete", n] : ["warn-extra", n]);
  return acts;
}
function reconcile(loop, prune) {
  const acts = diff(desired, actual, prune);
  console.log(`loop ${loop}: ${acts.length ? acts.length + " action(s)" : "in sync, nothing to do"}`);
  for (const [op, n, spec, why] of acts) {
    console.log(`  ${op.padEnd(10)} ${n}${why ? "  (" + why + ")" : ""}`);
    if (op === "create" || op === "update") actual[n] = { ...spec };
    if (op === "delete") delete actual[n];
  }
}
reconcile(1, false);   // prune off: extra objects are only reported
reconcile(2, true); reconcile(3, true);   // prune on: not-in-Git is removed; then converged

আউটপুট:

loop 1: 4 action(s)
  update     web  (image bazar-cart:1.7.2 -> bazar-cart:1.8.0)
  update     worker  (replicas 5 -> 2)
  create     redis
  warn-extra debug
loop 2: 1 action(s)
  delete     debug
loop 3: in sync, nothing to do

প্রথম loop-এ চারটি কাজ: web-এর image ১.৭.২ থেকে Git-এর ১.৮.০-এ (এটিই নতুন deploy), worker-এর হাতে বাড়ানো ৫টি copy আবার ২-এ (drift ঠিক), redis Git-এ আছে কিন্তু চলছিল না — তাই create, আর debug Git-এ নেই, কিন্তু prune বন্ধ থাকায় শুধু সতর্কবার্তা। দ্বিতীয় loop-এ prune চালু, তাই debug মুছে গেল। তৃতীয় loop-এ কিছুই করার নেই — system converged. অবস্থা মিলে গেলে loop আর কিছু বদলায় না — কাজটি idempotent. আর worker-কে ৫-এ রাখতে চাইলে cluster-এ হাতে বদলালে চলবে না, পরের loop-এ আবার ২ হবে; বদলাতে হবে Git-এ, PR দিয়ে।

  1. PRconfig repo
  2. Mergedesired
  3. Diffagent
  4. Applysync
  5. Driftহাতে বদল
  6. RevertGit-এ
bazar-cart · production cluster (কাল্পনিক)
Git-এ (desired)
Cluster-এ (actual)
Agent-এর অবস্থা
কী ঘটছে
  1. PR. সুমি config repository-তে web-এর image ১.৭.২ থেকে ১.৮.০ করার PR খুললেন। Cluster-এ কেউ সরাসরি হাত দেন না — পরিবর্তনের একমাত্র দরজা PR, তাই review আর history আপনা-আপনি।
  2. Merge. Review-এর পরে merge; main এখন বলে “web 1.8.0 × 3”. Cluster এখনো পুরোনো — agent দেখেনি, তাই অবস্থা OutOfSync.
  3. Diff. Agent নির্দিষ্ট সময় পরপর (এখানে ধরা ৩ মিনিট; webhook-এও হয়) Git থেকে desired state টানে আর cluster-এর actual-এর সাথে মেলায়: image আলাদা।
  4. Apply. Agent পার্থক্য ঘোচাল — rolling update-এ নতুন image, health check সবুজ। Desired = actual: Synced, Healthy. এটিই deploy — কোনো ডেভেলপার production-এর credential হাতে পাননি।
  5. Drift. রাতে একটি alert দেখে কেউ cluster-এ হাতে web-কে ৬টি copy-তে বাড়ালেন। এখন actual আর desired আলাদা — drift.
  6. Self-heal. পরের loop-এ agent আবার ৩-এ নামাল আর দলকে জানাল। ৬ সত্যিই দরকার হলে সঠিক পথ Git-এ PR — নইলে হাতের বদল প্রতিবার মুছে যাবে।
  7. Rollback = git revert. পরদিন ১.৮.০-তে error বাড়ল। দল image-এর commit-টি git revert করল; agent দেখল desired এখন ১.৭.২, আর cluster ফেরাল। Rollback-এর জন্যও force push নয় — ইতিহাসে দুটি ঘটনাই থাকে।

GitOps সব সমস্যার সমাধান নয়। Secret Git-এ সরাসরি রাখা যায় না — এনক্রিপ্ট করে বা secret manager-এর উল্লেখ দিয়ে। Database-এর data “desired state” নয়। আর ভুল PR merge হলে agent সেটিও বিশ্বস্তভাবে production-এ বসাবে — তাই config repository-তেও review, branch protection আর CI-র check দরকার।

৯ · DevSecOps — নিরাপত্তা শুরু থেকেই

পুরোনো ধারায় নিরাপত্তা-পর্যালোচনা হতো release-এর ঠিক আগে, একটি আলাদা দলের হাতে — তখন বড় সমস্যা পেলে হয় release পেছায়, নয় ঝুঁকি নিয়ে যায়। DevSecOps নিরাপত্তাকে pipeline-এর প্রতিটি ধাপে আর দলের সবার দায়িত্বে আনে — shift left-এর ভাবনা, যা testing-এর ক্ষেত্রে পর্ব ৪৫-৫১-এ দেখেছেন। মূল চর্চাগুলো এই কোর্সে ইতিমধ্যে এসেছে, আর এখানে শুধু জায়গামতো বসাই:

  • Commit-এর আগে আর commit stage-এ: secret scanning, signed commit (পর্ব ৫৭-এ Git-এ নিরাপত্তা), static analysis আর dependency-র দুর্বলতার scan (পর্ব ৫৮-এ Continuous integration).
  • Artifact-এ: artifact কোন source আর কোন build থেকে এল তার প্রমাণ (provenance), dependency-র তালিকা (SBOM), আর digest-এ সই — software supply chain-এর প্রতিরক্ষা। SLSA-র মতো কাঠামো এই স্তরগুলো সাজায়; বিস্তারিত দ্রুত বদলাচ্ছে, তাই লেখার সময়ের documentation দেখুন।
  • Deploy-এ: ন্যূনতম অনুমতি — deploy-এর credential শুধু pipeline বা GitOps agent-এর কাছে, ডেভেলপারের ল্যাপটপে নয়; prod-এ পরিবর্তন শুধু pipeline দিয়ে।
  • Production-এ: নিরাপত্তার ঘটনার log আর alert, আর ঘটনা ঘটলে incident response-এর আগে থেকে ঠিক করা ধাপ।

নিরাপত্তা দল এখানে “না” বলার দরজা নয়, সহজ নিরাপদ পথ বানিয়ে দেওয়া সহকর্মী। বিপর্যয়ের প্রস্তুতি — backup, RPO-RTO, failover — System Design-এর Failover আর disaster recovery পর্বে।

আরও গভীরে: মূল বই তিনটি: Jez Humble ও David Farley-র Continuous Delivery (২০১০) — pipeline-এর নকশার জন্য; Nicole Forsgren, Jez Humble ও Gene Kim-এর Accelerate (২০১৮) — DORA-র গবেষণা-পদ্ধতি আর চারটি metric; আর The DevOps Handbook (২০১৬; দ্বিতীয় সংস্করণ ২০২১) — তিন পথের বিস্তারিত চর্চা। পরিকাঠামোর দিকে Kief Morris-এর Infrastructure as Code বইটি পরিচিত, আর GitOps-এর নীতি OpenGitOps প্রকল্পের প্রকাশনায়।

পরীক্ষা ও ইন্টারভিউতে:

  • Continuous delivery আর continuous deployment-এর পার্থক্য? — দুটিতেই প্রতিটি পরিবর্তন release-যোগ্য; delivery-তে production-এ পাঠানো একটি মানুষের সিদ্ধান্ত (বোতাম), deployment-এ সব check পার হলে স্বয়ংক্রিয়।
  • Deployment pipeline-এর ধাপ? — commit stage (build, unit, analysis, artifact), acceptance stage, capacity ও অন্যান্য non-functional test, manual বা UAT, production; প্রতিটি ব্যর্থ হলে দ্রুত feedback.
  • “Build once, deploy many” কেন? — যা test হয়েছে ঠিক সেটিই production-এ চলে (একই digest); environment-ভেদে শুধু config বদলায়।
  • DORA-র চারটি metric? — deployment frequency, lead time for changes (গতি); change failure rate, time to restore service (স্থিতি; পরে failed deployment recovery time নামে)।
  • GitOps কী? — desired state declarative ভাবে Git-এ, agent টেনে নিয়ে অবিরাম reconcile করে; পরিবর্তন আর rollback দুটিই Git-এর commit দিয়ে।

১০ · AI-এর যুগে — delivery-র পরামর্শে AI-কে যাচাই

AI কয়েক সেকেন্ডে pipeline, deploy script আর Terraform file দেয়; কিন্তু এখানকার ভুল ধরা পড়ে production-এ — সবচেয়ে দামি জায়গায়। চেনা ভুলগুলো:

AI-এর চেনা ভুলকীভাবে ধরবেন
DORA-র বানানো band বা পরিসংখ্যান (“elite দল ২০৮ গুণ বেশি deploy করে” — কোন বছরের report, কোন সংজ্ঞা, বলা নেই)মূল report-এর বছর আর পৃষ্ঠা খুঁজে মেলানো; না পেলে সংখ্যাটি বাদ
প্রতিটি environment-এ আলাদা build, বা image-এর latest tagDeploy-এর সময় digest মেলানো; tag নয়, digest-এ pin
Secret সরাসরি config file বা GitOps repository-তে; prompt-এ আসল key দিয়ে প্রশ্নSecret manager-এর উল্লেখ; prompt-এ কখনো আসল secret নয়
Rollback-এর জন্য config repository-তে git reset --hard আর git push --force, সতর্কতা ছাড়াভাগ করা branch-এ git revert; throwaway clone-এ আগে চালানো
terraform apply -auto-approve বা সরাসরি prod-এ kubectl apply — plan বা review ছাড়াআগে plan বা diff দেখা, PR-এ review, pipeline দিয়ে প্রয়োগ
বানানো flag বা option (tool-এর পুরোনো বা অস্তিত্বহীন version)Tool-এর official documentation আর --help; version মিলিয়ে দেখা
Database migration-এর কথা না ভেবে “শুধু আগের version-এ ফিরুন”Migration ফেরানো যায় কি না দেখা; expand/contract-এর পরিকল্পনা
অন্যের repository থেকে script কপি, licence-এর উল্লেখ ছাড়াউৎস আর licence যাচাই (licence-এর আলোচনা পর্ব ৬৩-এ)

AI-কে delivery-র নকশা আর review-এর সহকারী হিসেবে ব্যবহারের একটি prompt — এতে যাচাই, সতর্কতা আর নিশ্চিত না হলে তা খোলাখুলি জানানোর নির্দেশ আছে:

তুমি একজন সতর্ক release engineer. নিচে আমার কাল্পনিক project-এর বিবরণ আর বর্তমান pipeline দিলাম (কোনো secret, token বা ভেতরের URL নেই)। [কোন ধরনের software, কয়টি environment, এখন কীভাবে deploy হয়] [বর্তমান pipeline-এর YAML বা ধাপের তালিকা] ১. Pipeline-কে deployment pipeline-এর ধাপে সাজাও (commit, acceptance, capacity, manual, production) আর বলো কোন ধাপ নেই। ২. Artifact কি একবারই build হয় আর একই digest সব environment-এ যায়? কোথায় আবার build হচ্ছে, দেখাও। ৩. Config আর secret কোথা থেকে আসে বলো; secret কোথাও কোডে বা Git-এ থাকলে চিহ্নিত করো। ৪. Rollback-এর পরিকল্পনা লেখো — database migration থাকলে কী হবে, সেটিসহ। force push বা reset --hard প্রস্তাব করবে না। ৫. DORA metric মাপার জন্য কোন log লাগবে বলো; কোনো band বা পরিসংখ্যান দিলে report-এর বছর বলো, নিশ্চিত না হলে "নিশ্চিত নই" লেখো।

AI-এর পরামর্শ — চেকলিস্ট

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

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

প্র ০১Continuous deployment কি সবসময় continuous delivery-র চেয়ে “ভালো”? একটি ব্যাংকের app, একটি mobile game আর একটি গাড়ির software-এর ক্ষেত্রে উত্তর কি একই?

না — আর পার্থক্যটি প্রযুক্তির চেয়ে ঝুঁকি আর নিয়ন্ত্রণের প্রশ্ন। Humble ও Farley-র বইয়ের মূল দাবি “প্রতিটি পরিবর্তন release-যোগ্য”, “প্রতিটি পরিবর্তন release হবেই” নয়। Continuous delivery একটি সামর্থ্য: যেকোনো সময় নিরাপদে পাঠাতে পারা। Continuous deployment একটি নীতি: সেই সামর্থ্য প্রতিবার ব্যবহার করা। ২০০৯-এর দিকে যাঁরা continuous deployment নিয়ে লিখতেন, তাঁদের প্রায় সবাই web service চালাতেন — যেখানে server নিজেদের হাতে, rollback মিনিটের কাজ, আর ক্ষতি সাধারণত সীমিত।

এবার তিনটি উদাহরণ ভাবুন। ব্যাংকের app-এ আইনি নিয়ন্ত্রণ, audit-এর প্রয়োজন আর অনেক সময় দুজন মানুষের অনুমোদনের নিয়ম থাকে — প্রতিটি পরিবর্তন স্বয়ংক্রিয়ভাবে যাওয়া নিয়মের বাইরে হতে পারে। কিন্তু continuous delivery এখানেও মূল্যবান: অনুমোদনের বোতাম চাপলে বাকি সব স্বয়ংক্রিয় আর পুনরুৎপাদনযোগ্য, আর audit-এর প্রমাণ (কে কখন কোন digest অনুমোদন করলেন) pipeline নিজেই রাখে। Mobile game-এ app store-এর পর্যালোচনা থাকে, আর ব্যবহারকারী কবে update নেবেন তা আপনার হাতে নেই; তাই server-এর অংশে continuous deployment, আর app-এ নিয়মিত release train ও feature flag মিলিয়ে চলা সাধারণ। গাড়ি বা চিকিৎসা-যন্ত্রের software-এ নিরাপত্তার মান, দীর্ঘ যাচাই আর মাঠে থাকা যন্ত্রে update পাঠানোর খরচ — এখানে প্রতিটি commit-এ deploy অর্থহীন, এমনকি বিপজ্জনক।

তবু তিন ক্ষেত্রেই একই শিক্ষা খাটে: ছোট batch, স্বয়ংক্রিয় test, একই artifact, আর পুনরুৎপাদনযোগ্য release. পার্থক্য শুধু শেষ বোতামটি কে, কখন চাপেন। DORA-র জরিপেও deploy-এর ঘনত্বকে “চাহিদামতো” (on demand) ধরা হয় — অর্থাৎ যখন দরকার তখন পাঠাতে পারা, প্রতি মিনিটে পাঠানো নয়।

মূল উপলব্ধি: Continuous delivery প্রায় সব software-এর লক্ষ্য হতে পারে; continuous deployment একটি প্রসঙ্গনির্ভর সিদ্ধান্ত, যা ঝুঁকি, নিয়ন্ত্রণ আর ফেরার খরচ দেখে নিতে হয়।

প্র ০২২০১২ সালের Knight Capital-এর ঘটনা প্রায়ই deployment-এর শিক্ষা হিসেবে পড়ানো হয়। প্রকাশিত বিবরণ অনুযায়ী কী ঘটেছিল, আর এই পর্বের কোন চর্চাগুলো ঝুঁকি কমাতে পারত?

মার্কিন শেয়ারবাজারের প্রতিষ্ঠান Knight Capital ২০১২ সালের ১ আগস্ট সকালে প্রায় ৪৫ মিনিটে কয়েকশো মিলিয়ন ডলার (প্রচলিত হিসাবে প্রায় ৪৪০ মিলিয়ন) হারায়। মার্কিন নিয়ন্ত্রক SEC-এর ২০১৩ সালের প্রকাশিত আদেশে যে বিবরণ আছে, তার সারকথা: একটি নতুন সুবিধার জন্য কোড হাতে আটটি server-এ বসানো হচ্ছিল; একটি server-এ নতুন কোড পৌঁছায়নি। নতুন কোড একটি পুরোনো flag-কে নতুন অর্থে ব্যবহার করছিল — আর পুরোনো server-এ সেই flag বহু বছর আগের অব্যবহৃত, মৃত কোড চালু করে দিল, যা অবিরাম order পাঠাতে থাকল। সতর্কবার্তা এসেছিল, কিন্তু তা যথাযথভাবে দেখা হয়নি, আর বন্ধ করার কোনো প্রস্তুত পদ্ধতি ছিল না। (বিস্তারিত SEC-এর আদেশ আর পরের বিশ্লেষণে; এখানে সরল করা।)

এই পর্বের ভাষায় কয়েকটি ফাঁক স্পষ্ট। এক, deploy ছিল হাতে আর আংশিক — একই artifact সব server-এ গেছে কি না, তা কেউ যাচাই করেনি। “Build একবার, deploy বহুবার” আর deploy-এর পরে প্রতিটি যন্ত্রের digest মেলানোর check থাকলে “সাতটিতে নতুন কোড, একটিতে পুরোনো” অবস্থা ধরা পড়ত, আর system সেভাবে চালুই হতো না। দুই, desired state-এর ধারণা নেই — GitOps-এর reconciler-এর মতো কোনো ব্যবস্থা “আটটির মধ্যে একটি আলাদা” খুঁজে বের করত। তিন, flag-এর অর্থ বদলানো আর মৃত কোড রেখে দেওয়া — পর্ব ১৭-এ দেখেছেন, flag-এর জীবনচক্র আর পরিষ্কার না রাখলে flag নিজেই debt. চার, rollback-এর প্রস্তুতি — একটি সুনির্দিষ্ট “সব বন্ধ” switch আর ফেরার মহড়া।

তবে সাবধান: পরের ঘটনা দেখে “সহজ সমাধান” বলা সহজ। ঘটনাটি দোষারোপের গল্প নয়, ব্যবস্থার গল্প — একজন মানুষের ভুল একটি ব্যবস্থায় এত বড় ক্ষতি করতে পারল কেন, সেটিই আসল প্রশ্ন।

মূল উপলব্ধি: হাতের, আংশিক আর যাচাইহীন deploy একটি ছোট ভুলকে বিপর্যয়ে বদলাতে পারে। স্বয়ংক্রিয় ও একরূপ deploy, digest-এর যাচাই, flag-এর পরিচ্ছন্নতা আর প্রস্তুত kill switch সেই সম্ভাবনা কমায়।

প্র ০৩একটি প্রতিষ্ঠান “DevOps engineer” পদে লোক নিয়ে একটি আলাদা “DevOps দল” বানাল, যারা সব pipeline আর deploy সামলায়। এটি কি DevOps? কখন এই নকশা কাজে লাগে, কখন নতুন দেয়াল তৈরি করে?

DevOps-এর শুরুর আলোচনাগুলোতে — ২০০৯-এর Velocity বক্তৃতা, DevOpsDays — মূল সমস্যা ছিল development আর operations-এর মাঝের দেয়াল: আলাদা লক্ষ্য, আলাদা পুরস্কার, আর একে অপরকে দোষ দেওয়া। সমাধান হিসেবে বলা হয়েছিল সহযোগিতা, যৌথ দায় আর স্বয়ংক্রিয়তা — নতুন কোনো পদ নয়। Patrick Debois-সহ অনেকেই পরে বলেছেন, শব্দটি একটি আন্দোলনের নাম ছিল, চাকরির শিরোনাম নয়।

তাই একটি আলাদা “DevOps দল” দুই রকম হতে পারে। খারাপ রূপে এটি development আর operations-এর মাঝখানে তৃতীয় একটি দল: ডেভেলপাররা কোড দেন DevOps দলকে, তারা দেন ops-কে — এখন দেয়াল দুটি, আর ডেভেলপাররা আগের মতোই production থেকে দূরে। Matthew Skelton-এর পরিচিত “DevOps Topologies” লেখায় এমন নকশাকে anti-pattern হিসেবে দেখানো হয়েছে, আর পরে Skelton ও Manuel Pais-এর বই Team Topologies (২০১৯) দলের গঠন নিয়ে আরও বিস্তারিত বলে।

ভালো রূপে এটি একটি platform দল: তারা pipeline-এর template, monitoring, পরিকাঠামোর module আর deploy-এর tool “স্ব-সেবা” পণ্য হিসেবে বানায়, যাতে প্রতিটি product দল নিজেই নিজের service deploy আর চালাতে পারে — “you build it, you run it” সম্ভব হয় প্রত্যেককে Kubernetes বিশেষজ্ঞ না বানিয়েই। পার্থক্য বোঝার প্রশ্ন: product দল কি deploy-এর জন্য ticket খুলে অপেক্ষা করে, নাকি নিজে বোতাম চাপে? Production-এর alert কার কাছে যায়? DORA metric কোন দলের হাতে?

ছোট প্রতিষ্ঠানে আলাদা দলের দরকারই না-ও থাকতে পারে — দুই-তিনজন অভিজ্ঞ সদস্য পুরো দলকে শেখালেই হয়।

মূল উপলব্ধি: DevOps একটি পদের নাম নয়, দেয়াল ভাঙার চর্চা। একটি দল যদি অন্যদের নিজে deploy আর চালাতে সক্ষম করে, তবে সে সাহায্য করছে; যদি মাঝখানে দাঁড়িয়ে হাতবদলের আরেকটি ধাপ হয়, তবে নতুন দেয়াল।

প্র ০৪একজন ব্যবস্থাপক চান DORA metric দিয়ে দশটি দলকে র‍্যাংক করে বোনাস দিতে। এতে সমস্যা কোথায়, আর metric-এর সৎ ব্যবহার কেমন?

সমস্যা তিন স্তরে। প্রথমটি পদ্ধতিগত। DORA-র গবেষণা জরিপভিত্তিক: হাজারো উত্তরদাতার নিজের দেওয়া তথ্য থেকে গুচ্ছ বের করা, আর সেই গুচ্ছের সাথে প্রতিষ্ঠানের ফলের সম্পর্ক দেখা। Accelerate-এ পরিসংখ্যানের পদ্ধতি বিস্তারিত ব্যাখ্যা করা আছে, কিন্তু সেটি জনসংখ্যার প্রবণতা — কোনো একটি দলের মূল্যায়নের মাপকাঠি হিসেবে বানানো নয়। দশটি দলের product, ঝুঁকি, পুরোনো কোড আর ব্যবহারকারী আলাদা: একটি payment দল আর একটি ভেতরের report-এর দলের deploy-এর ঘনত্ব তুলনা করা অর্থহীন।

দ্বিতীয়টি আচরণগত — Goodhart-এর সূত্র (১৯৭৫), যা প্রথমে মুদ্রানীতির প্রসঙ্গে বলা হয়েছিল। বোনাস বাঁধলে সংখ্যা বদলাবে, ব্যবস্থা নয়: ফাঁপা deploy, “এটি incident নয়” বিতর্ক, lead time-এর ঘড়ি দেরিতে চালু। আরও খারাপ, দলগুলো সমস্যা লুকাতে শিখবে — আর দোষারোপহীন postmortem-এর সংস্কৃতি, যা তৃতীয় পথের ভিত্তি, ভেঙে পড়বে। Software-এর বাইরেও এর পরিচিত উদাহরণ আছে: হাসপাতালের অপেক্ষার সময়ের লক্ষ্য বাঁধলে অপেক্ষার হিসাব শুরুর বিন্দু সরানো ইত্যাদি।

তৃতীয়টি অর্থগত: চারটি metric delivery-র স্বাস্থ্য দেখায়, ব্যবসার ফল নয়। দিনে দশবার একটি ভুল জিনিস পাঠানো দ্রুত ব্যর্থতা।

সৎ ব্যবহার তাহলে কেমন? প্রতিটি দল নিজের metric নিজে দেখে, নিজের আগের মাসের সাথে তুলনা করে, আর প্রশ্ন করে “কোথায় আটকে আছি?” — lead time বেশি হলে value stream-এ অপেক্ষা খোঁজে (review-এর সারি? manual test?), change failure rate বেশি হলে test-এর ফাঁক। ব্যবস্থাপক দেখেন প্রবণতা আর বাধা — কোন দল কোন সাহায্য চায় — র‍্যাংকিং নয়।

মূল উপলব্ধি: DORA metric একটি আয়না, স্কোরবোর্ড নয়। দলের নিজের উন্নতির প্রশ্নে এটি শক্তিশালী; পুরস্কার আর তুলনার হাতিয়ার হলে নিজের অর্থ হারায়।

প্র ০৫২০২৪ সালের জুলাইয়ে CrowdStrike-এর একটি update-এর পরে বিশ্বজুড়ে বহু Windows কম্পিউটার চালু হতে পারেনি। প্রকাশিত বিবরণ থেকে “config-ও কোড” কথাটির কী শিক্ষা পাওয়া যায়?

প্রকাশিত বিবরণ অনুযায়ী, CrowdStrike-এর নিরাপত্তা-software Falcon-এর জন্য ২০২৪ সালের ১৯ জুলাই একটি content update — software-এর নতুন version নয়, বরং sensor যে তথ্য-ফাইল পড়ে, তার একটি হালনাগাদ — পাঠানো হয়। ফাইলটির একটি অমিল sensor-এর kernel-স্তরের অংশে ভুল memory পড়ার কারণ হয়, আর আক্রান্ত Windows যন্ত্রগুলো বারবার crash করে। Microsoft-এর একটি প্রাথমিক হিসাবে প্রায় ৮৫ লাখ যন্ত্র আক্রান্ত হয়েছিল; বিমান, হাসপাতাল, ব্যাংক — নানা খাতে প্রভাব পড়ে। প্রতিষ্ঠানটির পরের প্রকাশিত পর্যালোচনায় যে উন্নতির কথা বলা হয়, তার মধ্যে ছিল এমন content update-ও ধাপে ধাপে (staged) পাঠানো আর আরও যাচাই। (বিস্তারিত প্রতিষ্ঠানটির আর অন্যদের প্রকাশিত বিশ্লেষণে; এখানে সরল করা।)

এই পর্বের দৃষ্টিতে শিক্ষাটি হলো: config আর data-ও production-এর আচরণ বদলায়, তাই কোডের মতোই তার delivery-র নিয়ম লাগে। অনেক দল কোডের জন্য চমৎকার pipeline রাখে — test, canary, ধাপে ধাপে rollout — কিন্তু config, feature flag বা rule-file “শুধু data” বলে সরাসরি সবার কাছে একসাথে পাঠায়। অথচ ব্যবহারকারীর কাছে কোনটি বদলাল, তাতে পার্থক্য নেই; যন্ত্র বন্ধ হলে বন্ধই।

কয়েকটি চর্চা এখানে প্রাসঙ্গিক: config-এর পরিবর্তনও version-সহ Git-এ আর review-এ (GitOps-এর ভাবনা); config-এর জন্যও স্বয়ংক্রিয় validation — যে প্রোগ্রাম ফাইলটি পড়বে, সেটি দিয়েই test; ছোট অংশে আগে পাঠানো, মাপ দেখা, তারপর বাড়ানো (canary — System Design-এর deployment পর্বে); আর ফেরার পথ, যা আক্রান্ত যন্ত্র নিজে চালু না হলেও কাজ করে। একটি সূক্ষ্ম কথা: নিরাপত্তা-software-এর ক্ষেত্রে দ্রুত হালনাগাদের প্রয়োজনও বাস্তব — নতুন আক্রমণ ঠেকাতে দেরি করা যায় না — তাই গতি আর সাবধানতার ভারসাম্য সহজ নয়।

মূল উপলব্ধি: Production-এর আচরণ যা-ই বদলায় — কোড, config, flag বা data — তা একই সাবধানতায় পাঠাতে হয়: version, যাচাই, ধাপে ধাপে rollout আর প্রস্তুত ফেরার পথ।

অনুশীলন

প্রথমে নিজে উত্তর লিখুন, তারপর মিলিয়ে দেখুন।

  1. হিসাব (DORA metric): একটি কাল্পনিক বিশ্ববিদ্যালয়ের ফলাফল পোর্টালের দল ১৪ দিনে ১০টি production deploy করেছে। প্রতিটি deploy-এর commit-গুলোর lead time (ঘণ্টা): D1: ৪, ৯ · D2: ২৬ · D3: ২ · D4: ৫, ৭, ৩০ · D5: ৩ · D6: ১২ · D7: ১, ৬ · D8: ৫০ · D9: ৪ · D10: ২, ৩. D4, D8 আর D9-এর পরে সমস্যা হয়েছিল; ফিরতে লেগেছিল যথাক্রমে ৯৫ মিনিট, ২০ মিনিট আর ৬ ঘণ্টা। (ক) Deployment frequency (দিনে ও সপ্তাহে) (খ) Lead time-এর nearest-rank median, গড় আর p90 (গ) Change failure rate (ঘ) ফেরার সময়ের median আর গড় (ঙ) দল যদি D9-কে “config-এর ভুল, deploy নয়” বলে বাদ দেয়, change failure rate কত দেখাবে, আর এটি কি ঠিক?

    (ক) ১০ ÷ ১৪ = দিনে ০.৭১, সপ্তাহে ০.৭১ × ৭ = ৫টি deploy.

    (খ) মোট ১৫টি commit. সাজানো: ১, ২, ২, ৩, ৩, ৪, ৪, ৫, ৬, ৭, ৯, ১২, ২৬, ৩০, ৫০. Median: ⌈০.৫ × ১৫⌉ = ⌈৭.৫⌉ = ৮ম মান = ৫ ঘণ্টা. গড়: যোগফল ১৬৪ ÷ ১৫ = ১০.৯ ঘণ্টা (প্রায়) — ২৬, ৩০ আর ৫০ ঘণ্টার তিনটি commit গড়কে দ্বিগুণের বেশি টেনেছে। p90: ⌈০.৯ × ১৫⌉ = ⌈১৩.৫⌉ = ১৪তম মান = ৩০ ঘণ্টা.

    (গ) ৩ ÷ ১০ = ৩০%.

    (ঘ) সাজানো: ২০, ৯৫, ৩৬০ মিনিট। Median: ⌈১.৫⌉ = ২য় মান = ৯৫ মিনিট; গড় (২০ + ৯৫ + ৩৬০) ÷ ৩ = ৪৭৫ ÷ ৩ ≈ ১৫৮ মিনিট.

    (ঙ) ২ ÷ ১০ = ২০% দেখাবে। কিন্তু D9-এর পরেই ব্যবহারকারী সমস্যায় পড়েছেন, আর config ওই deploy-এর সাথেই গেছে — অংশ ৩-এর মতো config-ও production-এর আচরণ বদলায়। বাদ দেওয়া মানে সংজ্ঞা সরু করে সংখ্যা সাজানো (Goodhart). সৎ পথ: ৩০% রাখা, আর postmortem-এ লেখা কেন config-এর ভুল pipeline-এ ধরা পড়ল না — তারপর config-এর জন্যও validation যোগ করা।

  2. আউটপুট অনুমান (GitOps reconciler): একটি reconciler-এর নিয়ম: Git-এ আছে কিন্তু চলছে না → create; দুই জায়গায় আছে কিন্তু কোনো মান আলাদা → update (কোন মান কী থেকে কী, বন্ধনীতে); চলছে কিন্তু Git-এ নেই → prune বন্ধ থাকলে warn-extra, চালু থাকলে delete. প্রতিটি loop-এ প্রথমে loop N: K action(s) (বা কিছু না থাকলে in sync, nothing to do) ছাপা হয়, তারপর প্রতিটি কাজ, আর create/update/delete সাথে সাথে প্রয়োগ হয়। Desired: api {api:3.2.0, 2}, web {web:5.0.1, 4}. Actual: api {api:3.2.0, 2}, web {web:5.0.1, 2}, cron {cron:1.0, 1}. Prune বন্ধ রেখে পরপর দুটি loop চালালে কী ছাপা হবে? System কি কখনো “in sync” হবে?

    অংশ ৮-এর reconciler-এ এই মান বসিয়ে চালানো আসল আউটপুট:

    loop 1: 2 action(s)
      update     web  (replicas 2 -> 4)
      warn-extra cron
    loop 2: 1 action(s)
      warn-extra cron

    প্রথম loop-এ api মিলে আছে, তাই কাজ নেই; web-এর শুধু replicas আলাদা (২ → ৪); cron Git-এ নেই, prune বন্ধ, তাই warn-extra. দ্বিতীয় loop-এ web মিলে গেছে, কিন্তু cron-এর সতর্কবার্তা প্রতিটি loop-এ ফিরবে। Prune বন্ধ থাকলে system কখনো “in sync” হবে না, যতক্ষণ না কেউ cron-কে Git-এ যোগ করেন, prune চালু করেন বা হাতে মুছে ফেলেন। অনেক GitOps tool-এ prune সাবধানে চালু করা হয়, যাতে ভুল config-এ কিছু হঠাৎ মুছে না যায়।

  3. সমালোচনা (metric নিয়ে খেলা): একটি কাল্পনিক দলের ব্যবস্থাপক ঘোষণা দিলেন: “পরের তিন মাসে deployment frequency দ্বিগুণ আর change failure rate ১০%-এর নিচে — তাহলে দলের বোনাস।” তিন মাস পরে: deploy সপ্তাহে ৮ থেকে ২৪, change failure rate ২২% থেকে ৮%, lead time-এর median ৩০ ঘণ্টা থেকে ৬ ঘণ্টা। কিন্তু খোঁজ নিয়ে দেখা গেল: (১) নতুন deploy-এর অর্ধেকের বেশিতে শুধু README বা comment বদল; (২) “১৫ মিনিটের কম সময়ের সমস্যা incident নয়” — নিয়ম নতুন; (৩) lead time এখন মাপা হয় PR approve থেকে, commit থেকে নয়; (৪) ব্যবহারকারীর অভিযোগ আগের মতোই। দলটি কী ভুল করেছে, ব্যবস্থাপক কী ভুল করেছেন, আর কীভাবে ঠিক করবেন?

    কী ঘটেছে: চারটি সংখ্যাই উন্নত দেখাচ্ছে, কিন্তু ব্যবস্থা বদলায়নি — Goodhart-এর সূত্রের পাঠ্যপুস্তকের উদাহরণ। (১) ফাঁপা deploy deploy frequency ফুলিয়েছে, আর একই সাথে change failure rate-এর হর (মোট deploy) বাড়িয়ে হারটি কমিয়েছে — README-এর deploy কখনো ভাঙে না। (২) Failure-এর সংজ্ঞা সরু করা হয়েছে, তাই আগের ২২%-এর সাথে নতুন ৮% তুলনাযোগ্যই নয়। (৩) Lead time-এর ঘড়ি দেরিতে চালু — review-এর অপেক্ষা, যা প্রায়ই সবচেয়ে বড় অংশ, চোখের আড়ালে। (৪) ব্যবহারকারীর অভিযোগ বদলায়নি — আসল ফলের একমাত্র স্বাধীন সংকেত বলছে কিছুই উন্নত হয়নি।

    ব্যবস্থাপকের ভুল: metric-কে লক্ষ্য আর পুরস্কারের সাথে বাঁধা, সংজ্ঞা স্থির না করা, আর গতির metric-এর পাশে স্বাধীন ফলের মাপ না রাখা। দলের ভুল: সংখ্যা সাজানো আর সংজ্ঞা নীরবে বদলানো — পেশাগত সততার প্রশ্নও এটি (পর্ব ৬৪-এ নৈতিকতা)।

    ঠিক করার পথ: সংজ্ঞা লিখে স্থির করুন (failure মানে ব্যবহারকারী-দৃশ্যমান যেকোনো সমস্যা বা rollback, lead time commit থেকে) আর পুরোনো সংখ্যা নতুন সংজ্ঞায় আবার হিসাব করুন। বোনাস metric থেকে আলাদা করুন। চারটির পাশে ফলের মাপ রাখুন — অভিযোগ, error rate, SLO.

  4. নকশা (deployment pipeline): একটি কাল্পনিক বিশ্ববিদ্যালয়ের ফলাফল পোর্টালের জন্য deployment pipeline নকশা করুন। শর্ত: ফল প্রকাশের দিনে খুব ভিড়; ভুল নম্বর দেখানো গুরুতর; database-এ শিক্ষার্থীর তথ্য; দলে ছয়জন। লিখুন: (ক) ধাপ আর environment, প্রতিটিতে কী test (খ) artifact আর config কীভাবে আলাদা থাকবে (গ) deploy আর release কীভাবে আলাদা করবেন (ঘ) rollback-এর পরিকল্পনা, migration-সহ (ঙ) কোন চারটি সংখ্যা মাপবেন, আর একটি বিপদের কথা।

    একটি সম্ভাব্য নকশা (একমাত্র সঠিক উত্তর নেই):

    (ক) Commit stage (১০ মিনিটের নিচে): lint, unit test — বিশেষ করে GPA-র হিসাবের boundary value test (পর্ব ৪৭), secret scan, artifact একবার build. Acceptance (env: test, কৃত্রিম data): ফল দেখা, PDF নামানো, লগইন। Capacity (env: perf): প্রকাশের দিনের অনুমিত চাপের কয়েক গুণে load test. Staging (ছদ্মনামের data): পরীক্ষা নিয়ন্ত্রক অফিসের হাতে-পরীক্ষা আর অনুমোদন। Production: বোতাম (continuous delivery), কারণ ভুল নম্বরের ঝুঁকি গুরুতর।

    (খ) একই digest সব environment-এ; database-এর ঠিকানা, flag আর secret environment থেকে। Deploy-এর আগে check: prod-এর digest = staging-এ সবুজ হওয়া digest.

    (গ) নতুন ফলাফল-পাতা flag-এর আড়ালে আগেই deploy; প্রকাশের দিন শুধু flag চালু, নতুন deploy নয়।

    (ঘ) প্রথম ফেরার পথ flag বন্ধ; আগের image হাতের কাছে। Migration expand/contract-এ, যাতে পুরোনো কোডও চলে; staging-এ rollback-এর মহড়া।

    (ঙ) চারটি DORA metric, পাশে প্রকাশের দিনের error rate ও p95 latency. বিপদ: প্রকাশের সপ্তাহে deploy কম হবে — সেটি স্বাভাবিক, ফাঁপা deploy দিয়ে পূরণের বিষয় নয়।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমHumble ও Farley-র ধাঁচের একটি deployment pipeline-এর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. 🛠️ Commit stage: compile, unit test, analysis
  2. 📦 Artifact একবার build করে repository-তে জমা
  3. 🧪 Acceptance stage: test environment-এ স্বয়ংক্রিয় acceptance test
  4. 📈 Capacity stage: চাপে গতির test
  5. 👀 Staging-এ exploratory testing আর অনুমোদন
  6. 🚀 একই artifact production-এ deploy

একটি দলের pipeline-এ প্রতিটি পরিবর্তন সব স্বয়ংক্রিয় test পার হয়ে staging-এ যায়। Production-এ পাঠাতে product owner একটি বোতাম চাপেন, যা তিনি সপ্তাহে কয়েকবার চাপেন। দলটি কোন অনুশীলন করছে?

  • Continuous deployment
  • Continuous delivery
  • শুধু continuous integration, delivery নয়
  • কোনোটিই নয়, কারণ একজন মানুষ বোতাম চাপেন

একটি দল একই commit থেকে staging-এর জন্য একবার আর তিন দিন পরে production-এর জন্য আবার build করে। Dependency-র version range আছে, lockfile নেই। প্রধান ঝুঁকি কী?

  • দুবার build করতে CI-এর সময় বেশি লাগে
  • কোনো ঝুঁকি নেই, কারণ commit একই
  • Production-এর artifact staging-এ test হওয়া artifact থেকে আলাদা হতে পারে, অর্থাৎ যা চলছে তা test হয়নি
  • Production-এর config staging-এর চেয়ে আলাদা হয়ে যাবে

একটি দল ২৮ দিনে ২০টি production deploy করেছে; তার ৫টির পরে rollback বা hotfix লেগেছে। Change failure rate আর সপ্তাহে deploy-এর গড় সংখ্যা কত?

  • ২৫%, সপ্তাহে ৫টি
  • ১৭.৯%, সপ্তাহে ৫টি
  • ২৫%, সপ্তাহে ০.৭১টি
  • ২০%, সপ্তাহে ৪টি

একটি deploy-এ পাঁচটি commit গেছে, যাদের lead time (ঘণ্টা) ২, ৩০, ৪, ৬ আর ১. Nearest-rank নিয়মে median lead time কত, আর গড় কত?

  • median ৬, গড় ৮.৬
  • median ৪, গড় ৬
  • median ৮.৬, গড় ৪
  • median ৪, গড় ৮.৬

একটি GitOps ব্যবস্থায় Git-এর desired state বলে একটি service-এর ৩টি copy চলবে, আর agent-এর self-heal চালু। রাতে একজন ইঞ্জিনিয়ার cluster-এ সরাসরি command দিয়ে ৬টি copy করলেন। পরের reconcile loop-এ সাধারণত কী হবে?

  • Agent Git-এর মান ৬-এ হালনাগাদ করবে
  • কিছুই হবে না, কারণ ৬ ≥ ৩
  • Agent drift ধরে আবার ৩টি copy-তে নামাবে; ৬ রাখতে হলে Git-এ পরিবর্তন লাগবে
  • Agent পুরো service মুছে নতুন করে বানাবে

deployment frequency-র সাথে বোনাস বাঁধার পরে একটি দলের deploy সপ্তাহে ৫ থেকে ৪০ হলো; বেশিরভাগ নতুন deploy-এ শুধু comment-এর বদল। Change failure rate-ও কমেছে। সবচেয়ে যুক্তিসংগত সিদ্ধান্ত কী?

  • দলটি এখন elite; DORA-র মতে গতি আর স্থিতি দুটিই বেড়েছে
  • Metric লক্ষ্য হওয়ায় সাজানো হয়েছে; ফাঁপা deploy দুটি সংখ্যাই বিকৃত করছে, তাই সংজ্ঞা আর প্রণোদনা ঠিক করতে হবে
  • Deployment frequency-র বদলে lead time-এর সাথে বোনাস বাঁধলেই সমস্যা মিটবে
  • Change failure rate কমেছে, তাই test-এর মান নিশ্চয়ই ভালো হয়েছে

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. CI → continuous delivery → continuous deployment: মেলানো ও যাচাই; প্রতিটি পরিবর্তন release-যোগ্য আর production একটি বোতামে (release on demand); বোতামও স্বয়ংক্রিয়। Humble ও Farley, Continuous Delivery (২০১০)।
  2. Deployment pipeline: commit stage → acceptance → capacity ও অন্যান্য → staging/UAT → production; আগে দ্রুত, পরে ধীর; প্রতিটি ব্যর্থতায় দ্রুত feedback; pipeline-এর বাইরে দিয়ে কিছু production-এ নয়।
  3. Build একবার, deploy বহুবার: একই digest dev থেকে prod পর্যন্ত; config আর secret environment থেকে (twelve-factor-এর নীতি)। Deploy ≠ release — flag দিয়ে আলাদা; সমস্যায় আগে ক্ষতি থামানো (rollback বা flag বন্ধ), migration-এর কথা মাথায় রেখে।
  4. DevOps = সংস্কৃতি: ২০০৯-এর DevOpsDays; CALMS; you build it, you run it; তিন পথ — flow, feedback, শেখা। আলাদা “DevOps দল” নতুন দেয়াল হতে পারে।
  5. DORA metric জোড়ায়: deployment frequency আর lead time (গতি), change failure rate আর time to restore (স্থিতি; পরে নাম বদলেছে); Git tag আর deploy log থেকে median-এ মাপুন; ছোট batch lead time কমায়; লক্ষ্য বা র‍্যাংকিং বানালে Goodhart. IaC আর GitOps-এ desired state Git-এ, agent reconcile করে, rollback মানে git revert.

পরের পর্বে: Delivery-র পথ তৈরি — এবার প্রশ্ন “কতদিন লাগবে?” পর্ব ৬০-এ software estimation: story point, planning poker, function point আর COCOMO II — অনুমানকে কীভাবে সৎ, পরিমাপযোগ্য আর পরিসরসহ বলবেন।

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

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান