상황
AWS VPC-TRIPKEY의 private subnet에 Galera DB 3대를 구성했다.
- db1:
10.250.150.30 - db2:
10.250.160.205 - db3:
10.250.170.141
초기 구성 목표는 다음과 같았다.
| 노드 | 역할 | read_only |
|---|---|---|
| db1 | writer | OFF |
| db2 | reader | ON |
| db3 | reader | ON |
db1을 bootstrap한 뒤 db2, db3를 클러스터에 join시키는 과정에서 db2/db3 컨테이너가 HEALTH=starting 상태에 머물고, RESTARTS가 계속 증가했다.
증상
db2/db3 상태 확인 시:
db2/db3 로그에서는 다음과 같은 메시지가 확인됐다.
이후 db2만 다시 join시켰을 때도 실패가 반복됐고, db1 donor 로그에서 핵심 원인이 확인됐다.
원인 1: db2/db3를 거의 동시에 Join 시도
초기에는 db1 bootstrap 후 db2가 완전히 Synced 상태가 되었는지 확인하지 못한 상태에서 db3도 바로 실행했다.
그런데 status-vm.sh에 실행 권한이 없어 상태 확인이 실패했고, db2의 SST 완료 여부를 확인하지 못한 채 db3까지 join을 시도했다.
결과적으로 db2와 db3가 동시에 db1에 SST를 요청했고, db1이 donor 역할을 처리하는 중 충돌이 발생했다.
원인 2: SST 계정 비밀번호 형식 오류
initdb-create-sst-user.sh는 SST 비밀번호가 hex 문자열이라고 가정한다.
하지만 초기 secrets 생성 시 sst_password.txt를 base64 방식으로 생성했다.
base64 문자열에는 /, +, = 같은 특수문자가 포함될 수 있어 SST 계정 생성 및 인증 과정에서 문제가 발생했다.
그 결과 db1에서 donor로 동작할 때 sstuser 인증에 실패했다.
해결 1: 스크립트 실행 권한 부여
각 DB 노드에서 스크립트 실행 권한을 부여했다.
이후 status-vm.sh로 클러스터 상태를 확인할 수 있게 됐다.
해결 2: db2/db3 데이터 볼륨 초기화
db1은 bootstrap된 정상 writer 노드였으므로 유지하고, join 실패 이력이 남은 db2/db3만 초기화했다.
db2:
db3:
down -v는 Galera 데이터 볼륨을 삭제하므로 bootstrap 노드인 db1에서는 실행하지 않았다.
해결 3: SST 비밀번호를 hex로 재생성
db1에서 SST 비밀번호를 hex 형식으로 재생성했다.
생성한 sst_password.txt를 db2, db3에도 동일하게 반영했다.
세 노드에서 checksum을 비교해 동일한 secret이 적용됐는지 확인했다.
해결 4: db1의 sstuser 비밀번호 갱신
db1은 이미 초기화가 끝난 상태였기 때문에 init script가 다시 실행되지 않았다.
따라서 db1에 직접 접속해 sstuser 비밀번호를 새 SST secret으로 갱신했다.
이후 db1 컨테이너를 재생성하여 새 secret 기반 wsrep_sst_auth 설정을 반영했다.
db1 상태:
해결 5: Join을 순차적으로 진행
db2와 db3를 동시에 올리지 않고, 한 노드가 완전히 Synced 된 뒤 다음 노드를 join시켰다.
db2 join:
db2 정상 상태:
db2가 정상화된 뒤 db3 join:
db3 정상 상태:
최종 검증
db1에서 write 테스트를 수행했다.
db2/db3에서 read 확인:
결과:
db2/db3에서 write 시도 시 정상적으로 차단됐다.
결론
문제는 Galera 네트워크 자체 장애가 아니라 다음 두 가지가 복합적으로 발생한 것이었다.
- db2/db3를 동시에 join시켜 SST donor 처리 충돌 발생
- SST 비밀번호를 base64로 생성해
sstuser인증 실패 발생
해결 후 AWS private subnet 내 Galera 3-node 클러스터는 정상 구성됐다.
| 노드 | 역할 | 상태 |
|---|---|---|
| db1 | writer | read_only=OFF, Synced |
| db2 | reader | read_only=ON, Synced |
| db3 | reader | read_only=ON, Synced |
향후 재구성 시에는 다음 순서를 지킨다.