EC2 with Netprobe

The EC2withNetprobe.yaml CloudFormation template provisions an EC2 Fleet with multiple instances configured with Self Announcing Netprobe. It uses EC2 Fleet to create instances and automates the setup of Netprobe installation and configuration as a systemd service during instance initialization via UserData.

Prerequisites Copied

Input Parameters Copied

Parameter Description Default Required
EC2 Fleet Configuration
AMIImageId AMI ID for the EC2 instances - ✓
InstanceType EC2 instance type (e.g., t2.micro, t3.medium) t2.micro
EC2Name Name prefix for the EC2 instances EC2withNetprobe
NumberOfInstances Number of EC2 instances to create in the fleet 1 ✓
KeyName Name of existing EC2 KeyPair - ✓
IamInstanceProfile Name of the IAM instance profile to attach - ✓
VpcId ID of the VPC where the instances will be launched - ✓
SubnetId ID of the subnet where the instances will be launched - ✓
SecurityGroupIds List of Security Group IDs to attach to the instances - ✓
OwnerEmail Email of the instance owner test@email.com
EC2Purpose Purpose of the EC2 instances Netprobe Deployment
AWS Credentials
AWSRegion AWS Region (e.g., ap-southeast-1, us-west-2) ap-southeast-1
Gateway Configuration
GatewayHost Gateway host for Netprobe connection - ✓
GatewayPort Gateway port for Netprobe connection 7039
Netprobe Configuration
NetprobeInstallDirectory Directory where Netprobe will be installed ~/geneos
S3NetprobeURL S3 URL to the Netprobe tar.gz file - ✓
NetprobePort Port number for Netprobe 7036
S3NetprobeSetupURL S3 URL to the Netprobe setup XML file - ✓
S3NetprobeServiceURL S3 URL to the Netprobe systemd service file - ✓

Configuration Copied

AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 Fleet with Netprobe deployment

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: "EC2 Fleet Configuration"
      Parameters:
      - AMIImageId
      - InstanceType
      - EC2Name
      - NumberOfInstances
      - KeyName
      - IamInstanceProfile
      - VpcId
      - SubnetId
      - SecurityGroupIds
      - OwnerEmail
      - EC2Purpose
    - Label:
        default: "AWS Credentials"
      Parameters:
      - AWSRegion
    - Label:
        default: "Gateway Configuration"
      Parameters:
      - GatewayHost
      - GatewayPort
    - Label:
        default: "Netprobe Configuration"
      Parameters:
      - NetprobeInstallDirectory
      - S3NetprobeURL
      - NetprobePort
      - S3NetprobeSetupURL
      - S3NetprobeServiceURL
    ParameterLabels:
      AMIImageId:
        default: "AMI Image ID"
      EC2Name:
        default: "EC2 Instance Name"
      NumberOfInstances:
        default: "Number of EC2 Instances"
      KeyName:
        default: "EC2 Key Pair Name"
      IamInstanceProfile:
        default: "IAM Instance Profile"
      VpcId:
        default: "VPC ID"
      SubnetId:
        default: "Subnet ID"
      SecurityGroupIds:
        default: "Security Group IDs"
      OwnerEmail:
        default: "Owner Email Address"
      EC2Purpose:
        default: "Purpose of the EC2 Instances"
      AWSRegion:
        default: "AWS Region"
      NetprobeInstallDirectory:
        default: "Netprobe Installation Directory"
      S3NetprobeURL:
        default: "S3 URL for Netprobe"
      NetprobePort:
        default: "Netprobe Port Number"
      GatewayHost:
        default: "Gateway Host"
      GatewayPort:
        default: "Gateway Port"
      S3NetprobeSetupURL:
        default: "S3 URL for Netprobe Setup File"
      S3NetprobeServiceURL:
        default: "S3 URL for Netprobe Service File"

Parameters:
  AMIImageId:
    Type: AWS::EC2::Image::Id
    Description: AMI ID for the EC2 instances (required)

  EC2Name:
    Type: String
    Description: Name for the EC2 instances
    Default: EC2withNetprobe

  NumberOfInstances:
    Type: Number
    Description: Number of EC2 instances to create in the fleet
    Default: 1
    MinValue: 1
    MaxValue: 100

  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Name of an existing EC2 KeyPair

  IamInstanceProfile:
    Type: String
    Description: Name of the IAM Instance Profile to attach to the EC2 instances

  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: ID of the VPC where the EC2 instances will be launched

  SubnetId:
    Type: AWS::EC2::Subnet::Id
    Description: ID of the subnet where the EC2 instances will be launched

  SecurityGroupIds:
    Type: List<AWS::EC2::SecurityGroup::Id>
    Description: List of Security Group IDs to attach to the EC2 instances

  OwnerEmail:
    Type: String
    Description: Email of the instance owner
    Default: test@email.com

  EC2Purpose:
    Type: String
    Description: Purpose of the EC2 instances
    Default: "Netprobe Deployment"

  InstanceType:
    Type: String
    Description: EC2 Instance Type (e.g., t2.micro, t3.medium)
    Default: t2.micro

  AWSRegion:
    Type: String
    Description: AWS Region for CLI configuration (e.g., ap-southeast-1, us-west-2)
    Default: ap-southeast-1

  NetprobeInstallDirectory:
    Type: String
    Description: Directory where Netprobe will be installed
    Default: "~/geneos"

  S3NetprobeURL:
    Type: String
    Description: S3 URL to the Netprobe tar.gz file

  NetprobePort:
    Type: Number
    Description: Port number for Netprobe
    Default: 7036

  GatewayHost:
    Type: String
    Description: Gateway host for Netprobe connection

  GatewayPort:
    Type: Number
    Description: Gateway port for Netprobe connection
    Default: 7039

  S3NetprobeSetupURL:
    Type: String
    Description: S3 URL to the Netprobe setup XML file

  S3NetprobeServiceURL:
    Type: String
    Description: S3 URL to the Netprobe systemd service file

Conditions:
  UseDefaultEC2Name: !Equals [!Ref EC2Name, ""]
  UseDefaultOwnerEmail: !Equals [!Ref OwnerEmail, ""]
  UseDefaultEC2Purpose: !Equals [!Ref EC2Purpose, ""]
  UseDefaultInstanceType: !Equals [!Ref InstanceType, ""]

Rules:
  RequireIamInstanceProfile:
    Assertions:
    - Assert: !Not [!Equals [!Ref IamInstanceProfile, ""]]
      AssertDescription: IamInstanceProfile must not be empty
  RequireAmiImageId:
    Assertions:
    - Assert: !Not [!Equals [!Ref AMIImageId, ""]]
      AssertDescription: AMIImageId must not be empty
  ValidateVpcSubnetRelationship:
    Assertions:
    - Assert:
        Fn::EachMemberEquals:
        - Fn::ValueOfAll:
          - AWS::EC2::Subnet::Id
          - VpcId
        - !Ref VpcId
      AssertDescription: The selected subnet must be in the specified VPC
  RequireS3NetprobeURL:
    Assertions:
    - Assert: !Not [!Equals [!Ref S3NetprobeURL, ""]]
      AssertDescription: S3NetprobeURL must not be empty
  RequireGatewayHost:
    Assertions:
    - Assert: !Not [!Equals [!Ref GatewayHost, ""]]
      AssertDescription: GatewayHost must not be empty
  RequireS3NetprobeSetupURL:
    Assertions:
    - Assert: !Not [!Equals [!Ref S3NetprobeSetupURL, ""]]
      AssertDescription: S3NetprobeSetupURL must not be empty
  RequireS3NetprobeServiceURL:
    Assertions:
    - Assert: !Not [!Equals [!Ref S3NetprobeServiceURL, ""]]
      AssertDescription: S3NetprobeServiceURL must not be empty

Resources:
  # Launch Template for the EC2 Fleet
  EC2LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: !Sub "${AWS::StackName}-LaunchTemplate"
      LaunchTemplateData:
        ImageId: !Ref AMIImageId
        InstanceType: !If [UseDefaultInstanceType, "t2.micro", !Ref InstanceType]
        KeyName: !Ref KeyName
        IamInstanceProfile:
          Name: !Ref IamInstanceProfile
        SecurityGroupIds: !Ref SecurityGroupIds
        UserData:
          Fn::Base64: !Sub |
            #!/bin/bash
            set -e
            
            echo --------------------------------Identifying OS and version--------------------------------
            if [ -f /etc/os-release ]; then
              . /etc/os-release
              OS=$ID
              VERSION_ID=$VERSION_ID
            elif [ -f /etc/redhat-release ]; then
              OS=$(awk '{print tolower($1)}' /etc/redhat-release)
              VERSION_ID=$(awk '{print $3}' /etc/redhat-release)
            else
              echo "ERROR: Unsupported OS"
              exit 1
            fi
            echo "Detected OS: $OS $VERSION_ID"

            echo --------------------------------Setting Up AWS CLI--------------------------------
            # Install unzip if not present
            case "$OS" in
              ubuntu)
                sudo apt-get update
                sudo apt-get install -y unzip
                ;;
              rhel)
                if [[ "$VERSION_ID" == 8* || "$VERSION_ID" == 9* ]]; then
                  sudo dnf install -y unzip
                elif [[ "$VERSION_ID" == 7* ]]; then
                  sudo yum install -y unzip
                fi
                ;;
            esac

            curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            unzip awscliv2.zip
            sudo ./aws/install
            # Set default values for optional parameters if they're empty
            AWS_REGION="${AWSRegion}"
            if [ -z "$AWS_REGION" ]; then
              AWS_REGION="ap-southeast-1"
            fi
            export AWS_DEFAULT_REGION=$AWS_REGION
            
            echo --------------------------------Setting Up Netprobe--------------------------------
            # Detect the default user dynamically
            if [ "$OS" = "ubuntu" ]; then
              DEFAULT_USER="ubuntu"
            else
              DEFAULT_USER="ec2-user"
            fi
            echo "Default user: $DEFAULT_USER"
            
            # Parse the netprobe install directory (handle ~ expansion)
            NETPROBE_DIR="${NetprobeInstallDirectory}"
            if [ -z "$NETPROBE_DIR" ]; then
              NETPROBE_DIR="~/geneos"
            fi
            if [[ "$NETPROBE_DIR" == ~* ]]; then
              NETPROBE_DIR=${!NETPROBE_DIR:1}
              NETPROBE_DIR="/home/$DEFAULT_USER$NETPROBE_DIR"
            fi
            
            sudo mkdir -p "$NETPROBE_DIR"
            sudo chown $DEFAULT_USER:$DEFAULT_USER "$NETPROBE_DIR"
            
            aws s3 cp "${S3NetprobeURL}" "$NETPROBE_DIR/netprobe.tar.gz"
            if [ ! -f "$NETPROBE_DIR/netprobe.tar.gz" ]; then
              echo "ERROR: Failed to download Netprobe package"
              exit 1
            fi
            
            cd "$NETPROBE_DIR"
            tar -xzf netprobe.tar.gz
            sudo chown -R $DEFAULT_USER:$DEFAULT_USER "$NETPROBE_DIR/"
            
            echo --------------------------------Downloading Netprobe Setup File--------------------------------
            aws s3 cp "${S3NetprobeSetupURL}" "$NETPROBE_DIR/netprobe/netprobe.setup.xml"
            if [ ! -f "$NETPROBE_DIR/netprobe/netprobe.setup.xml" ]; then
              echo "ERROR: Failed to download setup file"
              exit 1
            fi

            echo --------------------------------Installing Netprobe Dependencies--------------------------------
            case "$OS" in
              ubuntu)
                echo "System is Ubuntu"
                sudo apt install -y openjdk-21-jdk
                ;;
              rhel)
                if [[ "$VERSION_ID" == 8* || "$VERSION_ID" == 9* ]]; then
                  echo "System is RHEL 8 or 9"
                  sudo dnf install -y openssl-libs glibc libnsl2 libxcrypt zlib libstdc++ libgcc libtirpc krb5-libs libcom_err keyutils-libs libselinux pcre2 libcurl
                  sudo dnf install -y java-21-openjdk
                elif [[ "$VERSION_ID" == 7* ]]; then
                  echo "System is RHEL 7"
                  sudo yum install -y epel-release
                  sudo yum install -y java-21-openjdk || sudo yum install -y java-1.8.0-openjdk
                else
                  echo "Unsupported RHEL version"
                  exit 1
                fi
                ;;
            *)
              echo "Unsupported OS"
              exit 1
              ;;
            esac

            echo --------------------------------Setting up Environment Variables--------------------------------
            # Set default values for gateway parameters if they're empty
            GATEWAY_HOST_VAL="${GatewayHost}"
            GATEWAY_PORT_VAL="${GatewayPort}"
            if [ -z "$GATEWAY_PORT_VAL" ]; then
              GATEWAY_PORT_VAL="7039"
            fi
            
            # Set GATEWAY_HOST and GATEWAY_PORT environment variables permanently
            sudo sed -i '/^export GATEWAY_HOST=/d' /home/$DEFAULT_USER/.bashrc
            sudo sed -i '/^export GATEWAY_PORT=/d' /home/$DEFAULT_USER/.bashrc
            echo "export GATEWAY_HOST=$GATEWAY_HOST_VAL" >> /home/$DEFAULT_USER/.bashrc
            echo "export GATEWAY_PORT=$GATEWAY_PORT_VAL" >> /home/$DEFAULT_USER/.bashrc
            # Set for current session as well
            export GATEWAY_HOST=$GATEWAY_HOST_VAL
            export GATEWAY_PORT=$GATEWAY_PORT_VAL

            sudo sed -i '/^export JAVA_HOME=/d' /home/$DEFAULT_USER/.bashrc
            echo 'export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))' >> /home/$DEFAULT_USER/.bashrc
            
            echo --------------------------------Setting Up Netprobe Service--------------------------------
            # Set default value for netprobe port if empty
            NETPROBE_PORT_VAL="${NetprobePort}"
            if [ -z "$NETPROBE_PORT_VAL" ]; then
              NETPROBE_PORT_VAL="7036"
            fi
            
            # Download netprobe service file
            aws s3 cp ${S3NetprobeServiceURL} /tmp/netprobe.service.template
            if [ ! -f /tmp/netprobe.service.template ]; then
              echo "ERROR: Failed to download netprobe service file"
              exit 1
            fi
            
            # Substitute template variables with actual values
            sed -e "s|NETPROBE_DIR|$NETPROBE_DIR|g" \
                -e "s|NETPROBE_PORT|$NETPROBE_PORT_VAL|g" \
                -e "s|GATEWAY_HOST_VAL|$GATEWAY_HOST_VAL|g" \
                -e "s|GATEWAY_PORT_VAL|$GATEWAY_PORT_VAL|g" \
                /tmp/netprobe.service.template > /tmp/netprobe.service
            
            # Install service file
            sudo mv /tmp/netprobe.service /etc/systemd/system/netprobe.service
            sudo chown root:root /etc/systemd/system/netprobe.service
            sudo chmod 644 /etc/systemd/system/netprobe.service
            
            # Enable and start netprobe service
            sudo systemctl daemon-reload
            sudo systemctl enable netprobe.service
            sudo systemctl start netprobe.service
            
            # Wait a few seconds and check service status
            sleep 3
            if sudo systemctl is-active --quiet netprobe.service; then
              echo "SUCCESS: Netprobe service started successfully"
            else
              echo "WARNING: Netprobe service failed to start"
              sudo systemctl status netprobe.service
            fi
            
            echo "=== Netprobe Installation Complete ==="
        TagSpecifications:
        - ResourceType: instance
          Tags:
          - Key: Name
            Value: !If [UseDefaultEC2Name, "EC2withNetprobe", !Ref EC2Name]
          - Key: Owner
            Value: !If [UseDefaultOwnerEmail, "test@email.com", !Ref OwnerEmail]
          - Key: Purpose
            Value: !If [UseDefaultEC2Purpose, "Netprobe Deployment", !Ref EC2Purpose]
          - Key: StackName
            Value: !Ref AWS::StackName
          - Key: FleetManaged
            Value: "true"

  # EC2 Fleet
  EC2Fleet:
    Type: AWS::EC2::EC2Fleet
    Properties:
      Type: instant
      TargetCapacitySpecification:
        TotalTargetCapacity: !Ref NumberOfInstances
        DefaultTargetCapacityType: on-demand
      LaunchTemplateConfigs:
      - LaunchTemplateSpecification:
          LaunchTemplateId: !Ref EC2LaunchTemplate
          Version: !GetAtt EC2LaunchTemplate.LatestVersionNumber
        Overrides:
        - InstanceType: !Ref InstanceType
          SubnetId: !Ref SubnetId
      OnDemandOptions:
        AllocationStrategy: lowest-price
      SpotOptions:
        AllocationStrategy: lowest-price
        InstanceInterruptionBehavior: terminate


Outputs:
  FleetId:
    Description: The EC2 Fleet ID
    Value: !Ref EC2Fleet
    Export:
      Name: !Sub "${AWS::StackName}-FleetId"

  LaunchTemplateId:
    Description: The Launch Template ID
    Value: !Ref EC2LaunchTemplate
    Export:
      Name: !Sub "${AWS::StackName}-LaunchTemplateId"

  NumberOfInstancesCreated:
    Description: Number of EC2 instances in the fleet
    Value: !Ref NumberOfInstances

  GetInstanceIDsCommand:
    Description: Command to get instance IDs from this fleet
    Value: !Sub |
      aws ec2 describe-instances --filters "Name=tag:Name,Values=${EC2Name}" "Name=tag:StackName,Values=${AWS::StackName}" "Name=instance-state-name,Values=running" --query "Reservations[].Instances[].InstanceId" --output text
["Geneos"] ["Geneos > Netprobe"] ["User Guide"]

Was this topic helpful?