March 09, 2020     8min read

Fighting COVID-19 with AWS CDK


Folding@Home recently announced that they are supporting the simulation of protein folding to help study COVID-19.

In this post I'll show you how easy it is to start Folding on Amazon Fargate using AWS CDK. It was inspired by a small project k8s-fah by richstokes where he setup a method for running the folding client on Kubernetes clusters.

You should read this post if you are any of the following:

  • Interested in Infrastructure as Code
  • Interested in Simulating Protein Folding
  • Have a lot of Money or AWS Credits that you need to use

NOTE: I don't recommend actually running this unless you're mad rich and feel generous. It is meant as a way to practically learn how easy it is to spin up resources with AWS CDK.

What is Folding

Protein folding simulations done through Folding@Home are done in a distributed fashion leveraging peoples computers all over the world to solve a one big problem together.

Think of it like a big cake that is cut up into small pieces, and it is your responsibility to eat your part of that cake... Okay maybe this isn't the best analogy, but you get what I mean.

Illustration of COVID-19, created at the Centers for Disease Control and Prevention (CDC)
Illustration of COVID-19, created at the Centers for Disease Control and Prevention (CDC)

Proteins are not stagnant—they wiggle and fold and unfold to take on numerous shapes. We need to study not only one shape of the viral spike protein, but all the ways the protein wiggles and folds into alternative shapes in order to best understand how it interacts with the ACE2 receptor, so that an antibody can be designed - From Folding@Home Takes up the fight against COVID-19

I want to get involved but I'm lazy

That's perfect! So am I! That's why I use AWS CDK for most of my projects. CDK lets you define AWS Resources as code and quickly deploy a lot of infrastructure with very little code.

I'll give you a spoiler now, the only code you are going to need to deploy everything to AWS is the following.

const cluster = new ecs.Cluster(this, 'cluster');

const taskDefinition = new ecs.FargateTaskDefinition(this, 'task', {
  memoryLimitMiB: 8192,
  cpu: 4096
});

taskDefinition.addContainer('container', {
  image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../docker/')),
  logging: new ecs.AwsLogDriver({ streamPrefix: 'covid19' })
});

new ecs.FargateService(this, 'service', {
  cluster,
  taskDefinition
});

You're probably thinking, "wow that's amazing". And you've be correct in that thinking. Now lets move on to learning how to deploy it.

Deploying Folding@Home

Start by installing some basic dependencies on your computer, you'll need the following as a bare minimum in order to deploy the resources to.

  • NodeJS - The newer the better
  • AWS Profile - Although you don't need the full AWS CLI, it's worth installing and configuring your access keys.

For deploying, you have two options depending on how hands on or off you want to be:

  • Build from Scratch - Go through how to create a new CDK project and add all the resources you need to deploy.
  • Just Deploy - Pull down the existing repository and deploy it.

Building from Scratch

You've taken the approach to build the entire project from scratch! Good for you, I'm proud. Start off by running the following commands to setup a new AWS CDK project

# Install aws-cdk package globally
npm install -g aws-cdk

# Create a new CDK typescript project
mkdir cdk-fah-covid19 && cd cdk-fah-covid19
cdk init --language typescript

# Install the aws-ecs CDK constructs
npm install @aws-cdk/aws-ecs

With the project setup and all the dependencies we'll need installed, it's time to start setting up the code. Open up the lib/cdk-fah-covid19-stack.ts file and add the following content (might look familiar).

import * as cdk from '@aws-cdk/core';
import ecs = require('@aws-cdk/aws-ecs');

import path = require('path');

export class CdkFahCovid19Stack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 1. Create a Fargate cluster
    const cluster = new ecs.Cluster(this, 'cluster');

    // 2. Define resource limits for task
    const taskDefinition = new ecs.FargateTaskDefinition(this, 'task', {
      memoryLimitMiB: 8192,
      cpu: 4096
    });

    // 3. Add a container to the Task definition
    taskDefinition.addContainer('container', {
      image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../docker/')),
      logging: new ecs.AwsLogDriver({ streamPrefix: 'covid19' })
    });

    // 4. Create the service in our Fargate Cluster
    new ecs.FargateService(this, 'service', {
      cluster,
      taskDefinition
    });
  }
}

There are four steps that are taken to configure the Amazon Fargate service to run our folding at home container.

  1. Amazon Fargate cluster is create - by default this also included ALL the networking required as well
  2. Task Definition - Specifies the resources allocated to a task, tasks can include 1 or more containers
  3. Add a container to the Task - Along with setting up a container image, we also define some logging so we can monitor how the Folding is going.
  4. Register the task with the Fargate Cluster - The final step connecting the task definition and the cluster together.

Dockerfile

You might have noticed a random reference to ../docker/ in the previous code. This is where we will need to put our Folding@Home docker container that will automatically be uploaded for us to Amazon ECR.

Go ahead and create the file docker/Dockerfile in your project and add the following contents to it

FROM ubuntu:16.04
ENV DEBIAN_FRONTEND noninteractive

RUN apt update
RUN apt install wget -y

# Download/Install latest FAH client
# See here for latest - https://foldingathome.org/alternative-downloads/
RUN wget https://download.foldingathome.org/releases/public/release/fahclient/debian-stable-64bit/v7.5/fahclient_7.5.1_amd64.deb
RUN dpkg -i --force-depends fahclient_7.5.1_amd64.deb

EXPOSE 7396 36396

WORKDIR /var/lib/fahclient
CMD	["/usr/bin/FAHClient", \
	"--config", "/etc/fahclient/config.xml", \
	"--run-as", "fahclient", \
	"--pid-file=/var/run/fahclient.pid"]

And that's it! Move onto the next step to learn how to deploy it.

Just Deploy

If you are at this point then you've either completed the Build from Scratch section or you've decided to pull down the existing repository and just want to deploy it. Either way you're in the right place.

If you don't already have the repository, pull it down from the github and install the dependencies

# Clone repository
git clone https://github.com/t04glovern/cdk-fah-covid19.git

# Install dependencies
cd cdk-fah-covid19
npm install -g aws-cdk
npm install

Now we've got to transpile the typescript and prepare it for deploy. It's usually recommended to run this command in the background while you're working on typescript. However for this example run it then ctrl+c to exit once it's done

npm run watch

Finally, you're ready to deploy the stack. It's as easy as running the following command

cdk deploy

# CdkFahCovid19Stack: deploying...
# aws-cdk/assets:bb9ebb84d6a5d2887a7406685ff3ccb2178b47cb9ee4f1e54db1a84cb899a104: image already exists, skipping build and push
# CdkFahCovid19Stack: creating CloudFormation changeset...
#  0/60 | 9:31:46 pm | UPDATE_IN_PROGRESS   | AWS::ECS::TaskDefinition              | task (task117DF50A)
#  0/60 | 9:31:47 pm | UPDATE_IN_PROGRESS   | AWS::ECS::TaskDefinition              | task (task117DF50A) Resource creation Initiated
#  59/60 | 9:31:47 pm | UPDATE_COMPLETE      | AWS::ECS::TaskDefinition              | task (task117DF50A)
#  59/60 | 9:31:49 pm | UPDATE_IN_PROGRESS   | AWS::ECS::Service                     | service/Service (serviceService7DDC3B7C)
# 59/60 Currently in progress: serviceService7DDC3B7C
#  59/60 | 9:33:51 pm | UPDATE_COMPLETE      | AWS::ECS::Service                     | service/Service (serviceService7DDC3B7C)
#  59/60 | 9:33:53 pm | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack            | CdkFahCovid19Stack
#  ✅  CdkFahCovid19Stack

Note: the deploy can take up to 10-15 minutes as it needs to setup a whole bunch of networking services.

Checking Status

If you want to check in the status of the Folding, navigate to the ECS cluster portal and click on your cluster.

It will have a random name starting with CdkFahCovid19Stack.

Next open up the service by clicking on its name

CDK COVID-19 Fargate service
CDK COVID-19 Fargate service

You then want to click on the Logs tab and you should be able to view the logs coming out of the container currently Folding for you

CDK COVID-19 Fargate service logs
CDK COVID-19 Fargate service logs

Destroying Resources

This is important!, the configuration I've put in the repo will cost you a pretty penny to run long term.

To completely remove all the resources associated with this project, run the following

cdk destroy
# Are you sure you want to delete: CdkFahCovid19Stack (y/n)? y
# CdkFahCovid19Stack: destroying...

Summary

AWS CDK is a great way to deploy a lot of resources really fast, and putting it to the use of running Folding@Home containers is a fun little experiment.

Have you used Fargate for something interesting? Or maybe you're an avid Folding@Home contributor? Reach out to me on Twitter @nathangloverAUS and let me know!

devopstar

DevOpStar by Nathan Glover | 2020