.NET on AWS Blog
Deploy to Elastic Beanstalk with Azure DevOps
AWS Elastic Beanstalk makes deploying, managing, and scaling .NET web applications on Amazon Web Services incredibly easy. This powerful service is available to anyone developing or hosting .NET apps on IIS.
In this post, I’ll walk through setting up a continuous integration and deployment pipeline for an ASP.NET Core application, using Azure DevOps, Amazon Simple Storage Service (Amazon S3), and AWS Elastic Beanstalk.
First, I’ll create a simple ASP.NET MVC sample app in Visual Studio and push the source code to an Azure DevOps Git repository. Next, I’ll configure an Azure Pipelines build pipeline that will trigger on every code commit. The build pipeline will compile the application and package the binaries into artifacts. These build artifacts will be uploaded to an Amazon S3 bucket, which will act as a staging area for deployments. On the deployment side, I’ll set up an Azure release pipeline to integrate with Elastic Beanstalk. The release pipeline will create a new application version and deploy the same.
Overview of solution
This solution sets up a continuous integration and deployment pipeline to build, test, and deploy an ASP.NET Core application from Azure DevOps to AWS Elastic Beanstalk. The source code is stored in an Azure DevOps Git repository. Azure Pipelines provides the automation to build, test, package, and release the app on every code change. Elastic Beanstalk then runs the application in a managed environment.
Walkthrough
Steps:
- Create Azure DevOps Git Repository
- Provision Elastic Beanstalk Application & Environment
- Push ASP.NET Code to Azure DevOps Repo
- Configure Azure DevOps Service Connections
- Set Up Continuous Integration Pipeline
- Configure Continuous Delivery to Elastic Beanstalk
Prerequisites
For this walkthrough, you should have the following prerequisites installed and configured:
- An AWS account – with access to create IAM User
- Microsoft Visual Studio 2022
- Azure DevOps
- AWS Toolkit for Azure DevOps
Step 1: Create Azure DevOps Git Repository
The first step is to create a Git repository in Azure DevOps to store the application source code. This will serve as the central repository that will trigger our continuous integration and delivery workflow.
To create a new Git repo:
1. Log into your Azure DevOps organization and navigate to the project where you want to create the repository.
2. Select Repos > Files to open the Files view.
3. Choose the New Repository button.
4. Give your repository a name. Initialize it with a README and .gitignore if desired.
5. Choose Create to create the empty Git repository.
Now you have an Azure DevOps Git repo ready to store your application source code. Later, you’ll push your .NET application code to this repository. The Azure DevOps Git repository will act as the single source of truth for your code. Commits pushed to this repository will trigger your continuous integration pipeline to build, test, and deploy the application automatically.
Step 2: Provision Elastic Beanstalk Application & Environment
In the Elastic Beanstalk console, choose Create New Environment to set up an environment for deploying your .NET code. You can follow the same steps listed in my previous post, Deploy to Elastic Beanstalk with GitHub Actions.
Choose Web Server Environment. Name the Application something like “dotnet-mvc-app-host-ado“. For Platform, choose.NET core on Linux. Under Application Code, choose Sample Application to start with a basic default app. You’ll set up your deployment pipeline with your own code later. Choose Single Instance configuration for the demo. Then choose Next.
Next, configure service access. For Service Role, you can either create a new role or use an existing role.
- Service role name – Enter the name for an IAM role that Elastic Beanstalk will create to assume as a service role. Beanstalk will attach the required managed policies to it. For more details, follow Elastic Beanstalk service role
- EC2 key pair – Select an EC2 key pair to securely log in to your EC2 instances. Optional, if you want to login to the EC2.
- EC2 instance profile – Choose an IAM instance profile with managed policies that allow your EC2 instances to perform required operations. For more details, follow Elastic Beanstalk instance profile
With all required configuration entered, leave the rest of the information as default and choose to skip to review.
Note: The former instructions assume the AWS account has the default VPC. If not, or you want to use another VPC, use the VPC with internet access in the next page instead of choosing “skip to review”. For details on enabling VPC internet access, follow Enable VPC internet access using internet gateways
Finally, review all the settings and launch the environment.
Once the environment status changes to Healthy, you can access the sample application using the environment URL (under Domain). You’re now ready to deploy your own .NET code using Azure DevOps.
Step 3: Push ASP.NET Code to Azure DevOps Repo
Clone the repo you created in Azure DevOps. Create a new ASP.NET Core Web Application. For Location choose the path where you cloned the repo and check Place Solution and Project in the same directory. Choose dotnet-mvc for the name of the project. Select the Model-View-Controller template and target .NET 8.0 which is the current LTS release.
Note: Following similar steps, as in the previous post – Step 3: Publish and push the ASP.NET MVC application code to the GitHub repository.
Build and run the application locally to verify it works.
As you created the project in the cloned folder, simply commit and push the code from Visual Studio.
Step 4: Configure Azure DevOps Service Connections
Create an IAM user with permissions to access Elastic Beanstalk and S3. Attach the AWSElasticBeanstalkFullAccess and AmazonS3FullAccess managed policies.
Generate an access key and secret for the IAM user for CLI Use case.
For creating Service Connections, follow the steps at Supply task credentials using a service connection.
If you don’t see AWS connection type, install AWS Toolkit for Azure DevOps from the marketplace. For instructions on installing extension, follow Install extensions.
Step 5: Set Up Continuous Integration Pipeline
Navigate to the Pipelines section and create a new pipeline. Select your Azure Repos Git repository and select Starter pipeline. It will create a azure-pipelines.yml file in the repo. Replace it with the code below.
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
buildConfiguration: 'Release'
debug: 'Verbose'
project: 'dotnet-mvc/dotnet-mvc.csproj'
artifact_bucket: 'elasticbeanstalk-us-east-1-123456789012'
s3_path: 'dotnet-mvc-app'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'restore'
projects: $(project)
feedsToUse: 'select'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: $(project)
arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: false
projects: $(project)
arguments: '--output $(Build.ArtifactStagingDirectory)/$(Build.BuildId) -c $(buildConfiguration)'
zipAfterPublish: false
modifyOutputPath: false
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId)'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
replaceExistingArchive: true
- task: S3Upload@1
inputs:
awsCredentials: 'AWS'
regionName: 'us-east-1'
bucketName: '$(artifact_bucket)'
targetFolder: $(s3_path)
sourceFolder: '$(Build.ArtifactStagingDirectory)'
globExpressions: '$(Build.BuildId).zip'
Note: update the variables accordingly.
This will define the build steps that run on code changes. The build pipeline is set to do the following:
- Restore of Nuget Packages
- Build the Project
- Package (Zip the artifact needed)
- Upload it S3.
Choose Save and Run.
Configure Continuous Delivery to Elastic Beanstalk
Create a New Release pipeline with Empty – Template and specify Dev as the stage name.
Choose the Artifact type Build and select the build pipeline you created in the last step.
Enable continuous deployment, to trigger the release on every build.
Give the Release Definition a name, dotnet-mvc-app-release.
Choose Dev – Stage to define deployment steps. You will use AWS Elastic Beanstalk Create Version and AWS Elastic Beanstalk Deploy Application Tasks.
- AWS Elastic Beanstalk Create Version – Creates a new version of an application that can be deployed subsequently to an Elastic Beanstalk environment associated with the application. Follow the link for more information on the about the task.
- AWS Elastic Beanstalk Deploy Application – Deploys a new version of an application to an Elastic Beanstalk environment associated with the application. Follow the link for more information on the about the task.
Configure the Tasks
Create an Elastic Beanstalk Revision:
- For Credentials, choose AWS you created earlier
- For Region, choose the region of Elastic Beanstalk
- For Application, Elastic Beanstalk Application Name
- For Deployment Bundle Type, choose Pre-existing application bundle in Amazon S3
- For Deployment Bundle Object Key, use the variable to arrive dynamic value for the respective Build
- For Version Label, choose a unique value with $(Release.DeploymentID).
Deploy to Elastic Beanstalk:
- For Credentials, choose AWS you created earlier
- For region, choose the region of Elastic Beanstalk
- For Application, Elastic Beanstalk Application Name
- For Environment, Elastic Beanstalk Environment Name
- For Deployment Bundle Type, Existing application version
- For Version Label, choose a unique value
Once deployment is successful, access the application URL to view the changes live!
Now that you have continuous delivery set up, make a change to your application code to see it deploy automatically. In Visual Studio, open a view file like Views/Home/Index.cshtml. Make a simple visible change like updating the page heading. Commit this change and push it to Repo.
This will trigger your CI/CD workflow.
Build Pipeline:
Release Pipeline:
Updates are live in the Environment.
Thus, code changes are continuously built and released to Elastic Beanstalk using Azure DevOps. Your Build and Release Pipeline automatically builds, packages and deploys the latest updates in just minutes.
Clean up
To avoid incurring future charges, delete the resources by terminating the Elastic Beanstalk environment and deleting the Azure DevOps Pipeline and Repository.
Conclusion
In this post, I walked through setting up a CI/CD pipeline for .NET applications using Azure DevOps and AWS Elastic Beanstalk. By leveraging these cloud services, you can automatically build, package, and deploy our .NET code whenever you push changes to your repository.
The end-to-end solution showcases some key benefits:
– Azure DevOps Build Pipeline provides easy YAML-based workflows to define pipeline steps for building, testing, and packaging the artifact.
– Azure DevOps Release pipeline enable with the deployments.
– Elastic Beanstalk gives a managed environment to run .NET apps without provisioning servers.
– Changes pushed to Azure Repository trigger automatic build and deployments to Elastic Beanstalk environments.
Setting up this automation provides speed and reliability to the software delivery process. Code is shipped to users faster while maintaining quality through automated testing. This walkthrough demonstrated how Azure DevOps and AWS can streamline deployments for .NET developers. For more information, view the AWS Toolkit for Microsoft Azure DevOps User Guide.