Minio를 오브젝트 스토어로 사용하면서 재구축 시 오류 발생

minio를 객체 스토어로 사용할 때 디스플레이 재구축

I, [2022-09-01T00:37:48.192311 #1]  INFO -- : > cd /var/www/discourse && sudo -E -u discourse bundle exec rake s3:upload_assets
rake aborted!
Aws::S3::Errors::BadRequest: An error occurred when parsing the HTTP request PUT at '/'

minio에 여러 도메인을 설정했습니다

minio.example.com (minio 액세스 콘솔로 사용)
s3.example.com (minio API로 사용)

또한 버킷 이름도 추가했습니다.
bucket.s3.example.com (minio API로 사용)

모든 도메인은 올바르게 인증되어 있으며, s3.example.com 또는 bucket.s3.example.com을 사용하여 Cyberduck으로 계정에 연결하면 파일 업로드와 다운로드가 가능합니다.

app.yml의 S3 설정

  DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: anything
  discourse_s3_endpoint: https://s3.example.com
  DISCOURSE_S3_ACCESS_KEY_ID: *****
  DISCOURSE_S3_SECRET_ACCESS_KEY: ********
  #Discourse_s3_cdn_url: 
  DISCOURSE_S3_BUCKET: bucket
  DISCOURSE_S3_BACKUP_BUCKET: bucket/backups
  DISCOURSE_BACKUP_LOCATION: S3

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - sudo -E -u discourse bundle exec rake s3:upload_assets

관련 이슈를 검색해 보았지만 해결하지 못했습니다. vultr object storage를 사용하면 잘 작동합니다. 즉, minio와 discourse가 잘 함께 작동하지 않는 것일까요? 하지만 minio를 성공적으로 사용하는 사람들을 본 적이 있습니다. 모두에게 질문을 던져 봅니다. 이 문제가 곧 해결될 것이라고 믿습니다.

오브젝트 스토리지(S3 및 클론)를 업로드에 사용하는 방법을 따랐나요?

네, 여러 번 시청했고, 자신이 운영 중인 Discourse 인스턴스를 위해 실행 중인 MinIO 스토리지 서버 사용 기본 가이드도 함께 확인했습니다.

문제는 아직 해결되지 않았는데, Cyberduck의 Amazon S3 전송 프로토콜을 이용한 minio 계정 연결은 정상적으로 가능하고 minio 설정도 문제없이 작동하는 것으로 보이는데 이것이 궁금합니다.

MinIO 설정이 MinIO 클라이언트나 ?와 같은 다른 메커니즘에서 일반적으로 정상 작동하는지 확인하셨나요? 그리고 MinIO에 대해 적절한 URL과 설정을 사용하고 계신가요?

제 제안은 먼저 MinIO 및 s3cmd 명령줄 클라이언트와 모든 것이 호환되는지 확인하는 것입니다. 저는 이 “Cyberduck” 클라이언트에 대해 들어본 적이 없습니다 (좋은 이유: Windows와 Mac용이고, 저는 Linux 사용자입니다). 이 클라이언트에 "AWS S3"라고 표시되어 아마존의 전체 S3 API를 위해 설계되었을 가능성이 높고, S3 호환/양립성 항목에는 적합하지 않을 수 있으므로 MinIO 호환성을 확인해 드릴 수 없습니다. 작업하려는 서버 근처의 명령줄에 MinIO 클라이언트(mcli)를 설치한 후, 버킷에 파일을 수동으로 업로드해 보세요.

또한, MinIO의 경우 DISCOURSE_S3_BACKUP_BUCKET은 기존 버킷 내의 서브패스가 아니라 독립된 버킷으로 설계되어 있음을 명심하세요 (제 지식 범위 내에서). 현재 설정에서 이것이 문제를 일으킬 수도 있으며, 제가 작성한 예시와 귀하가 제공한 제 “How to” 링크에서도 이를 별도의 버킷으로 설정해 둔 이유입니다.

여기서 제가 가지고 있지 않은 정보는 실제로 요청이 이루어졌을 때 시스템이 BadRequest와 함께 조회에 사용한 URL 경로 등 구체적인 요청 정보입니다. 이는 INFO 레벨 로깅만 이루어지고 있기 때문으로 보입니다. rake 프로세스 중에 디버그 레벨 로깅을 얻을 수 있는 방법이 없나요 @pfaffman (또는 Discourse 쪽에 더 익숙한 다른 분들)?

그리고, Discourse 설정에 DISCOURSE_S3_INSTALL_CORS_RULE: false도 반드시 전달하세요. 앱 리빌더/베이커가 CORS 규칙을 시도하면 오류 메시지가 발생할 수 있습니다.

mcli를 사용하여 새 버킷을 생성하고 파일을 해당 버킷에 수동으로 전송했습니다

버킷에 전송된 파일이 보입니다. docker compose와 제 docker-compose.yml 파일을 사용하여 minio를 설치했는데, 이는 제가 올바른 단계로 minio를 설치했다는 뜻인가요?


version: '3'

services:
  minio:
    image: minio/minio:latest
    container_name: minio
    restart: always
    ports:
      - "9000:9000"
      - "9001:9001"
    
    volumes:
      - ./:/data

    environment:
      MINIO_ROOT_USER: ***** 
      MINIO_ROOT_PASSWORD: *****
      MINIO_SERVER_URL: https://s3.example.com
      MINIO_BROWSER_REDIRECT_URL: https://minio.example.com/

    command: server --console-address ":9001" /data

volumes:
  minio:

이후 웹 콘솔에 접속하여 두 개의 새 버킷을 생성하고, 오브젝트 스토어의 액세스 정책을 공개(public)로 설정했습니다.

Nginx proxy manager를 사용하여 minio.example.com을 포트 9001으로, s3.example.com과 bucket-name.example.com을 포트 9000으로 포워딩했습니다.

DISCOURSE_S3_BACKUP_BUCKET: 별도의 버킷을 사용하고 해당 버킷에 대해 포트 9000으로 도메인 이름 포워딩을 설정해 보았지만 작동하지 않습니다.

어떤 포트를 포워딩하라는 겁니까? http/https가 작동하도록 80/443인가요? 그것만 있으면 충분합니다. 포트 9000을 별도의 포트에 설정할 필요는 절대 없습니다. 별도의 버킷은 s3.example.com과 동일한 엔드포인트를 가지며, 이는 별개의 것이 아니므로 해당 구성을 잘못 수행하고 있습니다. 또한 MinIO 용어로, 경로 인증(path authentication)을 사용하는 경우 s3.example.com/BUCKETNAME이 되며, DNS 인증을 사용하는 경우(사용해야 하는 방식) URL 엔드포인트로는 BUCKET.s3.example.com이 됩니다. nginx 측에서 수신하고 내부 포트 9000으로 포워딩해야 하는 URL 엔드포인트입니다. 단, 이는 사용자의 클라이언트 측에서 설정할 것이 아니라 MinIO 측에서 설정해야 합니다.

MinIO 클라이언트는 path와 dns 스타일의 설정을 모두 지원합니다. 제 지식 범위 내에서 Discourse는 경로 스타일 설정이 아닌 URL 기반 메커니즘을 버킷 식별에 사용합니다(Discourse 개발진, 정정해 주세요). 따라서 현재 설정하고 있는 ‘기본’ 동작은 올바르지 않습니다.

현재 제 MinIO는 Docker화되어 있지 않지만, Discourse와 호환되려면 DNS 스타일 패싱을 사용해야 합니다. 즉, MINIO_DOMAIN=BASEDOMAINHERE 환경 변수를 추가하여 Discourse가 사용하려는 DNS 스타일 패싱이 작동하도록 해야 합니다. 예시에서는 MINIO_DOMAIN=s3.example.com이 될 것이며, 이후 NGINX는 Host 헤더를 포트 9000 또는 기본 비콘솔 서버 구성 요소가 실행되는 곳으로 백엔드에 전달하도록 구성해야 합니다. 또한 NGINX가 *.s3.example.com을 수신하고 MinIO 컨테이너로 올바르게 포워딩하도록 확인해야 합니다. 이는 MinIO Federation 설정의 일부이지만, 기본 URL에 여러 버킷 이름이 있는 단일 노드 인스턴스의 경우에도 Discourse와 함께 작동하려면 올바르게 설정되어 있는지 확인해야 합니다.

불행히도, 여기부터는 MinIO 구성에 대해 자세히 파고들어야 합니다. 그리고 제가 문서에서 명시하는 요건 중 하나는 Discourse 사이트의 범위를 벗어난 완전히 기능적이고 올바르게 구성된 MinIO 인스턴스를 갖추어야 한다는 것입니다. MinIO가 AWS S3처럼(bucket.s3.example.com 등) DNS 스타일 버킷 해석에 올바르게 구성되지 않았다고 생각하며, 이로 인해 기능이 작동하지 않는 것입니다.

참고로, 저는 Lubuntu 프로젝트(lubuntu.me, LXQt를 사용하는 Ubuntu 변형)의 Discourse 인스턴스를 MinIO와 함께 운영하며, Discourse와 올바르게 작동하도록 DNS 스타일 버킷 URL 해석을 사용하고 있습니다. 그렇지 않으면 BUCKET.basedomain.example.com에 대한 요청이 실패합니다.

흥미로운 사실은, MinIO를 DNS 스타일 패스에 맞게 올바르게 구성해야 한다고 명시해 두었는데, MinIO 설정 시 MINIO_DOMAIN을 포함하지 않았다면 DNS 스타일 패싱을 수행하지 않는다는 점입니다. Discourse를 위해 여기서는 이것이 필요하며, 제가 작성한 주의사항 섹션의 3번 항목에 다음과 같이 적혀 있습니다:

형, MINIO_DOMAIN을 설정하면 위의 오류는 사라지지만 새로운 오류가 발생해요.

Aws::S3::Errors::MalformedXML: The XML you provided was not well-formed or did not validate against our published schema.

discourse가 제 minio에 올바르게 접근할 수 있는 것 같아서 성공이 가까워진 것 같은 느낌이에요. 모든 minio 버킷을 삭제하고 discourse를 다시 빌드해 보니, 지정된 버킷이 존재하지 않는다는 메시지가 뜨더라고요.

이 기사(Discover AWS Official Knowledge Center Articles | AWS re:Post)를 통해 이 오류가 버킷 권한 때문에 발생하는 것 같다고 생각했어요. 튜토리얼 Setting up file and image uploads to S3를 살펴보니 Bucket Policy를 추가해야 하는 것 같더라고요.


               "s3:PutObject",
               "s3:PutObjectAcl",
               "s3:PutObjectVersionAcl",
               ....

하지만 minio는 Acl을 지원하지 않아서 's3:PutObjectAcl’은 지원되지 않는 동작이라는 알림이 나와요.

아마 minio의 이전 버전을 사용해야 할 것 같아요. 그러면 일이 좀 더 수월해질 수도 있겠네요 :sweat_smile:

이 문제는 app.yml을 통해 객체 저장소 변수를 추가하지 않음으로써 해결됩니다. 그렇지 않으면 MalformedXML 오류가 발생합니다. 설정에 s3 매개변수를 추가하기만 하면 됩니다. minio 설치 시 MINIO_DOMAIN 변수를 추가해야 합니다(저는 단일 노드 배포를 사용 중입니다).

도움 주셔서 감사합니다 @teward

이제 minio를 사용하여 파일을 업로드하고 백업할 수 있습니다.

아니요, MinIO는 PutObjectAcl을 지원하지 않습니다. 버킷 수준 권한은 지원하지만, 해당 API 형태로 객체 수준의 ACL은 지원하지 않습니다.

MinIO는 AWS API 전체를 지원하지 않습니다. 지원되는 전체 API 세트는 https://docs.minio/minio/baremetal/security/minio-identity-management/policy-based-access-control.html을 참조하세요.

DNS 스타일 버킷을 사용하려면 MINIO_DOMAIN을 추가해야 하며, 이것이 잘못된 PUT 요청이 발생하는 이유입니다. 더 진행하면 스키마에서 허용되는 것과 비교했을 때 XML에 실패가 나타나는 것을 볼 수 있습니다. MinIO가 실제로 지원하는 지원 세트에 포함된 변수가 아닌 변수가 포함된 정책을 절대 적용하지 않도록 주의하세요.

기억해 두세요: S3 호환이라는 것은 모든 지원되는 AWS S3 API 변수/엔드포인트/값에 대해 100% 일치한다는 뜻이 아닙니다.