Проект ЦИТадель
Слово «облако» затёрто маркетингом до полной прозрачности: им называют всё — от аренды виртуалки до почты в браузере. Эта статья — теоретическая: что такое облако технически, из чего оно собрано, что означают модели IaaS/PaaS/SaaS и границы ответственности, какие свойства облака действительно меняют архитектуру систем, а какие — только счёт. Парная статья «Облака на практике» посвящена выбору, миграции и экономике. Здесь нас интересуют устройство и принципы, переживающие смену поколений провайдеров; конкретные вендоры упоминаются только как иллюстрации.
В определении NIST у облака пять существенных характеристик: самообслуживание по требованию, доступ по сети, общий пул ресурсов, быстрая эластичность и измеряемый сервис. API — обычный способ реализовать самообслуживание и программируемость, но само определение им не ограничивается. Каждое слово несёт вес: ресурсы объединены и динамически распределяются между потребителями; их можно получить без переговоров с сотрудником провайдера; объём можно быстро менять; потребление измеряется. Тезис статьи, из которого выводится остальное: облако — это инфраструктура, ставшая программируемой. Не просто «чужие серверы», а ресурсы, доступные как сервис.
Под API-фасадом — три программных слоя поверх обычных дата-центров:
Плюс четвёртый, невидимый слой — оркестрация самого облака: планировщики, размещающие ВМ по серверам, учёт потребления и управляющая API-плоскость поверх всего. Гиперскейлер — это не только много оборудования, но и программная система, которая им управляет. Само оборудование тоже бывает специализированным: провайдеры проектируют собственные сетевые адаптеры, ускорители и серверные платформы.
У крупных провайдеров распространена двухуровневая схема «регион — зона», но определения, число зон и набор зональных сервисов не стандартизованы:
На языке главы 1 курса о распределённых системах: зона обычно служит доменом локального отказа, регион — доменом более крупного. Отсюда двухтактное правило проектирования: для высокой доступности систему размещают в нескольких зонах, если выбранные сервисы и приложение это поддерживают; для защиты от региональной аварии проектируют второй регион и процедуру переключения. Одного размещения ресурсов недостаточно: нужно проверить репликацию данных, кворумы, зависимости управляющей плоскости и поведение клиентов. Три зоны удобны многим кворумным системам, но это не универсальное свойство облака и не требование к каждой архитектуре. Подробнее об этом — в статье «Непрерывность и восстановление».
Классическая триада — это не «три продукта», а уровни разделения труда между вами и провайдером:
Полезный критерий выбора уровня — вопрос из статьи о Kubernetes, работающий и здесь: что вы готовы эксплуатировать сами и зачем? Каждая ступень вниз по лестнице (SaaS → PaaS → IaaS) покупает контроль ценой эксплуатационной нагрузки; движение без ответа на «зачем» — в обе стороны ошибка.
Одна из самых дорогих ошибок облачной эпохи — фраза «это в облаке, значит, безопасно и надёжно». Провайдеры используют модель разделённой ответственности: провайдер отвечает за нижние слои облака — физическую инфраструктуру и работу предоставляемых сервисов, — а клиент за свои данные, доступы и ключи, конфигурацию, патчи собственных ОС на IaaS и архитектуру приложения. Точная граница меняется от IaaS к SaaS и описывается документацией сервиса. Распространённый жанр инцидента — открытое всему миру объектное хранилище или утёкший ключ с избыточными правами: это ошибки на клиентской стороне границы. SLA также не делает отдельную ВМ или зону безотказной и может требовать определённой конфигурации. Облако снимает часть нижних слоёв ответственности, но не ответственность за данные и работу системы в целом.
Без разговора о деньгах теория неполна. Классический аргумент «CAPEX → OPEX» — не покупать оборудование, а платить за сервис — верен, но главный экономический смысл облака тоньше: эластичность позволяет оплачивать пик только во время пика. При неровной нагрузке собственное оборудование, купленное под максимум, часть времени простаивает, а облачные ресурсы можно выделять по кривой нагрузки. При стабильной круглосуточной загрузке своё оборудование или колокация иногда дешевле, но сравнивать нужно полную стоимость: оборудование, помещения, электроэнергию, сеть, персонал, резервирование и риск нехватки мощности. Между полюсами — скидки за обязательство по сроку или объёму и спот-мощности, которые провайдер может отозвать и потому годятся только для прерываемой работы. При переезде часто недооценивают исходящий и межзонный трафик, запросы к сервисам и надбавку за managed-возможности; правила бесплатного входящего трафика и тарификации выхода зависят от провайдера и маршрута. Управление этими затратами выросло в отдельную практику FinOps, которую разбирает практическая статья.
Если бы облако было только арендой серверов, статья бы здесь закончилась. Но программируемость инфраструктуры меняет способ строить системы:
Облако часто выигрывает при переменной и непредсказуемой нагрузке, необходимости быстро начать работу, потребности в managed-сервисах без собственной большой команды эксплуатации и географическом размахе. Своё оборудование или колокация могут выиграть при стабильной высокой загрузке, особых требованиях к аппаратуре и сети или наличии команды, для которой такая эксплуатация — профильная работа. Регуляторные требования не дают универсального ответа: они могут исключить часть регионов и сервисов, потребовать локального размещения либо, наоборот, сделать сертифицированный облачный сервис удобнее собственного. Возможен и гибрид, если для его частей есть техническое и экономическое обоснование. Правило нашего раздела применимо дословно: каждое размещение должно уметь назвать причину своего существования; «все уходят в облако» и «все возвращаются из облака» — одинаково слабые причины.
Объектное хранилище можно исследовать локально на SeaweedFS — распределённом хранилище с S3-совместимым API. Команда ниже запускает его упрощённый однодисковый режим mini: все службы и данные находятся в одном контейнере, поэтому этот опыт не даёт отказоустойчивости. Сначала установите AWS CLI, затем выполните:
$ docker volume create citadel-seaweed-data
$ docker run -d --name citadel-seaweed \
-p 127.0.0.1:8333:8333 \
-e AWS_ACCESS_KEY_ID=citadel-lab \
-e AWS_SECRET_ACCESS_KEY=citadel-lab-password \
-e S3_BUCKET=demo \
-v citadel-seaweed-data:/data \
chrislusf/seaweedfs:4.41
$ export AWS_ACCESS_KEY_ID=citadel-lab
$ export AWS_SECRET_ACCESS_KEY=citadel-lab-password
$ export AWS_DEFAULT_REGION=us-east-1
$ printf 'hello\n' | aws --endpoint-url http://127.0.0.1:8333 \
s3 cp - s3://demo/greeting.txt
$ aws --endpoint-url http://127.0.0.1:8333 s3 ls s3://demo/
$ aws --endpoint-url http://127.0.0.1:8333 \
s3 cp s3://demo/greeting.txt -
Учётные данные в примере предназначены только для локального опыта. В следующих командах сохраняйте перед подкомандой s3 или s3api параметр --endpoint-url http://127.0.0.1:8333.
aws --endpoint-url http://127.0.0.1:8333 s3api put-bucket-versioning --bucket demo --versioning-configuration Status=Enabled. Создайте объект folder/greeting.txt и «переименуйте» его командой s3 mv. Команда s3api list-object-versions должна показать версию нового ключа и маркер удаления старого: привычное переименование здесь составлено из копирования и удаления. Дважды перезапишите новый объект, выберите прежний идентификатор версии и восстановите содержимое командой s3api get-object --bucket demo --key folder/renamed.txt --version-id VERSION_ID previous.txt.aws --endpoint-url http://127.0.0.1:8333 s3 presign s3://demo/greeting.txt --expires-in 300, откройте её без учётных данных, а через пять минут проверьте отказ. Объясните, почему предподписанная ссылка является временным правом доступа к конкретной операции, а не просто адресом объекта.001. Запишите гипотезу до опыта: после потери одного volume-сервера ранее записанный объект доступен через оставшуюся копию, но новая запись, требующая двух копий, завершиться не должна. Проверьте чтение и запись, а после возврата сервера — состояние репликации: SeaweedFS не восстанавливает недостающие копии автоматически. Несколько контейнеров на одном компьютере позволяют исследовать отказ процесса, но не отказ физического узла или зоны.