Leverage OCI Functions for Automation
top of page
Search
  • Writer's pictureNikhil Verma

Leverage OCI Functions for Automation

Oracle Cloud Infrastructure (OCI) Functions is a serverless compute service that lets you create, run, and scale applications without managing any infrastructure. Functions are small but powerful blocks of code that generally do one simple thing. They are grouped into applications and stored as Docker images in a specified Docker registry. Functions can be invoked in response to a CLI command or signed HTTP request.

Here are some of the benefits of using OCI Functions:

  • Serverless: You don't have to provision or manage any infrastructure. OCI Functions takes care of all that for you.

  • Scalable: Functions can scale automatically to meet demand. You don't have to worry about provisioning enough capacity for your application.

  • Secure: OCI Functions is a secure service that is compliant with industry standards. Your code and data are protected.

  • Cost-effective: You only pay for the resources you use. There are no upfront costs or commitments.


I am going to showcase how to change VM shape when critical Memory alarm triggered using OCI functions.


Let's create function first :


Go to Developer services and Choose functions.

Let's create function :

Here i have set application name , shape and Network.

For Function deployment we can use either Cloud shell or Local.

Here i am using cloud shell


Login to Cloud Shell :

First we need to list Context and see you have right region context set :


fn list context

To set different region you can provide region name :


fn use context us-ashburn-1

Then we need to set Compartment where you have deployed this app


fn update context oracle.compartment-id ocid1.compartment

We need to create container registry to store Function container image . Here i am using Oracle Container registry


fn update context registry iad.ocir.io/tenancynamespace/prefix 

To connect this container registry we need to Generate your Auth token


Login to OCI registry and Enter Auth token


docker login -u 

Till here our context and Registry is ready , now we need to initialize function

Since i am going to use python script so i have initialized with runtime python.


fn init --runtime python compute


After initialize you will find three files : func.py,func.yaml & requirements.txt


Let's add our python script and renamed func.py to compute.py


In this example i am going to change VM shape with higher resources when function invoked by Memory alarm.


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.Standard.E2.1":
        new_shape = "VM.Standard.E2.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"}
    )

In this python script i am using OCI module so i have to update requirements with OCI.

Then i have updated func.yaml with my compute.py script name

Now all our function files ready ,let's deploy this function :


fn -v deploy --app computeapp



After Deployment in your computeapp you will find image and endpoint details.


To test this function i have deployed Test-linux VM with shape VM.standard.E2.1


To set alarm we need to create topic and subscription in Notifications.

I have created topic Name : Memory_alrm

Then i have created subscription where i have specified protocol Function and choose my compute function.

Now our subscription is ready.

Let's Create Alarm. In alarm i have choose Metric Namespace: oci_computeagent and Metric name : MemoryUtilization


In Metric Dimensions i have specified VM name: Test-linux

For Destination it will trigger Memory_alrm topic which will invoke function to change shape.


Let's generate Memory load using Stress-ng this will trigger this alarm which further invoke function to change this VM shape.


As you can see Alarm triggered as we have continuous 100% memory utlization for 1 min.

If you check function logs it is invoked and triggered VM shape change to VM.standard.E2.2

Now my instance going to stop to set this image shape change.

Finally my Instance shape change to VM.standard.E2.2

This is just one example , you can do lot more with OCI functions.

81 views0 comments
bottom of page