Cuando se trata de replicación de datos entre Buckets S3, nos encontramos comunmente con 2 escenarios:
- Los Buckets (Source & Target) se encuentran en la misma cuenta.
- Los Buckets (Source & Target) se encuentran en cuenas diferentes.
Es importante resaltar que existen multiples metodos para replicar datos entre buckets, sin embargo es fundamental entender el caso de uso que se esté abordando en ese momento. En esta publicación nos enfocaremos en casos donde estrictamente se replicará objetos entre S3 Buckets, por lo cual podriamos optar por utilizar la funcionalidad más standard ofrecida por el propio servicio de S3. Estas implementaciones las realizaremos utilizando CloudFormation.
Si bien ambos escenarios son muy similares, hay que considerar que difieren sensiblemente en la manera de que se deben implementar. Para el caso de que los Buckets se encuentran en la misma cuenta, no debe considerarse la incorporación de una Bucket Policy **en el Target Bucket, sin embargo debe considerarse la activación del **Versionado, ya que es condición necesaria para que funcione la replicación y además sirve para poder restaurar los objetos a su versión anterior.
Para desplegar la Solución #1 (Buckets en la misma Cuenta), deberemos crear los siguientes archivos:
- Archivo de Deploy (deploy.sh)
###
STACK_NAME="s3-replication-same-account-template"
TEMPLATE_FILE_NAME="s3-replication-same-account-template"
###
PROFILE="default"
ARTIFACTORY_BUCKET="**Nombre de un Random Bucket, para subir el tamplate**"
#1) Create Package
aws cloudformation package --template ./$TEMPLATE_FILE_NAME.yaml \
--s3-bucket $ARTIFACTORY_BUCKET \
--output json > $TEMPLATE_FILE_NAME-packaged-$ENV.yaml \
--profile $PROFILE
#2.1) Create Stack (From Package)
aws cloudformation create-stack --stack-name $STACK_NAME \
--parameters file://./parameters.json \
--template-body file://./$TEMPLATE_FILE_NAME-packaged-$ENV.yaml \
--profile $PROFILE \
--region us-east-1 \
--capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_NAMED_IAM
- Archivo de Parametros (parameters.json)
[
{
"ParameterKey": "pSampleType",
"ParameterValue": "same-account-replication"
}
]
- Archivo de Cloudformation (s3-replication-same-account- template.yaml)
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: "Same Account - S3 Replication"
Parameters:
pSampleType:
Description: S3 Replication Sample Type
Type: String
Resources:
#####################################################
#################### S3 BUCKET ######################
#####################################################
rSourceBucket:
#DependsOn: rReplicationRole
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${pSampleType}-source-bucket-${AWS::AccountId}"
VersioningConfiguration:
Status: Enabled
ReplicationConfiguration:
Role: !GetAtt rReplicationRole.Arn
Rules:
- Id: !Sub "${pSampleType}-sample"
Status: Enabled
Prefix: datalake
Destination:
Bucket: !GetAtt rDestinationBucket.Arn
StorageClass: STANDARD
Tags:
- Key: "S3-BucketName"
Value: !Sub "${pSampleType}-source-bucket-${AWS::AccountId}"
- Key: "CostCenter"
Value: "00000"
rDestinationBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${pSampleType}-destination-bucket-${AWS::AccountId}"
VersioningConfiguration:
Status: Enabled
Tags:
- Key: "S3-BucketName"
Value: !Sub "${pSampleType}-destination-bucket-${AWS::AccountId}"
- Key: "CostCenter"
Value: "00000"
#####################################################
##################### IAM ROLE ######################
#####################################################
rReplicationRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Sub "${pSampleType}-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "sts:AssumeRole"
Effect: "Allow"
Principal:
Service:
- "s3.amazonaws.com"
Policies:
- PolicyName: S3ReplicationPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- "s3:GetObjectVersionForReplication"
- "s3:GetObjectVersionAcl"
- "s3:GetObjectVersionTagging"
Resource: !Sub "arn:aws:s3:::${pSampleType}-source-bucket-${AWS::AccountId}/*"
- Effect: Allow
Action:
- "s3:ListBucket"
- "s3:GetReplicationConfiguration"
Resource: !Sub "arn:aws:s3:::${pSampleType}-source-bucket-${AWS::AccountId}"
- Effect: Allow
Action:
- "s3:ReplicateObject"
- "s3:ReplicateDelete"
- "s3:ReplicateTags"
Resource: !Sub "arn:aws:s3:::${pSampleType}-destination-bucket-${AWS::AccountId}/*"
Para desplegar la solución simplemente se debe ejecutar el archivo de deploy de la siguiente manera:
bash deploy.sh
Continuando con el despliegue de la Solución #2 (Buckets en distintas cuentas), deberemos crear los siguientes archivos:
- Archivo de Deploy Source (deploy_source.sh)
###
STACK_NAME="s3-replication-different-account-source-template"
TEMPLATE_FILE_NAME="s3-replication-different-account-source-template"
###
PROFILE="default"
ARTIFACTORY_BUCKET="**Nombre de un Random Bucket, para subir el tamplate**"
#1) Create Package
aws cloudformation package --template ./$TEMPLATE_FILE_NAME.yaml \
--s3-bucket $ARTIFACTORY_BUCKET \
--output json > $TEMPLATE_FILE_NAME-packaged-$ENV.yaml \
--profile $PROFILE
#2.1) Create Stack (From Package)
aws cloudformation create-stack --stack-name $STACK_NAME \
--parameters file://./parameters-source.json \
--template-body file://./$TEMPLATE_FILE_NAME-packaged-$ENV.yaml \
--profile $PROFILE \
--region us-east-1 \
--capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_NAMED_IAM
- Archivo de Deploy Target (deploy_destination.sh)
###
STACK_NAME="s3-replication-different-account-destination-template"
TEMPLATE_FILE_NAME="s3-replication-different-account-destination-template"
###
PROFILE="default"
ARTIFACTORY_BUCKET="**Nombre de un Random Bucket, para subir el tamplate**"
#1) Create Package
aws cloudformation package --template ./$TEMPLATE_FILE_NAME.yaml \
--s3-bucket $ARTIFACTORY_BUCKET \
--output json > $TEMPLATE_FILE_NAME-packaged-$ENV.yaml \
--profile $PROFILE
#2.1) Create Stack (From Package)
aws cloudformation create-stack --stack-name $STACK_NAME \
--parameters file://./parameters-destination.json \
--template-body file://./$TEMPLATE_FILE_NAME-packaged-$ENV.yaml \
--profile $PROFILE \
--region us-east-1 \
--capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_NAMED_IAM
- Archivo de Parametros Source (parameters-source.json)
[
{
"ParameterKey": "pSampleType",
"ParameterValue": "different-account-replication"
},
{
"ParameterKey": "pDestinationBucketName",
"ParameterValue": "different-account-replication-destination-bucket-aws-account-id"
}
]
- Archivo de Parametros Source (parameters-destination.json)
[
{
"ParameterKey": "pSampleType",
"ParameterValue": "different-account-replication"
},
{
"ParameterKey": "pReplicationRoleArn",
"ParameterValue": "arn:aws:iam::aws-account-id:role/different-account-replication-role"
}
]
- Archivo de Cloudformation (s3-replication-different-account-source-template.yaml)
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: "Same Account - S3 Replication"
Parameters:
pSampleType:
Description: S3 Replication Sample Type
Type: String
pDestinationBucketName:
Description: S3 Destination Bucket
Type: String
Resources:
#####################################################
#################### S3 BUCKET ######################
#####################################################
rSourceBucket:
#DependsOn: rReplicationRole
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${pSampleType}-source-bucket-${AWS::AccountId}"
VersioningConfiguration:
Status: Enabled
ReplicationConfiguration:
Role: !GetAtt rReplicationRole.Arn
Rules:
- Id: !Sub "${pSampleType}-sample"
Status: Enabled
Prefix: datalake
Destination:
Bucket: !Sub "arn:aws:s3:::${pDestinationBucketName}"
StorageClass: STANDARD
Tags:
- Key: "S3-BucketName"
Value: !Sub "${pSampleType}-source-bucket-${AWS::AccountId}"
- Key: "CostCenter"
Value: "00000"
#####################################################
##################### IAM ROLE ######################
#####################################################
rReplicationRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: !Sub "${pSampleType}-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "sts:AssumeRole"
Effect: "Allow"
Principal:
Service:
- "s3.amazonaws.com"
Policies:
- PolicyName: S3ReplicationPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- "s3:GetObjectVersionForReplication"
- "s3:GetObjectVersionAcl"
- "s3:GetObjectVersionTagging"
Resource: !Sub "arn:aws:s3:::${pSampleType}-source-bucket-${AWS::AccountId}/*"
- Effect: Allow
Action:
- "s3:ListBucket"
- "s3:GetReplicationConfiguration"
Resource: !Sub "arn:aws:s3:::${pSampleType}-source-bucket-${AWS::AccountId}"
- Effect: Allow
Action:
- "s3:ReplicateObject"
- "s3:ReplicateDelete"
- "s3:ReplicateTags"
Resource: !Sub "arn:aws:s3:::${pDestinationBucketName}/*"
- Archivo de Cloudformation (s3-replication-different-account-destination-template.yaml)
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: "Same Account - S3 Replication"
Parameters:
pSampleType:
Description: S3 Replication Sample Type
Type: String
pReplicationRoleArn:
Description: Role in the source account for the replication
Type: String
Resources:
#####################################################
#################### S3 BUCKET ######################
#####################################################
rDestinationBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${pSampleType}-destination-bucket-${AWS::AccountId}"
VersioningConfiguration:
Status: Enabled
Tags:
- Key: "S3-BucketName"
Value: !Sub "${pSampleType}-destination-bucket-${AWS::AccountId}"
- Key: "CostCenter"
Value: "00000"
# #####################################################
# ################## BUCKET POLICY ####################
# #####################################################
rDestinationBucketsPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Sub "${pSampleType}-destination-bucket-policy-${AWS::AccountId}"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
AWS: !Ref pReplicationRoleArn
Action:
- "s3:ReplicateObject"
- "s3:ReplicateDelete"
Resource: !Sub "${rDestinationBucket.Arn}/*"
- Effect: "Allow"
Principal:
AWS: !Ref pReplicationRoleArn
Action:
- "s3:List*"
- "s3:GetBucketVersioning"
- "s3:PutBucketVersioning"
Resource: !GetAtt rDestinationBucket.Arn
Para desplegar la solución simplemente se debe ejecutar el archivo de deploy pero en las 2 cuentas de AWS (Source & Target), de la misma manera que en el escenerio #1.
Para Finalizar, se debe considerar que la replicación entre objetos puede demorar algunos segundos o varios minutos, ya que va a depender de AWS, sin embargo AWS cuenta con RTC, que básicamente es un SLA, donde asegura que en el lapso de 15 minutos (Máximo) serán replicados los objetos desde el Source al Target. Es clave tener en consideración esta feature cuando se tratan de escenarios de casos de uso críticos donde contar con los objetos a tiempo es necesario.
Muchas gracias!
Cristian R. Carballo
https://www.linkedin.com/in/cristianrcarballo/
Top comments (0)