Коротко. ActiveScale предоставляет S3-совместимый REST API (S3 Standard) и холодный класс, совместимый с S3 Glacier. Поддерживаются бакеты, объекты, multipart, версионирование, Object Lock, lifecycle, квоты, репликация, IAM. Но «совместимость» не значит «любой AWS-клиент заработает без проверки»: подпись, кодирование ключей, query-параметры и адресацию надо тестировать.
1. Что есть
| Возможность | Поддержка |
|---|---|
| Бакеты/объекты, PUT/GET/HEAD/DELETE | да |
| Multipart upload | да (макс. объект до 50 TB на Z200) |
| Листинг, копирование | да |
| Presigned URL | да (с оговорками по времени) |
| Версионирование | да |
| Object Lock (WORM) | да |
| Lifecycle (переход в Cold, expiration) | да |
| Квоты аккаунтов | да |
| Bucket replication | да |
| IAM (пользователи, группы, политики) | да |
| Checksums | MD5; с 7.3 — CRC32/CRC32C/SHA-1/SHA-256 |
| NFS v3 | да, отдельный сценарий |
Про checksums: до 7.3 единственной суммой был MD5 (Content-MD5). С 7.3 появились
x-amz-checksum-crc32, -crc32c, -sha1, -sha256 — на PutObject, GetObject, CopyObject и
multipart. Современные SDK включают CRC32 по умолчанию, поэтому при клиенте «новом», а хранилище
старом это первое, что стоит проверить.
2. Endpoint и стиль адресации
- S3-фронт — на порту 443 ноды (vhost-стиль).
- Нужен S3-домен (FQDN), например
s3.<system>.<domain>; для IAM — отдельный IAM-домен. - Path-style (
https://host/<bucket>/<key>) работает всегда. - Virtual-hosted (
https://<bucket>.s3.<domain>/<key>) требует wildcard-DNS (*.s3.<domain>) и сертификат с SAN на wildcard.
Типовые ошибки:
:11000— это внутренний DSS-порт, не S3.s3.activescale.com— UI-обёртка, не endpoint.- Самоподписанный сертификат
CN=scalerdбез SAN — клиент валится на проверке имени хоста.
За портом 443 стоит прокси, а S3-движок слушает только loopback. Поэтому Server:
Quantum-ActiveScale ставит именно движок: по нему видно, что ответил S3, а не веб-сервер; по
x-amz-id-2 понятно, какая нода обслужила запрос. Незнакомый Host даёт редирект на дефолтный
домен — для клиента «307 непонятно куда», а причина в том, что имя хоста не описано в модели.
Подробнее: S3-домен, сертификат и DNS.
3. Подпись (SigV4) и не-ASCII
- Актуальная подпись — AWS Signature Version 4; окно времени ±15 минут.
- Не-ASCII ключи и значения метаданных должны кодироваться по спеке (процентное кодирование, верхний регистр hex).
- Некоторые клиенты (например, Ceph RGW cloud-transition) исторически спотыкаются на не-ASCII; проверяйте форму запроса и версию клиента.
Механика ошибки на не-ASCII обманчива. Клиент подписывает канонический запрос, где значение
метаданных — сырые байты UTF-8; шлюз при проверке пересобирает его и заменяет не-ASCII на ?.
Хэши не сходятся → 403 SignatureDoesNotMatch, хотя ключи верные и время в норме. Со стороны
клиента это выглядит как «неверный секрет», и дальше идёт охота за несуществующей проблемой.
Признак: подпись ломается только на объектах с не-ASCII в ключе или в x-amz-meta-*, ASCII в
том же бакете работает. Лечится на стороне клиента — процентным кодированием до подписи. Прокси,
который «нормализует» запрос, тоже работает, но это обход: лишняя точка отказа и своя эксплуатация.
Второй класс: 501 Not Implemented на неизвестный query-параметр. Шлюз отвечает 501 на любой
параметр вне своего списка — даже на безобидный ?foo=bar, и клиент трактует это как «операция не
поддерживается». Штатный путь — добавить параметр в список разрешённых через поддержку; в 7.0 так
поступили с x-id, который шлют некоторые AWS SDK.
Подробнее: S3 501 на неизвестный query-параметр.
4. IAM и resource policy
- Ключи без resource policy →
AccessDeniedдаже на листинг. - Resource policy назначается на бакет (PutResourcePolicy).
- IAM-домен обязателен для IAM-вызовов; по IP IAM не работает.
Типовой сценарий первого подключения: ключи созданы, aws s3 ls отвечает AccessDenied, инженер
идёт проверять ключи. Проверять надо политику на бакете: валидная пара ключей тут сама по себе не
даёт доступа ни к чему.
С 7.1 в IAM есть условия и переменные политик: ограничение по IP, времени, тиру Glacier, длительности Object Lock; переменные-подстановки (например, префикс = имя пользователя). С 7.2 — MFA (TOTP) для администраторов в UI, CLI и REST.
Деталь из практики: IAM-пути с [ и \ до 7.2 ломали вызовы, а на scaled-out нодах IAM работал
некорректно. Разное поведение на разных нодах — повод сверить версию.
Подробнее: IAM и resource policy.
5. Таблица операций: что проверять при подключении клиента
Не «прогнать всё», а пройти по операциям, которые клиент реально использует, зная на каждой, что именно ломается.
| Операция | Что проверять | Частая причина отказа |
|---|---|---|
PutObject |
200 и корректный ETag; заголовок x-amz-storage-class если нужен Cold |
несовпадение контрольной суммы (x-amz-checksum-* на старой сборке), 403 при не-ASCII метаданных |
GetObject |
байты совпадают с исходником, Content-Length, диапазонный запрос Range |
объект в GLACIER без restore; неверный ключ после процентного кодирования |
HeadObject |
200, размер, ETag, StorageClass |
лишний query-параметр → 501; объект в Cold, но HEAD должен работать всегда |
ListObjectsV2 |
число объектов и NextContinuationToken на большом бакете |
клиент ждёт ListObjects v1; лимит max-keys; отсутствие прав на листинг |
| Multipart upload | CreateMultipartUpload → UploadPart → Complete; объект >100 МБ |
таймаут на большом part; x-amz-storage-class в составном запросе (ломалось до 7.2); part нулевого размера |
CopyObject |
копия в тот же и другой бакет; метаданные перенеслись | копирование объекта из Cold требует restore; права на чтение источника и запись цели |
DeleteObjects (batch) |
удаление пачки, разбор ответа с ошибками по каждому ключу | клиент считает операцию атомарной; при версионировании остаются delete-маркеры |
| Presigned URL | ссылка работает в пределах срока, не «в будущем» | время в будущем блокировалось до 7.0; слишком длинный TTL; расхождение часов |
Важно не «работает/не работает», а поведение на границах: PutObject на 1 КБ пройдёт почти
всегда, а ломается на объекте в несколько гигабайт, на не-ASCII ключе или составной загрузке.
Поэтому в проверку берут самый крупный и самый «неудобный» объект из реального набора.
HeadObject — самая полезная операция для диагностики: не тянет тело и не требует restore. Если
HEAD даёт 200 с верным размером и классом, а GET — нет, проблема в состоянии объекта (Cold) или
правах, но не в связности и не в подписи.
6. Типовые клиенты и на что они спотыкаются
Классы клиентов ведут себя по-разному, и знать типовые точки отказа полезнее, чем названия конкретных продуктов.
Бэкап-системы. Пишут много, крупными объектами, часто multipart, проверяют контрольные суммы.
Три точки: (1) checksum-заголовки, которых нет на старой сборке; (2) ожидание атомарного
DeleteObjects; (3) «индексный» объект, который перезаписывается поверх — при версионировании
каждая перезапись оставляет версию, и бакет растёт быстрее, чем клиент считает. Последнее — самая
частая причина «занято втрое больше, чем данных».
Аналитические движки. Читают выборочно и много: ListObjectsV2 с префиксами, Range,
параллельные GET. Спотыкаются на (1) пагинации больших бакетов и max-keys; (2) range к объектам в
Cold (нужен ranged restore, с 7.1); (3) HEAD «на всякий случай» → 501 из-за своего параметра.
SDK и прикладной код. Самая пёстрая группа: (1) region — значение условное, но без него клиент
падает на конфигурации; (2) aws-chunked и потоковая подпись принимаются сборками не одинаково;
(3) автовключение CRC32 в новых SDK; (4) retry: клиент ретраит 403 и 501, хотя это не временные
ошибки, и создаёт шторм запросов.
Системы lifecycle и тиринга. Добавляют свои query-параметры и заголовки — именно они чаще
ловят 501 на неизвестный параметр и 403 на не-ASCII, перенося имя исходного объекта в
x-amz-meta-*.
Общее правило: выясните, какие операции клиент реально делает, а не какие умеет — debug-логи показывают это за пять минут.
7. Как воспроизвести проблему минимально
Задача — свести «ваш S3 не работает» к одному запросу, воспроизводимому с любой машины: сначала убедиться, что endpoint отвечает как S3, потом что подпись проходит на простом запросе, и только потом добавлять «подозрительные» элементы по одному.
# 1. Кто отвечает на порту: должен быть S3-движок, а не веб-сервер
curl -skI https://s3.<system>.<domain>/ | head -5
# ожидаем Server: Quantum-ActiveScale и x-amz-* заголовки
# 2. Сертификат: имя хоста, SAN, срок
openssl s_client -connect s3.<system>.<domain>:443 -servername s3.<system>.<domain> </dev/null 2>/dev/null \
| openssl x509 -noout -subject -dates -ext subjectAltName
Дальше — минимальный подписанный запрос. Проще всего через CLI, потому что он сам считает подпись:
aws --endpoint-url https://s3.<system>.<domain> --region us-east-1 \
s3api put-object --bucket <BUCKET> --key probe.txt --body /etc/hostname
aws --endpoint-url https://s3.<system>.<domain> --region us-east-1 \
s3api head-object --bucket <BUCKET> --key probe.txt
Если это работает, а «настоящий» клиент — нет, ищут разницу: --no-verify-ssl (не как решение, а
как проверку гипотезы про сертификат), затем --debug и список подписываемых заголовков.
Расхождение почти всегда там.
Без CLI подпись собирают вручную — тогда проверяют три вещи: SignedHeaders совпадает с фактически
отправленными заголовками; x-amz-content-sha256 соответствует телу (или UNSIGNED-PAYLOAD);
x-amz-date не уехал от ноды больше чем на 15 минут.
Что смотреть в ответе, по коду:
| Код | Что это значит | Куда смотреть |
|---|---|---|
403 SignatureDoesNotMatch |
подпись не сошлась | не-ASCII в подписанном заголовке, расхождение SignedHeaders, часы |
403 AccessDenied |
подпись верна, прав нет | resource policy бакета, права ключа, x-amz-* не в подписи |
404 NoSuchBucket / NoSuchKey |
не тот endpoint или не тот ключ | path-style vs virtual-hosted, процентное кодирование |
400 InvalidArgument |
параметр или значение не приняты | x-amz-storage-class, checksum-заголовок, form-параметры |
501 Not Implemented |
шлюз не знает query-параметр | список разрешённых параметров, версия клиента |
507 Storage is full |
раскладка не влезает | политика w+s ≤ N, число блоксторов (не свободное место) |
307 на другой хост |
незнакомый Host |
S3-домен в модели, DNS, стиль адресации |
Два правила экономят больше всего времени: не менять больше одной переменной за попытку и
сохранять фактический запрос, а не его описание — разница между «я отправил UTF-8» и «в
каноническом запросе восемь знаков ?» и есть весь баг.
8. Границы
- S3-совместимость не гарантирует 100% поведения AWS: проверяйте конкретные операции.
- Часть query-параметров может быть неизвестна шлюзу (
501); штатный путь — whitelist через поддержку/обновление. - Поведение presigned URL и Object Lock зависит от версии — сверяйтесь с release notes.
- NFS v3 — отдельный сценарий; на scaled-out нодах это не эквивалент S3.