aws / aws-rfdk

The Render Farm Deployment Kit on AWS is a library for use with the AWS Cloud Development Kit that helps you define your render farm cloud infrastructure as code.
https://docs.aws.amazon.com/rfdk/index.html
Apache License 2.0
107 stars 42 forks source link

Add construct for Deadline Webservice #108

Open koenverwimp opened 4 years ago

koenverwimp commented 4 years ago

I would like to have as well a Deadline web service running in my render farm.

Use Case

I use deadline web service to submit jobs via HTTP api programatically. As well read info about jobs/taks for monitoring.

Proposed Solution

Implement a construct to add Deadline Webservice into the service stack.

jusiskin commented 3 years ago

We are looking for requirements to help drive the design of this feature. In addition to the use-case @koenverwimp has already specified (programatically submitting jobs), we're looking for any additional input into the design requirements. Here are a couple of guiding questions that we'd like input on:

  1. What features of the Deadline Web Service are you interested in using? The Web Service provides the following features and we are interested to hear which features users intend to use:
  2. What infrastructure would you like to be able to connect to the web service? Some examples that we've identified so far:
    • Other AWS services (e.g. Lambda/CodeBuild)
    • CDK/CloudFormation custom resources to interact with Deadline resources during CDK deployment
  3. What kind of resource load (CPU/memory) you'd typically provision for the web service for your particular use-case. We’re interested in this to determine the default EC2 instance type that would be set by RFDK when deploying the Web Service.
  4. Other feedback – anything else that I might be missing that should be considered for RFDK support of the Deadline Web Service
jglisson commented 9 months ago

Was this ever accomplished? I would like to have access to the Deadline webservice for all three of the scenarios listed above with an instance stood up using RFDK.

ckimrie commented 7 months ago

I too would also like to request this feature.

Requirements gathering

To provide you some feedback @jusiskin to your questions:

  1. The HTTP REST API is our only need
  2. Combination of Lambdas and/or also custom developed business services running in a container (ECS/Fargate, App Runner)
  3. Our load requirements are low because it is a private internal API that is not bound to any public facing traffic. So it will be queried either on a schedule or in response to a queue of jobs coming into existense coming from somewhere (which can be rate limited). Currently using a t2.small and this is working fine for us.

Workaround for those in need now

I have developed the stack below that I can add quickly to any RFDK stack. This deploys a Deadline WebService behind a non-public App Load Balancer and takes advantage of the various "automagic" Deadline configuration features of the RFDK.

To access the web service, find the App Load Balancer DNS name and add the /api suffix followed by the REST resource you need:

http://<APP_LOAD_BALANCER_DNS_ADDRESS>/api

Example: 
http://internal-xxxxxx-12345678.eu-west-1.elb.amazonaws.com/api/jobs
deadline-api-stack.ts

```typescript import { Duration, Stack, StackProps } from "aws-cdk-lib"; import { InstanceClass, InstanceSize, InstanceType, MachineImage, Peer, Port, SubnetType, Vpc, } from "aws-cdk-lib/aws-ec2"; import { Construct } from "constructs"; import { RenderQueue } from "aws-rfdk/deadline"; import { AutoScalingGroup, HealthCheck, Signals, } from "aws-cdk-lib/aws-autoscaling"; import { ApplicationLoadBalancer, ApplicationProtocol, } from "aws-cdk-lib/aws-elasticloadbalancingv2"; import { DeadlineStack } from "./deadline-stack"; import { SessionManagerHelper } from "aws-rfdk"; export interface RestApiStackProps extends StackProps { vpc: Vpc; renderQueue: RenderQueue; } export class RestApiStack extends Stack { constructor(scope: Construct, id: string, props: RestApiStackProps) { super(scope, id, props); // Web server const webServerAsg = new AutoScalingGroup(this, "RestApiFleet", { vpc: props.vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS, }, instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.SMALL), machineImage: MachineImage.genericLinux({ [this.region]: DeadlineStack.DEADLINE_WORKER_AMI, }), minCapacity: 1, maxCapacity: 1, signals: Signals.waitForMinCapacity({ timeout: Duration.minutes(10), }), healthCheck: HealthCheck.elb({ grace: Duration.minutes(1), }), }); webServerAsg.userData.addSignalOnExitCommand(webServerAsg); SessionManagerHelper.grantPermissionsTo(webServerAsg); // Configure it as a worker for convenience props.renderQueue.configureClientInstance({ host: webServerAsg, }); // Start the Deadline Web Service as background process webServerAsg.userData.addCommands( "/opt/Thinkbox/Deadline10/bin/deadlinewebservice &", ); // Create an ALB so that we have a stable DNS address for the web server, independent of // auto-scaling group changes const appLb = new ApplicationLoadBalancer(this, "RestApiAlb", { vpc: props.vpc, internetFacing: false, vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS, }, deletionProtection: false, }); // Using port 80 for simplicity since this is only accessible inside of the private VPC // Update this to use HTTPS and using certs generated from the RenderFarm RootCA certificate // if you want to make it public or encrypted in transit const listener = appLb.addListener("ApiListener", { port: 80, }); listener.addTargets("WebServer", { port: 8081, protocol: ApplicationProtocol.HTTP, targets: [webServerAsg], }); webServerAsg.connections.allowFrom( appLb, Port.tcp(8081), "Allow traffic from ALB", ); // Allow traffic from anywhere in the VPC appLb.connections.allowFrom( Peer.ipv4("10.0.0.0/16"), Port.tcp(80), "Allow Web API access from VPC", ); } } ```

Note: