Очень заманчивая конфигурация была недавно анонсирована в рамках доступа "Всегда бесплатно". К сожалению, "очень быстро разбирают", а именно - сложно запустить экземпляр, постоянно вылазит ошибка “Out of Capacity”. Здесь мы решаем эту проблему, так как Oracle время от времени наращивает ёмкость.

Каждый арендатор получает бесплатно первые 3000 часов условных ЦП и 18 000 ГБ-часов в месяц для создания экземпляров Ampere A1 Compute с использованием конфигурации VM.Standard.A1.Flex (эквивалентно 4 условным ЦП и 24 ГБ памяти).

Начнем с установки консольной утилиты

https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm

Если вы предпочитаете использовать PHP и composer вместо консольной утилиты, вам сюда https://habr.com/ru/post/568386/ или https://github.com/hitrov/oci-arm-host-capacity (я использовал ранее разработанный мною пакет, подробней о нем писал тут https://habr.com/ru/post/541894/)

К слову, я также разместил ссылки на две эти статьи на Reddit, и кому-то использование CLI показалось сложным, им было намного проще с PHP вариантом.

Генерируем ключи доступа к API

После логина в веб-консоль кликаем иконку с профилем и затем User Settings

Далее идём по пути Resources -> API keys, жмём кнопку “Add API Key”

Копируем содержимое текстового поля, сохраняем в файле с именем config. Я поместил его в новую директорию /home/ubuntu/.oci вместе со скачанным приватным ключом *.pem

Настраиваем CLI

Устанавливаем путь к файлу конфигурации

OCI_CLI_RC_FILE=/home/ubuntu/.oci/config

Если вы не добавили бинарник OCI CLI себе в PATH, выполните

alias oci='/home/ubuntu/bin/oci'

(только замените путь на тот, куда утилита была установлена в самом начале).

Установите политику доступ к приватному ключу

oci setup repair-file-permissions --file /home/ubuntu/.oci/oracleidentitycloudservice***.pem

Протестируем аутентификацию, выполнив следующую команду (значение user берём из текстового поля во время генерации)

oci iam user get --user-id ocid1.user.oc1..aaaaaaaax72***d3q

Получаем параметры для запуска экземпляра

Нам нужно знать, который из доменов доступности (Availability Domain) бесплатен. Жмём меню Oracle Cloud -> Compute -> Instances

Жмём “Create Instance” и смотрим, где Availability Domain помечен как “Always Free Eligible”. В нашем случае видим, что это AD-2.

Почти каждая команда требует установленный параметр compartment-id. Давайте временно сохраним его в переменную окружения (замените на своё значение tenancy из config файла)

export C=ocid1.tenancy.oc1..aaaaaaaakpx***mpa

Наконец, соберём значения для запуска экземпляра:

  • availability-domain

  • shape

  • subnet-id

  • image-id

oci iam availability-domain list - all - compartment-id=$C

Пример вывода

{
  "data": [
    ...
    {
      "compartment-id": "ocid1.tenancy.oc1..aaaaaaaakpx***mpa",
      "id": "ocid1.availabilitydomain.oc1..aaaaaaaalcd***m2q",
      "name": "FeVO:EU-FRANKFURT-1-AD-2"
    },
    ...
  ]
}

Помните, нам нужен бесплатный (у меня это AD-2). Устанавливаем значение еще одной переменной окружения

export A=FeVO:EU-FRANKFURT-1-AD-2

Выберем тип (shape)

oci compute shape list --compartment-id=$C

Нас интересует VM.Standard.A1.Flex:

{
  "data": [
    ...
    {
      "baseline-ocpu-utilizations": null,
      "gpu-description": null,
      "gpus": 0,
      "is-live-migration-supported": false,
      "local-disk-description": null,
      "local-disks": 0,
      "local-disks-total-size-in-gbs": null,
      "max-vnic-attachment-options": {
        "default-per-ocpu": 1.0,
        "max": 24.0,
        "min": 2
      },
      "max-vnic-attachments": 2,
      "memory-in-gbs": 6.0,
      "memory-options": {
        "default-per-ocpu-in-g-bs": 6.0,
        "max-in-g-bs": 512.0,
        "max-per-ocpu-in-gbs": 64.0,
        "min-in-g-bs": 1.0,
        "min-per-ocpu-in-gbs": 1.0
      },
      "min-total-baseline-ocpus-required": null,
      "networking-bandwidth-in-gbps": 1.0,
      "networking-bandwidth-options": {
        "default-per-ocpu-in-gbps": 1.0,
        "max-in-gbps": 40.0,
        "min-in-gbps": 1.0
      },
      "ocpu-options": {
        "max": 80.0,
        "min": 1.0
      },
      "ocpus": 1.0,
      "processor-description": "3.0 GHz Ampere\u00ae Altra\u2122",
      "shape": "VM.Standard.A1.Flex"
    },
    ...
  ]
}

Надеюсь, вы ранее уже создавали VM.Standard.E2.1.Micro (с процессором AMD) из консоли - два таких экземпляра являются бесплатными. Если нет, сделайте это прежде - нам нужны существующие VNC, subnet, route table, security list и т.д.

oci network subnet list --compartment-id=$C

Обратите внимание на id

{
  "data": [
    {
      "availability-domain": null,
      "cidr-block": "10.0.0.0/24",
      "compartment-id": "ocid1.tenancy.oc1..aaaaaaaakpx***mpa",
      "defined-tags": {
        "Oracle-Tags": {
          "CreatedBy": "***",
          "CreatedOn": "2021-01-26T13:51:31.332Z"
        }
      },
      "dhcp-options-id": "ocid1.dhcpoptions.oc1.eu-frankfurt-1.aaaaaaaafh4***cvq",
      "display-name": "subnet-20210126-1549",
      "dns-label": "subnet01261551",
      "freeform-tags": {},
      "id": "ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaaahbb***faq",
      "ipv6-cidr-block": null,
      "ipv6-virtual-router-ip": null,
      "lifecycle-state": "AVAILABLE",
      "prohibit-internet-ingress": false,
      "prohibit-public-ip-on-vnic": false,
      "route-table-id": "ocid1.routetable.oc1.eu-frankfurt-1.aaaaaaaaqwe***p76q",
      "security-list-ids": [
        "ocid1.securitylist.oc1.eu-frankfurt-1.aaaaaaaaagnn***tca"
      ],
      "subnet-domain-name": "subnet***.vcn***.oraclevcn.com",
      "time-created": "2021-01-26T13:51:31.534000+00:00",
      "vcn-id": "ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaalox***y4a",
      "virtual-router-ip": "10.0.0.1",
      "virtual-router-mac": "00:00:17:***"
    }
  ]
}

...и сохраните его в переменную

export S=ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaaahbb***faq

Смотрим список образов

oci compute image list  --compartment-id=$C --shape=VM.Standard.A1.Flex

Я предпочитаю иметь весь установленный софт для разработки сразу из коробки - мой выбор - это “Oracle Linux Cloud Developer

{
  "data": [
    ...
    {
      "agent-features": null,
      "base-image-id": null,
      "billable-size-in-gbs": 14,
      "compartment-id": null,
      "create-image-allowed": true,
      "defined-tags": {},
      "display-name": "Oracle-Linux-Cloud-Developer-8.4-aarch64-2021.06.18-0",
      "freeform-tags": {},
      "id": "ocid1.image.oc1.eu-frankfurt-1.aaaaaaaa23zlxgcvdgb2zn4ffik6rda4g5daa5wa42svsgp4enljv4ywv6wa",
      "launch-mode": "NATIVE",
      "launch-options": {
        "boot-volume-type": "PARAVIRTUALIZED",
        "firmware": "UEFI_64",
        "is-consistent-volume-naming-enabled": true,
        "is-pv-encryption-in-transit-enabled": true,
        "network-type": "PARAVIRTUALIZED",
        "remote-data-volume-type": "PARAVIRTUALIZED"
      },
      "lifecycle-state": "AVAILABLE",
      "listing-type": null,
      "operating-system": "Oracle Linux Cloud Developer",
      "operating-system-version": "8",
      "size-in-mbs": 51200,
      "time-created": "2021-06-24T20:36:22.659000+00:00"
    },
    ...
  ]
}

Сохраняем image id

export I=ocid1.image.oc1.eu-frankfurt-1.aaaaaaaa23zlxgcvdgb2zn4ffik6rda4g5daa5wa42svsgp4enljv4ywv6wa

Также нам нужно создать несколько маленьких JSON файлов

  • instanceOptions.json

{
    "areLegacyImdsEndpointsDisabled": false
}
  • shapeConfig.json (можете изменить значения количества процессоров или ОЗУ). Возможные значения 1/6, 2/12, 3/18 and 2/24 соответственно. Обратите внимание, что образ “Oracle Linux Cloud Developer” требует минимум 8ГБ ОЗУ (таким образом, валидное для него значение - это как минимум 1/8)

{
    "ocpus": 4,
    "memoryInGBs": 24
}
  • availabilityConfig.json

{
    "recoveryAction": "RESTORE_INSTANCE"
}

Чтобы иметь безопасный зашифрованный доступ к экземпляру, нужно иметь сгенерированную пару ключей ~/.ssh/id_rsa и ~/.ssh/id_rsa.pub. Имя файла второго из них (публичного) должно быть передано в команду ниже. В сети достаточно инструкций, чтобы выполнить их генерацию, здесь мы опустим эту часть.

Наконец,

oci compute instance launch  --availability-domain $A  --compartment-id $C  --shape VM.Standard.A1.Flex  --subnet-id $S  --assign-private-dns-record true  --assign-public-ip false  --availability-config file:///home/ubuntu/availabilityConfig.json  --display-name my-new-instance  --image-id $I  --instance-options file:///home/ubuntu/instanceOptions.json  --shape-config file:///home/ubuntu/shapeConfig.json  --ssh-authorized-keys-file /home/ubuntu/.ssh/id_rsa.pub


Теперь вы можете настроить crontab для запуска этой команды, например, раз в минуту. Создайте .sh файл ("экспортируйте" переменные окружения до запуска) и убедитесь, что пользователь cron имеет доступ к приватному ключу. Опять же, здесь мы опустим эту часть.

Вывод команды (я тестировал с типом VM.Standard.E2.1.Micro, чтобы не уничтожать существующие экземпляры ARM)

Я полагаю, что достаточно безопасно оставить скрипт работать и проверять Cloud Console в браузере раз в несколько дней, поскольку когда экземпляр будет, наконец, создан, вы (API, CLI) не сможете создать их больше, чем разрешено, и станете получать в ответ что-то вроде

{
    "code": "LimitExceeded",
    "message": "The following service limits were exceeded: standard-a1-memory-count, standard-a1-core-count. Request a service limit increase from the service limits page in the console. "
}

или же снова

{
    "code": "InternalError",
    "message": "Out of host capacity."
}

Во всяком случае, именно так и есть в моем случае.

Если же вы перешли на тариф с оплатой по мере использования (Pay as you go), вам следует решить, как остановить вызовы OCI CLI (API) в случае успеха – чтобы не "попасть" на определеную сумму. Например, вы могли бы...

oci compute instance list --compartment-id $C

...периодически проверять вывод этой команды, чтобы знать, в какой момент cron должен быть отключен. Это не относится напрямую к проблеме, которую мы здесь решаем.

Если вам нужен безопасный способ с соответствующей проверкой, я сделал это в похожей инструкции с использованием PHP https://habr.com/ru/post/568386/

Назначаем публичный IP адрес

Мы не делаем это нарочно во время запуска команды, поскольку существует ограничение на два "недолговечных" (ephemeral) бесплатных IP адреса. Когда вы преуспеете в создании экземрляра, открываем консоль в веб-браузере, идём по пути Instance Details -> Resources -> Attached VNICs, выбирая его имя

Затем, Resources -> IPv4 Addresses -> … -> Edit

Выбираем ephemeral и кликаем по кнопке "Update"

Заключение

Вот, как вы будете логиниться в экземпляр после его создания (обратите внимание на имя пользователя - opc)

ssh -i ~/.ssh/id_rsa opc@ip.add.re.ss

Если же вы не назначили внешний (публичный) IP адрес, вы всё равно можете подключиться, используя его внутреннее доменное имя (internal FQDN) или частный (private) IP адрес (10.x.x.x) со страницы Instance Details, если экземпляр находится в той же сети VNIC, например,

ssh -i ~/.ssh/id_rsa opc@instance-20210714-xxxx.subnet.vcn.oraclevcn.com

Спасибо, что прочли!