cloud:aws:cloudformation
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
cloud:aws:cloudformation [2018/08/09 15:14] – skipidar | cloud:aws:cloudformation [2023/12/05 15:02] (current) – skipidar | ||
---|---|---|---|
Line 1: | Line 1: | ||
===== CloudFormation ===== | ===== CloudFormation ===== | ||
+ | |||
+ | ==== Why is Terraform better? ==== | ||
+ | |||
+ | * " | ||
+ | * " | ||
+ | * " | ||
+ | * CloudFormation has a very NOT user friendly lifecycle. Forcing to "is in ROLLBACK_COMPLETE state and can not be updated" | ||
+ | * Minor. Cloudformation " | ||
+ | * Cloudformation support of moving resources between stacks is very chatty | ||
+ | |||
+ | |||
+ | ==== Deploying with cloudformation ==== | ||
+ | |||
+ | If using nested-stacks first you need a bucket, | ||
+ | into which you will package nested stacks. | ||
+ | |||
+ | <sxh yaml> | ||
+ | AWSTemplateFormatVersion: | ||
+ | Description: | ||
+ | Resources: | ||
+ | |||
+ | MyS3SubstackBucket: | ||
+ | Type: AWS:: | ||
+ | Properties: | ||
+ | BucketName: my-alf-s3-package-bucket-2023-12-05 | ||
+ | AccessControl: | ||
+ | Tags: | ||
+ | - Key: Purpose | ||
+ | Value: CF stacks bucket | ||
+ | |||
+ | |||
+ | MyBucketPolicy: | ||
+ | Type: AWS:: | ||
+ | Properties: | ||
+ | Bucket: !Ref MyS3SubstackBucket | ||
+ | PolicyDocument: | ||
+ | Statement: | ||
+ | - Sid: AllowCloudFormationAccess | ||
+ | Effect: Allow | ||
+ | Principal: | ||
+ | Service: cloudformation.amazonaws.com | ||
+ | Action: s3:* | ||
+ | Resource: !Join | ||
+ | - '' | ||
+ | - - ' | ||
+ | - !Ref MyS3SubstackBucket | ||
+ | - /* | ||
+ | </ | ||
+ | |||
+ | now deploy the bucket | ||
+ | <sxh shell> | ||
+ | |||
+ | FILENAME=" | ||
+ | STACKNAME=" | ||
+ | REGION=" | ||
+ | |||
+ | # validate | ||
+ | aws cloudformation validate-template --template-body file:// | ||
+ | |||
+ | |||
+ | # check the change set | ||
+ | aws cloudformation deploy --stack-name $STACKNAME --template-file $FILENAME --region $REGION --no-execute-changeset | ||
+ | |||
+ | |||
+ | # execute via " | ||
+ | aws cloudformation deploy --stack-name $STACKNAME --template-file $FILENAME --region $REGION | ||
+ | |||
+ | |||
+ | # delete stack | ||
+ | # aws cloudformation delete-stack --stack-name $STACKNAME | ||
+ | </ | ||
+ | |||
+ | |||
+ | parent1.cloudformation.yaml | ||
+ | <sxh yaml> | ||
+ | AWSTemplateFormatVersion: | ||
+ | Description: | ||
+ | |||
+ | Parameters: | ||
+ | |||
+ | VpcIdParameter: | ||
+ | Type: String | ||
+ | Default: " | ||
+ | | ||
+ | packageBucket: | ||
+ | Type: String | ||
+ | Default: " | ||
+ | |||
+ | Resources: | ||
+ | |||
+ | SubStack1: | ||
+ | Type: AWS:: | ||
+ | Properties: | ||
+ | TemplateURL: | ||
+ | Parameters: | ||
+ | VpcId: !Ref VpcIdParameter | ||
+ | |||
+ | </ | ||
+ | |||
+ | substack.helloworld.cloudformation.yaml | ||
+ | <sxh yaml> | ||
+ | AWSTemplateFormatVersion: | ||
+ | Description: | ||
+ | |||
+ | Parameters: | ||
+ | VpcId: | ||
+ | Type: String | ||
+ | |||
+ | |||
+ | Resources: | ||
+ | |||
+ | MySecurityGroup: | ||
+ | Type: AWS:: | ||
+ | Properties: | ||
+ | GroupDescription: | ||
+ | VpcId: !Ref VpcId | ||
+ | SecurityGroupIngress: | ||
+ | - IpProtocol: tcp | ||
+ | FromPort: 80 | ||
+ | ToPort: 80 | ||
+ | CidrIp: 0.0.0.0/0 # Example: Allowing HTTP traffic from anywhere (Please adjust for your use case) | ||
+ | Tags: | ||
+ | - Key: Name | ||
+ | Value: MySecurityGroup | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | now you can package the stack | ||
+ | |||
+ | * the sub-stacks will end up in the package-bucket. | ||
+ | * a new file `packaged-root-template.yaml` is generated, where the `TemplateURL` field is replaced by s3 references. | ||
+ | * you can deploy the parent stack and see nested stacks being deployed too. | ||
+ | |||
+ | |||
+ | |||
+ | <sxh shell> | ||
+ | set -e | ||
+ | |||
+ | FILENAME=" | ||
+ | STACKNAME=" | ||
+ | REGION=" | ||
+ | PACKAGEBUCKET=" | ||
+ | |||
+ | |||
+ | # validate | ||
+ | # aws cloudformation validate-template --template-body file:// | ||
+ | |||
+ | |||
+ | # package uploading substacks | ||
+ | rm packaged-root-template.yaml | ||
+ | aws cloudformation package --template-file $FILENAME --s3-bucket $PACKAGEBUCKET | ||
+ | |||
+ | |||
+ | |||
+ | # check the change set, dont execute : " | ||
+ | # aws cloudformation deploy --stack-name $STACKNAME --template-file $FILENAME --region $REGION --no-execute-changeset | ||
+ | |||
+ | # arn of change set is printed, here arn: | ||
+ | |||
+ | # can see change-set | ||
+ | # aws cloudformation describe-change-set --change-set-name arn: | ||
+ | |||
+ | # can continue via | ||
+ | # aws cloudformation execute-change-set --change-set-name arn: | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | # execute via " | ||
+ | aws cloudformation deploy --stack-name $STACKNAME --template-file packaged-root-template.yaml --region $REGION | ||
+ | |||
+ | |||
+ | # delete stack | ||
+ | # aws cloudformation delete-stack --stack-name $STACKNAME | ||
+ | </ | ||
+ | |||
==== Structure ==== | ==== Structure ==== | ||
Line 180: | Line 359: | ||
} | } | ||
+ | </ | ||
+ | |||
+ | ==== Use !Sub in commands ==== | ||
+ | |||
+ | To reference cloudformation arguments in commands - use the " | ||
+ | < | ||
+ | Resources: | ||
+ | Parameters: | ||
+ | S3Prefix: | ||
+ | AllowedPattern: | ||
+ | ^s3:// | ||
+ | Description: | ||
+ | Type: String | ||
+ | |||
+ | ... | ||
+ | 04_execute: | ||
+ | command: !Sub | | ||
+ | ansible-playbook / | ||
</ | </ | ||
Line 558: | Line 755: | ||
| Human readable logs of the whole instance initiation | / | | Human readable logs of the whole instance initiation | / | ||
| Human readable logs of the cfn-init call | / | | Human readable logs of the cfn-init call | / | ||
+ | | Code from AWS:: | ||
+ | |||
+ | |||
+ | |||
=== Debug the initiation of the instance === | === Debug the initiation of the instance === | ||
Line 607: | Line 808: | ||
Stack A Export: | Stack A Export: | ||
- | <code> | + | <sxh js> |
" | " | ||
" | " | ||
Line 620: | Line 821: | ||
} | } | ||
} | } | ||
- | </code> | + | </sxh> |
Stack B Import | Stack B Import | ||
- | <code> | + | <sxh js> |
" | " | ||
" | " | ||
Line 640: | Line 841: | ||
} | } | ||
} | } | ||
- | </code> | + | </sxh> |
AWS specific parameters: | AWS specific parameters: | ||
* https:// | * https:// | ||
+ | |||
+ | |||
+ | |||
+ | ==== Structure ==== | ||
+ | |||
+ | |||
+ | Example of a custom definition in CLoudFormation. EFS with Fargate in this example | ||
+ | < | ||
+ | |||
+ | CustomTaskDefinition: | ||
+ | Type: ' | ||
+ | Version: ' | ||
+ | Properties: | ||
+ | ServiceToken: | ||
+ | TaskDefinition: | ||
+ | executionRoleArn: | ||
+ | containerDefinitions: | ||
+ | { | ||
+ | name: " | ||
+ | image: !Ref NavvisDockerImage, | ||
+ | memoryReservation: | ||
+ | logConfiguration: | ||
+ | logDriver: " | ||
+ | options: { | ||
+ | awslogs-group: | ||
+ | awslogs-datetime-format: | ||
+ | awslogs-region: | ||
+ | awslogs-stream-prefix: | ||
+ | } | ||
+ | }, | ||
+ | portMappings: | ||
+ | { | ||
+ | hostPort: 8080, | ||
+ | protocol: " | ||
+ | containerPort: | ||
+ | } | ||
+ | ], | ||
+ | command: [], | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ] | ||
+ | , | ||
+ | | ||
+ | | ||
+ | ] | ||
+ | } | ||
+ | ], | ||
+ | family: " | ||
+ | taskRoleArn: | ||
+ | requiresCompatibilities: | ||
+ | cpu: " | ||
+ | memory: " | ||
+ | networkMode: | ||
+ | volumes: [ | ||
+ | { | ||
+ | name: " | ||
+ | efsVolumeConfiguration: | ||
+ | fileSystemId: | ||
+ | } | ||
+ | }, | ||
+ | ] | ||
+ | } | ||
+ | CustomResourceFunction: | ||
+ | Type: ' | ||
+ | Properties: | ||
+ | Code: | ||
+ | ZipFile: | | ||
+ | const aws = require(' | ||
+ | const response = require(' | ||
+ | const ecs = new aws.ECS({apiVersion: | ||
+ | exports.handler = function(event, | ||
+ | console.log(" | ||
+ | if (event.RequestType === ' | ||
+ | ecs.registerTaskDefinition(event.ResourceProperties.TaskDefinition, | ||
+ | if (err) { | ||
+ | console.error(err); | ||
+ | response.send(event, | ||
+ | } else { | ||
+ | console.log(`Created/ | ||
+ | response.send(event, | ||
+ | } | ||
+ | }) | ||
+ | } else if (event.RequestType === ' | ||
+ | ecs.deregisterTaskDefinition({taskDefinition: | ||
+ | if (err) { | ||
+ | if (err.code === ' | ||
+ | console.log(`Task definition: ${event.PhysicalResourceId} does not exist. Skipping deletion.`) | ||
+ | response.send(event, | ||
+ | } else { | ||
+ | console.error(err) | ||
+ | response.send(event, | ||
+ | } | ||
+ | } else { | ||
+ | console.log(`Removed task definition ${event.PhysicalResourceId}`) | ||
+ | response.send(event, | ||
+ | } | ||
+ | }) | ||
+ | } else { | ||
+ | console.error(`Unsupported request type: ${event.RequestType}`) | ||
+ | response.send(event, | ||
+ | } | ||
+ | } | ||
+ | Handler: ' | ||
+ | MemorySize: 128 | ||
+ | Role: !GetAtt ' | ||
+ | Runtime: ' | ||
+ | Timeout: 30 | ||
+ | CustomResourceRole: | ||
+ | Type: ' | ||
+ | Properties: | ||
+ | AssumeRolePolicyDocument: | ||
+ | Version: ' | ||
+ | Statement: | ||
+ | - Effect: Allow | ||
+ | Principal: | ||
+ | Service: ' | ||
+ | Action: ' | ||
+ | Policies: | ||
+ | - PolicyName: ' | ||
+ | PolicyDocument: | ||
+ | Statement: | ||
+ | - Effect: Allow | ||
+ | Action: | ||
+ | - ' | ||
+ | - ' | ||
+ | Resource: ' | ||
+ | - Effect: Allow | ||
+ | Action: | ||
+ | - ' | ||
+ | - ' | ||
+ | - ' | ||
+ | Resource: ' | ||
+ | - Effect: Allow | ||
+ | Action: | ||
+ | - ' | ||
+ | Resource: ' | ||
+ | CustomLogsGroup: | ||
+ | Type: ' | ||
+ | Properties: | ||
+ | LogGroupName: | ||
+ | RetentionInDays: | ||
+ | |||
+ | |||
+ | NavvisServiceFargate: | ||
+ | Type: ' | ||
+ | Properties: | ||
+ | Cluster: {' | ||
+ | LaunchType: FARGATE | ||
+ | DesiredCount: | ||
+ | PlatformVersion: | ||
+ | DeploymentConfiguration: | ||
+ | MinimumHealthyPercent: | ||
+ | MaximumPercent: | ||
+ | TaskDefinition: | ||
+ | NetworkConfiguration: | ||
+ | AwsvpcConfiguration: | ||
+ | AssignPublicIp: | ||
+ | SecurityGroups: | ||
+ | - {' | ||
+ | Subnets: | ||
+ | - {' | ||
+ | - {' | ||
+ | - {' | ||
+ | LoadBalancers: | ||
+ | - ContainerName: | ||
+ | ContainerPort: | ||
+ | TargetGroupArn: | ||
+ | SchedulingStrategy: | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
cloud/aws/cloudformation.1533827693.txt.gz · Last modified: (external edit)