Auto Install Windows New Relic Agents in AWS Elastic Beanstalk

We use New Relic for Application Performance Monitoring on our ASP.NET and node.js applications. Recently, we’ve started moving our infrastructure from on-premise into Amazon Web Services (AWS). Because we’re just beginners, we started out with the Elastic Beanstalk service, which allows us to easily deploy new versions of our applications backed by a decent infrastructure.

In an on-premise situation, we’d manually install the .NET Agent and the Infrastructure Agent. But working with Elastic Beanstalk means we need to take a different approach to keep things efficient and consistent. The two primary goals are:

  • Automatically install .NET New Relic Agent and Infrastructure on Windows instances
  • Keep New Relic license key private (i.e. not in source control)

As far as .NET goes, the existing New Relic Elastic Beanstalk documentation is a bit too manual:

It says to “Follow the standard .NET agent installation”. To me, having to manually go into an instance and install the agent seems backwards. It should occur automatically when the environment is built; everything in the environment should be automatic.

.ebextensions

The AWS .ebextensions system is what allows us to automatically install the necessary agents. Here are the steps:

  1. In your project folder, create a folder called .ebextensions.

    Assuming you’re using a webdeploy package, make sure that this folder and all of its contents are included in your project (.csproj) file. Otherwise, they won’t be included in the package.

  2. Create a file called 01-new-relic-install.config.

    The .ebextensions system will apply any .config file in your .ebextensions folder in alphabetical order. So, if you want to specify an order for files to be applied, you must name them in order.

  3. The contents of the new relic config file:

    files:  
        "C:\\Users\\Public\\Downloads\\NewRelicAgent.msi": 
            source: "http://download.newrelic.com/dot_net_agent/release/NewRelicDotNetAgent_x64.msi"
        "C:\\Users\\Public\\Downloads\\NewRelicInfrastructureAgent.msi":
            source: "https://download.newrelic.com/infrastructure_agent/windows/newrelic-infra.msi"
    commands: 
        install_newrelic_infrastructure_agent:
            command: msiexec.exe /qn /i "C:\\Users\\Public\\Downloads\\NewRelicInfrastructureAgent.msi"
    container_commands:
        01_set-newrelic-infra-license-key:
            cwd: "C:\\Program Files\\New Relic\\newrelic-infra"
            command: "echo license_key: %NewRelic_license_key% > newrelic-infra.yml"
        02_stop-newrelic-infra:
            command: net stop newrelic-infra
            ignoreErrors: true
        03_start-newrelic-infra:
            command: net start newrelic-infra
            ignoreErrors: true
        04_install_newrelic_agent:
            command: msiexec.exe /i "C:\\Users\\Public\\Downloads\\NewRelicAgent.msi" /qb NR_LICENSE_KEY=%NewRelic_license_key%   
    

Let’s break this down, section by section.

files:

The two MSI files are downloaded from New Relic’s web site and placed in a folder on the machine. But there’s another way to do this: the .ebextensions system does allow you to specify the address of an MSI directly and the system will automatically install those packages. Because I install the newrelic-infra package without any parameters, it’s likely that I could use the packages system.

For the .NET New Relic Agent, we’re going to pass it a parameter during installation; downloading the package locally gives us the opportunity to specify how we want it installed.

commands:

There’s only one command here and it just installs the Infrastructure agent. Like I said, because I’m not passing any parameters, it’s likely that this could be switched to the packages: section and done automatically.

container_command:

It’s important to know the difference between commands and container_commands and it really boils down to when a step is executed. The container_commands documentation says:

Container commands run after the application and web server have been set up and the application version archive has been extracted, but before the application version is deployed.

That’s engineer-speak for “if you want to use environment variables in .ebextensions, use container_commands”. This serves our second goal: The only way to reference environment variables in an .ebextensions config file is to use container_commands. Ok, why is this important? Because we want to keep the New Relic license key out of source control.

With Elastic Beanstalk, we can set environment variables in the web dashboard:

Simply set the value of an environment variable called NewRelic_license_key to whatever your license key is.

Then, as Amazon executes the conainer_commands, it will be able to reference the license key from the environment variable you set rather than requiring you to hard code it or pull it from S3.

IMPORTANT: Make sure you set the environment variable before running the .config script. If you don’t (like I did), you’ll have to either manually fix issues with the license key or rebuild your environment.

The commands are executed in alphabetical order, so I’ve numbered them 01 through 04 to ensure they execute in a specific order.

01_set-newrelic-infra-license-key

This commands writes out the contents of the license key to a file that newrelic-infra reads on start up. With our commands 01, 02, and 03, we’re automatically performing the steps described in New Relic’s Windows Infrastructure documentation. After writing the file, we stop the service (if it’s running) and restart it in order to pick up the new license key. It would be great if New Relic allowed us to set the license key as part of the MSI just as they do with the .NET Agent. Which brings us to….

04_install_newrelic_agent

This is just a simple msiexec.exe command, but it has the parameter NR_LICENSE_KEY=%NewRelic_license_key% which specifies the license key at installation time, saving us from having to go back and set the key manually at a later date. See why it would be nice if New Relic supported this method on newrelic-infra?

Automatic and Consistent

I drop that .config file inside all of my ASP.NET applications. As long as I’ve made sure to set the environment variable before installing New Relic, as soon as the app deploys, my New Relic dashboard will light up with the application in APM and the server will be part of the Infrastructure monitoring.

There is an issue with server naming. I don’t use the server names for monitoring because they’re useless to me. When I want to see what’s going on with individual apps, I use the ec2Tag_Name grouping. See my first link below for a possible option in making sure the machine names are distinct.

References and Inspiration