Статьи

Kubernetes: скопировать набор данных в постоянный том StatefulSet

Neo4j кластеры на Кубернетес

В этом посте предполагается, что мы знакомы с развертыванием Neo4j на Kubernetes. Я написал статью в блоге Neo4j, объясняя это более подробно .

Набор StatefulSet, который мы создаем для наших основных серверов, требует постоянного хранилища , что достигается с помощью примитива PersistentVolumeClaim (PVC). Кластер Neo4j, содержащий 3 основных сервера, будет иметь следующие PVC:

1
2
3
4
5
$ kubectl get pvc
NAME                            STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
datadir-neo-helm-neo4j-core-0   Bound     pvc-043efa91-cc54-11e7-bfa5-080027ab9eac   10Gi       RWO            standard       45s
datadir-neo-helm-neo4j-core-1   Bound     pvc-1737755a-cc54-11e7-bfa5-080027ab9eac   10Gi       RWO            standard       13s
datadir-neo-helm-neo4j-core-2   Bound     pvc-18696bfd-cc54-11e7-bfa5-080027ab9eac   10Gi       RWO            standard       11s

Каждый из PVC имеет соответствующий PersistentVolume (PV), который его удовлетворяет:

1
2
3
4
5
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                                   STORAGECLASS   REASON    AGE
pvc-043efa91-cc54-11e7-bfa5-080027ab9eac   10Gi       RWO            Delete           Bound     default/datadir-neo-helm-neo4j-core-0   standard                 41m
pvc-1737755a-cc54-11e7-bfa5-080027ab9eac   10Gi       RWO            Delete           Bound     default/datadir-neo-helm-neo4j-core-1   standard                 40m
pvc-18696bfd-cc54-11e7-bfa5-080027ab9eac   10Gi       RWO            Delete           Bound     default/datadir-neo-helm-neo4j-core-2   standard                 40m

PVC и PV обычно создаются одновременно с развертыванием нашего StatefulSet. Нам нужно вмешаться в этот жизненный цикл, чтобы наш набор данных уже был готов до развертывания StatefulSet.

Развертывание существующего набора данных

Мы можем сделать это, выполнив следующие действия:

  • Создайте PVC с указанными выше именами вручную
  • Прикрепите стручки к этим ПВХ
  • Скопируйте наш набор данных на эти стручки
  • Удалить стручки
  • Разверните наш кластер Neo4j

Мы можем использовать следующий скрипт для создания PVCs и pods:

pvs.sh

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/env bash
  
set -exuo pipefail
  
for i in $(seq 0 2); do
  cat <<EOF | kubectl apply -f -
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: datadir-neo-helm-neo4j-core-${i}
  labels:
    app: neo4j
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
EOF
  
  cat <<EOF | kubectl apply -f -
kind: Pod
apiVersion: v1
metadata:
  name: neo4j-load-data-${i}
  labels:
    app: neo4j-loader
spec:
  volumes:
    - name: datadir-neo4j-core-${i}
      persistentVolumeClaim:
        claimName: datadir-neo-helm-neo4j-core-${i}
  containers:
    - name: neo4j-load-data-${i}
      image: ubuntu
      volumeMounts:
      - name: datadir-neo4j-core-${i}
        mountPath: /data
      command: ["/bin/bash", "-ecx", "while :; do printf '.'; sleep 5 ; done"]
EOF
  
done;

Давайте запустим этот скрипт для создания наших PVCs и модулей:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ./pvs.sh
++ seq 0 2
+ for i in $(seq 0 2)
+ cat
+ kubectl apply -f -
persistentvolumeclaim "datadir-neo-helm-neo4j-core-0" configured
+ cat
+ kubectl apply -f -
pod "neo4j-load-data-0" configured
+ for i in $(seq 0 2)
+ cat
+ kubectl apply -f -
persistentvolumeclaim "datadir-neo-helm-neo4j-core-1" configured
+ cat
+ kubectl apply -f -
pod "neo4j-load-data-1" configured
+ for i in $(seq 0 2)
+ cat
+ kubectl apply -f -
persistentvolumeclaim "datadir-neo-helm-neo4j-core-2" configured
+ cat
+ kubectl apply -f -
pod "neo4j-load-data-2" configured

Теперь мы можем скопировать нашу базу данных на модули:

1
2
3
4
for i in $(seq 0 2); do
  kubectl cp graph.db.tar.gz neo4j-load-data-${i}:/data/
  kubectl exec neo4j-load-data-${i} -- bash -c "mkdir -p /data/databases && tar -xf  /data/graph.db.tar.gz -C /data/databases"
done

graph.db.tar.gz содержит резервную копию из локальной базы данных, которую я создал:

01
02
03
04
05
06
07
08
09
10
11
12
13
$ tar -tvf graph.db.tar.gz
  
drwxr-xr-x  0 markneedham staff       0 24 Jul 15:23 graph.db/
drwxr-xr-x  0 markneedham staff       0 24 Jul 15:23 graph.db/certificates/
drwxr-xr-x  0 markneedham staff       0 17 Feb  2017 graph.db/index/
drwxr-xr-x  0 markneedham staff       0 24 Jul 15:22 graph.db/logs/
-rw-r--r--  0 markneedham staff    8192 24 Jul 15:23 graph.db/neostore
-rw-r--r--  0 markneedham staff     896 24 Jul 15:23 graph.db/neostore.counts.db.a
-rw-r--r--  0 markneedham staff    1344 24 Jul 15:23 graph.db/neostore.counts.db.b
-rw-r--r--  0 markneedham staff       9 24 Jul 15:23 graph.db/neostore.id
-rw-r--r--  0 markneedham staff   65536 24 Jul 15:23 graph.db/neostore.labelscanstore.db
...
-rw-------  0 markneedham staff     1700 24 Jul 15:23 graph.db/certificates/neo4j.key

Мы выполним следующую команду, чтобы проверить наличие баз:

01
02
03
04
05
06
07
08
09
10
11
$ kubectl exec neo4j-load-data-0 -- ls -lh /data/databases/
total 4.0K
drwxr-xr-x 6 501 staff 4.0K Jul 24 14:23 graph.db
  
$ kubectl exec neo4j-load-data-1 -- ls -lh /data/databases/
total 4.0K
drwxr-xr-x 6 501 staff 4.0K Jul 24 14:23 graph.db
  
$ kubectl exec neo4j-load-data-2 -- ls -lh /data/databases/
total 4.0K
drwxr-xr-x 6 501 staff 4.0K Jul 24 14:23 graph.db

Пока все хорошо. Стручки сделали свою работу, поэтому мы их снесем:

1
2
3
4
$ kubectl delete pods -l app=neo4j-loader
pod "neo4j-load-data-0" deleted
pod "neo4j-load-data-1" deleted
pod "neo4j-load-data-2" deleted

Теперь мы готовы развернуть наш кластер Neo4j.

1
helm install incubator/neo4j --name neo-helm --wait --set authEnabled=false

Наконец, мы выполним запрос Cypher, чтобы проверить, что серверы Neo4j использовали загруженную нами базу данных:

01
02
03
04
05
06
07
08
09
10
11
$ kubectl exec neo-helm-neo4j-core-0 -- bin/cypher-shell "match (n) return count(*)"
count(*)
32314
  
$ kubectl exec neo-helm-neo4j-core-1 -- bin/cypher-shell "match (n) return count(*)"
count(*)
32314
  
$ kubectl exec neo-helm-neo4j-core-2 -- bin/cypher-shell "match (n) return count(*)"
count(*)
32314

Успех!

Мы могли бы достичь аналогичных результатов, используя контейнер init, но у меня еще не было возможности опробовать этот подход. Если вы попробуете, дайте мне знать в комментариях, и я добавлю это в пост.

Опубликовано на Java Code Geeks с разрешения Марка Нидхэма, партнера нашей программы JCG . См. Оригинальную статью здесь: Kubernetes: скопируйте набор данных в PersistentVolume StatefulSet

Мнения, высказанные участниками Java Code Geeks, являются их собственными.