Вопрос или проблема
Итак, я пытаюсь настроить, чтобы каждому поду в StatefulSet вручную назначалась определенная PVC без использования volumeClaimTemplates.
Я использую patch для каждого пода и StatefulSet, но это не работает.
Так что вот мой код из pvc.yaml файла:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: busybox-pvc-0
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: busybox-pvc-1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: busybox-pvc-2
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
и вот мой код из statefullset.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: busybox
spec:
serviceName: "busybox-service"
replicas: 3
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- name: busybox-storage
mountPath: /mnt/data
volumes:
- name: busybox-storage
persistentVolumeClaim:
claimName: busybox-pvc-0
и я пытаюсь использовать “patch” вот так, но получаю ошибку такого типа:
dev_2@Tadhak-dev-02:~/Backup/Opensearch/Stateful_PVC$ minikube kubectl -- patch pod busybox-0 --type="json" -p '[{"op": "replace", "path": "/
spec/volumes/0/persistentVolumeClaim/claimName", "value": "busybox-pvc-0"}]'
The request is invalid: the server rejected our request due to an error in our request
dev_2@Tadhak-dev-02:~/Backup/Opensearch/Stateful_PVC$ minikube kubectl -- patch pod busybox-1 --type="json" -p '[{"op": "replace", "path": "/spec/volumes/0/persistentVolumeClaim/claimName", "value": "busybox-pvc-1"}]'
The Pod "busybox-1" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`,`spec.initContainers[*].image`,`spec.activeDeadlineSeconds`,`spec.tolerations` (only additions to existing tolerations),`spec.terminationGracePeriodSeconds` (allow it to be set to 1 if it was previously negative)
core.PodSpec{
Volumes: []core.Volume{
{
Name: "busybox-storage",
VolumeSource: core.VolumeSource{
... // 7 identical fields
ISCSI: nil,
Glusterfs: nil,
PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{
- ClaimName: "busybox-pvc-0",
+ ClaimName: "busybox-pvc-1",
ReadOnly: false,
},
RBD: nil,
Quobyte: nil,
... // 18 identical fields
},
},
{Name: "kube-api-access-jzfbk", VolumeSource: {Projected: &{Sources: {{ServiceAccountToken: &{ExpirationSeconds: 3607, Path: "token"}}, {ConfigMap: &{LocalObjectReference: {Name: "kube-root-ca.crt"}, Items: {{Key: "ca.crt", Path: "ca.crt"}}}}, {DownwardAPI: &{Items: {{Path: "namespace", FieldRef: &{APIVersion: "v1", FieldPath: "metadata.namespace"}}}}}}, DefaultMode: &420}}},
},
InitContainers: nil,
Containers: {{Name: "busybox", Image: "busybox", Command: {"/bin/sh", "-c", "sleep 3600"}, VolumeMounts: {{Name: "busybox-storage", MountPath: "/mnt/data"}, {Name: "kube-api-access-jzfbk", ReadOnly: true, MountPath: "/var/run/secrets/kubernetes.io/serviceaccount"}}, ...}},
... // 30 identical fields
}
Итак, как сделать, чтобы это работало, чтобы каждому поду в StatefulSet вручную назначалась определенная PVC без использования volumeClaimTemplates.
busybox-0 → busybox-pvc-0 ,
busybox-1 → busybox-pvc-1 ,
busybox-2 → busybox-pvc-2 ,
Ответ или решение
Вопрос о том, как правильно настроить составные элементы Kubernetes, такие как StatefulSet, подчеркивает важность понимания работы с постоянными хранилищами (PVC) при развертывании приложений, требующих сохранения состояния. В данном случае, требуется вручную назначить каждое хранилище (PVC) для конкретного пода в StatefulSet без использования шаблонов volumeClaimTemplates. Это особенно важно в ситуациях, где доступность данных имеет критическое значение.
Теория
Kubernetes предлагает StatefulSet как специализированный контроллер, который обеспечивает уникальные идентификаторы для каждого пода, гарантируя, что он восстанавливается в определенном порядке. Это делает его идеальным выбором для приложений, требующих сохранения состояния, таких как базы данных или распределенные системы.
Обычно, когда мы говорим о привязке PVC к подам в StatefulSet, используется volumeClaimTemplates
, которые автоматически создают PVC для каждого пода с уникальным именем. Однако, если требуется индивидуальная привязка уже существующих PVC к подам, необходимо использовать подходы, обходящиеся без авто-создания PVC.
Пример
Обратимся к YAML-конфигурации, предоставленной в вопросе. Начнем с того, что создано несколько PVC, которые можно использовать для каждого пода:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: busybox-pvc-0
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: busybox-pvc-1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: busybox-pvc-2
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Эти PVC соотносятся с подами, которые будут развернуты в рамках StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: busybox
spec:
serviceName: "busybox-service"
replicas: 3
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- name: busybox-storage
mountPath: /mnt/data
volumes:
- name: busybox-storage
persistentVolumeClaim:
claimName: busybox-pvc-0
Применение
В вашей текущей конфигурации все поды будут пытаться использовать busybox-pvc-0
, что приводит к конфликту, так как PVC с ReadWriteOnce
не могут быть смонтированы несколькими подами одновременно. Чтобы решить эту проблему и правильно привязать уникальные PVC к каждому поду, вам нужно вручную создать StatefulSet с индивидуализированной конфигурацией для каждого пода. Можно использовать аннотации или labels для различения подов, чтобы каждый из них ссылался на свой уникальный PVC.
Обновите StatefulSet, как показано ниже:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: busybox
spec:
serviceName: "busybox-service"
replicas: 3
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "sleep 3600"]
volumeMounts:
- name: busybox-storage
mountPath: /mnt/data
volumeMounts:
- name: pvc-identifier
mountPath: /mnt/data
initContainers:
- name: init
image: busybox
command:
- sh
- -c
- |
case $(hostname -s) in
busybox-0)
ln -s /mnt/data/busybox-pvc-0 /mnt/data ;;
busybox-1)
ln -s /mnt/data/busybox-pvc-1 /mnt/data ;;
busybox-2)
ln -s /mnt/data/busybox-pvc-2 /mnt/data ;;
esac
Данные изменения используют initContainers
, чтобы привязывать поды к конкретным PVC, основываясь на имени хоста. Тем самым каждый под будет иметь доступ к правильному PVC.
Таким образом, важным моментом здесь является использование initContainers
для обеспечения правильной конфигурации подов с необходимыми PVC при развертывании StatefulSet в Kubernetes.