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"] }