.NET on AWS Blog

.NET Workflows for arm64 with Amazon CodeCatalyst: Part 2

Overview

In Part 1 of this blog post, I showed how to modify the .NET serverless application blueprint to build, test and deploy using arm64 compute in Amazon CodeCatalyst. In Part 2, I’ll show you how to use CodeCatalyst to create a workflow using the AWS Cloud Development Kit (CDK) to build, test and deploy an ASP.NET Core application as a load-balanced containerized service in Amazon Elastic Container Service (ECS) using AWS Fargate on arm64. Read Part 1 for details on using arm64 for .NET, and for tools to modernize legacy .NET Framework applications to modern cross-platform .NET.

Deploy ASP.NET Core web API to ECS Fargate on Graviton

Prerequisites

Overview

In this post, I will walk through creating a CodeCatalyst workflow that builds and runs unit tests for an ASP.NET Core application using arm64 compute, then deploys the application as an Amazon ECS service with Fargate, running on Graviton arm64. There are several different ways to deploy to Amazon ECS from CodeCatalyst, including using a build action to build and push the container to Amazon Elastic Container Registry (Amazon ECR), then using CLI commands to update the ECS service. That requires an existing ECS service, however, so I am using the CDK to encapsulate building and pushing the container image, and provisioning the ECS service with load-balancer with just a few lines of code. I will use an existing project blueprint as a starting point.

Walkthrough

In CodeCatalyst, create a new project and select the ASP.NET Core web API blueprint, then choose Next. The CodeCatalyst console will display a readme file on the right side with information about this template. Scroll down to the Connections and permissions section to review how CodeCatalyst will access resources in your AWS account. Then follow the steps below to create the project.

  1. Provide a name for your project, and choose an AWS account connection. The connection you choose represents the AWS account to which your application will be deployed.
  2. For Deployment role, select the AWS IAM role that you configured when you linked your AWS account.
  3. For AWS deployment service, leave the selection as None.

Note: this blueprint includes pre-defined workflows for deploying to ECS, AWS App Runner, and AWS Elastic Beanstalk. The existing ECS blueprint does not yet support deploying to Graviton containers at the time this blog was published.

  1. Expand the Code node, and enter a repository name. This will be the name of the Git repo used to store all the project files.
  2. For the .NET Project name, enter, AspNetFargateGraviton. For this walkthrough, it’s important to use that name exactly to avoid having to edit file paths later on.
  3. Choose the AWS region you will deploy in, then choose, Create project.
  4. After the project is created, the default workflow that builds the solution and runs the included unit tests will kick off.
  5. Navigate to the project’s Workflows via the CI/CD menu on the left, and select the main workflow. The visual layout for the main workflow should be shown, similar to below:

Visual layout view of the initial main workflow, showing two actions, WorkflowSource and Build_And_Test

  1. Select Edit at the top right to enter edit mode, and select the Visual layout if it’s not already selected (your workflow may be in YAML mode by default).
  2. In the visual layout mode, select the Build_And_Test action to show the configuration options for this action on the right.
  3. On the right pane, select the Configuration tab to show the options for compute type, and under Compute fleet – optional, choose an arm64 instance, such as Linux.Arm64.Large as in the example below.

The Compute type options in the build action configuration tab.

  1. Ensure the workflow is still valid by selecting “Validate” at the top right. Then, select Commit to commit your changes. Note that the changes are actually made to the /.codecatalyst/workflows/main.yaml file in your project’s Git repository.

Now that you’ve created a new ASP.NET Core project, and modified its workflow to build and run tests on arm64 compute, let’s add a project to deploy it. In the following steps, you will add a CDK project that will deploy the ASP.NET Core application to a new ECS Service on Fargate arm64 with load balancing:

  1. Clone your CodeCatalyst project repository locally:
    1. Navigate to Source Repositories via the Code menu on the left
    2. Click on the repository name you chose when creating the project
    3. Choose “Clone repository” at the top right for the git clone URL. See the CodeCatalyst documentation for detailed instructions on cloning repos.

Note: you could also use CodeCatalyst’s integrated Dev Environments to do this, but for simplicity, I’m providing instructions for working on your local computer.

  1. Open the local folder containing the cloned repository, and note the folder structure – there is a “.codecatalyst” folder containing the workflow yaml files, and also “src” and “tests” folders containing the ASP.NET Core and unit test projects respectively.
  2. AWS CDK projects must be initialized in an empty folder. For this reason, open a new file explorer (or Finder on macOS), and create a new folder somewhere outside of this repository named FargateServiceCDK.
    Again, to avoid needing to edit files later on, use that exact folder name.
  3. Open a command line or terminal and navigate (“cd”) into the new FargateServiceCDK folder.
  4. Initialize a new CDK app for .NET using this command:
    cdk init app --language csharp
  5. In your file explorer, you’ll notice that the FargateServiceCdk folder now contains several files (including cdk.json and .gitignore), and a /src folder. The CDK project itself is in /src/FargateServiceCdk.
  6. Copy the .gitignore and cdk.json files from the FargateServiceCdk folder to the root of your CodeCatalyst repository folder (AspNetFargateGraviton), overwriting the .gitignore file already present.
  7. Copy the /src/FargateServiceCdk folder from the CDK project into the /src folder of the AspNetFargateGraviton CodeCatalyst repository. After you copy this folder, and the two files from step 7, your CodeCatalyst repository folder should look like this, with the src/ folder containing both the ASP.NET Core project and the CDK project folders:

File explorer view showing the folder structure of the full solution.

  1. Open the src/FargateServiceCdk/FargateServiceCdkStack.cs file in your favorite code editor, and add the following using statements at the top of the file:
using Amazon.CDK.AWS.EC2;
using Amazon.CDK.AWS.ECR;
using Amazon.CDK.AWS.Ecr.Assets;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.ECS.Patterns;
using Amazon.CDK.AWS.IAM;
using System.IO;
  1. Below the comment “// The code that defines your stack goes here”, paste the following lines of code that build a Docker image and use it in a load-balanced ECS Fargate service:
// The code that defines your stack goes here
var image = new DockerImageAsset(this, "CdkCreatedImage", new DockerImageAssetProps
{
    Directory = Path.Join(Directory.GetCurrentDirectory()),
    Platform = Platform_.LINUX_ARM64,
    BuildArgs = {}
});

var cluster = new Cluster(this, "MyFargateCluster",
    new ClusterProps
    {
        Vpc = new Vpc(this, "MyAspNetVpc", new VpcProps { MaxAzs = 3 })
    });

new ApplicationLoadBalancedFargateService(this, "AspNetFargateService",
    new ApplicationLoadBalancedFargateServiceProps
    {
        Cluster = cluster,
        DesiredCount = 2,
        TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions
        {
            Image = ContainerImage.FromEcrRepository(image.Repository, image.ImageTag),
            ExecutionRole = Role.FromRoleName(this, "ecsRole", "ecsTaskExecutionRole")
        },
        PublicLoadBalancer = true,
        RuntimePlatform = new RuntimePlatform
        {
            CpuArchitecture = CpuArchitecture.ARM64,
            OperatingSystemFamily = OperatingSystemFamily.LINUX
        },
        MemoryLimitMiB = 1024,
    }); 

Note that the new DockerImageAsset platform is set to LINUX_ARM64 for the container image. Also, the ApplicationLoadBalancedFargateService has the RuntimePlatform’s CpuArchitecture property set to ARM64, which will set this property in the ECS Task Definition.

  1. Save the changes to the file, and then, in a command line or terminal, navigate to the src/FargateServiceCdk directory and ensure the CDK project builds using the dotnet build command.
  2. Because the container build will happen in the context of the CDK app, the relative paths to the project files in the Dockerfile are not correct. The simplest solution is to move it. Move the Dockerfile from the src\AspNetFargateGraviton folder up to the root of the repository (to the same folder as the cdk.json file).
  3. Change directory back to the root folder of the repository (e.g., cd ../..), so that you are in the AspNetFargateGraviton folder; this is important so that all your changes are committed.
  4. Using Git, stage your changes, commit them to your local repository, then push them back to CodeCatalyst:
    git add .
    git commit -m "added CDK project"
    git push
  5. In CodeCatalyst, you can browse to the files in your repository to ensure the cdk.json, and src/FargateServiceCdk folder are there.

Update Workflow with AWS CDK Deploy Action

Now that you have added the CDK project that will containerize our application and deploy it as a load-balanced ECS service, you need to update the “main” workflow to actually invoke the CDK application. You also will add an action to bootstrap your AWS account for CDK (this only needs to be done once, but it won’t hurt to have it as part of your workflow).

  1. In CodeCatalyst, navigate back to the main workflow, and select Edit to enter edit mode. Switch to Visual mode if the editor opens in YAML mode.
  2. Select the +Actions link, find the AWS CDK bootstrap action, and click the + (plus) symbol to add it to the workflow:

Workflow Actions list pane showing the AWS CDK bootstrap action.

  1. When you add an action, the properties for that action open in a pane on the right. In that pane, on the Inputs tab, select Build_And_Test in the Depends on drop-down.
  2. On the Configuration tab, select default_environment as the Environment, your linked AWS account and AWS IAM role, and the region you wish to deploy to.
  3. Next, using the +Actions link, add the AWS CDK deploy task, and choose AWSCDKbootstrap as the action it depends on.
  4. On the AWS CDK deploy task’s Configuration tab, choose the same environment, AWS account and IAM role you used for the bootstrap action.
  5. For Stack name enter FargateServiceCdkStack (this is the name assigned to the stack in src\FargateServiceCdk\Program.cs).
  6. Expand the Advanced node, and for Compute type, select an arm64 compute type under Compute fleet – optional. For example, Linux.Arm64.Large.
  7. Ensure your workflow now looks like the example below, validate your changes, then commit them using the controls at the top right.

Visual layout view of the complete workflow, with actions for build and test, CDK bootstrap, and CDK deploy.

  1. After you commit your changes, a new workflow run will kick off, which can take several minutes to complete. After it completes, select the last action in the workflow (the AWSCDKdeploy_nn action), and in the right-hand details pane, select the Variables tab.
  2. On the Variables tab, under Output variables, locate the variable whose name starts with “AspNetFargateServiceServiceURL”, and copy the value, which is the URL to the load balancer for your application.
  3. Paste the URL into a browser. You should see the message, “Hello Web API”.

Congratulations, you have successfully created a CodeCatalyst workflow to build, test, and deploy an ASP.NET Core application using the AWS CDK, all on AWS Graviton arm64.

Cleanup

In order to avoid incurring ongoing charges for your application, you can tear down all the resources by deleting the AWS CloudFormation stack that the CDK used to provision them. The CloudFormation stack ARN is listed in the output variables of the AWSCDKdeploy action of your workflow (in the same location as the load-balancer URL). Note the name of the stack. In the AWS Management Console for the AWS account you deployed to, navigate to the CloudFormation console, locate the stack, and delete it. If you wish to deploy the application again, you can run the CodeCatalyst workflow again, and it will re-provision the resources.

Conclusion

AWS Graviton arm64 processors offer compelling price-performance for .NET workloads in the cloud. In this post, you learned how to create a CodeCatalyst workflow for an ASP.NET Core application that containerizes, builds, and tests the application code using Graviton compute in CodeCatalyst, and then deploys the application with the AWS CDK as a load-balanced service in Amazon ECS running on Graviton. Get started building your own .NET workflows in Amazon CodeCatalyst today, and learn more about CodeCatalyst workflows and blueprints in the documentation.