Ошибка при пересборке с использованием 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: Произошла ошибка при парсинге HTTP-запроса PUT по пути '/'

Я настроил несколько доменов для Minio

minio.example.com (как консоль доступа к Minio)
s3.example.com (как API Minio)

Также добавлено имя бакета:
bucket.s3.example.com (как API Minio)

Все домены правильно аутентифицированы, и подключение к аккаунту через Cyberduck с использованием s3.example.com или bucket.s3.example.com работает без проблем для загрузки и выгрузки файлов.

Мои настройки S3 в файле app.yml

  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. Возможно, Minio и Discourse плохо совместимы? Однако я видел, что люди успешно используют Minio. Прошу всех помочь: уверен, что эту проблему скоро удастся решить.

Следовали ли вы использованию объектного хранилища для загрузок (S3 и клоны)?

Да, я смотрел это много раз, а также изучил Базовое руководство по использованию сервера хранения MinIO, запущенного вами для вашего экземпляра Discourse

Проблема не решена. Меня беспокоит то, что подключение к учётной записи MinIO через протокол Amazon S3 в Cyberduck доступно, и, по-моему, мои настройки MinIO работают корректно.

Вы подтвердили, что ваша конфигурация MinIO в целом работает с другими механизмами, такими как клиент MinIO или ? И что вы используете правильные URL-адреса и конфигурацию для работы с MinIO?

Моя рекомендация: сначала убедитесь, что всё соответствует требованиям клиентов командной строки MinIO и s3cmd. Я никогда не слышал о клиенте «Cyberduck» (и на то есть причина: он для Windows и Mac, а я пользователь Linux), и не могу подтвердить его совместимость с MinIO и другими системами, так как на нём указано «AWS S3». Скорее всего, он разработан для полного API S3 от Amazon, а не для совместимых с S3 решений. Установите клиент MinIO (mcli) в командной строке на сервере или рядом с ним, а затем попробуйте вручную загрузить файл в свои бакеты.

Кроме того, имейте в виду, что переменная DISCOURSE_S3_BACKUP_BUCKET при использовании MinIO предназначена для отдельного бакета, а не для подпути внутри существующего бакета (насколько мне известно). Возможно, это также нарушает работу текущей настройки, поэтому в приведённом мной примере и в ссылке на мою инструкцию, которую вы предоставили, указан отдельный бакет.

У меня нет информации о конкретном запросе, который фактически был выполнен — о пути URL и т. п., который использовала система при запросе с ошибкой BadRequest. Похоже, это связано с тем, что логирование ведётся только на уровне INFO. Есть ли способ включить логирование уровня debug во время процесса rake, @pfaffman (или другие, кто лучше знаком с стороной Discourse)?

ТАКЖЕ убедитесь, что в конфигурации Discourse передан параметр DISCOURSE_S3_INSTALL_CORS_RULE: false. Если приложение-реконструктор/пекарь попытается применить правила CORS, это приведёт к ошибке.

Я создал новый бакет с помощью mcli и вручную отправил в него файл

Я вижу отправленный файл в бакете. Значит ли это, что я установил MinIO правильно? Я установил MinIO с помощью Docker Compose, используя файл docker-compose.yml:


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:

Затем я зашёл в веб-консоль, создал два новых бакета и установил политику доступа для объектного хранилища как публичную.

Я использую Nginx Proxy Manager для перенаправления minio.example.com на порт 9001, а s3.example.com и bucket-name.example.com — на порт 9000.

DISCOURSE_S3_BACKUP_BUCKET: Я пробовал использовать отдельный бакет и настроить перенаправление доменного имени на порт 9000 для этого бакета, но это не работает.

Какие порты перенаправляются? 80/443, чтобы работали HTTP/HTTPS? Этого достаточно. Вам никогда не нужно настраивать порт 9000 отдельно. У каждого отдельного бакета будет тот же конечный адрес, что и у s3.example.com — это не отдельная сущность, поэтому ваша конфигурация НЕВЕРНА. Не забывайте также, что в терминологии MinIO, если вы используете аутентификацию по пути, вы получите s3.example.com/BUCKETNAME, а если используете аутентификацию по DNS (как и следует), то BUCKET.s3.example.com для конечных адресов URL, которые должны приниматься на стороне Nginx и перенаправляться на внутренний порт 9000. Вам не нужно настраивать это на своей стороне; это должно быть настроено на стороне MinIO.

Клиент MinIO поддерживает как настройку в стиле path, так и в стиле dns. Насколько мне известно, Discourse использует механизм на основе URL для идентификации бакетов, а не настройку в стиле path (поправьте меня, разработчики Discourse, если я ошибаюсь). Следовательно, конфигурация, которую вы настраиваете по умолчанию, неверна.

Теперь о том, что мой MinIO не работает в Docker, но для соответствия требованиям Discourse вам необходимо использовать настройку в стиле DNS, то есть добавить переменную окружения MINIO_DOMAIN=BASEDOMAINHERE, чтобы стиль DNS, который хочет использовать Discourse, работал. В вашем примере это будет MINIO_DOMAIN=s3.example.com, а затем ваш Nginx должен быть настроен так, чтобы передавать заголовок Host на бэкенд на порт 9000 или туда, где работают основные компоненты сервера (не консольные). Затем вам нужно убедиться, что Nginx принимает запросы для *.s3.example.com и правильно перенаправляет их в контейнер MinIO. Это часть настройки федерации MinIO, но даже для одноузловых экземпляров с несколькими именами бакетов на базовом URL вам необходимо убедиться, что всё правильно настроено, если вы хотите, чтобы это работало с Discourse.

К сожалению, именно здесь вам придется углубиться в конфигурацию MinIO. И одно из требований, которое я указываю в документе, заключается в том, что у вас должен быть полностью функциональный и правильно настроенный экземпляр MinIO, что выходит за рамки сайта Discourse. Я считаю, что ваш MinIO не настроен должным образом для разрешения имен бакетов в стиле DNS, как это делает AWS S3 (например, bucket.s3.example.com), и поэтому не работает.

Обратите внимание: я запускаю экземпляр Discourse для проекта Lubuntu (lubuntu.me) (вариант Ubuntu, использующий LXQt) с использованием MinIO с разрешением имен бакетов в стиле DNS, чтобы обеспечить корректную работу с Discourse; в противном случае запрос к BUCKET.basedomain.example.com будет неудачным.

Интересный факт: я даже указываю, что ваш MinIO должен быть правильно настроен для путей в стиле DNS. Если при настройке MinIO вы не указали MINIO_DOMAIN, он не будет поддерживать пути в стиле DNS. А для Discourse это необходимо, как указано в пункте 3 моего раздела с оговорками:

Привет, бро. Установка переменной MINIO_DOMAIN устранила вышеуказанные ошибки, но появились новые:

Aws::S3::Errors::MalformedXML: Предоставленный вами XML не является корректно сформированным или не прошел проверку против нашей опубликованной схемы.

Мне кажется, я почти добился успеха, так как Discourse может корректно обращаться к моему MinIO. Я попробовал удалить все бакеты MinIO и пересобрать Discourse, но получил сообщение, что указанный бакет не существует.

Согласно этой статье Discover AWS Official Knowledge Center Articles | AWS re:Post, я думаю, что ошибка вызвана правами доступа к бакету. В руководстве Настройка загрузки файлов и изображений в S3 указано, что, похоже, мне нужно добавить политику бакета (Bucket Policy):

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

Однако MinIO не поддерживает ACL и выдает ошибку: unsupported action ‘s3:PutObjectAcl’.

Возможно, мне стоит использовать более старую версию MinIO, что может упростить задачу :sweat_smile:

Проблема решается тем, что переменные объектного хранилища не добавляются через app.yml. В противном случае возникнет ошибка MalformedXML — просто добавьте параметр s3 в настройки. При установке Minio необходимо добавить переменную MINIO_DOMAIN (я использую развёртывание на одном узле).

Спасибо @teward за помощь.

Теперь я могу загружать файлы и выполнять резервное копирование с помощью Minio.

Нет, MinIO не поддерживает PutObjectAcl. Он поддерживает разрешения на уровне бакета, но не ACL на уровне объекта в таком виде API.

MinIO НЕ поддерживает полный API AWS. См. https://docs.min.io/minio/baremetal/security/minio-identity-management/policy-based-access-control.html для полного списка поддерживаемых API.

Переменная MINIO_DOMAIN должна быть добавлена для работы бакетов в формате DNS, именно поэтому происходит некорректный PUT. По мере дальнейшего анализа мы видим ошибки в XML, связанные с тем, что не соответствует разрешённым схемам. Убедитесь, что вы НИКОГДА не применяете политики, содержащие переменные, которые не поддерживаются в наборе, фактически поддерживаемом MinIO.

Помните: совместимость с S3 НЕ означает 100% соответствие всем поддерживаемым переменным, конечным точкам и значениям API AWS S3.