볼륨 백업이 존재하지 않는다면 복원할 방법이 없다.
그래서 주기적으로 볼륨 백업을 하는 게 좋다. 특히, 사용자가 별도로 선언하지 않은 볼륨은 microk8s 삭제나 재설치 과정에서 유실될 수 있으므로 별도 백업을 해두는 것이 안전하다.
Linux에 snap으로 microk8s를 설치할 경우, microk8s가 볼륨을 저장하는 디렉토리는 /var/snap/microk8s/common/default-storage이다.
snap이 아닌 다른 방법으로 설치했다면, pv 설정을 통해 확인할 수 있다.
kubectl get pv
kubectl get pv <PV 이름> -o json | grep '.spec.hostPath.path'
K8s service가 아니라 deployment/replicaset/statefulset, pod을 모두 내리는 게 필요하다. pod을 삭제하면 deployment에 의해 pod이 재설치/재기동될 수 있으므로 deployment와 pod를 멈추고 위 명령대로 볼륨을 복원한 다음에 서비스를 재시작해야 한다.
일반적으로 pod을 삭제한 후에도 PersistentVolumeClaim(PVC)는 살아 있고, PVC가 살아있는 동안에는 PV도 유지되기 때문에 볼륨 디렉토리에 접근 가능하다.
kubectl delete deployment <deployment 이름>
또는
kubectl delete statefulset <statefulset 이름>
rsync -av <백업 디렉토리>/* <신규 디렉토리>
pod를 재시작하여 변경된 볼륨을 볼 수 있도록 한다.
[Warning]
DB 볼륨은 단순히 복사한다고 동작하지 않는다. DBMS가 보관하고 있는 접속 패스워드도 파일시스템에 저장되므로 볼륨을 백업으로부터 복원하게 되면 현재 설정된 정보를 유실하게 되므로 복잡한 패스워드 재설정과 DBMS 서비스 재시작 작업이 필요하다.
kubectl delete deployment <deployment 이름>
또는
kubectl delete statefulset <statefulset 이름>
DB 볼륨은 백업 파일을 가지고 복원하면서 암호화된 접속 패스워드가 의도치 않게 변경될 수 있다. 그러므로 재설정이 필요하다.
DB 접속 패스워드는 보통 환경변수에 적혀 있거나 아니면 secret으로 관리된다.
kubectl get pod <pod 이름> -o yaml
kubectl get secret <secret 이름> -o yaml
암호화된 패스워드를 확인했다면 복사해서 다음과 같이 확인한다.
echo "암호화된 패스워드" | base64 --decode
kubectl exec -it <PostgreSQL pod 이름> -- bash
vi /opt/bitnami/postgresql/conf/pg_hba.conf
md5를 모두 trust로 변경한다.
[Tip]
vi가 설치되어 있지 않은 경우에는, sed 's/md5/trust/' 원본파일 > 신규파일 명령을 이용하자.
pg_ctl reload
psql -U postgres
ALTER USER <username> WITH PASSWORD '패스워드';
앞서 확인했던 패스워드로 재설정한다.
vi /opt/bitnami/postgresql/conf/pg_hba.conf
trust로 되어 있던 것을 md5로 되돌린다.
pg_ctl reload
kubectl exec -it <MySQL pod 이름> -- bash
vi /etc/my.cnf
bitnami에서 제공하는 mariadb의 경우,
vi /opt/bitnami/mariadb/conf/my.cnf
[mysqld] 섹션에 다음 내용을 추가한다.
[mysqld]
skip-grant-tables
pod를 재시작한다.
kubectl delete pod <MySQL pod 이름>
pod가 재시작한 후에 root로 접속한다.
kubectl exec -it <MySQL pod 이름> -- mysql -u root
USE mysql;
UPDATE user SET authentication_string=PASSWORD('패스워드') WHERE User='root';
FLUSH PRIVILEGES;
/etc/my.cnf를 원복한다.
vi /etc/my.cnf
pod를 재시작한다.
kubectl delete pod <MySQL pod 이름>
kubectl edit configmap <DB config map 이름>
mysqldump -u root <DB 이름> > backup.sql
또는
mariadb-dump -u root <DB 이름> > backup.sql
pod 내부에 생성된 backup.sql 파일을 호스트로 다운로드한다.
kubectl cp <DB pod 이름>:backup.sql .
이 과정을 docker-compose로도 할 수가 있는데, 다음의 docker-compose.yml을 생성하고 컨테이너를 실행한다.
version: '3.8'
services:
mariadb:
image: mariadb:11
container_name: mariadb-temp
volumes:
- /mnt/data/backup/blog-data-wp-mariadb-0-pvc-d7f566c0-3670-4ddc-b230-f8730b5aa9c5/data:/var/lib/mysql
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_ROOT_HOST=%
command: --skip-grant-tables
ports:
- "3306:3306"
여기서 주의할 점은 볼륨의 경로에서 /data로 끝나는 경로와 /var/lib/mysql이 매핑되어야 한다는 점과, 외부에 공개할 포트가 3306이라는 점이다.
docker exec -it mariadb-temp bash
앞서 언급한 것처럼 mysqldump나 mariadb-dump 명령을 이용해서 덤프할 수 있다.
애플리케이션의 pod를 재시작한다
kubectl delete pod <애플리케이션 pod 이름>