Discourse v3.0.6에서 v3.1.1로 업그레이드 시 오류 - Bookmark:Class에 정의되지 않은 메서드 `register_bookmarkable`

기존 백엔드 데이터베이스에 연결하되 복원 없이 새로 설치해 보셨나요?

그렇다면 UI에서 설정했지만 데이터베이스에 저장되지 않은 설정들이 손실될 수 있다는 뜻이겠죠. 하지만 그 외에 무엇이 백업되고 복원되는지는 잘 모르겠습니다.

bitnami 대신 실제 표준 설치를 사용하는 것을 고려해 보시는 것이 좋습니다. 당신의 문제는 “데이터베이스 마이그레이션의 버그” 때문이 아니라 bitnami 특유의 문제입니다.

Kubernetes에 표준 설치 방법이 아직 있나요?

Kubernetes에서 수동 설치가 가능한가요? 가능하다면, 그렇게 표준 설치를 수행할 수 있습니다. (저는 직접 시도해 본 적이 없어서 Kubernetes가 어떻게 작동하는지 정확히 모릅니다)

표준 설치의 장점과 비트나미 헬름 차트의 독립적이고 비공인된 성격에 대해 충분히 이해하고 있습니다. 문제의 원인이 디스코urs(Discourse) 자체에 있다는 것을 암시하려는 의도는 없었습니다. 제가 비트나미를 계속 사용하는 이유는, 비트나미 차트 관련 문제를 해결하는 데 드는 비용과 공식적으로 지원되는 설치 방식을 기반으로 한 동등한 헬름 차트를 직접 개발한 후 그 차트 관련 문제를 해결하는 데 드는 비용 사이의 계산에 달려 있기 때문입니다.

고려해 보았지만, "주류 경로(on the main path)"에 머물기 위해 기본 차트 설정을 수정하는 것을 피하고 있습니다. 그럼에도 불구하고, 마이그레이션이 성공할지 확인해 보기 위해 기존 데이터베이스를 유지한 채 디플로이먼트(Deployment) 이미지 태그만 오버라이드하여 디스코urs 서버만 v3.2.0으로 업그레이드해 보았지만, 여전히 실패했습니다.

디스코urs가 생성한 SQL 덤프 파일을 사용하여 kubectl exec로 postgres 컨테이너에 접속하여 데이터베이스를 수동으로 삭제하고 복원해 보았지만, sidebar_sections 테이블에 대한 오류로 실패했습니다. 가장 최근에는 새로운 VM을 생성하여 표준 설치 방식으로 디스코urs v3.3.0을 설치했습니다. 백업 복원을 시도했을 때 동일한 오류가 발생했습니다.

제 결론은, 프로덕션 백업 아카이브가 디스코urs 자체에 의해 생성되었음에도 불구하고, 제 프로덕션 인스턴스(v3.0.6)의 데이터베이스 구조가 디스코urs가 기대하는 것과 어딘가 달라 마이그레이션 오류를 유발하고 있다는 것입니다. 만약 이것이 사실이라면, 제 선택지에 대해 비관적으로 볼 수밖에 없습니다. 현재 제가 가진 유일한 아이디어는 백업 아카이브의 SQL 덤프 파일을 직접 수정하여 복원 과정의 db 마이그레이션 단계에서 DuplicateTable 오류를 일으키는 테이블을 제거하는 것입니다.

Bitnami의 Helm Charts를 사용하려면 그들의 지원을 사용해야 합니다.

이 글이 저처럼 이 난감한 상황에 몇 시간 동안 헤매는 일이 없도록 누군가에게 도움이 되기를 바라며, Bitnami Helm 차트(v11에서 v12)를 사용하는 환경에서 Discourse v3.0.6에서 v3.2.0으로 업그레이드하는 데 마침내 성공한 과정을 공유합니다. 위에서 언급된 내용으로 인해 추가적인 면책 조항은 필요하지 않을 수 있지만, 이 문제는 Bitnami의 Helm 차트와 그들의 커스텀 이미지 내의 버그로 인해 발생하며, 공식 Discourse 릴리스에는 영향을 미치지 않습니다.

아래 설명은 업그레이드를 진행하는 방법을 보여줍니다. "production site(프로덕션 사이트)"는 업그레이드 대상인 Discourse 사이트의 Helm 차트 릴리스를 의미하며, "migration site(마이그레이션 사이트)"는 discourse-dev 네임스페이스에서 병렬로 배포되는 임시 차트 릴리스를 가리킵니다.

프로덕션 사이트

  1. 백업 관리 패널(/admin/backups)에서 프로덕션 포럼을 읽기 전용 모드로 설정합니다.
  2. 백업 관리 패널을 사용하여 백업을 생성합니다. 백업 아카이브를 로컬로 다운로드합니다.

마이그레이션 사이트

  1. Bitnami 차트 v12.6.2(Discourse v3.2.0)의 새 인스턴스를 설치합니다. Discourse 서버 Deployment를 0으로 스케일링합니다.

    $ kubectl scale -n discourse-dev deployment discourse --replicas 0
    deployment.apps/discourse scaled
    
  2. SQL 파일 db_init.sql을 생성합니다:

    cat > /tmp/db_init.sql << EOF
    DROP DATABASE bitnami_application;
    CREATE DATABASE bitnami_application;
    GRANT ALL PRIVILEGES ON DATABASE bitnami_application TO bn_discourse;
    CREATE EXTENSION hstore;
    CREATE EXTENSION pg_trgm;
    ALTER database bitnami_application owner to bn_discourse ;
    EOF
    
  3. 데이터베이스 포드에 복사하고 실행합니다:

    $ kubectl cp -n discourse-dev db_init.sql discourse-dev-postgresql-0:/tmp/
    
    $ kubectl exec -n discourse-dev -it discourse-dev-postgresql-0 -- bash -c \
        'PGPASSWORD=$POSTGRES_PASSWORD psql -U postgres \
         < /tmp/db_init.sql'
    DROP DATABASE
    CREATE DATABASE
    GRANT
    ERROR:  extension "hstore" already exists
    ERROR:  extension "pg_trgm" already exists
    ALTER DATABASE
    
  4. 백업 아카이브를 추출하고, SQL 덤프 파일을 데이터베이스 포드에 복사한 후 적용합니다:

    $ ls
    discourse-2024-03-04-143102-v20230119094939.tar.gz
    $ tar xvf discourse-2024-03-04-143102-v20230119094939.tar.gz 
    $ gunzip dump.sql.gz 
    $ kubectl cp -n discourse-dev dump.sql discourse-dev-postgresql-0:/tmp/
    $ kubectl exec -n discourse-dev -it discourse-dev-postgresql-0 -- bash -c \
        'PGPASSWORD=$POSTGRES_PASSWORD psql -U bn_discourse \
         --dbname bitnami_application \
         < /tmp/dump.sql'
    
  5. Discourse 포드를 시작합니다.

    $ kubectl scale -n discourse-dev deployment discourse --replicas 1
    deployment.apps/discourse scaled
    
  6. 로그를 모니터링하고 업그레이드를 방해하는 테이블을 삭제합니다:

    $ kubectl logs --prefix -f -n discourse-dev -c discourse -l app.kubernetes.io/name=discourse
    $ kubectl logs --prefix -f -n discourse-dev -l app.kubernetes.io/name=postgresql
    
  7. DB 마이그레이션이 실패하는 것을 모니터링하고, 마이그레이션이 성공할 때까지 관련 테이블을 수동으로 삭제합니다:

    $ kubectl exec -n discourse-dev -it discourse-dev-postgresql-0 -- bash -c \
        'PGPASSWORD=$POSTGRES_PASSWORD psql -U bn_discourse --dbname bitnami_application -c "\
        DROP TABLE sidebar_sections; \
        DROP TABLE sidebar_urls; \
        DROP TABLE chat_threads; \
        DROP TABLE form_templates; \
        DROP TABLE category_settings; \
        DROP TABLE category_form_templates; \
        DROP TABLE theme_svg_sprites; \
        DROP TABLE user_chat_thread_memberships; \
        DROP TABLE summary_sections; \
        "'
    
  8. 업로드 폴더 백업을 복원합니다:

    $ PODNAME=$(kubectl get pod -n discourse-dev -l app.kubernetes.io/name=discourse --output=jsonpath={.items..metadata.name} | cut -f1 -d' ')
    $ kubectl cp -n discourse-dev -c discourse uploads $PODNAME:/bitnami/discourse/public/
    $ kubectl exec -n discourse-dev -c discourse $PODNAME -- bash -c 'chown -R 999:0 /bitnami/discourse/public/uploads/'
    
  9. 어떤 이유에서인지 플러그인이 자동으로 다운로드 및 설치되지 않았습니다. 이를 수동으로 수행하고 플러그인 기능을 확인합니다.

    root@discourse-54c6d6fb7c-z9285:/bitnami/discourse/plugins$ git clone https://github.com/discourse/discourse-oauth2-basic
    root@discourse-54c6d6fb7c-z9285:/bitnami/discourse/plugins$ git clone https://github.com/discourse/discourse-math
    root@discourse-54c6d6fb7c-z9285:/bitnami/discourse/plugins$ chown -R 999:0 discourse-oauth2-basic discourse-math
    
  10. 백업 관리 패널을 사용하여 새로 복원된 사이트의 백업을 생성합니다.

프로덕션 사이트

  1. 원래의 배포를 삭제하고 PV/PVC를 제거합니다.
  2. Bitnami 차트 v12.6.2(Discourse v3.2.0)의 새 인스턴스를 설치합니다.
  3. https://$BASE_URL/u/admin-login을 사용하여 이메일 링크로 로그인합니다.
  4. 백업 관리 패널을 사용하여 백업 아카이브를 업로드하고 복원합니다.