Skip to content
This repository has been archived by the owner on Sep 25, 2020. It is now read-only.

SpotFleet CloudFormation #69

Merged
merged 15 commits into from
Jun 26, 2017
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,46 @@ application/config/environments/*.local.yml
.DS_Store
.AppleDouble
.LSOverride

### https://raw.github.com/github/gitignore/9f6724149b9a0a861b402683f6c50c5f085d130b/node.gitignore

# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

infrastructure/**/built
7 changes: 7 additions & 0 deletions infrastructure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## How to Deploy

```bash
# BUCKET_NAME is used for `aws cloudformation package`
# STACK_NAME is used for `aws cloudformation deploy`
$ BUCKET_NAME=bucket-name STACK_NAME=stack-name bin/deploy
```
30 changes: 30 additions & 0 deletions infrastructure/bin/deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

if [ -z "$BUCKET_NAME" ]; then
echo 'BUCKET_NAME is required'
exit 1
fi

if [ -z "$STACK_NAME" ]; then
echo 'STACK_NAME is required'
exit 1
fi

TEMPLATE_FILE=cloudformation.yml

# Move project root
cd "$(dirname "$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$0")")/.." || exit 1

sh -c 'cd ./functions/RunEcsTask && npm install && npm run build && cp -rf ./node_modules ./built/'

mkdir -p ./built

aws cloudformation package \
--template-file "$TEMPLATE_FILE" \
--output-template-file ./built/cloudformation.yml \
--s3-bucket "$BUCKET_NAME"

aws cloudformation deploy \
--capabilities CAPABILITY_NAMED_IAM \
--template-file built/cloudformation.yml \
--stack-name "$STACK_NAME"
226 changes: 226 additions & 0 deletions infrastructure/cloudformation.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: revieee development settings
Resources:

Expand Down Expand Up @@ -163,6 +164,71 @@ Resources:
Properties:
ClusterName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeCluster ] ]

#------ SpotFleet ---------#
EcsSpotFleetRequest:
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfigData:
IamFleetRole: !GetAtt FleetIAMRole.Arn
SpotPrice: !Ref SpotPrice
TargetCapacity: !Ref TargetCapacity
LaunchSpecifications:
# NOTE:
# If you want to use other type of ec2 instances,
# fix these parameters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parametersでinstanceType指定できるようにした方が良い気がします。(デフォルト設定はいれておいて)
weightを偏らせているのでMainInstanceTypeとSubInstanceTypeとか?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たしかに!
parameterに入れといた方が、typeやidを変えたいときに、コード変えなくても大丈夫ですしね。
対応しておきます

- EbsOptimized: 'false'
InstanceType: 'm4.large'
ImageId: 'ami-3a000e5d'
WeightedCapacity: '4'
UserData:
Fn::Base64: !Sub |
#!/bin/bash
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
NetworkInterfaces:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このプロパティはいらないような?
subnetでpublic ipを振るように設定しているので特に指定しなければ勝手にpub ip付けてくれると思います。

MapPublicIpOnLaunch: true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このプロパティは、NetworkInterfacesのDeleteOnTerminationをtrueにするために書きました。
( それ以外の属性は、require trueのもののみ書いてる状態です )

明示的に指定しない場合、Subnet設定だけで Network Interfaceが消えるという資料を見つけられなかったからです。とはいえ、この設定だといるかいらないか判断かつかないので、一回消してみて、Network Interfaceが消えなかったら、再度対応します!

AssociatePublicIpAddress: ture
DeviceIndex: 0
SubnetId: !Ref ContainerInstanceSubnet1a
Groups:
- !GetAtt ContainerInstanceSecurityGroup.GroupId
DeleteOnTermination: true

- EbsOptimizes: 'false'
InstanceType: 'm3.large'
ImageId: 'ami-3a000e5d'
SubnetId:
Ref: ContainerInstanceSubnet1c
WeightedCapacity: '1'
UserData:
Fn::Base64: !Sub |
#!/bin/bash
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
NetworkInterfaces:
AssociatePublicIpAddress: ture
DeviceIndex: 0
SubnetId: !Ref ContainerInstanceSubnet1a
Groups:
- !GetAtt ContainerInstanceSecurityGroup.GroupId
DeleteOnTermination: true

FleetIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- 'arn:aws:iam::951787653356:role/revieee-spot-fleeet-role'
RoleName: !Join [ "-", [ !Ref "AWS::StackName", FleetIAMRole ] ]

#------- SpotFleet/ --------#

EndpointInstanceIamRole:
Type: AWS::IAM::Role
Properties:
Expand Down Expand Up @@ -199,6 +265,159 @@ Resources:
Value: RevieeeEndpointInstance
# UserData: [TODO] run itamae

# ------ API Gateway ------

ApiRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- apigateway.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "states:*"
Resource: "*"
PolicyName: !Join [ "-", [ !Ref "AWS::StackName", AWSStepFunctionsFullAccess ] ]
RoleName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeApiRole ] ]

RevieeeApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Join [ "-", [ !Ref "AWS::StackName", RevieeeApi ] ]
RevieeeApiResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref RevieeeApi
ParentId: !GetAtt RevieeeApi.RootResourceId
PathPart: "stage"
RevieeeApiCreateMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RevieeeApi
ResourceId: !Ref RevieeeApiResource
AuthorizationType: NONE
HttpMethod: POST
Integration:
IntegrationHttpMethod: POST
IntegrationResponses:
- StatusCode: 200
PassthroughBehavior: WHEN_NO_TEMPLATES
RequestTemplates:
application/json: !Sub
- |-
{
"input": "{}",
"name": "Hello",
"stateMachineArn": "${stateMachineArn}"
}
- { stateMachineArn: !Ref StateMachineCreate }
Type: AWS
Uri: !Join [ "", [ "arn:aws:apigateway:", !Ref "AWS::Region", ":states:action/StartExecution" ] ]
Credentials: !GetAtt ApiRole.Arn
MethodResponses:
- StatusCode: 200
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: RevieeeApiCreateMethod
Properties:
RestApiId: !Ref RevieeeApi
StageName: pub

# ------ /API Gateway ------

# ------ StepFunctions ------

StateMachineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- states.ap-northeast-1.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "lambda:InvokeFunction"
Resource: "*"
PolicyName: !Join [ "-", [ !Ref "AWS::StackName", StatesExecutionPolicy ] ]
RoleName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeStateMachineRole ] ]

StateMachineCreate:
Type: AWS::StepFunctions::StateMachine
Properties:
DefinitionString: !Sub
- |-
{
"Comment": "Run ECS Task",
"StartAt": "RunEcsTask",
"States": {
"RunEcsTask": {
"Type": "Task",
"Resource": "${taskArn}",
"End": true
}
}
}
- { "taskArn": !Ref RunEcsTaskFunction }
RoleArn: !GetAtt StateMachineRole.Arn

# ------ /StepFunctions ------

# ------ Lambda ------

RunEcsTaskFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: "ecs:RunTask"
Resource: "*"
PolicyName: !Join [ "-", [ !Ref "AWS::StackName", RunEcsTaskFunctionPolicy ] ]
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
RoleName: !Join [ "-", [ !Ref "AWS::StackName", RevieeeRunEcsTaskFunctionRole ] ]

RunEcsTaskFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs6.10
CodeUri: ./functions/RunEcsTask/built/
Role: !GetAtt RunEcsTaskFunctionRole.Arn

# ------ /Lambda ------

# Parameter
Parameters:
SSHPort:
Expand All @@ -209,6 +428,13 @@ Parameters:
Type: String
AcceptCidrIp:
Type: String
# Parameters for SpotFleetRequest
SpotPrice:
Default: 0.139
Type: Number
TargetCapacity:
Default: 2
Type: Number
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pataiji
来週レビューお願いします 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

差分、見やすい様に lambda-endpointをmerge先に向けています。
コードに問題無ければ masterにmergeします。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pataiji
指摘して貰った点修正したので、今日、暇な時にレビューお願いします!!


Conditions:
SSHKeySpecified:
Expand Down
23 changes: 23 additions & 0 deletions infrastructure/functions/RunEcsTask/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "run-ecs-task",
"version": "0.0.1",
"description": "Lambda function that to run ECS Task",
"main": "index.js",
"scripts": {
"build": "tsc -p ./tsconfig.json",
"clean": "rm -rf ./built"
},
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/speee/webapp-revieee"
},
"devDependencies": {
"@types/aws-lambda": "0.0.12",
"@types/node": "^7.0.31",
"aws-sdk": "^2.71.0",
"tslint": "^5.4.3",
"typescript": "^2.3.4"
}
}
32 changes: 32 additions & 0 deletions infrastructure/functions/RunEcsTask/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Callback, Context } from "aws-lambda";
import * as AWS from "aws-sdk";

const ecs = new AWS.ECS();

export function handler(event: any, context: Context, callback: Callback) {
const envBranch: AWS.ECS.KeyValuePair = {
name: "BRANCH",
value: "master",
};
const containerOverride: AWS.ECS.ContainerOverride = {
name: "main",
environment: [envBranch],
};
const taskOverride: AWS.ECS.TaskOverride = {
containerOverrides: [containerOverride],
};
const params: AWS.ECS.RunTaskRequest = {
cluster: "revieee",
taskDefinition: "arn:aws:ecs:ap-northeast-1:951787653356:task-definition/im-ieul-core:3",
overrides: taskOverride,
};

(async () => {
return await ecs.runTask(params).promise();
})().then((result: AWS.ECS.RunTaskResponse) => {
console.log(result.tasks);
callback(null, result.tasks[0].taskArn);
}).catch((err: AWS.AWSError) => {
callback(err);
});
}
Loading