स्टेटफुलसेट्स और कubernetis में स्थायी स्टोरेज

संरक्षित डेटा के साथ क्रमबद्ध स्केलिंग वाले स्टेटफुल एप्लिकेशन्स को तैनात करें

कुबर्नेट्स स्टेटफुलसेट्स वे समाधान हैं जो स्थायी पहचान, स्थायी स्टोरेज, और व्यवस्थित तैनाती पैटर्न की आवश्यकता वाले स्टेटफुल एप्लिकेशन्स को प्रबंधित करने के लिए डिज़ाइन किए गए हैं—डेटाबेस, वितरित प्रणालियों, और कैशिंग लेयर्स के लिए आवश्यक। यदि आप कुबर्नेट्स के नए हैं या एक क्लस्टर सेटअप कर रहे हैं, तो विकास के लिए k3s या MicroK8s जैसे कुबर्नेट्स डिस्ट्रीब्यूशन्स का पता लगाने का विचार करें, या उत्पादन-ग्रेड क्लस्टर्स के लिए Kubespray के साथ कुबर्नेट्स इंस्टॉल करना

कॉफी शॉप में प्रस्तुति इस सुंदर छवि को AI मॉडल Flux 1 dev द्वारा उत्पन्न किया गया है।

स्टेटफुलसेट्स क्या हैं?

स्टेटफुलसेट्स कुबर्नेट्स के एक वर्कलोड API ऑब्जेक्ट हैं जो विशेष रूप से स्टेटफुल एप्लिकेशन्स को प्रबंधित करने के लिए डिज़ाइन किए गए हैं। डिप्लॉयमेंट्स के विपरीत जो सभी पॉड्स को आदान-प्रदान योग्य मानते हैं, स्टेटफुलसेट्स प्रत्येक पॉड के लिए एक अनूठी पहचान बनाए रखते हैं जिसमें क्रम और अनूठापन के बारे में गारंटी होती है।

मुख्य विशेषताएं:

  • स्थिर नेटवर्क पहचानकर्ता: प्रत्येक पॉड को एक भविष्यवाणी योग्य होस्टनेम मिलता है जो रीस्टार्ट्स के माध्यम से बना रहता है
  • स्थायी स्टोरेज: पॉड्स के साथ पुनर्निर्धारण के माध्यम से चलने वाले समर्पित PersistentVolumeClaims
  • व्यवस्थित तैनाती: पॉड्स क्रमानुसार बनाए जाते हैं (0, 1, 2…) और विपरीत क्रम में समाप्त होते हैं
  • व्यवस्थित अपडेट्स: रोलिंग अपडेट्स क्रमानुसार आगे बढ़ते हैं, जिससे एप्लिकेशन स्थिरता सुनिश्चित होती है

स्टेटफुलसेट्स PostgreSQL, MySQL, MongoDB, Cassandra, Elasticsearch, Kafka, ZooKeeper, Redis, और etcd जैसे एप्लिकेशन्स के लिए महत्वपूर्ण हैं—किसी भी वर्कलोड के लिए जहां पॉड पहचान और डेटा स्थायित्व महत्वपूर्ण हैं।

कुबर्नेट्स में स्थायी स्टोरेज को समझना

कुबर्नेट्स एक उन्नत स्टोरेज अभिसरण परत प्रदान करता है जो स्टोरेज प्रबंधन को पॉड लाइफसाइकिल से अलग करता है:

स्टोरेज घटक

PersistentVolume (PV): क्लस्टर में स्टोरेज का एक टुकड़ा जो एक एडमिनिस्ट्रेटर द्वारा प्रोविजन किया जाता है या एक StorageClass के माध्यम से डायनामिक रूप से बनाया जाता है। PVs पॉड्स से स्वतंत्र रूप से मौजूद होते हैं।

PersistentVolumeClaim (PVC): एक पॉड द्वारा स्टोरेज का अनुरोध। PVCs उन PVs से बंधते हैं जो उनकी आवश्यकताओं (आकार, एक्सेस मोड, स्टोरेज क्लास) से मेल खाते हैं।

StorageClass: विभिन्न प्रोविजनर्स (AWS EBS, GCE PD, Azure Disk, NFS, आदि) और पैरामीटर्स जैसे रिप्लिकेशन, प्रदर्शन टियर, और बैकअप पॉलिसी के साथ स्टोरेज के विभिन्न “क्लास” को परिभाषित करते हैं।

एक्सेस मोड्स

  • ReadWriteOnce (RWO): एकल नोड द्वारा रीड-राइट के रूप में माउंट किया गया वॉल्यूम
  • ReadOnlyMany (ROX): कई नोड्स द्वारा रीड-ऑनली के रूप में माउंट किया गया वॉल्यूम
  • ReadWriteMany (RWX): कई नोड्स द्वारा रीड-राइट के रूप में माउंट किया गया वॉल्यूम (विशेष स्टोरेज बैकएंड्स की आवश्यकता होती है)

स्टेटफुलसेट स्टोरेज आर्किटेक्चर

स्टेटफुलसेट्स volumeClaimTemplates का उपयोग करके प्रत्येक पॉड रिप्लिका के लिए स्वचालित रूप से PersistentVolumeClaims बनाते हैं। यह डिप्लॉयमेंट्स से मूल रूप से अलग है:

volumeClaimTemplates कैसे काम करते हैं

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-service
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "fast-ssd"
      resources:
        requests:
          storage: 10Gi

जब आप इस स्टेटफुलसेट बनाते हैं:

  1. कुबर्नेट्स पॉड mysql-0 और PVC data-mysql-0 बनाता है
  2. फिर पॉड mysql-1 और PVC data-mysql-1 बनाता है
  3. अंत में पॉड mysql-2 और PVC data-mysql-2 बनाता है

हर पॉड को अपना समर्पित 10GB स्थायी वॉल्यूम मिलता है। यदि mysql-1 को हटा दिया जाता है या पुनर्निर्धारित किया जाता है, तो कुबर्नेट्स इसे पुनः बनाता है और उसी data-mysql-1 PVC को पुनः जोड़ता है, जिससे सभी डेटा संरक्षित रहता है।

स्टेटफुलसेट्स के लिए एक हेडलेस सर्विस बनाना

स्टेटफुलसेट्स को स्थिर नेटवर्क पहचान प्रदान करने के लिए एक हेडलेस सर्विस की आवश्यकता होती है:

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  clusterIP: None  # यह इसे एक हेडलेस सर्विस बनाता है
  selector:
    app: mysql
  ports:
  - port: 3306
    name: mysql

यह प्रत्येक पॉड के लिए DNS एंट्री बनाता है:

  • mysql-0.mysql-service.default.svc.cluster.local
  • mysql-1.mysql-service.default.svc.cluster.local
  • mysql-2.mysql-service.default.svc.cluster.local

एप्लिकेशन्स इन स्थिर DNS नामों का उपयोग करके सीधे विशिष्ट पॉड इंस्टेंस से कनेक्ट कर सकते हैं।

स्टेटफुलसेट तैनाती पैटर्न

जटिल कुबर्नेट्स तैनातियों को प्रबंधित करने वाले टीमों के लिए, Helm Charts स्टेटफुलसेट्स को टेम्पलेटिंग, वर्जनिंग, और डिपेंडेंसी प्रबंधन के साथ पैकेज और तैनात करने का एक शक्तिशाली तरीका प्रदान करते हैं। Helm विभिन्न वातावरणों में स्टेटफुलसेट कॉन्फ़िगरेशन को प्रबंधित करने को सरल बनाता है।

व्यवस्थित स्केलिंग

3 से 5 रिप्लिकाओं तक स्केलिंग करते समय:

kubectl scale statefulset mysql --replicas=5

कुबर्नेट्स पॉड्स को क्रमानुसार बनाता है: mysql-3 → तैयार होने का इंतजार → mysql-4

5 से 3 रिप्लिकाओं तक स्केलिंग करते समय:

kubectl scale statefulset mysql --replicas=3

कुबर्नेट्स विपरीत क्रम में समाप्त करता है: mysql-4 → समाप्त होने का इंतजार → mysql-3

रोलिंग अपडेट्स

स्टेटफुलसेट्स दो अपडेट रणनीतियों का समर्थन करते हैं:

OnDelete: मैनुअल अपडेट्स—पॉड्स केवल तब अपडेट होते हैं जब आप उन्हें हटा देते हैं RollingUpdate: स्वचालित क्रमानुसार अपडेट्स विपरीत ऑर्डिनल क्रम में

spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 2  # केवल पॉड्स को अपडेट करें जिनकी ऑर्डिनल >= 2 है

partition पैरामीटर कैनरी तैनातियों को सक्षम बनाता है—आप उच्च-नंबर वाले पॉड्स को पहले अपडेट कर सकते हैं और सभी रिप्लिकाओं तक रोल आउट करने से पहले परीक्षण कर सकते हैं।

स्टोरेज बेस्ट प्रैक्टिसेस

डायनामिक प्रोविजनिंग

हमेशा डायनामिक वॉल्यूम प्रोविजनिंग के लिए StorageClasses का उपयोग करें:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  iops: "3000"
  throughput: "125"
allowVolumeExpansion: true
reclaimPolicy: Retain

allowVolumeExpansion: PVCs को पुनः बनाए बिना रीसाइज करने की अनुमति देता है reclaimPolicy: Retain PV डेटा को PVC हटाने के बाद बनाए रखता है, Delete इसे स्वचालित रूप से हटा देता है

PVC रिटेंशन पॉलिसी

कुबर्नेट्स 1.23+ persistentVolumeClaimRetentionPolicy का समर्थन करता है:

spec:
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Retain    # स्टेटफुलसेट हटाने पर PVCs बनाए रखें
    whenScaled: Delete     # स्केलिंग डाउन करने पर PVCs हटा दें

विकल्प:

  • Retain: PVCs बनाए रखें (डिफ़ॉल्ट व्यवहार, सबसे सुरक्षित)
  • Delete: स्वचालित रूप से PVCs हटा दें (डेवलपमेंट वातावरणों के लिए उपयोगी)

बैकअप रणनीतियां

वॉल्यूम स्नैपशॉट्स: VolumeSnapshot संसाधनों का उपयोग करके पॉइंट-इन-टाइम बैकअप बनाएं

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: mysql-snapshot-20251113
spec:
  volumeSnapshotClassName: csi-snapclass
  source:
    persistentVolumeClaimName: data-mysql-0

एप्लिकेशन-लेवल बैकअप्स: mysqldump, pg_dump, या Velero जैसे उपकरणों का उपयोग डेटाबेस-विशिष्ट बैकअप्स के लिए करें

वितरित रिप्लिकेशन: एप्लिकेशन-लेवल रिप्लिकेशन (MySQL रिप्लिकेशन, PostgreSQL स्ट्रीमिंग रिप्लिकेशन) को प्रथम रक्षा लाइन के रूप में कॉन्फ़िगर करें

वास्तविक दुनिया के उपयोग के मामले

डेटाबेस क्लस्टर (PostgreSQL)

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:16
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgres-secret
              key: password
        - name: PGDATA
          value: /var/lib/postgresql/data/pgdata
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "standard"
      resources:
        requests:
          storage: 20Gi

वितरित कैश (Redis)

Redis क्लस्टर्स के लिए आपको दोनों स्टेटफुलसेट और सावधानीपूर्वक कॉन्फ़िगरेशन की आवश्यकता होती है:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: redis-service
  replicas: 6
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7-alpine
        command:
        - redis-server
        - "--appendonly"
        - "yes"
        - "--appendfsync"
        - "everysec"
        ports:
        - containerPort: 6379
          name: redis
        volumeMounts:
        - name: data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 5Gi

मेसेज क्यू (Kafka)

Kafka को लॉग्स के लिए स्थायी स्टोरेज और ब्रोकर कोऑर्डिनेशन के लिए स्थिर नेटवर्क पहचान की आवश्यकता होती है:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kafka
spec:
  serviceName: kafka-service
  replicas: 3
  selector:
    matchLabels:
      app: kafka
  template:
    metadata:
      labels:
        app: kafka
    spec:
      containers:
      - name: kafka
        image: confluentinc/cp-kafka:7.5.0
        ports:
        - containerPort: 9092
          name: kafka
        env:
        - name: KAFKA_BROKER_ID
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        volumeMounts:
        - name: data
          mountPath: /var/lib/kafka/data
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 100Gi

निगरानी और समस्या निवारण

इस अनुभाग में उपयोग किए गए कubernetess कमांड्स की एक व्यापक संदर्भ के लिए, देखें Kubernetes Cheatsheet

StatefulSet स्थिति की जांच करें

# StatefulSet विवरण देखें
kubectl get statefulset mysql
kubectl describe statefulset mysql

# पॉड निर्माण क्रम और स्थिति की जांच करें
kubectl get pods -l app=mysql -w

# PVC स्थिति देखें
kubectl get pvc
kubectl describe pvc data-mysql-0

सामान्य समस्याएं

पॉड पेंडिंग में फंस गया है: PVC स्थिति और स्टोरेज उपलब्धता की जांच करें

kubectl describe pod mysql-0
kubectl get events --sort-by='.lastTimestamp'

स्टोरेज पूर्ण: अगर StorageClass अनुमति देता है तो PVC को बढ़ाएं

kubectl patch pvc data-mysql-0 -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

पॉड समाप्त नहीं हो रहा: एप्लिकेशन-स्तर की लॉक्स या वॉल्यूम अनमाउंट समस्याओं की जांच करें

kubectl delete pod mysql-0 --grace-period=0 --force

निगरानी के लिए मेट्रिक्स

  • स्टोरेज उपयोग: PVC क्षमता और उपयोग प्रतिशत की निगरानी करें
  • I/O प्रदर्शन: IOPS, थ्रूपुट, और लेटेंसी का ट्रैक करें
  • पॉड रीस्टार्ट्स: बार-बार रीस्टार्ट स्टोरेज समस्याओं का संकेत दे सकते हैं
  • PVC बाइंडिंग समय: धीमी बाइंडिंग प्रोविजनिंग समस्याओं का सुझाव देती है

माइग्रेशन रणनीतियां

StatefulSets में माइग्रेट करते समय, सुनिश्चित करें कि आपका Kubernetes क्लस्टर सही ढंग से कॉन्फ़िगर किया गया है। होमलैब या छोटे क्लस्टर सेटअप्स के लिए, अपने वर्कलोड आवश्यकताओं के लिए सही प्लेटफॉर्म चुनने के लिए हमारी Kubernetes डिस्ट्रीब्यूशन्स की व्यापक तुलना की समीक्षा करें।

Deployment से StatefulSet तक

  1. volumeClaimTemplates के साथ StatefulSet बनाएं
  2. Deployment को धीरे-धीरे स्केल डाउन करें
  3. StatefulSet पॉड्स में डेटा रिस्टोर करें बैकअप से
  4. DNS/Service संदर्भ अपडेट करें
  5. पुराने Deployment और PVCs को हटाएं

माइग्रेशन से पहले बैकअप लें

# मौजूदा PVCs का स्नैपशॉट लें
kubectl get pvc -o yaml > pvc-backup.yaml

# वॉल्यूम स्नैपशॉट्स बनाएं
kubectl apply -f volume-snapshot.yaml

सुरक्षा विचार

स्टोरेज एन्क्रिप्शन

StorageClass पैरामीटर्स का उपयोग करके रेस्ट में एन्क्रिप्शन सक्षम करें:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: encrypted-storage
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  encrypted: "true"
  kmsKeyId: arn:aws:kms:us-east-1:123456789012:key/abcd-1234

एक्सेस कंट्रोल

RBAC का उपयोग करके StatefulSets और PVCs को बनाने/संपादित करने वाले लोगों को सीमित करें:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: statefulset-manager
rules:
- apiGroups: ["apps"]
  resources: ["statefulsets"]
  verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["get", "list", "create", "delete"]

नेटवर्क पॉलिसी

पॉड-टू-पॉड संचार को सीमित करें:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: mysql-network-policy
spec:
  podSelector:
    matchLabels:
      app: mysql
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 3306

प्रदर्शन अनुकूलन

स्टोरेज प्रदर्शन टीयर्स

वर्कलोड के आधार पर उपयुक्त StorageClasses चुनें:

  • उच्च IOPS: भारी रैंडम रीड/राइट के साथ डेटाबेस (gp3, io2)
  • उच्च थ्रूपुट: लॉग एग्रीगेशन, एनालिटिक्स (st1, sc1)
  • संतुलित: सामान्य उद्देश्य एप्लिकेशन्स (gp3)

पॉड वितरण

पॉड एंटी-एफिनिटी का उपयोग करके StatefulSet पॉड्स को उपलब्धता ज़ोन के माध्यम से फैलाएं:

spec:
  template:
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: mysql
            topologyKey: topology.kubernetes.io/zone

रिसोर्स रिक्वेस्ट्स और लिमिट्स

सुसंगत प्रदर्शन के लिए उपयुक्त रिसोर्स सेट करें:

resources:
  requests:
    cpu: "2"
    memory: "4Gi"
    ephemeral-storage: "10Gi"
  limits:
    cpu: "4"
    memory: "8Gi"
    ephemeral-storage: "20Gi"

उन्नत पैटर्न

इनिट कंटेनर्स के साथ स्टेटफुल एप्लिकेशन

डेटाबेस इनिशियलाइजेशन के लिए इनिट कंटेनर्स का उपयोग करें:

spec:
  template:
    spec:
      initContainers:
      - name: init-mysql
        image: mysql:8.0
        command:
        - bash
        - "-c"
        - |
          if [[ ! -d /var/lib/mysql/mysql ]]; then
            mysqld --initialize-insecure --datadir=/var/lib/mysql
          fi          
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql

साइडकार्स के लिए मल्टी-कंटेनर पॉड्स

बैकअप साइडकार्स या मॉनिटरिंग एजेंट्स जोड़ें:

spec:
  template:
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        # ... mysql config ...
      - name: backup-sidecar
        image: mysql-backup:latest
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
          readOnly: true

डायनैमिक कॉन्फ़िगरेशन के लिए ConfigMaps

StatefulSet परिभाषा से कॉन्फ़िगरेशन को अलग करें:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  my.cnf: |
    [mysqld]
    max_connections=200
    innodb_buffer_pool_size=2G    
---
spec:
  template:
    spec:
      containers:
      - name: mysql
        volumeMounts:
        - name: config
          mountPath: /etc/mysql/conf.d
      volumes:
      - name: config
        configMap:
          name: mysql-config

उपयोगी लिंक्स