== Infrastructure models: part 2
Это второй пост про модели инфраструктуры. В первой части мы рассмотрели модель //infrastructure as code// и знакового представителя - Terraform. В этой части поговорим о том, что значить быть провайдером, какой чеклист функциональности должен быть реализован.

Q: А чем нам (пользователям) интересен провайдер?
A: Есть такие наблюдения:
  * если все провайдеры дают единообразный API, с которым работают существующие инструменты и библиотеки - то понимать и использовать инфраструктуру проще.
  * если провайдер при реализации сосредоточен на собственной логике, полагаясь на и переиспользуя существующие фреймворки и сервисы - то инфраструктура развивается быстрее.

== Larger picture
Мы остановились на том, что Terraform - это client side часть процесса управления инфраструктуры. Но это не описывает систему в целом. Немного детализировав, можно получить такую картину:
%%
┌────────┐
│        │
│  User  ├─────────┐
│        │         │                 ┌────────────────────┐
└────────┘   ┌─────▼───────┐         │pgsql-xdsfq-instance│
             │  infra.hcl  │         └─────────▲──────────┘
             │             │                   │
             └─────┬───────┘                   │
                   │                           │
                   │                           │
                   │                     ┌─────┴──────┐
             ┌─────▼────┬───────┐        │            │
             │Terraform │Plugin ├────────►  Provider  │
             └──────────┴───────┘        │            │
                                         └────────────┘
%%
Последовательность выглядит так:
  * пользователь описывает своё представление о инфраструктуре, например, описав инстанс postgresql базы.
  * запускает ##terraform apply##, который интепретирует .HCL файл
  * ##terraform## через //provider plugin// обращается в //API// провайдера и передаёт свой интент
  * провайдер в ответ на запросы инициирует реальные изменения (поднятие VM и запуск там PostgreSQL)
  * провайдер отвечает "ОК" (синхронно или асинхронно)
  * ##terraform## сохраняет состояние и завершает работу

У нас появились новые термины и объекты. Давайте с ними разберёмся.

== Provider
Это непосредственно поставщик нашей инфраструктуры - control plane объектов. Провайдеры бывают разные:
  * В AWS для всех объектов это может быть один провайдер.
  * Для внутренних сервисов Яндекса (каждый с уникальным API и т.д.) - потенциально много провайдеров.

Работа провайдера обычно //асинхронна// - он принимает запрос и в фоне запускает задачу развёртывания нужных объектов (например, запуск виртуальной машины и настройку в ней PostgreSQL). Это важное наблюдение, т.к. во многом определяет то, как пользователь взаимодействует.

Для взаимодействия нам минимально необходимо:
  * Сетевой endpoint на стороне провайдера (отказоустойчивый и высокодоступный)
  * Реализация API в виде сервера (это может быть HTTP REST, gRPC и т.д)
  * Модель и реализация механизмов аутентификации и авторизации.

Для работы с Terraform каждому провайдеру нужно реализовать адаптер - ((https://www.terraform.io/docs/extend/index.html provider plugin)). Давайте посмотрим на каждую часть пазла.

=== Network endpoint
Нам нужны:
  * Сетевая связность
  * Репликация
  * Балансировка

//Сетевая связность// - не такое общедоступное благо, как может казаться, живя внутри Яндекса. Все внутренние ресурсы у нас доступны по сети. Совсем другая картина в публичных облаках, где для доступа к сервису внутри своей приватной виртуальной сети, нужно настраивать VPN, либо пользоваться jump машинами, например, прокидывая SSH туннели.

//Репликация// - инфраструктура должна обладать высокой надёжностью, которая достигается репликаций. Для этого размещаем несколько endpoint'ов в разных failure domain'ах, которые для клиента выглядят как один. Так трафик попадает во все наши внутренние сервисы благодаря работе L3 manager'а и фермам с IPVS за ним. Но эта функциональность небесплатна. Нужно уметь настраивать и эксплуатировать такую конструкцию. Там много тонкостей ("подводные грабли"), которые нужно помнить и //понимать//, а это, зачастую, приходит только с опытом нештатных/аварийных ситуаций.

//Балансировка// - это естественный результат наличия репликации, когда запросы клиентов и порождённые ими запросы к внутренним бекендам нужно обрабатывать. О том, как это делать, сломано немало копий, как в академическом мире, так и в практических реализациях (например, Facebook Katran, Google Maglev и другие).

Решение этих задач для Terraform'а out of scope.

=== API
Имея сетевой endpoint мы можем начать обмениваться данными, передавая наш интент через код/Terraform провайдеру. Но что конкретно будет передаваться? Тут задачу можно поделить на две:
  * модель API
  * сервер, который её реализует

В современном мире есть огромный //выбор//, наиболее распространёнными будем считать ((https://en.wikipedia.org/wiki/Representational_state_transfer REST)) over HTTP и [
((https://grpc.io/ gRPC)). Обе эти модели (особенно REST) достаточно абстрактны и не дают //однозначного// ответа на возможные вопросы:
  * как идентифицировать объекты (name, id, uuid, guid или их сочетание)
  * как смоделировать иерархии объектов, их связи и коллекции
  * как описать части ресурса
  * какими средствами передавать какие-то дополнительные мета-данные (заголовки, доп. поля) и в каком формате
  * как эволюционировать схемы данных и версионировать API

Да, есть гайды и десятки подходов, но даже беглый обзор API публичных облачных провайдеров показывает - даже REST у каждого очень свой. Это не помогает реализации клиентов и работе с несколькими провайдерами.

При реализации API провайдеру нужно:
  * Выбрать язык и фреймворк (только для Go их существуют ((https://github.com/mingrammer/go-web-framework-stars десятки))
  * Дописать необходимую функциональность (логи, аудит, рейтлимиты и т.д)

Многие аспекты здесь важны и ошибки (или чаще: нереализация из-за нехватки сил) могут болезненно ударить по клиентам. Безусловно, каждый провайдер в чём-то уникален и какие-то аспекты должны отличаться, но в подавляющем большинстве случаев единообразие было бы полезным.

Решение этих задач для Terraform'а out of scope.

=== Authn and authz
На различные //объекты//, которые предоставляет, нужно предоставлять различные _права_ на операции с нимим. Для этого нужно:
  * реализовать модель (например, ((https://en.wikipedia.org/wiki/Discretionary_access_control DAC)), ((https://en.wikipedia.org/wiki/Mandatory_access_control MAC)), ((https://en.wikipedia.org/wiki/Role-based_access_control RBAC или ABAC)))
  * предоставить инструменты (для управления моделью)

Сложность здесь состоит в том, что ошибки в этой части могут влиять на конфиденциальность данных и вызывать финансовые последствия. Безопасность - это сложно.

== Bonus: admin side
Если начали говорить про провайдеров, то там (тут) работают люди, которые помимо dev задач решают ещё и административные:
%%
┌────────┐
│        │
│  User  ├─────────┐
│        │         │                 ┌────────────────────┐
└────────┘   ┌─────▼───────┐         │pgsql-xdsfq-instance│
             │  infra.hcl  │         └─────────▲──────────┘
             │             │                   │
             └─────┬───────┘                   │
                   │                           │
                   │                           │
                   │                     ┌─────┴──────┐      ┌─────────┐
             ┌─────▼────┬───────┐        │            │      │         │
             │Terraform │Plugin ├────────►  Provider  ◄──────┤  Admin  │
             └──────────┴───────┘        │            │      │         │
                                         └────────────┘      └─────────┘

%%
Стоит упомянуть такие:
  * управление квотами
  * настройка политик (доступные версии, feature flag'и для разных клиентов)
  * просмотр и анализ пользовательских объектов
  * обновление самой инфраструктуры

Для этих задач так же нужны инструменты, которые приходится самостоятельно реализовывать каждому провайдеру.

== Outro
Теперь у нас есть неплохое понимание инфраструктуры как системы клиент-провайдер. И достаточно много мест, где ситуацию можно улучшить (зачастую упростив) как для клиентов, так и для провайдеров. Попробуем в следующей части посмотреть на ещё один подход и реализацию.
