Documentation Videos View Site

# Managing Compute Instances with OCI Run Command and Ansible

This document provides a guide to writing Ansible playbooks that use version 5.5 of the Oracle Cloud Infrastructure (OCI) collection to manage and interact with OCI compute instances. Specifically, this guide focuses on using the oracle.oci.oci_compute_instance_agent_instance_agent_command module to execute commands on compute instances through the OCI Instance Agent. Using this method does not require the management SSH key pairs on your OCI compute instances, thus simplifying your configuration.

Note

To run privileged commands with Run Command on OCI the ocarun user must be given sudo permissions. See the section Running Privileged Commands below for more details

# On Linux:

sudo echo "ocarun ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/101-oracle-cloud-agent-run-command

# On Windows:

Add-LocalGroupMember -Group "Administrators" -Member "NT SERVICE\OCARUN" | Restart-Service -Name OCARUN -Force

# Understanding the Agent Command Modules

The oracle.oci.oci_compute_instance_agent_instance_agent_command module allows you to create and manage instance agent commands on OCI compute instances. This module leverages the OCI Instance Agent, which is a lightweight service that runs on compute instances and enables you to execute commands, manage plugins, and perform other management tasks without SSH access. For additional infomarion on OCI Run Command, see: https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/runningcommands.htm

# Checking Command Execution Status and Output

The oci_compute_instance_agent_instance_agent_command module creates and submits commands but returns immediately after creation. To check the execution status and retrieve command output, you need to use the oci_compute_instance_agent_instance_agent_command_execution_facts module.

# Basic Playbook Example

Here is a simple example of an Ansible playbook that runs a command on an OCI compute instance.

# Execute command on OCI compute instance
---
- hosts: localhost
  gather_facts: false

  vars:
   compartment_id: "ocid1.compartment.oc1..example"
   instance_id: "ocid1.instance.oc1.iad.example"

  tasks:
    - name: Run system update command
    oracle.oci.oci_compute_instance_agent_instance_agent_command:
      compartment_id: "{{ compartment_id }}"
      instance_id: "{{ instance_id }}"
      display_name: "System Update Command"
      content:
        source:
          source_type: "TEXT"
          text: |
            #!/bin/bash
            sudo yum update -y
            echo "Update completed at $(date)"
      execution_time_out_in_seconds: 600
      register: command_result

    - name: wait for command to complete
      oracle.oci.oci_compute_instance_agent_instance_agent_command_execution_facts:
        instance_id: "{{ cmdb360_ci['compute']['sourceId'] }}"
        instance_agent_command_id: "{{ command_result.instance_agent_command.id }}"
      register: command_status
      until: command_status.instance_agent_command_executions[0].lifecycle_state not in ['ACCEPTED', 'IN_PROGRESS']
      retries: 60
      delay: 10

    - name: fail if command failed
      ansible.builtin.fail:
        msg: 
          - "Command execution failed"
          - "Output: {{ command_status.instance_agent_command_executions[0].content.text.splitlines() | default('No output') }}"
      when: command_status.instance_agent_command_executions[0].lifecycle_state == 'FAILED'

    - name: display command status
      ansible.builtin.debug:
        msg: 
          - "Command State: {{ command_status.instance_agent_command_executions[0].lifecycle_state }}"
          - "Exit Code: {{ command_status.instance_agent_command_executions[0].content.exit_code | default('N/A') }}"   

    - name: display command output
      ansible.builtin.debug:
        msg:  "{{ command_status.instance_agent_command_executions[0].content.text.splitlines() | default('No output') }}"

Note: Multiple commands may also be supplied on a single line separated by ‘\n’

# Access and Privileges

The credentail used for Run Command is an API key associated with associted to a user. That user needs the ‘manage instance-agent-command-family’ permission in compartments where the compute instances reside. Additionally, the compute instances on which the command is being run, need to belong to a Dynamic Group with the ‘use instance-agent-command-execution-family’ permission. See the following document for more information about configuring this access: https://docs.cmdb360.com/docs/Satellites/OCI-satellite/ConfigureOciAccess/ConfigureOciAccess

# Understanding and Configuring Agent Polling

The OCI Instance Agent operates on a polling mechanism where the agent periodically checks for new commands from the OCI service. By default, the Instance Agent polls for new commands approximately every 4 minutes. This polling interval can cause delays between when you submit a command and when it actually starts executing on the instance.

# Default Polling Behavior

When you create an instance agent command using the Ansible module, the following sequence occurs:

  1. The command is created in the OCI service and enters the ACCEPTED state
  2. The Instance Agent polls the OCI service on its regular interval (default: ~4 minutes)
  3. The agent discovers the new command and begins execution (state changes to IN_PROGRESS)
  4. The command executes on the instance
  5. The agent reports completion back to the OCI service (state changes to SUCCEEDED or FAILED)

This means there can be a several minute delay before your command starts executing, which is important to account for when planning automation workflows or setting timeout values.

# Adjusting the Polling Interval

You can reduce the polling interval to make the Instance Agent check for commands more frequently. This is configured directly on the compute instance by modifying the Run Command Agent configuration file.

# Configuration Steps

To adjust the polling interval on a Linux instance:

  1. SSH into your compute instance or use a console connection

  2. Check the current Run Command config file settings

    sudo cat /etc/oracle-cloud-agent/plugins/runcommand/config.yml
    
  3. Edit the Run Command configuration file

    sudo vi /etc/oracle-cloud-agent/plugins/runcommand/config.yml
    
  4. Modify the pollCommandInterval setting and save the changes

  5. Restart the Instance Agent service

    sudo systemctl restart oracle-cloud-agent
    

# Considerations and Recommendations

· Lower polling intervals (e.g., 30 seconds) result in faster command execution but increase API calls and agent overhead. This can cause issues with the Oracle Discovery Satellite’s ability to poll resources. Especially if a large number of compute instances have lowered polling intervals.

· API call limits are at the tenant level, thus all compute instance agents in the tenancy effect this limit

· Higher polling intervals (e.g., 5-10 minutes) are suitable for periodic maintenance tasks

· For time-sensitive operations, configure a 30-60 second polling interval

· Remember to account for the polling delay when setting execution_time_out_in_seconds in your playbooks

· Monitor system resources if you significantly reduce the polling interval on many instances

· Consider using different polling intervals for different instance groups based on their automation needs

# Running Privileged Commands

By default, the Run Command agent cannot execute privileged commands. The Compute Instance Run Command plugin runs as the ocarun user on both Linux and Windows. This user must be given the appropriate access in order to execute privileged commands. Several playbooks offered by CMDB-360 require this access and so it is highly recommended to grant this access to the ocarun user.

# On Linux:

To run privileged commands on a Linux machine using the OCI Run Command feature, you must grant sudo permissions to the ocarun user on the target instance. The ocarun user is the default user under which the Compute Instance Run Command plugin executes scripts on Linux instances. This is the mechanism that the oracle.oci.oci_compute_instance_agent_instance_agent_command module uses to run commands on the remote instance.

To grant grant sudo permissions to the ocarun user to run all commands with sudo without needing a password, SSH to the compute instance as a privileged user and create a sudoers file with the following command

sudo echo "ocarun ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/101-oracle-cloud-agent-run-command

Alternatively, you can list specific commands instead of allowing all commands for a more secure configuration. Consult the sudo man page for syntax details.

# On Windows:

To allow it to run privileged commands on a Windows instance, you need to add the ocarun user to the local Administrators group.

Run the following command in an elevated PowerShell session:

Add-LocalGroupMember -Group "Administrators" -Member "NT SERVICE\OCARUN" | Restart-Service -Name OCARUN -Force

You can apply this configuration either via cloudbase-init at instance launch time, or by connecting to the instance after launch and running it manually.

# Troubleshooting

# Polling Issues

If commands are not being picked up by the agent even after adjusting the polling interval:

· Verify the Instance Agent plugin is enabled in the OCI console (Instance Details > Oracle Cloud Agent tab)

· Check that the oracle-cloud-agent service is running:

sudo systemctl status oracle-cloud-agent

· Review agent logs for errors:

sudo journalctl -u oracle-cloud-agent.service -n 100

· Ensure the instance has network connectivity to OCI services

· Verify IAM policies allow the instance to access the Instance Agent API

· Try restarting the agent service after configuration changes

# Authentication Errors

Ensure your OCI configuration file has the correct credentials and that the API key has not expired. Verify that your user has the necessary IAM permissions in the compartment.

# Command Timeout

If commands consistently timeout, increase the execution_time_out_in_seconds value. Note that the module creates the command but may return before execution completes. Use oci_compute_instance_agent_instance_agent_command_facts to poll for command completion status. Consider breaking complex commands into smaller steps. Also remember that the Instance Agent polling interval (default 5 minutes) adds delay before command execution begins - configure a shorter polling interval for time-sensitive operations.

# Permission Denied Errors

Commands run as the ocarun user. Use sudo in your scripts for operations requiring elevated privileges. Ensure the sudoers configuration allows passwordless sudo for ocarun.

# Additional Resources

· OCI Instance Agent Documentation: https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm

· Running Commands on an Instance: https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/runningcommands.htm

· Ansible Documentation: https://docs.ansible.com/

· Ansible OCI Collection: https://docs.oracle.com/en-us/iaas/tools/oci-ansible-collection/5.5.0/

# Conclusion

The oracle.oci.oci_compute_instance_agent_instance_agent_command module in the OCI Ansible collection provides a powerful and reliable way to manage OCI compute instances through Ansible automation. By leveraging the Instance Agent, you can execute commands, deploy configurations, and manage your infrastructure without the complexity of SSH key management or direct network access.

As you develop your Ansible playbooks, remember to follow best practices for security, error handling, and idempotency. Start with simple commands and gradually build more complex automation workflows as you become familiar with the module’s capabilities and limitations. The Ansible OCI collection makes it easier than ever to build robust, production-ready automation for your OCI infrastructure.