Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
implemented |
@abrandl
|
@glopezfernandez
|
@fabian
@craig-gomes
| devops data stores | 2021-02-08 |
데이터베이스 테스팅
알림: 이 청사진은 일부 구현되었습니다. 계속해서 툴링에 대해 반복할 계획이 있습니다. 아래 내용은 개발 워크플로에 데이터베이스 테스팅을 포함하기 전에 작성된 역사적인 버전입니다.
우리는 reverted migrations의 공통 테마를 식별했으며, 개발 환경에서 성공적으로 테스트된 후에도 프로덕션 및 스테이징에서 실패한 마이그레이션을 발견했습니다. 또한, 우리는 스테이징에서 성공적인 테스트에도 불구하고 프로덕션에서의 문제를 경험했습니다. 이러한 실패는 상당히 비용이 많이 듭니다: 가용성에 중대한 영향을 미치고, 배포를 차단하며, 사건의 에스컬레이션이 발생할 수 있습니다. 이러한 에스컬레이션은 사건을 확인하고 원래의 버전 작성자의 개입 없이(시간대 및/또는 에스컬레이션의 중요성 때문에) 되돌리거나 수정해야 합니다. 많은 경우, 이는 오리지널 저자의 개입 없이 이루어질 수 있습니다. 우리의 증가된 배포 속도와 엄격한 가동 시간 요구 사항을 고려할 때, 데이터베이스 테스팅을 개선해야 하는 필요성은 이른바 개발 프로세스 초기(좌측 이동)에서 매우 중요합니다.
개발자의 관점에서, 프로덕션 환경으로 마이그레이션을 충분히 큰 데이터셋에서 확인하는 것은 어려울 뿐만 아니라 불가능합니다.
우리의 주요 목표는 개발자에게 신규 마이그레이션 및 다른 데이터베이스 관련 변경 사항에 대한 즉각적인 피드백을 제공하고, 이를 높은 효율(특히 인프라 비용 측면)과 보안 수준을 유지하면서 하는 것입니다.
현재 상황
개발자들은 어떠한 환경에 배포하기 전에 데이터베이스 마이그레이션을 테스트하는 것이 기대됩니다. 그러나 GitLab.com과 같은 큰 환경으로의 테스트를 수행하는 능력이 부족합니다. 개발자 데이터베이스 마이그레이션 스타일 가이드는 마이그레이션에 대한 지침을 제공하며, 우리는 코드 리뷰 및 CI 및 스테이징에서 마이그레이션을 확인하는 데 중점을 둡니다.
코드 리뷰 단계는 데이터베이스 리뷰어와 유지 관리자가 커밋된 마이그레이션을 매뉴얼으로 확인하는 것을 포함합니다. 이는 종종 문제가 되는 패턴 및 경험상의 GitLab.com 특정 동작을 인지하고 발견하는 것을 요구합니다. 마이그레이션을 Merge하기 전에 테스트를 수행하기 전에 마이그레이션을 테스트 가능한 대규모 환경은 없습니다.
CI에서의 테스트는 매우 작은 데이터베이스에서 수행됩니다. 보통은 정방향/역방향 마이그레이션 일관성을 확인하고, 잘 알려진 문제 행동(정적 코드 검사)을 감지하기 위해 RuboCop 규칙을 평가하며(올바른 파일 추가 등) 몇 가지 다른 기술적인 검사도 있습니다. 즉, 우리는 일반적으로 코드 또는 다른 단순한 오류를 발견할 수 있지만 - 가능하다면 유닛 테스트에서도 일반적으로 커버되지 않는 - 데이터 관련 오류를 드러내지 못합니다.
한 번 Merge되면 마이그레이션은 스테이징 환경에 배포됩니다. 2021년 1월 기준으로 그 데이터베이스 크기는 프로덕션 데이터베이스 크기의 5% 미만이며 최근 데이터 분포는 프로덕션 사이트와 같지 않습니다. 종종, 스테이징에서 성공한 마이그레이션이 프로덕션에서 쿼리 타임아웃이나 다른 예기치 않은 문제로 실패합니다. 스테이징에서 문제를 잡았더라도, 이는 조정하는 데 비용이 많이 들며 가능하다면 개발 주기 초기에 가능한 한 빨리 이러한 문제를 잡고 싶습니다.
오늘날, 우리는 얇은 복제된 프로덕션 데이터베이스에 대한 경험을 쌓고 이미 이를 사용하여 프로덕션 쿼리 계획, 최적화로 자동쿼리 피드백 및 제안을 개발자에 제공하고 있습니다. 이는 Slack(ChatOps 사용) 및 postgres.ai에서 사용할 수 있는 Database Lab 및 Joe을 기반으로 합니다.
비전
개발자로서:
- 나는 GitLab 코드 변경에 작업 중이며 데이터 마이그레이션을 포함하고 무거운 데이터베이스 쿼리를 변경합니다.
- 내 코드를 푸시하고, Merge Request을 만들고, 설명에 예제 쿼리를 제공합니다.
- 파이프라인이 데이터 마이그레이션을 실행하고 큰 규모의 환경(복사본)에서 쿼리를 조사합니다 (GitLab.com의 복사본).
- 파이프라인이 완료되면 Merge Request에 마이그레이션 및 내가 제공한 쿼리에 대한 자세한 피드백과 정보를 받습니다. 이는 프로덕션 데이터베이스의 전체 복사본을 기반으로 하며 매우 가까운 상태입니다(분 단위).
데이터베이스 마이그레이션에 대한 정보 수집은 실행된 복사본에서 집계된 것을 포함합니다:
- 전체 실행 시간
- 마이그레이션이 실행되는 쿼리에 대한 상세 통계 (쿼리를 정규화하고 빈도 및 실행 시간을 플롯으로 표시)
- 마이그레이션 중에 유지되는 위험한 락 (프로덕션 환경에서 블로킹 상황을 발생시킬 수 있는 락)
데이터베이스 쿼리에 대해 자동으로 수집할 수 있는 것은:
- 시각화를 통한 쿼리 계획
- 실행 시간 및 프로덕션에 대한 예측
- Joe로부터 최적화에 대한 제안
- 메모리 및 IO 통계
이러한 피드백을 받은 후:
- 나는 데이터 마이그레이션의 성능 문제를 조사할 수 있습니다.
- 수정된 내용을 푸시한 후, 위의 사이클을 반복하고 최종적으로 데이터베이스 리뷰를 위한 Merge Request을 보낼 수 있습니다. 데이터베이스 리뷰 중에 데이터베이스 리뷰어와 유지 관리자는 도입된 변경의 성능에 관한 판단을 내리기 위해 추가 생성된 정보를 모두 활용할 수 있습니다.
이 정보 수집은 보호된 안전한 환경에서 수행되어, 프로덕션 데이터에 무단 액세스가 없고 이 환경에서 안전하게 코드를 실행할 수 있도록 합니다.
의도된 이점은 다음과 같습니다:
- 좌측 이동: 개발자가 GitLab.com에서 일어날 수 있는 대규모 데이터베이스 성능을 이해하고 자체 서비스 형식으로 기대되는 변화를 이해할 수 있도록 함
- 실제 데이터(불일치 또는 예기치 않은 패턴이 있는)가 있는 프로덕션 규모 데이터셋에 대해서만 발생하는 오류를 식별
- 데이터베이스 리뷰에 관련된 세부 정보를 자동으로 제공함으로써 코드 리뷰(개발자, 리뷰어, 유지 관리자)에 참여하는 모든 사람에 대해 판단력있는 결정을 내릴 수 있도록 정보 수집 단계를 자동화
기술 및 다음 단계
이미 postgres.ai의 Database Lab을 사용 중이며, 이는 얇게 복제 기술입니다. 우리는 프로덕션 데이터와 최신 상태인 PostgreSQL 복제본을 유지하지만 실질적인 프로덕션 트래픽을 처리하지는 않습니다. 이것은 우리가 데이터를 빠르게 복사본 만들 수 있는 Database Lab을 실행합니다(초 단위로).
내부적으로, 이는 ZFS를 기반으로 하며 “얇게 복제 기술”을 구현합니다. 즉, ZFS 스냅숏을 사용하여 데이터를 복제하고 복제된 데이터를 기반으로 전체 읽기/쓰기 PostgreSQL 클러스터를 노출합니다. 이것은 얇게 복제라고 합니다. 이는 상당히 수명이 짧으며 사용이 끝나면 곧 파괴될 것입니다.
얇은 복제는 완전히 읽기/쓰기 가능합니다. 이를 통해 우리는 이 위에 마이그레이션을 실행할 수 있습니다.
Database Lab은 우리가 얇은 복제를 관리하는 데 상호작용할 수 있는 API를 제공합니다. 마이그레이션 및 쿼리 테스트를 자동화하기 위해서는 gitlab/gitlab-org
CI 파이프라인에 단계를 추가합니다. 이 단계를 위해 주어진 Merge Request에 대해 다음과 같은 단계를 수행하는 자동화를 트리거합니다:
- 이 테스트 세션을 위해 프로덕션 데이터와 함께 얇은 복제를 만듭니다.
- Merge Request에서 GitLab 코드를 가져옵니다.
- 마이그레이션을 실행하고 모든 필요한 정보를 수집합니다.
- 쿼리 테스트를 실행하고 모든 필요한 정보를 수집합니다.
- 마이그레이션 및 쿼리 테스트 결과를 Merge Request으로 다시 게시합니다.
- 얇은 복제를 파괴합니다.
단기
단기적인 초점은 보통 스키마 변경인 정기 이관을 테스트하고, 기존의 Postgres.ai의 Database Lab 인스턴스를 활용하는 것입니다.
이 프로세스를 안전하게 유지하고 규정 준수 목표를 충족시키기 위해 러너 환경은 프로덕션 환경으로 취급되어 동일하게 잠금 처리되고 모니터링되며 감사됩니다. 데이터베이스 관리자만이 CI 파이프라인 및 해당 작업 출력에 액세스할 수 있습니다. 그 외 모든 사람들은 Merge Request에 다시 올라간 결과와 통계만 볼 수 있습니다.
위에서 개요된 실행 단계를 추가하는 내부 운영용 GitLab에 안전한 CI 파이프라인을 구현합니다. 이 파이프라인의 목표는 다음 문제를 해결하는 것입니다:
어떻게든 프로덕션 데이터를 강력하게 보호하되, 모든 사람(GitLab 팀/개발자)이 프로덕션 데이터를 포함하는 thin-clone에서 임의 코드를 실행할 수 있도록 합니다.
이를 원칙적으로 취급해, 코드를 실행하는 GitLab Runner 인스턴스와 해당 콘테이너가 네트워크 수준에서 잠겨 있어 네트워크를 통해 어떤 데이터도 무단으로 외부로 유출될 수 없도록 합니다. 또한, GitLab Rails 코드(및 해당 데이터베이스 이관)를 실행하는 컨테이너 내부에서 외부와의 통신이 일어나지 않도록 합니다.
게다가, 작업 결과(코드에서 출력된 결과를 포함한)를 확인하는 능력을 내부 운영용 GitLab 파이프라인의 유지자 및 소유자 수준으로 제한하고, 원본 MR에는 간략한 요약만 제공합니다. 한 작업에서 문제나 오류가 발생하는 경우 MR을 검토할 데이터베이스 관리자는 원래 작업을 자세히 확인할 수 있습니다.
이 단계를 구현함으로써 이미 우리는 GitLab CI를 통해 thin-clone된 GitLab.com 데이터베이스에서 데이터베이스 이관을 자동으로 실행하고, 그 결과를 Merge Request 및 개발자에게 피드백을 제공할 수 있습니다. 이 피드백의 내용은 시간이 지남에 따라 발전할 것으로 예상되며, 지속적으로 추가할 수 있습니다.
우리는 이미 파이프라인에 대한 MVC-스타일 구현 및 피드백이 포함된 예제 Merge Request을 참고할 수 있습니다.
단기 목표에 대한 자세한 내용은 이 이벤트에서 확인할 수 있습니다.
중기 - 향상된 피드백, 쿼리 테스트 및 백그라운드 이관 테스트
중기적으로, 테스트 파이프라인이 Merge Request으로 돌아오는 보고의 세부 수준을 확장하고 쿼리 테스트까지 범위를 확장할 계획입니다. 이를 통해 데이터베이스 코드 리뷰와 thin-clone 기술을 활용한 경험을 살려서 GitLab 워크플로에 가까운 곳으로 다시 가져오게 됩니다. 다양한 도구(postgres.ai
, joe
, Slack, 계획 시각화 등)에 의존하는 대신, GitLab로 되돌아와 Merge Request에 직접 작업합니다.
둘째로, 백그라운드 이관 테스트도 다룰 계획입니다. 이러한 이관은 일반적으로 긴 시간 동안 실행되도록 예정된 데이터 이관입니다. 스케줄링 단계와 작업 실행 단계의 성공은 보통 데이터 분배에 많이 의존하며, 이 정상적으로 실행되는 것은 실제 프로덕션 데이터에서 이러한 이관을 실행할 때만 나타납니다. 백그라운드 이관에 대해 확신을 얻기 위해 다음과 같은 피드백을 제공할 계획입니다:
- 스케줄링 단계 - 쿼리 통계(예: 쿼리 실행 시간의 히스토그램), 작업 통계(작업 수, 총 소요 시간 등), 일괄 처리 크기.
- 실행 단계 - 예제 작업을 몇 개 실행하여 쿼리 및 실행 통계를 수집합니다.
장기 - GitLab 제품에 통합
이러한 기능을 GitLab 제품으로 추출하는 데 대한 기회가 있습니다. 예를 들어, Merge Request에 쿼리 예제를 주석으로 달고 테스트 실행에서 얻은 피드백을 Merge Request 설명과 코멘트에 사용하는 대신, 이를 Merge Request과 직접적으로 작업하는 일등 시민으로 만들 수 있습니다. 이러한 아이디어를 평가하고, 초기 단계에서 사용되는 대로 이러한 경험을 제품에 되돌려보도록 계획하고 있습니다.
토론된 대체 아이디어: 익명화
이 문제의 핵심에는 프로덕션 데이터에 잠재적으로 임의의 코드를 실행하고, 프로덕션 데이터가 충분히 보호되었는지 확인하는 우려가 있습니다. 위에서 논의된 접근 방식은 실제로 상기된 코드의 출력에 대한 액세스를 강력하게 제한함으로써 이 문제를 해결합니다.
우리가 논의한 대체적인 접근 방식은 프로덕션 데이터를 “스크럽”하고 익명화하는 것입니다. 이 데이터베이스에서 모든 민감한 데이터를 제거하고, 결과 데이터 세트를 데이터베이스 테스트에 사용하는 것입니다. 이 접근 방식을 포기한 다수의 단점이 있었기 때문에 이러한 방식을 수용하지 않기로 결정하였습니다:
- 익명화는 본질적으로 복잡합니다. 이를 “스크럽된 클론”이 실제로 공개적으로 사용해도 안전하다고 평가하는 것은 어려운 문제입니다. 서로 다른 데이터 유형은 서로 다른 익명화 기술이 필요할 수 있으며(예: JSON 필드 내의 민감한 정보 익명화), 한 번에 한 가지 속성에만 초점을 맞추는 것은 데이터 세트가 완전히 익명화되었다는 것을 보장하지 않습니다(예: 조인 공격 또는 타임스탬프를 사용하여 퍼블릭 프로필/프로젝트와 맞추어 사용자를 식별하는 등).
- 익명화에는 민감한 속성 세트를 추적하고 업데이트하는 추가 프로세스가 필요하며, 데이터베이스 스키마가 변경될 때마다 지속적인 유지보수 및 보안 검토가 필요합니다.
- 데이터를 “민감하게” 표시하는 것은 오류가 발생하기 쉬우며, 데이터 유형에 대해 잘못된 익명화 접근 방식이 사용되거나 하나의 민감한 속성이 실수로 해당되지 않았을 경우 데이터 침해가 발생할 수 있습니다.
- 스크럽은 민감한 데이터를 제거하는 것뿐만 아니라 데이터 분배도 변경시키며, 이는 이관 및 쿼리 성능에 큰 영향을 미칩니다.
- 스크럽은 데이터베이스 내용을 심각하게 변경시킵니다. 이는 많은 데이터의 업데이트로 이어지며, 다양한 데이터 저장 세부 정보의 변경으로 이어지게 되므로, 이관 및 쿼리 성능에 영향을 줍니다.