새 기능 #13766
스냅샷 클론의 fsid 충돌 제거와 phase 3 실장비 검증 기록
설명
개요¶
클론(clone)은 origin의 블록 단위 복사본이라 XFS UUID까지 그대로 물려받는다. knfsd는 export에 fsid=가 없으면 파일시스템 UUID에서 fsid를 유도하므로, origin과 클론을 동시에 export하면 클라이언트가 한쪽을 마운트하고 다른 쪽 내용을 읽는다. 실패가 아니라 조용히 틀린 답이고, create_share_from_snapshot이 만든 모든 클론이 이 상태였다.
그래서 드라이버가 클론을 처음 export하기 전에 UUID를 다시 만든다. 그 시점이 어떤 클라이언트도 파일 핸들을 쥐고 있지 않은 유일한 구간이다. UUID는 슈퍼블록에 있으므로 재부팅과 failover를 견디고, export 쪽에는 새로운 상태가 생기지 않는다. export마다 fsid=를 명시하는 방안은 그 값을 영속적으로 소유할 주체가 필요하고 드라이버가 share별로 다른 값을 넘길 경로도 없어서 채택하지 않았다.
순서는 xfs_admin이 강제한다. xfs_admin은 더러운 로그를 거부하고 lvcreate -s는 freeze도 sync도 하지 않으므로, 클론을 nouuid로 한 번 마운트해 로그를 재생하고 언마운트한 다음에야 UUID를 바꿀 수 있다. 이 왕복이 nouuid가 살아남는 마지막 자리다. 이후 마운트와 ensure_share, Pacemaker 파일시스템 리소스에서는 모두 빠졌기 때문에, 재생성이 누락되면 origin의 fsid로 조용히 export되는 대신 마운트가 실패한다. 이미 마운트된 클론을 만난 재시도는 이 블록을 통째로 건너뛴다. 이미 export 중일 수 있고, 클라이언트 밑에서 UUID를 바꾸면 파일 핸들이 stale이 되기 때문이다.
엔드포인트는 배포 요구사항이며, 드라이버가 탐지하지 않는다. 버전 가드가 없으므로 이 엔드포인트가 없는 GMS에서는 create_share_from_snapshot만 404로 실패하고 나머지는 계속 동작한다. 404를 잡아 nouuid로 물러서는 방안은 결함을 되살리면서 성공처럼 보이게 만들기 때문에 채택하지 않았다.
이 작업과 함께 phase 3도 계획 단계를 벗어난다. 2노드 ASE4 장비에서 돌린 회차를 문서에 기록한다.
작업 내용¶
POST /filesystem/regenerate_uuid를 클라이언트에 래핑한다. libgms가 앞뒤 UUID를 비교해 실패를 상태 코드로 알려주므로 본문은 보지 않는다.- mock 파일시스템에 UUID 개념을 넣는다. 클론은 origin의 UUID를 복사하고, 중복 UUID 마운트는
nouuid없이는 거부하며, 재생성은 마운트된 파일시스템이나 재생되지 않은 로그를 거부한다. 실제 XFS와xfs_admin이 하는 그대로다. - 클론이 처음 export되기 전에 UUID를 재생성한다.
nouuid는 로그 재생 왕복에서만 쓰고, Pacemaker 리소스에nouuid를 붙이던 헬퍼는 제거한다. - e2e와 HA 통합 검사에서 클론의 마운트 옵션과 UUID가 origin과 다른지 확인한다.
docker-compose.live.yml의profiles와depends_on을!override로 바꾼다. compose가 시퀀스와 매핑을 병합하는 탓에 mock이 여전히--profile integration에 딸려 오고 있었다.- 클론 UUID 설계 근거를
docs/{en,ko}/shares.md에 적는다. - 2노드 ASE4 장비에서 확인한 phase 3 결과를
docs/{en,ko}/testing.md에 기록한다. share 수명주기 전체, 클론 fsid의 재생성 전후 대조, 계획된 failover와 비계획 failover, fault injection이 필요 없는 오류-동시성 경로.