K8sにデプロイしたApache SolrのPVCを拡張してみた

# はじめに

同様の作業はHarborでも行なっていましたが今回はSolrに対して実行した際のメモを作成しました。

SolrをK8s環境で使用してしばらく経過しましたが、使用したPVC設定ファイルの初期値がZookeeperに10GB, Solrに1GBを割り当てる仕様だったため将来のために少し拡張しておこうかなと思っています。

なお後述するように新しいK8s,Rookの環境を利用している場合には、この手順に依らずにPVCを直接kubectl editで拡張することが可能です。

# 環境

* Kubernetes 1.16.9
* Rook/Ceph v1.0.6
* Solr v8.3 (docker.io/solr:8 official image)
* ZooKeeper v3.4.10 ([K8s公式Zookeepr設定手順](https://kubernetes.io/docs/tutorials/stateful-application/zookeeper/))

## 【注意】Kubernetes v1.18以降での対応

K8sがv1.18以降で、Rook/Cephがv1.14以降であれば、そのままPVCの拡張を行なうことが可能です。

:::note warn
これ以降の作業は古いK8s, Rookを利用している場合にのみ必要になります。
:::

# 参考情報

* [HarborのPVCがfullになってしまったので拡張した作業のメモ](https://qiita.com/YasuhiroABE/items/359b8bbcbb0088302750)

# 現状の確認

どれくらいPVCを消費しているか、dfコマンドの出力から確認します。

```bash:各サーバーのPVC消費状況を確認
$ kubectl -n solr exec -it solr-server-3   -- df
Filesystem      1K-blocks     Used  Available Use% Mounted on
...
/dev/rbd0         1038336   552060     486276  54% /var/solr
...

$ kubectl -n solr exec -it zk-2   -- df
Filesystem      1K-blocks     Used  Available Use% Mounted on
...
/dev/rbd1        10475520    59776   10415744   1% /var/lib/zookeeper
...
```

solr-server-0からsolr-server-3まで確認すると、SolrのPVCは既に50%前後が消費されていて、今後不足する可能性があります。
zk-0からza-2まで確認すると、ZookeeperのPVCはあらかじめ10GB確保されていて、1%程度の利用率でほぼ問題ない状況です。

# Solrの状況

次のようなYAMLファイルでDeployしています。

```yaml:deploy-solr.yaml
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: solr-server
  namespace: solr
  labels:
    app: solr-server
spec:
  serviceName: solr-server
  replicas: 4
  selector:
    matchLabels:
      app: solr-server
  template:
    metadata:
      labels:
        app: solr-server
    spec:
      containers:
      - name: solr-server
        image: solr:8
        args:
        - "-cloud"
        - "-z"
        - "zk-cs:2181"
        ports:
        - containerPort: 8983
        livenessProbe:
          httpGet:
            path: /solr/
            port: 8983
          initialDelaySeconds: 5
          periodSeconds: 5
        volumeMounts:
        - name: solr-server-storage
          mountPath: /var/solr
      securityContext:
        runAsUser: 8983
        fsGroup: 8983
  volumeClaimTemplates:
  - metadata:
      name: solr-server-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: rook-ceph-block
      resources:
        requests:
          storage: 1Gi
```

PVCは単純なYAMLで作成しているので、同様の手順を繰り返せば細かな設定も同様になるはずです。
Harborの際はHelmだったので確認していないところで特殊な.metadata.annotationsが設定されていることも想定されたので少し慎重でしたが、今回はその部分では気楽に進めていけます。

```yaml:pvc/solr-server-storage-solr-server-0の定義
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    volume.beta.kubernetes.io/storage-provisioner: ceph.rook.io/block
  creationTimestamp: "2019-11-28T14:14:03Z"
  finalizers:
  - kubernetes.io/pvc-protection
  labels:
    app: solr-server
  name: solr-server-storage-solr-server-0
  namespace: solr
  resourceVersion: "45622592"
  selfLink: /api/v1/namespaces/solr/persistentvolumeclaims/solr-server-storage-solr-server-0
  uid: 7a0b813c-471b-4f47-8bb1-7ff8bf5fed3a
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: rook-ceph-block
  volumeMode: Filesystem
  volumeName: pvc-7a0b813c-471b-4f47-8bb1-7ff8bf5fed3a
```

solr-serverは4つのPodで稼動しているので、PVCは次のような状況になっています。

```bash:PVCの状況
$ kubectl -n solr get pvc
NAME                                STATUS   VOLUME                                     CAPACITY   ACCESS MODE
S   STORAGECLASS      AGE
datadir-zk-0                        Bound    pvc-af49f774-37ce-4381-9e06-378296da47ab   10Gi       RWO    rook-ceph-block   346d
datadir-zk-1                        Bound    pvc-63b191cb-102f-4137-9e79-d1f0f38a487a   10Gi       RWO    rook-ceph-block   346d
datadir-zk-2                        Bound    pvc-f1872e30-5ed1-498c-b941-ee8075b3b794   10Gi       RWO    rook-ceph-block   346d
solr-server-storage-solr-server-0   Bound    pvc-7a0b813c-471b-4f47-8bb1-7ff8bf5fed3a   1Gi        RWO    rook-ceph-block   346d
solr-server-storage-solr-server-1   Bound    pvc-bbf6f572-48c8-4992-b97a-fa8ce4685d05   1Gi        RWO    rook-ceph-block   346d
solr-server-storage-solr-server-2   Bound    pvc-40af1b09-6976-4eab-9634-02001ed65682   1Gi        RWO    rook-ceph-block   346d
solr-server-storage-solr-server-3   Bound    pvc-146116ba-07e8-4a8f-be5f-9405c98921a3   1Gi        RWO    rook-ceph-block   346d
```

# 基本的な進め方

SolrのPVCを拡張する作業を進めますが、概ね次のような方法をとります。

1. 情報退避用のPVCを4つ作成する
2. statefulset.apps/solr-server を削除
3. (2)のPVCと、pvc/solr-server-storage-solr-server-[0-3]をマウントするためのPodを作成する
5. 各PVCの内容を(2)のPVCに退避する
6. (3)のPodを削除する
7. pvc/solr-server-storage-solr-server-[0-3]を削除する
8. 100GBのサイズで、pvc/solr-server-storage-solr-server-[0-3]を作成する
9. (2)のPVCと(7)のPVCをマウントするため、(3)のPodを再度作成する
10. PVCの内容をコピーし、Podを削除する
11. statefulset.apps/solr-server を作成し、稼動確認

作業自体は、過去に行なったHarborのPVCを拡張する時と同様です。

## 情報退避用のPVCを4つ作成する

次のYAMLファイルをkubectl apply -fに指定して、PVCを作成します。

```yaml:01-pvc-temp-volume.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tmp-solr-0
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tmp-solr-1
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tmp-solr-2
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tmp-solr-3
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 2Gi
```

## statefulset.apps/solr-server を削除

solr-serverが起動したままでは、PVCの操作ができないため、Podを停止するため、StatefulSetの定義を削除します。

```bash:StatefulSetの削除
$ kubectl -n solr delete statefulset.apps/solr-server
```

## 各PVCをマウントしたPodを作成する

次のYAMLファイルを元にPodを作成します。

```yaml:deploy-temp-pod.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: workspace
  namespace: solr
spec:
  replicas: 1
  selector:
    matchLabels:
      app: workspace
  template:
    metadata:
      labels:
       app: workspace
    spec:
      containers:
      - name: workspace
        image: nginx:1.19.3-alpine
        imagePullPolicy: "Always"
        volumeMounts:
        - name: solr-data-storage-0
          mountPath: /data-solr-0
        - name: solr-data-storage-1
          mountPath: /data-solr-1
        - name: solr-data-storage-2
          mountPath: /data-solr-2
        - name: solr-data-storage-3
          mountPath: /data-solr-3
        - name: temp-data-storage-0
          mountPath: /data-tmp-0
        - name: temp-data-storage-1
          mountPath: /data-tmp-1
        - name: temp-data-storage-2
          mountPath: /data-tmp-2
        - name: temp-data-storage-3
          mountPath: /data-tmp-3
      volumes:
      - name: solr-data-storage-0
        persistentVolumeClaim:
          claimName: solr-server-storage-solr-server-0
      - name: solr-data-storage-1
        persistentVolumeClaim:
          claimName: solr-server-storage-solr-server-1
      - name: solr-data-storage-2
        persistentVolumeClaim:
          claimName: solr-server-storage-solr-server-2
      - name: solr-data-storage-3
        persistentVolumeClaim:
          claimName: solr-server-storage-solr-server-3
      - name: temp-data-storage-0
        persistentVolumeClaim:
          claimName: tmp-solr-0
      - name: temp-data-storage-1
        persistentVolumeClaim:
          claimName: tmp-solr-1
      - name: temp-data-storage-2
        persistentVolumeClaim:
          claimName: tmp-solr-2
      - name: temp-data-storage-3
        persistentVolumeClaim:
          claimName: tmp-solr-3
```

## 各PVCの内容を退避用PVCにコピーする

作成したPodを利用して、次の要領でデータをコピーします。

```bash:
$ kubectl -n solr exec -it workspace-5f9bd87b6f-jwqmz -- sh

## 現状のFilesystemを確認する
/ # df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/rbd4              1038336    493900    544436  48% /data-solr-2
/dev/rbd7              2086912     35572   2051340   2% /data-tmp-2
/dev/rbd9              2086912     35572   2051340   2% /data-tmp-3
/dev/rbd0              1038336    477732    560604  46% /data-solr-0
/dev/rbd5              1038336    550484    487852  53% /data-solr-3
/dev/rbd6              2086912     35572   2051340   2% /data-tmp-0
/dev/rbd2              1038336    488944    549392  47% /data-solr-1
/dev/rbd8              2086912     35572   2051340   2% /data-tmp-1

# apk update
# apk add rsync
# rsync -av /data-solr-0/. /data-tmp-0/.
# rsync -av /data-solr-1/. /data-tmp-1/.
# rsync -av /data-solr-2/. /data-tmp-2/.
# rsync -av /data-solr-3/. /data-tmp-3/.

## 同サイズになっているか確認する
# df 
/ # df |grep rbd|sort
/dev/rbd0              1038336    477732    560604  46% /data-solr-0
/dev/rbd2              1038336    488944    549392  47% /data-solr-1
/dev/rbd4              1038336    491024    547312  47% /data-solr-2
/dev/rbd5              1038336    550484    487852  53% /data-solr-3
/dev/rbd6              2086912    478920   1607992  23% /data-tmp-0
/dev/rbd7              2086912    491996   1594916  24% /data-tmp-2
/dev/rbd8              2086912    490080   1596832  23% /data-tmp-1
/dev/rbd9              2086912    551904   1535008  26% /data-tmp-3
```

## Podを削除する

Podが起動したままではPVCの操作ができないため、Podを削除します。

```bash
$ kubectl -n solr delete deployment/workspace
```

## pvc/solr-server-storage-solr-server-[0-3]を削除する

kubectlを使用して、PVCを削除する。

```bash:PVCの削除
$ kubectl -n solr delete pvc/solr-server-storage-solr-server-0
$ kubectl -n solr delete pvc/solr-server-storage-solr-server-1
$ kubectl -n solr delete pvc/solr-server-storage-solr-server-2
$ kubectl -n solr delete pvc/solr-server-storage-solr-server-3
```

## 100GBのサイズで、pvc/solr-server-storage-solr-server-[0-3]を作成する

削除したPVCの名前で、サイズを増強したPVCを作成します。

```yaml:pvc-create-solr-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: solr-server-storage-solr-server-0
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 50Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: solr-server-storage-solr-server-1
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 50Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: solr-server-storage-solr-server-2
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 50Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: solr-server-storage-solr-server-3
  namespace: solr
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 50Gi
```

## 作業用Podを再度作成する

```bash:作業用Podを再度作成する
$ kubectl -n solr apply -f deploy-temp-pod.yaml
```

## PVCの内容をコピーする

今度は/data-tmp-*の内容を/data-solr-*にコピーします。

```bash:
$ kubectl -n solr exec -it workspace-5f9bd87b6f-x2cq6 -- sh
## 作業前に/data-solr-[0-3]が空になっていることを確認する
/ # df |grep rbd|sort
/dev/rbd0             52403200     89172  52314028   0% /data-solr-2
/dev/rbd2             52403200     89172  52314028   0% /data-solr-1
/dev/rbd4             52403200     89172  52314028   0% /data-solr-3
/dev/rbd5             52403200     89172  52314028   0% /data-solr-0
/dev/rbd6              2086912    478920   1607992  23% /data-tmp-0
/dev/rbd7              2086912    490080   1596832  23% /data-tmp-1
/dev/rbd8              2086912    491996   1594916  24% /data-tmp-2
/dev/rbd9              2086912    551544   1535368  26% /data-tmp-3

# apk update
# apk add rsync
# rsync -av /data-tmp-0/. /data-solr-0/.
# rsync -av /data-tmp-1/. /data-solr-1/.
# rsync -av /data-tmp-2/. /data-solr-2/.
# rsync -av /data-tmp-3/. /data-solr-3/.

## 同サイズになっているか確認する
/ # df |grep rbd|sort
/dev/rbd0             52403200    545596  51857604   1% /data-solr-2
/dev/rbd2             52403200    543680  51859520   1% /data-solr-1
/dev/rbd4             52403200    608744  51794456   1% /data-solr-3
/dev/rbd5             52403200    532520  51870680   1% /data-solr-0
/dev/rbd6              2086912    478920   1607992  23% /data-tmp-0
/dev/rbd7              2086912    490080   1596832  23% /data-tmp-1
/dev/rbd8              2086912    491996   1594916  24% /data-tmp-2
/dev/rbd9              2086912    551544   1535368  26% /data-tmp-3

# exit
```

作業が終ったら、作業用のPodは削除します。

```bash:再度Podを削除する
$ kubectl -n solr delete -f deploy-temp-pod.yaml
```

## statefulset.apps/solr-server を作成

オリジナルのYAMLファイルを利用して、SatefulSetを再度作成します。

```bash
$ kubectl -n solr apply -f deploy-solr.yaml
```

無事に起動したらdfコマンドで/var/solrのファイルシステムが拡張されていることを確認します。

```bash
$ kc exec -it solr-server-0  -- df /var/solr

Filesystem     1K-blocks   Used Available Use% Mounted on
/dev/rbd0       52403200 491924  51911276   1% /var/solr
```

システムの稼動の確認は、SolrのコンソールからQueryを実行して確認します。

* http://192.168.1.150:8983/solr/

# 作業用PVCの削除

Solrが問題なく稼動すれば、今度は作業用のPVCを削除します。
ただこの作業は全てがうまく稼動するようになってから、しばらく様子をみて実行してください。