Вопрос или проблема
Я управляю средой OpenShift, поддерживаемой службой Ceph, предоставляющей блочные устройства RBD. Когда одно и то же тома подключается к нескольким узлам (например, при использовании режима блочного тома), я наблюдаю неожидаемое поведение: изменения, внесенные в одну из томов, не отражаются на других узлах, которые также подключают то же самое RBD-тома.
Примечание: Чтобы избежать путаницы, так как много людей задают другие вопросы, я не пытаюсь монтировать файловую систему с этих устройств. Я взаимодействую напрямую с блочным устройством.
Например, рассмотрим PersistentVolumeClaim, как этот:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: blockvol
spec:
accessModes:
- ReadWriteMany
volumeMode: Block
resources:
requests:
storage: 1Gi
Это томо подключено как блочное устройство к нескольким подам с помощью следующего развертывания:
apiVersion: apps/v1
kind: Deployment
metadata:
name: bvexample
spec:
replicas: 2
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- blockvol
topologyKey: kubernetes.io/hostname
containers:
- name: blockvol
image: docker.io/python:3.12
env:
- name: NODE
valueFrom:
fieldRef:
fieldPath: spec.nodeName
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 100m
memory: 1Gi
volumeDevices:
- devicePath: /dev/blockvol
name: blockvol
command:
- sleep
- inf
volumes:
- name: blockvol
persistentVolumeClaim:
claimName: blockvol
Когда все запущено и работает, мы видим, что поды работают на двух разных узлах в кластере:
$ kubectl get pod -l app=blockvol -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
bvexample-6f64cffc5f-5f5jc 1/1 Running 0 6m27s 10.128.17.189 wrk-29 <none> <none>
bvexample-6f64cffc5f-k8bjr 1/1 Running 0 6m27s 10.131.17.137 wrk-35 <none> <none>
Устройство доступно как /dev/blockvol
внутри подов:
$ kubectl get pod -l app=blockvol -o name |
xargs -IPOD sh -c 'echo === POD ===; kubectl exec POD -- ls -l /dev/blockvol'
=== pod/bvexample-6f64cffc5f-5f5jc ===
brw-rw-rw-. 1 root disk 252, 16 Sep 25 01:09 /dev/blockvol
=== pod/bvexample-6f64cffc5f-k8bjr ===
brw-rw-rw-. 1 root disk 252, 16 Sep 25 01:09 /dev/blockvol
Изначально устройство содержит только нули:
1000820000@bvexample-6f64cffc5f-k8bjr:/$ od -N16 -xa /dev/blockvol
0000000 0000 0000 0000 0000 0000 0000 0000 0000
nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul
0000020
Если я запишу данные на это устройство, я ожидаю, что эти изменения будут видны немедленно на других узлах. Однако, если в одном поде я выполню:
1000820000@bvexample-6f64cffc5f-k8bjr:/$ echo this is a test. > /dev/blockvol
1000820000@bvexample-6f64cffc5f-k8bjr:/$ od -N16 -xa /dev/blockvol
0000000 6874 7369 6920 2073 2061 6574 7473 0a2e
t h i s sp i s sp a sp t e s t . nl
0000020
Другой под — на другом узле — продолжает видеть исходные данные:
1000820000@bvexample-6f64cffc5f-5f5jc:/$ od -N16 -xa /dev/blockvol
0000000 0000 0000 0000 0000 0000 0000 0000 0000
nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul
0000020
Если я убью поды, заставив их переназначиться на новые узлы:
$ kubectl delete pod -l app=blockvol
Тогда изменения будут видны на блочном устройстве в обоих местах:
=== pod/bvexample-6f64cffc5f-bkb5q ===
0000000 6874 7369 6920 2073 2061 6574 7473 0a2e
t h i s sp i s sp a sp t e s t . nl
0000020
=== pod/bvexample-6f64cffc5f-vv595 ===
0000000 6874 7369 6920 2073 2061 6574 7473 0a2e
t h i s sp i s sp a sp t e s t . nl
0000020
Похоже, что драйвер RBD кэширует изменения локально, пока устройство RBD не будет отсоединено от узла, в этот момент изменения действительно записываются на диск. Это… регулярное поведение для устройств RBD? Какой-то параметр конфигурации? Это было неожиданно и означает, что режим ReadWriteMany
фактически является ложью (да, вы можете записать в него, но вы не сможете фактически прочитать эти данные нигде).
Ответ или решение
Ваш вопрос касается поведения RBD-устройств в Ceph, когда они смонтированы на нескольких узлах, что может вызывать недоразумения в плане видимости данных между ними. Давайте рассмотрим вашу ситуацию подробнее и постараемся воссоздать полное понимание проблемы.
Проблема
Вы используете RBD (RADOS Block Device) в рамках OpenShift кластера, и при работе с блочными устройствами (volumeMode: Block) изменения, которые вы вносите в блок устройства в одном из подов, не отображаются в другом поде, запущенном на другом узле, пока блок-устройство не будет размонтировано. Выходит, что данные "кэша" на одном узле не синхронизируются с другим узлом до тех пор, пока одно из устройств не будет отключено.
Описание поведения RBD
К сожалению, такое поведение действительно может иметь место, когда вы напрямую взаимодействуете с блочными устройствами, и это связано с особенностями работы RBD и кэширования в драйверах. RBD не предназначен для одновременной записи из нескольких источников, поскольку он не реализует механизмы блокировки или синхронизации данных на уровне блочного устройства. Поэтому, когда вы записываете данные на одно устройство, другие узлы не видят изменения, пока устройство не будет размонтировано.
Рекомендации по решению проблемы
-
Подумайте о механизмах синхронизации: Если вам нужна функциональность, в которой данные должны быть видимыми для всех узлов немедленно, вам, возможно, стоит рассмотреть использование системы управления данными, такой как файловая система, обеспечивающая консистентность, например, CephFS (Ceph File System) вместо RBD-устройств. CephFS поддерживает распределенные файловые системы и может справляться с многими конкурентными запросами.
-
Рассматривайте архитектуру приложения: Возможно, есть смысл изменить способ работы приложений, чтобы избежать одновременного доступа к блочным устройствам из различных подов. Предусмотрите механизм очередей или другие методы, которые позволят отложить операции записи и избежать конфликтов.
-
Проверьте настройки Ceph и RBD: Вы можете изучить настройки RBD, такие как
rbd_cache
, которые отвечают за кэширование. Хотя кэширование на уровне блока может повысить производительность, оно может также привести к проблемам с согласованностью, как вы уже заметили. Может быть, изменение параметров кэширования поможет. -
Изучите уровни производительности и доступности Ceph: Если вам необходимо высокое согласование данных при многопользовательском доступе, возможно, вам стоит переосмыслить, действительно ли RBD является вашим наилучшим вариантом или стоит обратить внимание на другие решения.
Заключение
Таким образом, поведение, которое вы наблюдаете, связано с механизмом кэширования в RBD и тем, как блочные устройства работают с записью данных и отзывом их обратно в хранилище. Рекомендуется рассмотреть использование альтернативных подходов для управления данными или же адаптировать логику вашего приложения, чтобы минимизировать проблемы с согласованностью данных.