Обчислення
Навіщо це
Section titled “Навіщо це”Віртуальна машина є найстарішою хмарною послугою, і решта сервісів або працює на ній, або скопійована з неї. Рішень при цьому кілька: з якого сімейства взяти інстанс, чи годиться для задачі ARM, як машина налаштовує себе під час першого запуску і що станеться, коли провайдер забере її серед ночі.
Три факти визначають відповіді. Інстанс на 2 vCPU коштує від $0.07 до $0.10 за
годину залежно від процесора й провайдера. Його spot-варіант у Azure на 79%
дешевший, але провайдер може забрати машину за 30 секунд. А кожна машина має
локальну адресу 169.254.169.254, за якою будь-який процес на ній читає
метадані, зокрема тимчасові ключі доступу.
Передумови. Регіони й зони доступності (модуль 1), акаунти й бюджети (модуль 2), ролі й тимчасові облікові дані (модуль 3). Гіпервізор і віртуальні машини розібрано в курсі ОС.
Що ви орендуєте
Section titled “Що ви орендуєте”Інстанс (instance) є віртуальною машиною, яку гіпервізор провайдера запускає на фізичному сервері: ви отримуєте кількість vCPU, обсяг пам’яті, мережевий інтерфейс із заявленою пропускною здатністю і диски. У AWS гіпервізором є Nitro з розвантаженням мережі й дисків на окремі карти, в Azure Hyper-V, в GCP KVM. Як це працює, розібрано в курсі ОС, тут воно вважається відомим.
Слово vCPU потребує уточнення. На x86 vCPU зазвичай є апаратним потоком: два vCPU можуть ділити одне фізичне ядро (SMT). На ARM-процесорах AWS Graviton і Azure Cobalt SMT немає, vCPU відповідає цілому ядру (для Cobalt 100 це прямо написано в документації Azure). Тому порівнювати «2 vCPU» на x86 і на ARM за ціною напряму не можна, продуктивність міряють на власному навантаженні.
На одному фізичному сервері живуть інстанси різних клієнтів. Гіпервізор ізолює їх, але кеші процесора й пропускна здатність пам’яті спільні. Через це той самий тип показує різну затримку в різні дні, а для чутливих навантажень існують виділені хости (dedicated host) за окрему плату.
Сімейства інстансів
Section titled “Сімейства інстансів”Назва типу кодує призначення. Розібравши її, ви бачите характеристики без довідника.
| Провайдер | Приклад | Як читати |
|---|---|---|
| AWS | m7g.large |
m сімейство (general purpose), 7 покоління, g процесор Graviton, large розмір |
| Azure | Standard_D2ps_v6 |
D сімейство, 2 vCPU, p ARM, s підтримка Premium SSD, v6 версія |
| GCP | c4a-standard-2 |
c4a серія (C4 на Axion), standard співвідношення пам’яті до vCPU, 2 vCPU |
Сімейства розрізняються співвідношенням ресурсів. Загальні (general purpose) дають близько 4 ГіБ пам’яті на vCPU і підходять для веб-серверів, невеликих баз даних, більшості застосунків. Оптимізовані під обчислення дають 2 ГіБ на vCPU і вищу частоту. Оптимізовані під пам’ять дають 8 ГіБ і більше на vCPU для кешів і баз в пам’яті. Оптимізовані під сховище мають швидкі локальні NVMe-диски. Окрема гілка — прискорювачі (GPU), яким присвячено модуль 14.
| Призначення | AWS | Azure | GCP |
|---|---|---|---|
| Загальне | M, T (burstable) | D, B (burstable) | N, E, C4 |
| Обчислення | C | F | C2, H3 |
| Пам’ять | R, X | E, M | M |
| Сховище | I, D | L | Z3 |
| Burstable | T | B | E2 (спільні ядра) |
Burstable-інстанси (T, B) мають базовий рівень процесора нижче за
100% і накопичують кредити, коли простоюють. Вони дешеві й підходять для
сервісів, що більшість часу майже нічого не роблять. Якщо ж кредити
закінчуються, процесор урізається до базового рівня; в AWS режим unlimited
дозволяє продовжити за додаткову плату. GCP має гнучкість, якої немає в інших:
власні типи машин (custom machine types), де кількість vCPU і обсяг пам’яті
задаються окремо.
ARM: Graviton, Cobalt, Axion
Section titled “ARM: Graviton, Cobalt, Axion”Кожен провайдер розробив власний ARM-процесор: AWS Graviton (суфікс g
в m7g, m8g), Azure Cobalt 100 (серія Dpsv6; раніше Azure пропонував
Ampere Altra в Dpsv5) і Google Axion (серія C4A). Власний процесор дає
провайдерові контроль над ціною й енергоспоживанням, а клієнтові часто
знижку, але не однакову: за цінами з розділу «Скільки це коштує» ARM-варіант
дешевший на 19% в AWS, на 27% в Azure і лише на 8% в GCP. Покоління процесорів у
цих порівняннях різні, тож точну різницю дає лише вимір власного навантаження.
Щоб перейти на ARM, потрібні три речі. Образ ОС має бути зібраний під
arm64. Контейнерні образи мають бути мультиархітектурними (наприклад,
docker buildx build --platform linux/amd64,linux/arm64, докладніше в
модулі 8). Нативні залежності (бібліотеки на C,
wheel-пакети Python, бінарники Node) мають існувати під arm64. Java, Go і
Python без нативних розширень зазвичай переносяться без змін.
Образи
Section titled “Образи”Образ (image) містить диск з ОС і встановленим ПЗ, з якого створюється інстанс. У AWS він називається AMI (Amazon Machine Image), в Azure це образ із Marketplace або з Azure Compute Gallery, в GCP образ у проєкті з родинами образів (image family). Публічні образи дають провайдер і дистрибутиви (Amazon Linux, Ubuntu від Canonical), власний золотий образ (golden image) збирають інструментом на кшталт Packer: ставлять залежності, агенти моніторингу й застосунок, фіксують результат.
Навіщо це, видно під час автомасштабування. Якщо машина після старту п’ять хвилин ставить пакети, нова потужність з’являється через п’ять хвилин. Образ із усім уже встановленим стартує за десятки секунд. Заразом інфраструктура стає незмінною (immutable): машину не лагодять, а замінюють новою з нового образу. Снапшот диска зберігає стан одного диска, образ додає до нього метадані для запуску машин; диски розібрано в модулі 6 і в модулі 14 курсу ОС.
cloud-init
Section titled “cloud-init”Машина з образу ще не знає, як її звати, яку конфігурацію взяти й кому
дозволити вхід по SSH. cloud-init входить у більшість образів Linux, на першому
запуску читає дані від провайдера (user data) і застосовує їх: створює
користувачів, кладе ключі, ставить пакети, пише файли, виконує команди.
Формат буває декларативним (файл #cloud-config у YAML) або скриптом з
#!/bin/bash. За замовчуванням user data виконується лише один раз за життя
інстанса.
Що варто знати наперед:
- Логи лежать у
/var/log/cloud-init-output.log;cloud-init status --waitблокує, доки налаштування не завершиться. Це перше, що дивляться, якщо машина «піднялася, але нічого не працює». - Помилка в скрипті не зупиняє машину: вона вважається створеною до завершення cloud-init, тож готовність перевіряйте health check.
- Секрети в user data класти не можна. Їх бачить кожен, хто читає метадані машини, і кожен із правом описати інстанс через API. Секрети машина бере зі сховища секретів за своєю роллю.
- Розмір обмежений (в EC2 16 КБ): довгі скрипти лежать в об’єктному сховищі, а в user data лишається завантажувач.
GCP має власний механізм поряд із cloud-init: ключ метаданих startup-script
виконується гостьовим агентом на кожному старті. На образах Ubuntu працює й
cloud-init через ключ user-data. Azure приймає custom_data і передає його
cloud-init.
Сервіс метаданих
Section titled “Сервіс метаданих”Процесу на машині потрібно дізнатися про себе: ідентифікатор інстанса,
зону, мережеві налаштування, теги, а головне тимчасові облікові дані ролі, під
якою машина працює (модуль 3). Для цього кожна хмара віддає
машині HTTP-сервіс на локальній адресі 169.254.169.254, доступний лише
зсередини машини (запит до цієї адреси не виходить за межі хоста).
Механізм у трьох провайдерів однаковий, різняться лише обов’язкові заголовки.
# IMDSv2: спершу токен, потім запит із токеномTOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token \ -H 'X-aws-ec2-metadata-token-ttl-seconds: 300')curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \ http://169.254.169.254/latest/meta-data/instance-id# Заголовок Metadata:true обов'язковий; проксі треба обійтиcurl -s -H 'Metadata:true' --noproxy '*' \ 'http://169.254.169.254/metadata/instance?api-version=2025-04-07'# Заголовок Metadata-Flavor: Google обов'язковийcurl -s -H 'Metadata-Flavor: Google' \ http://metadata.google.internal/computeMetadata/v1/instance/nameТой самий сервіс віддає й токени доступу. В AWS це шлях …/meta-data/iam/security-credentials/<роль>,
в Azure /metadata/identity/oauth2/token для керованої ідентичності, в GCP
…/instance/service-accounts/default/token. Саме цю можливість використовує SDK,
коли ви не задаєте ключів явно.
IMDSv1 і IMDSv2
Section titled “IMDSv1 і IMDSv2”Перша версія сервісу метаданих EC2 (IMDSv1) відповідала на будь-який простий GET. Якщо застосунок на машині можна змусити зробити HTTP-запит за адресою, яку вказав зловмисник, ця вразливість називається SSRF (server-side request forgery), і зловмисник отримує тимчасові ключі ролі машини.
IMDSv2 вимагає двох кроків. Спершу PUT-запит на /latest/api/token із
заголовком X-aws-ec2-metadata-token-ttl-seconds (від 1 секунди до 6 годин)
повертає токен, потім усі GET передають його в заголовку
X-aws-ec2-metadata-token. Захист складається з кількох дрібних перепон, які
разом відсікають типові SSRF:
- Вразливі місця в застосунках найчастіше дозволяють лише GET і рідко дозволяють довільні заголовки, а тут потрібен PUT із власним заголовком.
- Відповідь на PUT за замовчуванням має обмеження hop limit = 1 на рівні IP: пакет із токеном не проходить далі за саму машину, тож контейнер у власній мережі або зворотний проксі його не побачить.
- PUT-запити з заголовком
X-Forwarded-Forсервіс відхиляє, тобто запит, який прийшов через проксі, не проходить.
Вимагати IMDSv2 можна на трьох рівнях. Для інстанса це параметр
http_tokens = "required". Для образу це властивість imds-support = v2.0
(Amazon Linux 2023 вже задає її, тому нові інстанси на ньому вимагають
IMDSv2). Для регіону акаунта це значення за замовчуванням, яке задається
командою aws ec2 modify-instance-metadata-defaults --http-tokens required.
Що бувало без цього захисту, показано в розборі нижче; інцидент Capital One докладно розглянуто в модулі 12.
Spot і preemptible
Section titled “Spot і preemptible”Провайдери мають вільну потужність, яку не купили за звичайною ціною.
Її вони продають зі знижкою, зберігаючи право забрати машину назад. Це
spot-інстанс: в AWS Spot Instance, в Azure Azure Spot VM, в GCP Spot VM
(попередник preemptible VM мав ліміт 24 години, у Spot його немає).
Знижка суттєва. Для Azure D2s_v5 Linux в eastus поточна spot-ціна $0.020266 проти $0.096 on-demand, це мінус 79%. GCP заявляє знижки до 91% відносно on-demand для багатьох типів машин; AWS заявляє до 90%. Ціни spot змінюються залежно від попиту й від типу машини та зони, тож будь-яке фіксоване число тут орієнтир.
Перерваного інстанса ви не отримаєте безкоштовно назад: провайдер надсилає сигнал, чекає й зупиняє машину. Скільки чекає, залежить від хмари.
| AWS | Azure | GCP | |
|---|---|---|---|
| Час до зупинки | 2 хвилини | до 30 секунд | до 30 секунд (типово) |
| Як приходить сигнал | метадані spot/instance-action; подія EventBridge |
Scheduled Events, подія Preempt |
ключ метаданих preempted = TRUE і ACPI G2 soft off |
| Що станеться потім | terminate, stop або hibernate | Deallocate (типово) або Delete | STOP (типово) або DELETE |
AWS до того ж надсилає rebalance recommendation, коли потужність у пулі
стає дефіцитною, раніше за 2-хвилинне сповіщення і без гарантії. В Azure
машину виселяють і через ціну: для неї задають максимальну ціну, а -1
означає «не вище за ціну звичайної машини». GCP у режимі Preview дозволяє
збільшити повідомлення до 120 секунд.
Реагувати на сигнал доводиться самому. Нижче мінімальний цикл, який перевіряє його; в AWS документація радить опитувати кожні 5 секунд.
TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token \ -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600')while true; do code=$(curl -s -o /dev/null -w '%{http_code}' \ -H "X-aws-ec2-metadata-token: $TOKEN" \ http://169.254.169.254/latest/meta-data/spot/instance-action) [ "$code" = 200 ] && { echo 'переривання за 2 хвилини'; break; } sleep 5done# Scheduled Events: подія EventType = Preemptcurl -s -H 'Metadata:true' --noproxy '*' \ 'http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01'# Блокує, доки ключ preempted не стане TRUEcurl -s -H 'Metadata-Flavor: Google' \ 'http://metadata.google.internal/computeMetadata/v1/instance/preempted?wait_for_change=true'Зупинка за 30 секунд залишає мало. Тому spot підходить для навантажень, які переносять втрату машини: пакетна обробка, CI-агенти, рендеринг, безстанові вузли за балансувальником. Для бази даних або єдиного інстанса застосунку він не годиться. Основні прийоми: зберігати стан поза машиною (черга, об’єктне сховище), вміти продовжити роботу з контрольної точки, і розподіляти потужність по кількох типах інстансів і зонах, щоб один дефіцитний пул не забрав усе.
Групи автомасштабування
Section titled “Групи автомасштабування”Одна машина не витримує ні збою, ні піку. Група автомасштабування (autoscaling group) тримає задану кількість однакових інстансів, замінює зламані й додає чи прибирає машини за метрикою.
| AWS | Azure | GCP | |
|---|---|---|---|
| Група | Auto Scaling group (ASG) | Virtual Machine Scale Set (VMSS), режим Flexible | Managed Instance Group (MIG), зональна або регіональна |
| Шаблон | launch template | модель scale set | instance template |
| Spot у групі | mixed instances policy | priority = "Spot", priority_mix |
шаблон із provisioning_model = SPOT |
Скрізь однакові три поняття. Мінімум, максимум і бажана кількість (min / max / desired) задають межі. Перевірка стану (health check) вирішує, що інстанс зламався, і група замінює його новим із шаблону. Політика найчастіше є відстеженням цілі (target tracking): «тримай середнє завантаження процесора на 50%», далі група сама рахує, скільки машин додати.
Швидкість реакції обмежена часом старту: метрика збирається хвилину, потім машина створюється, завантажується ОС, виконується cloud-init, застосунок прогрівається. Через це група часто «встигає» вже наприкінці різкого піку. Відомий заздалегідь пік краще закладати розкладом, а старт скорочувати золотим образом. Група в кількох зонах доступності дає базову відмовостійкість: коли зона недоступна, інстанси створюються в решті (модуль 13).
Як це в трьох хмарах
Section titled “Як це в трьох хмарах”| Функція | AWS | Azure | GCP |
|---|---|---|---|
| Віртуальна машина | EC2 | Azure Virtual Machines | Compute Engine |
| ARM-процесор | Graviton (g) |
Cobalt 100 (ps, pds) |
Axion (C4A) |
| Образ | AMI | Marketplace / Compute Gallery | image / image family |
| Налаштування при старті | user data (cloud-init) | custom_data (cloud-init) |
startup-script, user-data |
| Сервіс метаданих | IMDS, v2 із токеном | IMDS, заголовок Metadata:true |
metadata server, Metadata-Flavor |
| Дешева переривана | Spot Instance (2 хв) | Spot VM (30 с) | Spot VM (30 с) |
| Група | Auto Scaling group | VM Scale Set | Managed Instance Group |
Чим це відрізняється і що з цього випливає. В AWS і GCP зупинений інстанс не
коштує за обчислення, лише за диски й адреси. В Azure вимкнення зсередини ОС
залишає машину виділеною, і за неї платять повністю, поки ви не виконаєте
deallocate (докладніше нижче). Захист метаданих у AWS
залежить від вашого налаштування (http_tokens), а в Azure і GCP основний
захист (Metadata:true, Metadata-Flavor) уже вбудований і не вимикається.
Час до зупинки spot у 4 рази різний: скрипт завершення, написаний під AWS,
ляже на 30 секундах Azure чи GCP.
Приклади нижче створюють одну ARM-машину, яка встановлює nginx через cloud-init. В AWS вона вимагає IMDSv2.
data "aws_ssm_parameter" "al2023_arm" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"}
resource "aws_instance" "web" { ami = data.aws_ssm_parameter.al2023_arm.value instance_type = "t4g.small"
user_data = <<-EOT #cloud-config packages: - nginx runcmd: - systemctl enable --now nginx EOT
user_data_replace_on_change = true
metadata_options { http_endpoint = "enabled" http_tokens = "required" http_put_response_hop_limit = 1 }
tags = { Name = "web" }}variable "resource_group_name" { type = string}
variable "subnet_id" { type = string}
variable "ssh_public_key" { type = string}
resource "azurerm_network_interface" "nic" { name = "nic-web" location = "eastus" resource_group_name = var.resource_group_name
ip_configuration { name = "internal" subnet_id = var.subnet_id private_ip_address_allocation = "Dynamic" }}
resource "azurerm_linux_virtual_machine" "web" { name = "web" resource_group_name = var.resource_group_name location = "eastus" size = "Standard_D2ps_v6" admin_username = "azureuser" network_interface_ids = [azurerm_network_interface.nic.id]
admin_ssh_key { username = "azureuser" public_key = var.ssh_public_key }
os_disk { caching = "ReadWrite" storage_account_type = "Premium_LRS" }
source_image_reference { publisher = "Canonical" offer = "ubuntu-24_04-lts" sku = "server-arm64" version = "latest" }
custom_data = base64encode(<<-EOT #cloud-config packages: - nginx runcmd: - systemctl enable --now nginx EOT )}resource "google_compute_instance" "web" { name = "web" machine_type = "c4a-standard-2" zone = "us-central1-a"
boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-2404-lts-arm64" type = "hyperdisk-balanced" } }
network_interface { network = "default" }
metadata = { "user-data" = <<-EOT #cloud-config packages: - nginx runcmd: - systemctl enable --now nginx EOT }}Cloud-init працює однаково: packages ставить nginx, runcmd вмикає службу. Перед запуском на Azure перевірте назву образа для ARM, командою az vm image list --architecture Arm64 --publisher Canonical --offer ubuntu-24_04-lts --all -o table; для GCP тип диска hyperdisk-balanced потрібен для машин C4A.
Тепер група автомасштабування з spot-потужністю. В AWS базова частина
береться on-demand, решта spot із кількох типів. В Azure це scale set у
режимі Flexible з priority_mix. В GCP регіональна група з автоскейлером на
шаблоні зі Spot.
variable "subnet_ids" { type = list(string)}
data "aws_ssm_parameter" "al2023_arm" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"}
resource "aws_launch_template" "web" { name_prefix = "web-" image_id = data.aws_ssm_parameter.al2023_arm.value instance_type = "m7g.large"
metadata_options { http_tokens = "required" http_put_response_hop_limit = 1 }}
resource "aws_autoscaling_group" "web" { name = "web" min_size = 2 max_size = 10 vpc_zone_identifier = var.subnet_ids capacity_rebalance = true
mixed_instances_policy { instances_distribution { on_demand_base_capacity = 1 on_demand_percentage_above_base_capacity = 0 spot_allocation_strategy = "price-capacity-optimized" }
launch_template { launch_template_specification { launch_template_id = aws_launch_template.web.id version = "$Latest" }
override { instance_type = "m7g.large" } override { instance_type = "m8g.large" } override { instance_type = "m6g.large" } } }}
resource "aws_autoscaling_policy" "cpu" { name = "cpu-50" autoscaling_group_name = aws_autoscaling_group.web.name policy_type = "TargetTrackingScaling"
target_tracking_configuration { predefined_metric_specification { predefined_metric_type = "ASGAverageCPUUtilization" } target_value = 50 }}variable "resource_group_name" { type = string}
variable "subnet_id" { type = string}
variable "ssh_public_key" { type = string}
resource "azurerm_orchestrated_virtual_machine_scale_set" "web" { name = "vmss-web" resource_group_name = var.resource_group_name location = "eastus" platform_fault_domain_count = 1 sku_name = "Standard_D2ps_v6" instances = 2 zones = ["1", "2", "3"]
priority = "Spot" eviction_policy = "Delete" max_bid_price = -1
priority_mix { base_regular_count = 1 regular_percentage_above_base = 0 }
os_profile { linux_configuration { admin_username = "azureuser"
admin_ssh_key { username = "azureuser" public_key = var.ssh_public_key } } }
source_image_reference { publisher = "Canonical" offer = "ubuntu-24_04-lts" sku = "server-arm64" version = "latest" }
os_disk { storage_account_type = "Premium_LRS" caching = "ReadWrite" }
network_interface { name = "nic" primary = true
ip_configuration { name = "internal" primary = true subnet_id = var.subnet_id } }}resource "google_compute_instance_template" "web" { name_prefix = "web-" machine_type = "c4a-standard-2" region = "us-central1"
disk { source_image = "ubuntu-os-cloud/ubuntu-2404-lts-arm64" disk_type = "hyperdisk-balanced" auto_delete = true boot = true }
network_interface { network = "default" }
scheduling { provisioning_model = "SPOT" preemptible = true automatic_restart = false on_host_maintenance = "TERMINATE" }
lifecycle { create_before_destroy = true }}
resource "google_compute_region_instance_group_manager" "web" { name = "web-mig" base_instance_name = "web" region = "us-central1"
version { instance_template = google_compute_instance_template.web.self_link_unique }}
resource "google_compute_region_autoscaler" "web" { name = "web-autoscaler" region = "us-central1" target = google_compute_region_instance_group_manager.web.id
autoscaling_policy { min_replicas = 2 max_replicas = 10 cooldown_period = 90
cpu_utilization { target = 0.6 } }}В Azure правила масштабування задаються окремим ресурсом azurerm_monitor_autoscale_setting, у якому потрібні два правила: на збільшення й на зменшення кількості машин. AWS і GCP роблять це самі: target tracking і autoscaler тримають ціль в обидва боки.
Скільки це коштує
Section titled “Скільки це коштує”Ціни на 2 vCPU і 8 ГіБ пам’яті, Linux, on-demand, американські долари за годину й за місяць у 730 годин. Станом на вересень 2026, з офіційних сторінок цін провайдерів (Amazon EC2 On-Demand Pricing, Azure Retail Prices API, Compute Engine pricing). Регіони: us-east-1, eastus, us-central1.
| Тип | За годину | За місяць (730 год) | |
|---|---|---|---|
| AWS x86 | m7i.large |
$0.1008 | $73.58 |
| AWS ARM | m7g.large |
$0.0816 | $59.57 |
| Azure x86 | Standard_D2s_v5 |
$0.096 | $70.08 |
| Azure ARM | Standard_D2ps_v6 |
$0.0702 | $51.25 |
| GCP x86 | n2-standard-2 |
$0.097118 | $70.90 |
| GCP ARM | c4a-standard-2 |
$0.0898 | $65.55 |
Spot: Azure Standard_D2s_v5 коштує $0.020266 за годину (−79%). Для GCP на
сторінці Spot VMs поточна ціна n2-standard-2 становить $0.058256 за годину
. Для AWS spot-ціну не наводжу:
вона змінюється залежно від зони й моменту, її дивляться в Spot Instance
Advisor і в історії цін.
У цю суму не входить кілька позицій, які легко забути.
- Диск. Завантажувальний диск оплачується окремо й у всіх трьох продовжує коштувати, поки машина зупинена.
- Публічна IPv4-адреса. В AWS і Azure вона коштує $0.005 за годину (близько $3.65 на місяць) на кожну адресу, навіть без трафіку.
- Вихідний трафік. Розглянуто в модулі 5.
- Зупинена, але не звільнена машина в Azure. Якщо вимкнути її зсередини
ОС, статус буде
Stopped, а compute-ресурси лишаються закріпленими, тож оплата триває. Лише статусStopped (deallocated)знімає плату за обчислення.
Білінг посекундний, з мінімумом 60 секунд в EC2 і в GCP . Знижки за зобов’язання (Savings Plans, Reserved Instances, committed use discounts) і порівняння моделей оплати розглядає модуль 13.
Розбір: один запит до 169.254.169.254
Section titled “Розбір: один запит до 169.254.169.254”Ця адреса стала ключовою деталлю інциденту Capital One 2019 року: неправильно налаштований вебзастосунковий файрвол (WAF) на EC2-інстансі дозволяв зловмиснику змусити його виконати HTTP-запит за довільною адресою. Повну хронологію, масштаб і наслідки розібрано в модулі 12, а тут показано лише механізм, який робить такий запит небезпечним.
- Зловмисник змушує WAF відправити GET на
http://169.254.169.254/latest/meta-data/iam/security-credentials/. Це SSRF: запит іде не від зловмисника, а зсередини машини. - IMDSv1 відповідає на простий GET і повертає ім’я ролі, а другим запитом ключі
цієї ролі:
AccessKeyId,SecretAccessKeyіToken. - Роль машини має права на сервіси AWS. Що вона може, те зловмисник і робить зі своєї машини, поки ключі не втратять чинність.
Проти IMDSv2 перший крок закінчується відповіддю 401: вразливий застосунок шле простий GET без токена, а токен створюється PUT-запитом із власним заголовком. Це закриває лише один шлях. Зловмисник із кодом, що виконується всередині машини, отримає токен і ключі так само, як власний застосунок. Тому додатково потрібні ролі з найменшими привілеями (модуль 3), а решта захисних шарів описана в модулі 12.
Типові помилки розуміння
Section titled “Типові помилки розуміння”«vCPU — це ядро». На x86 це найчастіше апаратний потік, два vCPU можуть ділити одне ядро. На ARM-процесорах Graviton і Cobalt vCPU відповідає ядру. Порівнювати типи за кількістю vCPU без вимірювання не можна.
«Spot — це безкоштовна знижка». Плата за знижку — переривання. Без зберігання стану поза машиною й реакції на сигнал вона обернеться втратою роботи.
«IMDSv2 захищає від усього». Він закриває SSRF із простим GET. Код, що виконується на машині, метадані читає в будь-якому разі; його обмежують правами ролі.
«Зупинена машина нічого не коштує». Диск і публічна адреса лишаються в рахунку у всіх трьох хмарах, а в Azure зупинка без deallocate залишає й плату за обчислення.
Перевір себе
Джерела
Section titled “Джерела”- AWS: Spot Instance interruption notices
- AWS: Use the Instance Metadata Service to access instance metadata
- AWS blog: Amazon EC2 Instance Metadata Service IMDSv2 by default
- Amazon Linux 2023: IMDSv2
- Amazon EC2 On-Demand Pricing
- Azure Spot Virtual Machines
- Azure Instance Metadata Service
- Azure Dpsv6-series (Cobalt 100)
- Azure Retail Prices API
- Google Cloud: Spot VMs
- Google Cloud: View and query VM metadata
- Google Cloud: General-purpose machine pricing
- cloud-init documentation
- Курс ОС: Віртуалізація і контейнери