シナリオA: VMの自動サイズ変更

通知ファンクションおよびモニタリング・サービスを使用して、メモリーを超える仮想マシン(VM)の自動サイズ変更を設定します。

このシナリオには、VMをサイズ変更するファンクションの作成と、その関数にメッセージを送信するアラームの作成が含まれます。アラームが起動すると、通知サービスがアラームのメッセージを宛先トピックに送信し、さらにトピックのサブスクリプションに展開します。このシナリオでは、トピックのサブスクリプションには、ファンクションおよび自分のEメール・アドレスとSMS電話番号が含まれています。ファンクションは、アラーム・メッセージの受信時に呼び出されます。

ノート

通知サービスには、ファンクションが呼び出された後にそのファンクションに関する情報はありません。詳細は、ファンクションが呼出しまたは実行されない場合のトラブルシューティング情報を参照してください。

このイメージは、ファンクションを使用してVMをサイズ変更するシナリオのコンテキストにおける通知を示しています。

必須IAMポリシー

Oracle Cloud Infrastructureを使用するには、管理者からポリシーでセキュリティ・アクセス権が付与されている必要があります。コンソールまたは(SDK、CLIまたはその他のツールを使用した) REST APIのどれを使用しているかにかかわらず、このアクセス権が必要です。権限を持っていない、または認可されていないというメッセージが表示された場合は、持っているアクセス権のタイプと作業しているコンパートメントを管理者に確認してください。

管理者グループのメンバーであれば、このシナリオを実行するために必要なアクセス権はすでに持っています。それ以外の場合は、モニタリング通知およびファンクションにアクセスする必要があります。ファンクションをトピックのサブスクリプションとして追加するには、そのファンクションに対してFN_INVOCATION権限を持っている必要があります。仮想マシンのサイズを変更するには、コンピュート・インスタンスを更新する権限がある必要があります。他のOracle Cloud Infrastructureリソース(コンピュート・インスタンスなど)へのアクセスをファンクションに認可するには、動的グループにファンクションを含め、それらのリソースへのアクセス権を動的グループに付与するポリシーを作成します。詳細は、実行しているファンクションからの他のOracle Cloud Infrastructureリソースへのアクセスを参照してください。

タスク1: ファンクションの作成および認可

ファンクションを作成して、任意のSDKを使用してVMsのサイズを変更し、(動的グループにファンクションを含めてその動的グループ・アクセス権を付与する) VMsへのアクセスを認可すると、他のすべてのシナリオ・ステップをコンソールで完了できます。または、Oracle Cloud Infrastructure CLIまたはAPIを使用して、各操作を自分で実行することもできます。

ファンクションが他のOracle Cloud Infrastructureリソースにアクセスすることの認可の詳細は、実行しているファンクションからの他のOracle Cloud Infrastructureリソースへのアクセスを参照してください。

ファンクション・コードのサンプル
ノート

このコード例では、データベース経由で冪等性を処理することをお薦めします。

次のコード例は、VMのサイズを変更するファンクションを示しています。ファンクションの作成およびデプロイの手順は、ファンクションの作成およびデプロイを参照してください。

import io
import json
import oci

from fdk import response

def increase_compute_shape(instance_id, alarm_msg_shape):
    signer = oci.auth.signers.get_resource_principals_signer()
    compute_client = oci.core.ComputeClient(config={}, signer=signer)
    current_shape = compute_client.get_instance(instance_id).data.shape
    print("INFO: current shape for Instance {0}: {1}".format(instance_id,current_shape), flush=True)
    if current_shape != alarm_msg_shape:
        return "The shape of Instance {} differs from the Alarm message".format(instance_id)
    # improve the logic below to handle more scenarios, make sure the shapes you select are available in the region and AD
    if  current_shape == "VM.Standard1.1":
        new_shape = "VM.Standard2.1"
    elif current_shape == "VM.Standard2.1":
        new_shape = "VM.Standard2.2"
    else:
        return "Instance {0} cannot get a bigger shape than its current shape {1}".format(instance_id,current_shape)
    print("INFO: new shape for Instance {0}: {1}".format(instance_id,new_shape), flush=True)
    try:
        update_instance_details = oci.core.models.UpdateInstanceDetails(shape=new_shape)
        resp = compute_client.update_instance(instance_id=instance_id, update_instance_details=update_instance_details)
        print(resp, flush=True)
    except Exception as ex:
        print('ERROR: cannot update instance {}'.format(instance_id), flush=True)
        raise
    return "The shape of Instance {} is updated, the instance is rebooting...".format(instance_id)

def handler(ctx, data: io.BytesIO=None):
    alarm_msg = {}
    message_id = func_response = ""
    try:
        headers = ctx.Headers()
        message_id = headers["x-oci-ns-messageid"]
    except Exception as ex:
        print('ERROR: Missing Message ID in the header', ex, flush=True)
        raise
    print("INFO: Message ID = ", message_id, flush=True)
    # the Message Id can be stored in a database and be used to check for duplicate messages
    try:
        alarm_msg = json.loads(data.getvalue())
        print("INFO: Alarm message: ")
        print(alarm_msg, flush=True)
    except (Exception, ValueError) as ex:
        print(str(ex), flush=True)

    if alarm_msg["type"] == "OK_TO_FIRING":
        if alarm_msg["alarmMetaData"][0]["dimensions"]:
            alarm_metric_dimension = alarm_msg["alarmMetaData"][0]["dimensions"][0]   #assuming the first dimension matches the instance to resize
            print("INFO: Instance to resize: ", alarm_metric_dimension["resourceId"], flush=True)
            func_response = increase_compute_shape(alarm_metric_dimension["resourceId"], alarm_metric_dimension["shape"])
            print("INFO: ", func_response, flush=True)
        else:
            print('ERROR: There is no metric dimension in this alarm message', flush=True)
            func_response = "There is no metric dimension in this alarm message"
    else:
        print('INFO: Nothing to do, alarm is not FIRING', flush=True)
        func_response = "Nothing to do, alarm is not FIRING"

    return response.Response(
        ctx, 
        response_data=func_response,
        headers={"Content-Type": "application/json"}
    )
ファンクションを動的グループに含める

ファンクションOCID (フォーマットはocid1.fnfunc.oc1.iad.exampleuniqueID)を見つけてノートにとり、関連する動的グループに次のルールを指定します:

resource.id = '<function-ocid>'
動的グループにVM (コンピュート・インスタンス)へのアクセス権を付与するポリシーを作成します

次のポリシーを追加します:

allow dynamic-group <dynamic-group-name> to use instances in tenancy

タスク2: トピックの作成

トラブルシューティングのヘルプは、通知のトラブルシューティングを参照してください。

  • ノート

    このシナリオの別のコンソール・ワークフローには、アラームの作成時、そのトピックの追加のサブスクリプションの作成時、新しいトピックおよび最初のサブスクリプションの作成が含まれます。
    1. 「トピックの作成」パネルを開きます。
      1. ナビゲーション・メニューを開き、「開発者サービス」をクリックします。「アプリケーション統合」で、「通知」をクリックします。
      2. 操作権限を持つコンパートメントを選択します。
      3. 「トピックの作成」をクリックします。
    2. 「名前」に、「アラーム・トピック」と入力します。
    3. 「作成」をクリックします。
  • oci ons Topic createコマンドおよび必須パラメータを使用してトピックを作成します:

    oci ons topic create --name <name> --compartment-id <compartment_OCID>

    例:

    oci ons topic create --name "Alarm Topic" --compartment-id "<compartment_OCID>"

    CLIコマンドのパラメータおよび値の完全なリストは、通知のコマンドライン・リファレンスを参照してください。

  • CreateTopic操作を実行してトピックを作成します。

    例:

    POST /20181201/topics
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "name": "Alarm Topic",
      "compartmentId": "<compartment_OCID>"
    }

タスク3: サブスクリプションの作成

ファンクション・サブスクリプションを作成する前に、ファンクションをデプロイする必要があります。

トラブルシューティングのヘルプは、通知のトラブルシューティングを参照してください。

    1. 前に作成したトピックを選択します。
      1. ナビゲーション・メニューを開き、「開発者サービス」をクリックします。「アプリケーション統合」で、「通知」をクリックします。
      2. 操作権限を持つコンパートメントを選択します。
      3. 前に作成したトピックの名前(例の名前はアラームのトピック)をクリックします。
    2. ファンクション・サブスクリプションを作成します。
      1. 「サブスクリプションの作成」パネルを開きます: トピックの詳細ページで、「サブスクリプションの作成」をクリックします。
        「サブスクリプションの作成」パネルが開きます。
      2. 「プロトコル」で、「ファンクション」を選択します。
      3. 残りのフィールドに入力します。
        フィールド 摘要
        ファンクション・コンパートメント ファンクションを含むコンパートメントを選択します。
        機能アプリケーション ファンクションを含むアプリケーションを選択します。
        関数 関数を選択します。
      4. 「作成」をクリックします。
        新しいファンクション・サブスクリプションの確認は必要ありません。
    3. SMSサブスクリプションを作成します。
      1. 「サブスクリプションの作成」パネルを開きます: トピックの詳細ページで、「サブスクリプションの作成」をクリックします。
        「サブスクリプションの作成」パネルが開きます。
      2. 「プロトコル」で、「SMS」を選択します。
      3. 残りのフィールドに入力します。
        フィールド 摘要
        電話番号の国を選択します。開始する前にを参照してください。
        電話番号 E.164書式を使用して電話番号を入力します。
      4. 「作成」をクリックします。
      5. 新しいSMSサブスクリプションの確認: 電話で受信した指示に従います。
    4. Eメール・サブスクリプションを作成します。
      1. 「サブスクリプションの作成」パネルを開きます: トピックの詳細ページで、「サブスクリプションの作成」をクリックします。
        「サブスクリプションの作成」パネルが開きます。
      2. 「プロトコル」で、「電子メール」を選択します。
      3. 残りのフィールドに入力します。
        フィールド 摘要
        電子メール 電子メール・アドレスを入力してください。
      4. 「Create」をクリックします。
      5. 新しい電子メール・サブスクリプションの確認:電子メールを開き、確認URLに移動します。
  • ノート

    SMSおよび電子メール・サブスクリプションを作成した後、確認します。

    oci ons Subscription createコマンドおよび必須パラメータを使用して、各サブスクリプションを作成します:

    oci ons subscription create --protocol <subscription_type> --subscription-endpoint <endpoint> --compartment-id <compartment_OCID> --topic-id <topic_OCID>

    ファンクション・サブスクリプションの例:

    oci ons subscription create --protocol "ORACLE_FUNCTIONS" --subscription-endpoint "<function-ocid>" --compartment-id "<compartment_OCID>" --topic-id "<topic_OCID>"

    SMSサブスクリプションの例:

    oci ons subscription create --protocol "SMS" --subscription-endpoint "<sms-endpoint>" --compartment-id "<compartment_OCID>" --topic-id "<topic_OCID>"

    Eメール・サブスクリプションの例:

    oci ons subscription create --protocol "EMAIL" --subscription-endpoint "john.smith@example.com" --compartment-id "<compartment_OCID>" --topic-id "<topic_OCID>"

    CLIコマンドのパラメータおよび値の完全なリストは、通知のコマンドライン・リファレンスを参照してください。

  • ノート

    SMSおよび電子メール・サブスクリプションを作成した後、確認します。

    CreateSubscription操作を実行して、各サブスクリプションを作成します。

    ファンクション・サブスクリプションの例:

    POST /20181201/subscriptions
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "topicId": "<topic_OCID>",
      "compartmentId": "<compartment_OCID>",
      "protocol": "ORACLE_FUNCTIONS",
      "endpoint": "<function_OCID>"
    }

    SMSサブスクリプションの例:

    POST /20181201/subscriptions
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "topicId": "<topic_OCID>",
      "compartmentId": "<compartment_OCID>",
      "protocol": "SMS",
      "endpoint": "<sms-endpoint>"
    }

    Eメール・サブスクリプションの例:

    POST /20181201/subscriptions
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "topicId": "<topic_OCID>",
      "compartmentId": "<compartment_OCID>",
      "protocol": "EMAIL",
      "endpoint": "john.smith@example.com"
    }

タスク4: アラームの作成

トラブルシューティングのヘルプは、通知のトラブルシューティングを参照してください。

    1. 「アラームの作成」ページを開きます。
      1. ナビゲーション・メニューを開き、「監視および管理」をクリックします。「モニタリング」で、「アラーム定義」をクリックします。
      2. 「アラームの作成」をクリックします。

    2. 「アラーム名」に、「VM Memory Alarm」と入力します。
    3. 「メトリックの説明」で、メトリック、間隔および統計を選択します。

      フィールド このシナリオの値の例
      コンパートメント 自動的にサイズ変更するVMを含むコンパートメントを選択します。
      メトリック・ネームスペース oci_computeagent
      メトリック名 MemoryUtilization
      間隔 1m
      統計 最大
    4. 「トリガー・ルール」で、アラームしきい値を設定します。

      フィールド このシナリオの値の例
      演算子 次より大きい
      90
      トリガー遅延分数 1
    5. 「通知」「宛先」で、前に作成したトピックを選択します。
      フィールド このシナリオの値の例
      宛先サービス Notifications Service
      コンパートメント 前に作成したトピックを含むコンパートメントを選択します。
      トピック 前に作成したトピックを選択します。
    6. 「アラームの保存」をクリックします。

  • oci monitoring alarm createコマンドと必須パラメータを使用して、アラームを作成します:

    oci monitoring alarm create --display-name <name> --compartment-id <compartment_OCID> --metric-compartment-id <compartment_OCID> --namespace <metric_namespace> --query-text <mql_expression> --severity <level> --destinations <file_or_text> --is-enabled <true_or_false>

    例:

    oci monitoring alarm create --display-name "VM Memory Alarm" --compartment-id "<compartment_OCID>" --metric-compartment-id "<compartment_OCID>" --namespace "oci_computeagent" --query-text "MemoryUtilization[1m].max() > 90" --severity "CRITICAL" --destinations "<topic-ocid>" --is-enabled true

    CLIコマンドのパラメータおよび値の完全なリストは、モニタリングのコマンドライン・リファレンスを参照してください。

  • CreateAlarm操作を実行してアラームを作成します。

    例:

    POST /20180401/alarms
    Host: telemetry.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "displayName": "VM Memory Alarm",
      "compartmentId": "<compartment_OCID>",
      "metricCompartmentId": "<compartment_OCID>",
      "namespace": "oci_computeagent",
      "query": "MemoryUtilization[1m].max() > 90",
      "severity": "CRITICAL",
      "destinations":
      [
        "<topic_OCID>"
      ],
      "isEnabled": true
    }