Kubernetes ওয়ার্কলোডের জন্য প্রোডাকশন বেসলাইন
রিকোয়েস্ট, প্রোব, ডিসরাপশন বাজেট, সুশৃঙ্খল শাটডাউন ও পড নিরাপত্তা: প্রথম ইনসিডেন্টের আগেই একটি প্রোডাকশন Deployment-এ যে সেটিংস থাকা উচিত।
উদাহরণগুলো সাধারণ ও ব্যাখ্যামূলক। এগুলো কোনো ক্লায়েন্টের এনভায়রনমেন্ট থেকে নেওয়া নয়: থ্রেশহোল্ড ও সেটিংস নিজের সিস্টেম অনুযায়ী ঠিক করুন।
কেন বেসলাইন
Kubernetes প্রায় কোনো কনফিগারেশন ছাড়াই প্রায় সবকিছু চালায়, আর সমস্যাটা সেখানেই: ডিফল্টগুলো শুরু করার জন্য বাছা, টিকে থাকার জন্য নয়। নিচের সেটিংসগুলো প্রথম দিনে যোগ করা সস্তা, আউটেজের সময় আবিষ্কার করা ব্যয়বহুল। এগুলো স্টেটলেস Deployment-এর জন্য; স্টেটফুল ওয়ার্কলোডের আরও দরকার।
রিকোয়েস্ট ও লিমিট
শিডিউলার পডগুলোকে তাদের requests অনুযায়ী বসায়, আর Horizontal Pod Autoscaler সেগুলোর তুলনায় ব্যবহার মাপে। requests ছাড়া পড অন্ধভাবে বসানো হয় এবং CPU-এর ভিত্তিতে অটোস্কেল হতে পারে না।
মেমরি সংকোচন করা যায় না: যে কন্টেইনার মেমরি লিমিট ছাড়ায় তাকে বন্ধ করে দেওয়া হয়। মেমরি লিমিট request-এর সমান বা কাছাকাছি রাখুন, যাতে পড কখনো এমন মেমরিতে শিডিউল না হয় যা সে ধরে রাখতে পারবে না। CPU আলাদা — CPU লিমিটের ওপরে কন্টেইনার থ্রটল হয়, যা লেটেন্সি হিসেবে দেখা দেয়। অনেক টিম লেটেন্সি-সংবেদনশীল সার্ভিসে CPU requests রাখে আর CPU লিমিট বাদ দেয়; যা-ই বেছে নিন, থ্রটলিং মাপুন।
তিনটি প্রোব, তিনটি কাজ
- Readiness ঠিক করে পড ট্র্যাফিক পাবে কি না। শেয়ার করা নির্ভরতা নিয়ে সাবধান: সব পড একসঙ্গে readiness-এ ব্যর্থ হলে সার্ভিসের কোনো এন্ডপয়েন্টই থাকে না।
- Liveness ঠিক করে কন্টেইনার রিস্টার্ট হবে কি না। এটিকে প্রসেসের মধ্যেই সীমিত রাখুন: এটি ডেটাবেস যাচাই করলে ডেটাবেস আউটেজে সব পড একসঙ্গে রিস্টার্ট হবে।
- Startup ধীর অ্যাপ চালু হওয়া পর্যন্ত অন্য প্রোবগুলো আটকে রাখে, liveness-এর বিলম্ব না বাড়িয়ে।
নোড ড্রেন ও জোন ব্যর্থতা সামলানো
নোড আপগ্রেড ও অটোস্কেলিং সবসময় পড সরিয়ে দেয়। PodDisruptionBudget সীমিত করে একটি স্বেচ্ছামূলক বিঘ্ন একসঙ্গে কতগুলো রেপ্লিকা বন্ধ করতে পারে, আর topology spread constraints রেপ্লিকাগুলোকে আলাদা জোনে রাখে, যাতে একটি জোনের ব্যর্থতা পুরো সার্ভিসকে নিয়ে না যায়।
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api
spec:
maxUnavailable: 1
selector:
matchLabels: { app: api }
সুশৃঙ্খল শাটডাউন
একটি পড মুছে ফেলা হলে সার্ভিস এন্ডপয়েন্ট থেকে তার অপসারণ আর তার কন্টেইনারগুলোর বন্ধ হওয়া (প্রথমে preStop হুক, তারপর SIGTERM) একই সময়ে শুরু হয়। যে অ্যাপ সঙ্গে সঙ্গে বন্ধ হয়, সে তখনও তার দিকে পাঠানো অনুরোধ হারায়। লোড ব্যালান্সারকে হালনাগাদ হতে দিতে একটি ছোট preStop বিরতি যোগ করুন, SIGTERM পেলে চলমান কাজ শেষ করুন, এবং terminationGracePeriodSeconds বিরতি ও ড্রেনের মোট সময়ের চেয়ে বেশি রাখুন।
সিকিউরিটি কনটেক্সট ও ইমেজ
নন-রুট ব্যবহারকারী হিসেবে চালান, সব Linux capabilities বাদ দিন, প্রিভিলেজ এসকেলেশন বন্ধ করুন এবং রুট ফাইলসিস্টেম কেবল-পড়ার হিসেবে মাউন্ট করুন; restricted Pod Security Standard এর বেশিরভাগই নেমস্পেস স্তরে প্রয়োগ করে। পরিবর্তনযোগ্য ট্যাগের বদলে ডাইজেস্ট দিয়ে ইমেজ উল্লেখ করুন, যাতে যা পরীক্ষা হয়েছে ঠিক সেটিই চলে।
সব একসঙ্গে
বেসলাইন প্রয়োগ করা একটি Deployment। মানগুলো কেবল উদাহরণ: requests এই উদাহরণ থেকে নয়, পরিমাপ করা ব্যবহার থেকে ঠিক করুন।
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels: { app: api }
template:
metadata:
labels: { app: api }
spec:
terminationGracePeriodSeconds: 45
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels: { app: api }
securityContext:
runAsNonRoot: true
seccompProfile: { type: RuntimeDefault }
containers:
- name: api
image: registry.example.com/api@sha256:<digest>
resources:
requests: { cpu: 250m, memory: 256Mi }
limits: { memory: 256Mi }
readinessProbe:
httpGet: { path: /ready, port: 8080 }
periodSeconds: 5
livenessProbe:
httpGet: { path: /live, port: 8080 }
periodSeconds: 10
failureThreshold: 3
startupProbe:
httpGet: { path: /live, port: 8080 }
periodSeconds: 5
failureThreshold: 30
lifecycle:
preStop:
sleep: { seconds: 5 } # native sleep action, Kubernetes 1.30+
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: { drop: ["ALL"] }