스키마 드리프트 원인 추적 및 해결

기존 배포 환경의 백업을 복원하여 사이트를 마이그레이션하려고 시도하고 있습니다. 스키마 불일치(소스가 타깃보다 최신)로 인해 복원이 실패하고 있습니다.

두 배포 환경의 관리자/플러그인 엔드포인트를 확인해 보니 목록에 포함된 플러그인, 상태, 버전이 모두 일치하여 원인이 무엇인지 잘 모르겠습니다. 혹시 모르니 테마와 컴포넌트를 모두 복원해 보았지만 역시 변화가 없었습니다. 두 사이트 모두 앱 버전 3.1.3을 사용하고 있으므로 이 경우 근본적인 원인으로 보이지 않습니다.

사이트에 플러그인이 설치된 상태에서 인스턴스가 재배포되고, 해당 플러그인이 설치되지 않은 상태로 데이터베이스가 보존된 것이 아닌가 추측해 봅니다. 하지만 이는 단순한 추측일 뿐입니다. 특정 인스턴스나 데이터베이스가 주어졌을 때, 스키마 드리프트(schema drift)의 원인을 결정적으로 파악할 수 있는 방법이 있을까요? 그리고 타깃 사이트를 소스와 일치시키거나 상위 집합으로 만드는 것 외에, 버전을 하향(down rev)하는 방법이 있을까요?

기존 버전이 베타였거나, 테스트는 통과했지만 안정화되지 않은 상태라서 최신 안정판이 실제로는 더 오래된 버전일 수도 있을까요?

(가능하다면) 커밋 번호가 일치하는지 확인해 보세요.

백업은 데이터베이스(db)의 것이므로 플러그인 데이터가 있는지 여부는 중요하지 않을 것 같습니다. 단순히 플러그인 데이터만 추가될 뿐 실제로는 사용되지 않으니까요…

그렇지 않을 것 같지만, 개발 환경이니까 뭐든 가능하겠죠.

schema_migrations 테이블(또는 컨테이너에 복제된 코드)에서 스키마 버전을 해당 변경 사항과 매칭시키기 위해 수동으로 확인할 수 있는 항목이 있는지 알고 계신가요?

파일 이름을 바꾸면 UI를 통해 업로드를 진행할 수는 있지만, 저는 max(schema_migrations) 기준으로 차단하는 merger를 사용 중입니다. 너무 많은 부분을 해킹하는 것은 정말로 피하고 싶습니다.

이 중 일부는 마이그레이션 버전 불일치가 발생할 수 있는 운영 작업보다 앞서 나가는 내용입니다. 마이그레이션 버전을 변경 사항으로 추적하는 방법을 더 잘 이해하면, 이런 상황이 다시 발생했을 때 조정(reconciling)을 위한 런북(runbook)을 작성할 수 있기를 바랍니다.

rails db:version

를 discourse 디렉터리에서 명령줄로 실행할 수 있습니다… 하지만 복원하지 않았다면 도움이 되지 않을 수도 있습니다 …

또는 psql에서:

SELECT * FROM schema_migrations ORDER BY version DESC LIMIT 1;

그 결과를 GitHub에서 검색하여 커밋을 교차 참조할 수 있습니다 …

예: https://github.com/search?q=repo%3Adiscourse%2Fdiscourse+20231222030024&type=code

마이그레이션 파일을 살펴보고 추가된 시점의 커밋을 확인하여 날짜 등을 검증하세요.

참고: 이는 당연히 코드 커밋과 반드시 동일하지는 않습니다! 더 오래된 것일 수도 있습니다 :slight_smile: (git log -1으로 확인할 수 있습니다)

네, max schema_migration 값은 확인할 수 있습니다(백업 파일 이름만 봐도요). 하지만 테이블을 확인해 보니 단순히 날짜 값만 있고, 어디서 온 건지 흔적이 없어요.

예를 들어, 정상적인 값은 20230823100627이고, 사이트 쪽은 20231022224833이에요. post_migrate 폴더(또는 저장소의 다른 곳)에서 "20231022"에 해당하는 파일조차 찾을 수 없어요.

분명 눈앞에 있는 것 같은데요. 네, 8월 이후에 무단으로 버전이 섞여 들어온 액션을 찾아내기 위해 과거 변경 이력과 이메일들을 뒤져볼 생각이에요.

잠깐, 개발 인스턴스를 프로덕션 데이터베이스로 복원하거나 그 반대를 시도하고 있는 건가?

나는 그런 걸 시도해 본 적이 없고, 프로덕션에서 프로덕션으로만 복원해 봤어. (데이터베이스 이름과 기타 설정이 일관되게 유지되니까.)

이 경우 Dev 인스턴스에서 새로 프로비저닝된 “Merge” 인스턴스로의 마이그레이션입니다. 이후 merger를 사용하여 다른 Dev 인스턴스를 가져와, 현재 진행 중인 인스턴스 통합 작업을 테스트할 예정입니다. 스키마 마이그레이션 리비전이 동기화되어 있어야 하는 것은 사전 조건입니다(당연한 결과입니다). 이 경우 대상 환경은 1022이고 소스는 0823입니다. 제가 보유한 모든 3.1.3 버전에서는 0823으로 되어 있어, 1022가 어디서 유래했는지 파악하는 것이 어려웠습니다. 이것이 제가 역추적하려는 부분인데, 아직 흔적을 찾지 못했습니다.

음, 워크플로가 아주… 특이하시네요!

이상적으로는 개발 환경에 데이터를 유지할 필요가 없어야 하며, 데이터베이스를 삭제한 후 마이그레이션을 다시 실행할 수 있어야 합니다.

분기된 두 개의 개발 인스턴스를 병합하려면 일반적으로 마이그레이션을 포함해 브랜치의 코드를 병합한 후, 처음부터 새 인스턴스를 생성하게 됩니다.

이것이 바로 작업할 수 있도록 일부 픽스처를 미리 채워주는 rake 태스크가 제공되는 이유 중 하나입니다: rake dev:populate

우리는 400개 이상의 플러그인에 대한 모든 마이그레이션 ID를 데이터베이스로 보유하고 있어, 이를 플러그인에 쉽게 매핑할 수 있습니다. 이 ID는 discourse-automation에서 온 것입니다.

하하, 얼마 전에 목장의 동물들이 모두 헛간에서 탈출해서 이제 모두를 다시 우리로 데려오려고 하고 있어요. 아니면 적어도 그게 현실적으로 가능한지 알아보는 중이죠.

그리고 인스턴스 파일 시스템을 살펴보니 실종된 조각을 찾았어요.

사람들은 automate 플러그인을 보고 있었지만, 다른 환경에서는 한 번도 활성화된 적이 없어서 플러그인 목록에는 있었지만 스키마 변경은 이루어지지 않았어요. 이상적인 상황은 아니지만, 이 작업에 대한 제 힌트는 비활성 상태일지라도 과거에 활성화되었을 수 있으므로 설치된 모든 플러그인의 저장소를 확인하는 거예요.

이제 일부 R&D 플러그인을 제거하고 재배포를 진행하며, 플러그인의 /db 항목을 더 세심하게 주시하고 기록 관리도 더 철저히 하고 있습니다.

참고로, GitHub 검색이 여기서 큰 도움이 됩니다.

네, 결국 인스턴트 런타임 자체를 확인하면서 저희도 해결 방법을 찾았지만, 이상적인 방식은 아닙니다. 운영 런북에 기록해 두면 나중에 필요할 때 도움이 될 것 같네요. 자동화 저장소가 비활성화되어 있고 누가 사용했는지 기록이 없어서 조직 내 해당 저장소를 확인하지 않았는데, 제 판단 착오였습니다.

@RGJ 해당 데이터베이스가 공개적으로 접근 가능한 곳이 있을까요? 인스턴트 파일 시스템을 활용하는 방식은 “동작은” 하지만, 제가 선호하는 방식보다 더 복잡해집니다.

사람들이 커밋을 푸시하지 않았다는 뜻이야?

당신은 무엇을 구하려는 거야?

네, discourse 저장소 자체에서 검색을 시도했는데, 결과가 나올지 확실하지 않아서 전 세계를 훑는 방식은 피했습니다. 범위를 지정하지 않고 검색하는 것은 비용이 너무 크지만, Discourse 공식 작업에 대한 검색 결과가 있는지 확인하려고 조직(Org) 수준까지 범위를 넓혀 보지는 않았습니다.

독립적인 팀들이 동일한 비즈니스 문제를 해결하기 위해 시작한 3~4개의 Discourse 인스턴스를 보유하고 있으며, 이전 작업 내용을 잃지 않으면서 모든 팀을 단일 인스턴스로 통합할 수 있는지 검토하고 있습니다.

개발 환경에서 데이터를 유지하는 것이 좋은 관행이라는 것이 믿기지가 않습니다.

데이터가 중요하다면, 해당 작업은 더 엄격하게 관리되는 환경에서 프로덕션에 존재해야 할 것입니다.

사용자가 정확히 무엇을 하려는지는 전체적으로 알지 못하지만, 제 의견으로는 솔루션은 어디에나 배포할 수 있는 플러그인 형태여야 하며, 특정 버전의 Discourse에 완전히 의존할 필요도 없고, 자체 픽스처 시딩을 제외하고 특정 데이터가 미리 입력되어 있는지에 대해 신경 쓸 필요도 없습니다.

네 :100:

이번 작업에서는 몇몇 Dev 인스턴스를 사용하여 Prod 인스턴스에 대한 이러한 병합 작업의 타당성을 검토하고 있습니다. 런북(runbook)을 충분히 견고하게 만들 수 있다면, 모든 데이터와 인스턴스는 Prod 수준의 품질을 갖추게 되며, 그동안 독립적인 팀들에 의해 관리되어 왔습니다. 따라서 저는 현재 성공적인 병합을 가로막는 장애물들이 무엇인지 파악하는 데 집중하고 있습니다. 스키마 버전은 명확한 핵심 요소 중 하나이며, 애플리케이션과 플러그인 모두 "병합 가능성(mergability)"에 영향을 미칠 수 있고 실제로도 미칩니다. 다행히도 Prod 인스턴스들은 0823 버전을 표시하고 있으므로, 이 특정 문제는 Prod 환경에서 실행될 때 발생하지 않을 것입니다. 하지만 스키마 드리프트(schema drift)를 분석하는 방법을 아는 것은 필수적이었으며, 이는 우리의 운영 문서(opdocs)에 큰 도움이 될 것입니다.

아, 네. 프로덕션 DB 병합을 프로토타입으로 테스트 중이시군요. 흥미롭네요.

하지만 구체적으로 무엇을 병합하려는 건가요?

인스턴스 간 토픽(그리고 해당 사용자!) 이동을 공식적으로 지원한다는 사실은 알고 계셨나요?

네, 기존 주제와 관련 콘텐츠가 수천 개나 있어서 일회성 항목들이 좀 엉망이 되어 있네요.

Merge two Discourse sites into one 이 링크는 다른 스크립트를 사용하지만 기본 아이디어는 동일합니다.

스키마에 대한 또 다른 미묘한 차이점을 발견했습니다. 배포에서 자동화 플러그인을 제거하고 다시 배포했습니다. 그러다 보니 schema_migration이 최신 버전으로 0823으로 되돌아간 것을 확인했습니다. 그래서 자동화 플러그인을 병합하려는 인스턴스에 설치하지 않아도 괜찮을 것 같았습니다. 하지만 다시 가져오기(import)를 실행했을 때 PG::UndefinedTable: ERROR: relation "discourse_automation_automations" does not exist 오류가 발생했습니다. 즉, 마이그레이션 버전은 되돌아갔지만 실제 데이터베이스에 적용된 해당 스키마 변경 사항은 여전히 남아 있는 것 같습니다.