Unas notas fáciles y breves sobre AWS CloudFormation para no olvidarnos

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 DeletionPolicy attribute, AWS CloudFormation deletes the resource by default.

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html

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

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

Leave a Reply

Your email address will not be published. Required fields are marked *