#amazon-web-services #amazon-s3 #azure-devops #yaml #amazon-cloudformation
Вопрос:
Я хочу автоматизировать процесс создания корзины с помощью конвейера CI/CD на основе данных, упомянутых в одном из файлов yaml. Итак, у меня есть ведро.файл yaml, содержащий имена всех сегментов. Этот файл продолжает меняться по мере добавления новых имен блоков в будущем. В настоящее время именно так обстоит дело с ведром.ямл выглядит
BucketName:
- test-bucket
- test-bucket2
- test-bucket3
У меня есть один шаблон.файл yaml, который является шаблоном cloudformation для создания корзин s3. Вот как это выглядит:
Resources:
S3Bucket:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: This will come from bucket.yaml
Итак, шаблон.yaml будет извлекать имена ведер из ведра.файл yaml и должен создать 3 ведра, как указано в файле bucket.yaml. Если кто-то добавит еще 2 ведра в ведро.ямл, затем шаблон.yaml также должен создать эти 2 новых ведра. Кроме того, если кто-то удалит какое-либо имя корзины из корзины.yaml, тогда эти ведра также должны быть удалены. Я не мог выяснить процесс в своих исследованиях, просто нашел информацию по кусочкам.Итак, здесь у меня есть конкретные вопросы, если это возможно сделать:
- Как получить имена ведер из ведра.yaml и шаблон.yaml должен создать все ведра.
- Если кто-то обновит/добавит/удалит имя корзины в корзине.ямл, шаблон.yaml должен соответствующим образом обновить их. Кроме того, пожалуйста, объясните, как я буду это делать с помощью конвейера CI/CD в Azure DevOps.
Ответ №1:
- По поводу вашего первого вопроса:
Как получить имена ведер из ведра.yaml и шаблон.yaml должен создать все ведра.
В bucket.yaml
вы можете использовать параметры для настройки BucketName
.
Например:
parameters:
- name: BucketName
type: object
default:
- test-bucket
- test-bucket2
- test-bucket3
steps:
- ${{ each value in parameters.BucketName }}:
- script: echo ${{ value }}
На этом шаге можно просмотреть значения параметра BucketName
.
В template.yaml
том, что вы можете позвонить bucket.yaml
, как показано ниже.
trigger:
- main
extends:
template: bucket.yaml
- По вашему второму вопросу:
Если кто-то обновит/добавит/удалит имя корзины в корзине.ямл, шаблон.yaml должен соответствующим образом обновить их.
Нет никакого простого способа сделать это. Вы можете попробовать написать сценарий для запуска в конвейере, чтобы выполнить следующие действия:
- Перечислите все созданные сегменты. Это список существующих корзин.
- Сравните список существующих сегментов со списком значений параметра
BucketName
, чтобы проверить, какие сегменты необходимо добавить, а какие необходимо удалить. - Если в параметре указано ведро, но его нет в существующих ведрах, это ведро должно быть создано как новое ведро.
- Если ведро указано в существующих ведрах, но не в параметре, это ведро следует удалить.
Комментарии:
1. Могу ли я использовать эти шаблоны yaml в своей задаче создания/обновления CF в конвейерах CI/CD?
2. Привет @RamanBalyan, обычно вы не можете использовать шаблон в задаче конвейера. Шаблон используется для повторного использования этапов, заданий, шагов и переменных в конвейере YAML. Но вызов задачи в другой задаче не поддерживается.
Ответ №2:
BucketName:
- test-bucket
- test-bucket2
- test-bucket3
Требования подразумевают, что все сегменты S3 будут созданы одинаковым образом и что никаких отклонений от заданного шаблона Cloudformation ( AWS::S3::Bucket
) не требуется.
Требования требуют, чтобы мы отслеживали, какие сегменты S3 необходимо удалить. Cloudformation не удалит сегменты S3, так как фрагмент шаблона Cloudformation содержит политику удаления сохранения.
Решение:
Сегменты S3 могут быть помечены определенным образом, чтобы идентифицировать их как принадлежащие текущему конвейеру CI/CD. Сегменты S3 могут быть перечислены, и все сегменты S3, которые помечены правильным образом, но все же не существуют, bucket.yaml
могут быть удалены.
Я бы лично просто создал корзины S3, необходимые для конвейера CI/CD, с помощью AWS SDK, и вручную управлял удалением корзины S3. Если приложению требуется корзина S3, они должны создать ее самостоятельно в стеке Cloudformation своего приложения, чтобы они могли !Изменить ее и настроить так, как они хотят (например, шифрование в состоянии покоя, управление версиями, правила жизненного цикла и т. Д.).
Техническое примечание:
Для удаления корзины S3 также необходимо удалить ее содержимое. Для этого нам потребуется перечислить все объекты в корзине S3, а затем удалить их. Некоторая документация для Java SDK [здесь]. Только впоследствии вызов API для удаления корзины S3 завершится успешно.
Вы можете заставить Cloudformation удалить ваши объекты S3 с помощью пользовательского ресурса. Тем не менее, я не нахожу пользовательские ресурсы, с которыми интересно работать, поэтому, если вы можете использовать AWS SDK в своем конвейере CI/CD, я бы, вероятно, просто использовал это.
Пользовательский ресурс для удаления содержимого корзины может выглядеть примерно так в Cloudformation: (Это пользовательский ресурс, который использует Лямбду. Лямбда-код удалит содержимое корзины S3, если пользовательский ресурс будет удален)
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-custom-resources-lambda-lookup-amiids.html
ExampleBucketOperationCustomResource:
Type: AWS::CloudFormation::CustomResource
DependsOn: [Bucket, ExampleBucketOperationLambdaFunction]
Properties:
ServiceToken: !GetAtt ExampleBucketOperationLambdaFunction.Arn
# Custom properties
BucketToUse: !Ref S3BucketName
ExampleBucketOperationLambdaFunctionExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "ExampleBucketOperationLambda-ExecutionRole"
Path: "/"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
Policies:
- PolicyName: "ExampleBucketOperationLambda-CanAccessCloudwatchLogs"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- PolicyName: "ExampleBucketOperationLambda-S3BucketLevelPermissions"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:ListBucket
Resource:
- !Sub "arn:aws:s3:::${S3BucketName}"
- PolicyName: "ExampleBucketOperationLambda-S3ObjectLevelPermissions"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:DeleteObject
- s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${S3BucketName}/*"
# Test payload:
# {"RequestType":"Create","ResourceProperties":{"BucketToUse":"your-bucket-name"}}
ExampleBucketOperationLambdaFunction:
Type: AWS::Lambda::Function
DependsOn: ExampleBucketOperationLambdaFunctionExecutionRole
# DeletionPolicy: Retain
Properties:
FunctionName: "ExampleBucketOperationLambda"
Role: !GetAtt ExampleBucketOperationLambdaFunctionExecutionRole.Arn
Runtime: python3.8
Handler: index.handler
Timeout: 30
Code:
ZipFile: |
import boto3
import cfnresponse
def handler(event, context):
eventType = event["RequestType"]
print("The event type is: " str(eventType));
bucketToUse = event["ResourceProperties"]["BucketToUse"]
print("The bucket to use: " str(bucketToUse));
try:
# Requires s3:ListBucket permission
if (eventType in ["Delete"]):
print("Deleting everyting in bucket: " str(bucketToUse));
s3Client = boto3.client("s3")
s3Bucket = boto3.resource("s3").Bucket(bucketToUse)
for currFile in s3Bucket.objects.all():
print("Deleting file: " currFile.key);
s3Client.delete_object(Bucket=bucketToUse, Key=currFile.key)
print("All done")
responseData = {}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
except Exception as e:
responseData = {}
errorDetail = "Exception: " str(e)
errorDetail = errorDetail "nt More detail can be found in CloudWatch Log Stream: " context.log_stream_name
print(errorDetail)
cfnresponse.send(event=event, context=context, responseStatus=cfnresponse.FAILED, responseData=responseData, reason=errorDetail)
Ответ №3:
Спасибо за приведенные выше ответы. Я выбрал другой путь для решения этой проблемы. Я использовал AWS CDK, чтобы реализовать то, что я точно хотел. Я лично использовал AWS CDK для Python и создал инфраструктуру с его помощью.