Voy a dejar por aquí un mini post con cuatro notas básicas sobre AWS CloudFormation para tenerlo a mano. Son las típicas cosas que nunca me acuerdo y has de mirar todo el rato.
Deletion policies en AWS CloudFormation
Hay tres tipos de políticas de borrado:
- Retain
- Delete
- Snapshot
Si usamos Retain, AWS CloudFormation borrará el recurso lógico será borrado pero físicamente, el recurso de AWS seguirá existiendo.
Si escogemos Delete, al borrar un recurso de AWS Cloudformation el recurso será eliminado.
Con snapshot, el recurso lógico será eliminado del stack pero físicamente, será destruido y ejecutado un último snapshot.
AWSTemplateFormatVersion: '2010-09-09'
Resources:
myS3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
If a resource has no
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.htmlDeletionPolicy
attribute, AWS CloudFormation deletes the resource by default.
Como hacer un condicional en AWS CloudFormation
Conditions:
IsProdEnvironment: !Equals
- !Ref 'Environment'
- prod
# A la hora de crear un recurso
Replica:
Type: AWS::RDS::DBInstance
Condition: IsProdEnvironment
# A la hora de crear un recurso dentro de otro
# Solo creamos el ingress rule SI NO es Producción.
Resources:
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${Environment}-benancio-sg"
GroupDescription: !Sub "${Environment}-benancio-sg"
SecurityGroupIngress:
- !If
- IsProdEnvironment
- !Ref AWS::NoValue
- Description: "Allow access from salchipapa service when is not Production"
FromPort: 3306
ToPort: 3306
IpProtocol: tcp
SourceSecurityGroupId:
Fn::ImportValue: !Sub "${Environment}-salchipapa-service"
Como hacer un mapping en AWS CloudFormation
Mappings:
RegionMap:
us-east-1:
HVM64: "ami-0ff8a91507f77f867"
HVMG2: "ami-0a584ac55a7631c0c"
Resources:
myEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: !FindInMap
- RegionMap
- !Ref 'AWS::Region'
- HVM64
InstanceType: m1.small
Funciones en AWS CloudFormation
Fn::ImportValue
Cuando queremos importar el valor que ha sido exportado desde otro stack, utilizaremos Fn::ImportValue
The intrinsic function
Fn::ImportValue
returns the value of an output exported by another stack. You typically use this function to create cross-stack references. In the following example template snippets, Stack A exports VPC security group values and Stack B imports them.
Task: Type: AWS::ECS::TaskDefinition Properties: Memory: '1024' Cpu: '1024' NetworkMode: awsvpc TaskRoleArn: Fn::ImportValue: !Sub ${Environment}-role-arn
El stack que exporta:
Outputs: ConnectorRole: Description: IAM Role Value: !GetAtt ConnectorRole.Arn Export: Name: !Sub ${EnvName}-role-arn
Fn::Sub
Substitución de strings
The intrinsic function
Fn::Sub
substitutes variables in an input string with values that you specify. In your templates, you can use this function to construct commands or outputs that include values that aren’t available until you create or update a stack
En algunos sitios, recomiendan utilizar Sub en vez de Join cuando queremos construir strings.
Por ejemplo, en vez de hacer esto:
RoleName: # hello-world-dev-{region}-lambdaRole
!Join
- '-'
- - 'hello-world'
- 'dev'
- !Ref 'AWS::Region'
- 'lambdaRole'
Podríamos utilizar Sub
PolicyName:
!Sub 'hello-world-dev-${AWS::Region}-lambdaRole
Además, con !Sub también podemos utilizar variables!
SourceArn:
!Sub
- 'arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*'
- { RestApi: Ref: ApiGatewayRestApi }
Fn::GetAtt
La función intrínseca
Fn::GetAtt
devuelve el valor de un atributo de un recurso de la plantilla.
Fn::Ref
La función intrínseca
Ref
devuelve el valor del parámetro o el recurso especificado.
Normalmente, utilizaremos Ref para acceder a parámetros dentro de nuestro template y GetAtt cuando queremos acceder a valores de recursos ya especificados en el mismo.
myDNS:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneId:
Fn::ImportValue: !Sub "${Environment}-my-zone"
RecordSets:
- Name: !Sub "service.mizone.${Environment}."
Type: A
AliasTarget:
HostedZoneId: !GetAtt ApiALBInternal.CanonicalHostedZoneID
DNSName: !GetAtt ApiALBInternal.DNSName
- Al especificar el nombre lógico de un parámetro, devuelve el valor del parámetro.
- Al especificar el nombre lógico de un recurso, devuelve un valor que se suele utilizar para hacer referencia a dicho recurso, como un ID físico.
Tipos más usados de objetos en AWS CloudFormation
Outputs
Outputs: ConnectorRole: Description: Role Value: !GetAtt Role.Arn Export: Name: !Sub ${EnvName}-role-arn
La sección Outputs
opcional declara valores de salida que puede importar a otras pilas (para crear referencias cruzadas de pilas), devolver en respuesta (para describir las llamadas a la pila), o ver en la consola de AWS CloudFormation. Por ejemplo, puede declarar la salida para el nombre del bucket de S3 para una pila
para que sea más fácil encontrar el bucket.
Stack Policy
La Stack Policy define que acciones se pueden hacer o no en nuestro stack . El ejemplo más fácil sería imaginar que tenemos algo muy crítico, como una base de datos. Y no queremos borrarla ni que nadie la borre pase lo que pase. Podríamos definir una stack policy para evitar que esto pase. Vamos a proteger nuestra RDS llamada “myDB”
StackPolicy": {
"Statement": [
{
"Action": "Update:*",
"Effect": "Allow",
"Principal": "*",
"Resource": "*"
},
{
"Action": [
"Update:Delete"
],
"Effect": "Deny",
"Principal": "*",
"Resource": "LogicalResourceId/myDB"
}
]
}
}
Desactivar stack policy via CLI
aws cloudformation set-stack-policy --stack-name myStack --stack-policy-body file://body.json
cat body.json
{
"Statement" : [
{
"Effect" : "Allow",
"Action" : "Update:*",
"Principal": "*",
"Resource" : "*"
}
]
}
Importar recursos existentes en un stack
- Import existing resources into a cloudformation
- It was already possible to remove resources from a stack without deleting them by setting the
DeletionPolicy
toRetain
. This, together with the new import operation, enables a new range of possibilities. For example, you are now able to:- Create a new stack importing existing resources.
- Import existing resources in an already created stack.
- Migrate resources across stacks.
- Remediate a detected drift.
- Refactor nested stacks by deleting children stacks from one parent and then importing them into another parent stack.
- https://aws.amazon.com/es/blogs/aws/new-import-existing-resources-into-a-cloudformation-stack/
- It was already possible to remove resources from a stack without deleting them by setting the
Crear stack usando la CLI
aws cloudformation create-stack --template-body file://infrastructure/02-ecs.yml --capabilities=CAPABILITY_IAM --stack-name Devops-ECS --profile app --region eu-west-1 --tags Key=Contact,Value=test Key=Role,Value=test Key=Repo,Value=test Key=Env,Value=test Key=Team,Value=test Key=Project,Value=test
AWS CloudFormation y cfn-Init
https://advancedweb.hu/how-to-use-cfn-init-to-set-up-ec2-instances-with-cloudformation/
https://docs.aws.amazon.com/es_es/AWSCloudFormation/latest/UserGuide/cfn-signal.html
Links
- https://medium.com/@windix/s3-bucket-notification-to-lambda-in-cloudformation-without-circular-reference-f8f56ec5342c
- https://aws-blog.de/2019/08/getting-around-circular-cloudformation-dependencies-s3-event-lambda-role.html
- https://docs.aws.amazon.com/es_es/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
- https://theburningmonk.com/2019/05/cloudformation-protip-use-fnsub-instead-of-fnjoin/
- https://theburningmonk.com/cloudformation-ref-and-getatt-cheatsheet/