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

このトピックでは、メモリーを超える仮想マシン(VM)の自動サイズ変更を設定する方法について説明します。

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

ノート

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

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

必須IAMポリシー

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

If you're a member of the Administrators group, you already have the required access to execute this scenario. Otherwise, you need access to Monitoring, Notifications, and Functions. You must have FN_INVOCATION permission against the function to be able to add the function as a subscription to a topic. To resize VMs, the function must be authorized to update compute instances. To authorize your function for access to other Oracle Cloud Infrastructure resources, such as compute instances, include the function in a dynamic group  and create a policy to grant the dynamic group access to those resources. For more information, see Accessing Other Oracle Cloud Infrastructure Resources from Running Functions.

タスク1:機能の作成および承認

優先SDKを使用してVMのサイズを変更するファンクションを作成し、ファンクションにVMへのアクセスを認可(ファンクションを動的グループに含め、その動的グループにアクセス権を付与)すると、コンソールで他のすべてのシナリオ・ステップを完了できます。または、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:アラーム、トピックおよびサブスクリプションの作成

コンソール、CLIまたはAPIでアラーム、トピックおよびサブスクリプションを作成できます。

コンソールの使用

この項では、コンソールを使用したアラーム、トピックおよびサブスクリプションの作成手順を示します。ファンクションをデプロイする必要があります。

ノート

このシナリオの別のワークフローには、最初にトピックおよびサブスクリプションを作成し、次にアラームの作成時にこのトピックを選択することが含まれます。

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

アラーム、トピックおよび関数サブスクリプションの作成

この例では、コンソールを使用して、高メモリー使用量が検出されたときにファンクションを実行するためのメッセージを送信するアラームを作成する手順を説明します。このプロセス中に、ファンクションを参照するトピックを作成します。後でSMSおよび電子メール・サブスクリプションを追加できます。

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

  3. 「アラームの作成」ページの「アラームの定義」の下で、しきい値を設定します: 

    • メトリックの説明
      • コンパートメント: (VMを含むコンパートメントを選択します)
      • メトリック・ネームスペース: oci_computeagent
      • メトリック名: MemoryUtilization
      • 間隔: 1m
      • 統計: 最大
    • トリガー・ルール:

      • 演算子: 次より大きい
      • : 90
      • トリガー遅延分数: 1
  4. 「通知」「宛先」でファンクションを選択します:
    • 宛先サービス: 通知サービス
    • コンパートメント: (トピックおよび関連サブスクリプションを作成するコンパートメントを選択します)
    • トピック: 「トピックの作成」をクリックします

      ノート

      トピックおよびファンクション・サブスクリプションをすでに作成している場合は、新規トピックを作成するのではなく、ここでそのトピックを選択できます。
      • トピック名: アラームのトピック機密情報の入力は避けてください。
      • サブスクリプション・プロトコル: ファンクション
      • ファンクション・コンパートメント: (ファンクションを含むコンパートメントを選択します)
      • ファンクション・アプリケーション: (ファンクションを含むアプリケーションを選択します)
      • ファンクション: (ファンクションを選択します)
  5. 「アラームの保存」をクリックします。

SMSサブスクリプションの追加

この例では、コンソールを使用して、アラーム設定時に作成したトピックにSMSサブスクリプションを追加する手順を示します。

  1. ナビゲーション・メニューを開き、「開発者サービス」をクリックします。「アプリケーション統合」で、「通知」をクリックします。
  2. サブスクリプションを追加するトピックの名前をクリックします。

  3. トピックの詳細ページで、「サブスクリプションの作成」をクリックします。
  4. サブスクリプションの作成」ダイアログ・ボックスで、SMSサブスクリプションを設定します:

    • プロトコル:「SMS」を選択します。
    • :電話番号の国を選択します。
    • 電話番号: E.164形式を使用して、電話番号を入力します。

      SMSエンドポイントの例:

  5. 「作成」をクリックします。

    SMSサブスクリプションが作成され、指定した電話番号にサブスクリプション確認メッセージが送信されます。サブスクリプションは、確認されるまで「保留中」ステータスのままです。

  6. 新しいSMSサブスクリプションを確認するには、受信した確認メッセージの手順に従います。(「REPLY 」CONFIRM」というフレーズの後にトピック名が続くメッセージを探してください。)
電子メール・サブスクリプションの追加(オプション)

この例では、コンソールを使用して、アラーム設定時に作成したトピックにオプションの電子メール・サブスクリプションを追加する手順を示します。

  1. ナビゲーション・メニューを開き、「開発者サービス」をクリックします。「アプリケーション統合」で、「通知」をクリックします。
  2. サブスクリプションを追加するトピックの名前をクリックします。

  3. トピックの詳細ページで、「サブスクリプションの作成」をクリックします。
  4. サブスクリプションの作成」ダイアログ・ボックスで、電子メール・サブスクリプションを設定します:

    • プロトコル: 「電子メール」を選択します。
    • 電子メール: 電子メール・アドレスを入力します。
  5. 「作成」をクリックします。

    電子メール・サブスクリプションが作成され、指定された電子メール・アドレスにサブスクリプション確認URLが送信されます。サブスクリプションは、確認されるまで「保留中」ステータスのままです。

  6. 新しい電子メール・サブスクリプションを確認するには、電子メールを開き、確認URLに移動します。

CLIの使用

この項では、CLIを使用したトピック、サブスクリプションおよびアラームの作成手順を示します。ファンクションをデプロイする必要があります。

APIの使用およびリクエストの署名の詳細は、REST APIおよびセキュリティ資格証明を参照してください。SDKの詳細は、ソフトウェア開発キットとコマンドライン・インタフェースを参照してください。
  1. トピックの作成

    コマンド・プロンプトを開き、oci ons topic createコマンドを実行します: 

    oci ons topic create --name "Alarm Topic" --compartment-id "<compartment-ocid>"
  2. サブスクリプションの追加

    このトピックに、ファンクションOCID、SMS電話番号およびオプションの電子メール・アドレスを参照するサブスクリプションを追加します。

    • ファンクション・サブスクリプションの作成: コマンド・プロンプトを開き、oci ons subscription createコマンドを実行します:

      oci ons subscription create --compartment-id "<compartment-ocid>" --topic-id "<topic-ocid>" --protocol "ORACLE_FUNCTIONS" --subscription-endpoint "<function-ocid>"
    • SMSサブスクリプションの作成:コマンド・プロンプトを開き、oci ons subscription createコマンドを実行します:

      oci ons subscription create --compartment-id "<compartment-ocid>" --topic-id "<topic-ocid>" --protocol "SMS" --subscription-endpoint "<sms-endpoint>"
    • 電子メール・サブスクリプションの作成(オプション):コマンド・プロンプトを開き、oci ons subscription createコマンドを実行します:

      oci ons subscription create --compartment-id "<compartment-ocid>" --topic-id "<topic-ocid>" --protocol "EMAIL" --subscription-endpoint "john.smith@example.com"
  3. アラームの作成

    メモリーのしきい値を定義し、このトピックを宛先として参照するアラームを作成します: コマンド・プロンプトを開き、oci monitoring alarm createコマンドを実行します: 

    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

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

APIの使用

この項では、APIを使用したトピック、サブスクリプションおよびアラームの作成手順を示します。ファンクションをデプロイする必要があります。

APIの使用およびリクエストの署名の詳細は、REST APIおよびセキュリティ資格証明を参照してください。SDKの詳細は、ソフトウェア開発キットとコマンドライン・インタフェースを参照してください。

次の操作を使用します:

  1. CreateTopic: トピックの作成。

    CreateTopicリクエストの例
    POST /20181201/topics
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "name": "Alarm Topic",
      "compartmentId": "<compartment_OCID>"
    }
  2. CreateSubscription:このトピックに、ファンクションOCID、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>"
    }
    CreateSubscriptionリクエストの例: 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>"
    }
    CreateSubscriptionリクエストの例: 電子メール
    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"
    }
  3. CreateAlarm: メモリーしきい値を定義し、このトピックを参照するアラームを作成します。

    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
    }

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