Raspberry pi

퍼시스턴스 볼륨을 사용하면 기존 파일이 사라지는 문제 해결

[혜안] 2022. 8. 11. 10:26
728x90

라즈베리파에4에 쿠버네티스를 설치하고 mysql 커스텀 이미지 올리는 작업을 했습니다.

2022.08.08 - [Raspberry pi] - 라즈베리파이4 도커허브에 없는 오픈소스 직접 빌드하기 : mariadb

 

라즈베리파이4 도커허브에 없는 오픈소스 직접 빌드하기 : mariadb

라즈베리파이4 라즈비안 환경에 쿠버네티스 클러스터를 구성 중입니다. 2022.08.03 - [Raspberry pi] - 라즈베리파이4 쿠버네티스 설치 라즈베리파이4 쿠버네티스 설치 결국 라즈비안 64bit를 포기하고 32

viewise.tistory.com

2022.08.10 - [Raspberry pi] - 도커 레지스트리 (nexus3 oss) 만들기 : 커스텀빌드 이미지 올리기

 

도커 레지스트리 (nexus3 oss) 만들기 : 커스텀빌드 이미지 올리기

라즈베리파이용 mariadb 이미지가 도커허브에 없어서 직접 이미지를 빌드했습니다. 2022.08.08 - [Raspberry pi] - 라즈베리파이4 도커허브에 없는 오픈소스 직접 빌드하기 : mariadb 라즈베리파이4 도커허

viewise.tistory.com

 

사설 레포지토리를 설치해서, 빌드한 도커 이미지를 올렸고, 

쿠버네티스에서 다운로드받아 동작시키는데까지 성공은 했는데,

퍼시스턴스 볼륨 설정을 하면 mysql이 정상적으로 올라오지 않아 Pod가 반복 재기동하는 문제가 발생했습니다.

마지막 포스팅에서 "잘 동작하네요" 라는 멘트를 작성하고  포스팅을 올리고 나니 바로 아래와 같은 문제가 보였습니다.

$ k get pod -w
NAME                              READY   STATUS    RESTARTS   AGE
fan-controller-spgm8              1/1     Running   0          7h32m
mariadb-custom-794865cbbd-w4ngl   1/1     Running   0          4s
mariadb-custom-794865cbbd-w4ngl   0/1     Error     0          37s
mariadb-custom-794865cbbd-w4ngl   1/1     Running   1 (4s ago)   40s
mariadb-custom-794865cbbd-w4ngl   0/1     Error     1 (36s ago)   72s
mariadb-custom-794865cbbd-w4ngl   0/1     CrashLoopBackOff   1 (16s ago)   87s
mariadb-custom-794865cbbd-w4ngl   1/1     Running            2 (18s ago)   89s

 

디스크립션에서는 이렇다 할 단서가 보이지 않았구요.

$ k get desdescribe pod mariadb-custom-794865cbbd-w4ngl 
Name:         mariadb-custom-794865cbbd-w4ngl
Namespace:    default
Priority:     0
Node:         raspberrypi4/192.168.0.49
Start Time:   Wed, 10 Aug 2022 14:20:47 +0100
Labels:       app=mariadb-custom
              pod-template-hash=794865cbbd
Annotations:  <none>
Status:       Running
IP:           10.244.0.68
IPs:
  IP:           10.244.0.68
Controlled By:  ReplicaSet/mariadb-custom-794865cbbd
Containers:
  mariadb-arm7:
    Container ID:   containerd://d7c28e6e1573ac3b3e4215fe8964d558d27476e2b26c376146d18700e21ea8bd
    Image:          private.repo:8099/mariadb-arm7:0.3
    Image ID:       private.repo:8099/mariadb-arm7@sha256:845eb2faf3a1e3d076827a0c4bb131ba7ed688e685999a919281cb77848dd95e
    Port:           3306/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Wed, 10 Aug 2022 14:26:32 +0100
      Finished:     Wed, 10 Aug 2022 14:27:04 +0100
    Ready:          False
    Restart Count:  5
    Environment:    <none>
    Mounts:
      /var/lib/mysql from sqldb (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9x459 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             False 
  ContainersReady   False 
  PodScheduled      True 
Volumes:
  sqldb:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  pvc-sqldb
    ReadOnly:   false
  kube-api-access-9x459:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  6m53s                  default-scheduler  Successfully assigned default/mariadb-custom-794865cbbd-w4ngl to raspberrypi4
  Normal   Pulled     3m14s (x5 over 6m52s)  kubelet            Container image "private.repo:8099/mariadb-arm7:0.3" already present on machine
  Normal   Created    3m13s (x5 over 6m50s)  kubelet            Created container mariadb-arm7
  Normal   Started    3m13s (x5 over 6m49s)  kubelet            Started container mariadb-arm7
  Warning  BackOff    108s (x11 over 5m41s)  kubelet            Back-off restarting failed container

 

마지막 로그는 그냥 fail 입니다.

$ k logs --previous mariadb-custom-794865cbbd-w4ngl
[2022-08-10 22:32:34.149] Starting MariaDB database server: mariadbd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . failed!

 

그런데 희한한건, 디버그를 위해 이미지를 떠서 들어가면 mysql을 이상없이 동작시킬 수 있었습니다.

$ k debug mariadb-custom-794865cbbd-n6lj6 -it --copy-to=maria-debug --container=mariadb-custom-794865cbbd-n6lj6 --image=private.repo:8099/mariadb-arm7 -- bash
root@maria-debug:/var/lib# cd /etc/init.d/
root@maria-debug:/etc/init.d# ./mariadb start
Starting MariaDB database server: mariadbd . . . . . . . . . ..
root@maria-debug:/etc/init.d# ps -ef|grep mysql
root        39     1  0 14:30 pts/0    00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql      154    39  5 14:30 pts/0    00:00:01 /usr/sbin/mariadbd --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --skip-log-error --pid-file=/run/mysqld/mysqld.pid --socket=/run/mysqld/mysqld.sock
root       155    39  0 14:30 pts/0    00:00:00 logger -t mysqld -p daemon error

 

단서를 찾은 건, 퍼시스턴스 볼륨을 마운트한 경로에 아무런 파일이 생기지 않는다는 점이었습니다.

cmlee@raspberrypi4:/dataspace/pv-sqldb $ cd ll
total 8
drwxr-xr-x 2 cmlee cmlee 4096 Aug 10 09:05 .
drwxr-xr-x 3 root  root  4096 Aug  5 06:10 ..

처음엔 mysql이 올라오지 못했으니 아무런 파일이 생기지 않는거라 생각을 했지만,

혹시 권한이 없어 파일 생성을 못하는 것인가 싶어 유심히 보니, 쓰기 권한이 cmlee 유저 외에는 없었습니다.

일단 권한을 모두 주고 기다려봤습니다. Pod가 계속 반복재기동을 하니까요.

cmlee@raspberrypi4:/dataspace/pv-sqldb $ ll
total 110628
drwxrwxrwx 2 root            root                 4096 Aug 10 15:45 .
drwxr-xr-x 3 root            root                 4096 Aug  5 06:10 ..
-rw-rw---- 1 systemd-resolve systemd-journal     16384 Aug 10 15:45 aria_log.00000001
-rw-rw---- 1 systemd-resolve systemd-journal        52 Aug 10 15:45 aria_log_control
-rw-rw---- 1 systemd-resolve systemd-journal       864 Aug 10 15:45 ib_buffer_pool
-rw-rw---- 1 systemd-resolve systemd-journal  12582912 Aug 10 15:45 ibdata1
-rw-rw---- 1 systemd-resolve systemd-journal 100663296 Aug 10 15:45 ib_logfile0

오오~ 그랬더니 파일이 뭔가 생깁니다.

역시 권한 문제였나 싶었죠. 

소유자 이름이 systemd-resolve 인 이유는, 우연히 겹치는 userid 라 그렇습니다.

컨테이너 내부에서 보면 이렇게 보입니다.

cmlee@raspberrypi4:/dataspace/pv-sqldb $ k exec -it mariadb-custom-794865cbbd-w4ngl -- ls -al /var/lib/mysql
total 110628
drwxrwxrwx 2 root  root       4096 Aug 10 14:48 .
drwxr-xr-x 1 root  root       4096 Aug  6 15:28 ..
-rw-rw---- 1 mysql mysql     16384 Aug 10 14:48 aria_log.00000001
-rw-rw---- 1 mysql mysql        52 Aug 10 14:48 aria_log_control
-rw-rw---- 1 mysql mysql       864 Aug 10 14:48 ib_buffer_pool
-rw-rw---- 1 mysql mysql 100663296 Aug 10 14:48 ib_logfile0
-rw-rw---- 1 mysql mysql  12582912 Aug 10 14:48 ibdata1

 

하지만 그래도 문제는 해결되지 않았습니다.

그래서 퍼시스턴스 볼륨을 주지 않았을 때에 저 경로에 어떤 파일들이 생기는지 확인해 보았습니다.

root@maria-debug:/var/lib/mysql# ls -al
total 122944
drwxr-xr-x 1 mysql mysql      4096 Aug 10 14:30 .
drwxr-xr-x 1 root  root       4096 Aug  6 15:28 ..
-rw-rw---- 1 mysql mysql     24576 Aug 10 14:30 aria_log.00000001
-rw-rw---- 1 mysql mysql        52 Aug 10 14:30 aria_log_control
-rw-r--r-- 1 root  root          0 Aug  6 15:28 debian-10.5.flag
-rw-rw---- 1 mysql mysql       972 Aug  6 15:28 ib_buffer_pool
-rw-rw---- 1 mysql mysql 100663296 Aug 10 14:30 ib_logfile0
-rw-rw---- 1 mysql mysql  12582912 Aug  6 15:28 ibdata1
-rw-rw---- 1 mysql mysql  12582912 Aug 10 14:30 ibtmp1
-rw-rw---- 1 mysql mysql         0 Aug  6 15:32 multi-master.info
drwx------ 1 mysql mysql      4096 Aug  6 15:28 mysql
-rw-r--r-- 1 root  root         15 Aug  6 15:28 mysql_upgrade_info
drwx------ 2 mysql mysql      4096 Aug  6 15:28 performance_schema

훨씬 더 많은 파일들이 보이네요.

 

그리하여 곰곰히 생각해본 결과,

/var/lib/mysql 이라는 경로에는 mysql의 db data들이 저장되는데,

통상 db data는 mysql이 설치되는 때에 상당량의 db data 관련 파일들이 이미 생성됩니다.

Docker파일을 다시 봅니다.

$ cat Dockerfile 
FROM debian
RUN apt update -y && apt install mariadb-server -y
RUN sed -i 's/bind-address/bind-address = 0.0.0.0 #/i' /etc/mysql/mariadb.conf.d/50-server.cnf
RUN mkdir /mysql_scripts
COPY mySqlScript.sql /mysql_scripts/
RUN /etc/init.d/mariadb start && mysql -uroot --password="" -e "source /mysql_scripts/mySqlScript.sql"
CMD /etc/init.d/mariadb start && tail -f /dev/null

RUN은 도커이미지를 빌드할 때에 실행됩니다.

CMD는 이미지가 올라올때에 실행되구요.

즉,

mariadb-server를 설치한 도커이미지라면, 위에 마운트한 /var/lib/mysql 경로에는 상당량의 db data 파일들이 이미 생성된 상태입니다.

그 상태에서, 쿠버네티스 퍼시스턴스 볼륨을 동일한 경로에 마운트하면, 기존에 설치한 db data들은 가려지고, 비어있는 폴더가 되는 겁니다.

이게 Pod가 정상적으로 올라오지 않는 원인이었습니다.

 

그래서 해결 방법은?

Dockerfile을 아래와 같이 수정했습니다.

$ cat Dockerfile
FROM debian
RUN apt update -y && apt install mariadb-server -y
RUN sed -i 's/bind-address/bind-address = 0.0.0.0 #/i' /etc/mysql/mariadb.conf.d/50-server.cnf
RUN mkdir /mysql_scripts
COPY mySqlScript.sql /mysql_scripts/
RUN /etc/init.d/mariadb start && mysql -uroot --password="" -e "source /mysql_scripts/mySqlScript.sql"
RUN /etc/init.d/mariadb stop
RUN mv /var/lib/mysql /var/lib/mysql_temp && mkdir /var/lib/mysql
CMD mv /var/lib/mysql_temp/* /var/lib/mysql/ && /etc/init.d/mariadb start && tail -f /dev/null

mariadb-server를 설치하는 과정은 매우 오래 걸립니다.

따라서 Pod 실행 시점에 새로 설치는 올바른 방법은 아닌 것 같고, 

/var/lib/mysql에 설치된 파일들을 그대로 보존하다가, 퍼시스턴스 볼륨이 마운트된 후에 다시 넣어주면 될 것으로 판단하여,

mariadb-server를 다 설치하고 초기화 스크립트를 실행한 후에,

mariadb를 멈추고, 

RUN /etc/init.d/mariadb stop

/var/lib/mysql 경로를 /var/lib/mysql_temp로 바꿔줍니다. 그리고 /var/lib/mysql 빈폴더를 만들어 줍니다.

RUN mv /var/lib/mysql /var/lib/mysql_temp && mkdir /var/lib/mysql

/var/lib/mysql 빈폴더를 만들어주는 이유는, 퍼시스턴스 볼륨이 마운트되지 않더라도 동작하게 하기 위함입니다.

 

마지막으로 Pod가 올라와서 mariadb를 기동하기 전에, /var/lib/mysql_temp/ 밑에 있는 모든 파일을 /var/lib/mysql 밑으로 이동시킵니다.

CMD mv /var/lib/mysql_temp/* /var/lib/mysql/ && /etc/init.d/mariadb start && tail -f /dev/null

CMD는 Pod가 올라올때마다 실행할 내용이지만, /var/lib/mysql_temp/ 밑에 모든 파일을 move 시키는 최초 시점에만 시간이 걸릴 뿐, 그 다음부터는 빈 폴더이므로 반복실행되어도 부담은 없습니다.

 

이렇게 하고, 다시 이미지를 빌드하여, 쿠버네티스에서 퍼스스턴스 볼륨을 할당하고 기동해보았습니다.

cmlee@raspberrypi4:/dataspace/pv-sqldb $ ll
total 122932
drwxrwxrwx 4 root            root                 4096 Aug 10 16:44 .
drwxr-xr-x 3 root            root                 4096 Aug  5 06:10 ..
-rw-rw---- 1 systemd-resolve systemd-journal     24576 Aug 10 16:44 aria_log.00000001
-rw-rw---- 1 systemd-resolve systemd-journal        52 Aug 10 16:44 aria_log_control
-rw-r--r-- 1 root            root                    0 Aug 10 16:26 debian-10.5.flag
-rw-rw---- 1 systemd-resolve systemd-journal       972 Aug 10 16:26 ib_buffer_pool
-rw-rw---- 1 systemd-resolve systemd-journal  12582912 Aug 10 16:26 ibdata1
-rw-rw---- 1 systemd-resolve systemd-journal 100663296 Aug 10 16:44 ib_logfile0
-rw-rw---- 1 systemd-resolve systemd-journal  12582912 Aug 10 16:44 ibtmp1
-rw-rw---- 1 systemd-resolve systemd-journal         0 Aug 10 16:27 multi-master.info
drwx------ 2 systemd-resolve systemd-journal      4096 Aug 10 16:26 mysql
-rw-r--r-- 1 root            root                   15 Aug 10 16:26 mysql_upgrade_info
drwx------ 2 systemd-resolve systemd-journal      4096 Aug 10 16:26 performance_schema

퍼시스턴스 볼륨이 할당된 경로에 파일들이 제대로 생성되어 있네요.

 

 

$ k get pod
NAME                              READY   STATUS    RESTARTS   AGE
fan-controller-spgm8              1/1     Running   0          19h
mariadb-custom-545bdbb445-9m4gk   1/1     Running   0          9h

9시간 째 중단없이 잘 동작하고 있습니다.

퍼시스턴스 볼륨이 이론적으로는 단순하지만, 실제 적용시켜보면 디테일이 다르네요.

 

고려할 사항:

퍼시스턴스 볼륨은 Pod와 라이프사이클이 다릅니다. 통상 데이터베이스 컨테이너에서 퍼시스턴스 볼륨을 사용하는 목적은, Pod의 불시 종료, 업그레이드, 교체 등의 상황이 발생하더라도, db data는 이와 상관없이 보존하기 위함인데요. 이럴 경우 위 Dockerfile에 작성된 바와 같이 Pod 기동 시 내부에 있던 초기화된 db data가 퍼시스턴스 볼륨 내의 데이터를 무조건 덮어쓰게 하는 동작은 상용 환경에서는 위험할 수 있습니다.

학습용, 개인용으로만 참고하시기 바랍니다.

 

 

728x90