Тестирование A/B, синие/зеленые развертывания, канареечные релизы. Разные, но все же столько общего. Все они имеют разные цели, но используют в основном, используя одно и то же техническое решение под капотом. Мы делаем такие испытания по нескольким причинам. Один — сделать тест A/B и определить, какую версию наших пользователей нравится лучшие. Уверен, что можно сделать A/B тестирование на клиентской стороне, но лично мне упростить на стороне сервера. Голубые/зеленые и канаречные развертывания сделаны, чтобы убедиться, что новая версия приложений работает так, как мы ожидаем и дам нам простой способ откатываться в предыдущую версию в случае проблемы. Все это важные практики в культуре DevOps.
Многие услуги от AWS предлагают это решение из коробки, одна услуга, которая не является Humentfront. К счастью, Cloudfront имеет возможность запустить лямбда @ kems, которую мы можем использовать для этого.
Все исходный код для этой настройки найден на [GitHub] [Github-link]
Представляем Lambda @ Edge
Лямбда может бежать в четырех разных местах в потоке запроса.
Запрос на зритель — работает, когда CloudFront получает запрос от зрителя. Происхождение запроса — бежит до того, как Cloudfront пересылает запрос к началу. Ответ происхождения — работает, когда CloudFront получает ответ от происхождения. Ответ зрителя — работает до того, как Cloudfront возвращает ответ на зрителя.
Существует несколько ограничений, когда дело доходит до лямбда @ kemun, можно только создавать функции в Python и Node.js. Функции запроса и реагирования Viewer могут выделить только 128 МБ памяти только в течение 3 секунд. Вы не можете использовать переменные среды, вы не можете использовать Последние Алиас версии, поддерживаются только фиксированные версии. Журналы публикуются в краевой регион, который вы получаете, а не на US-East-1 Регион, даже если функции должны быть развернуты в этом регионе. Обязательно прочитайте Документация Прежде чем начать работать с лямбда @ жрать.
Обзор решения
В этом решении мы собираемся использовать две разные функции лямбда для Запрос на зритель и Ответ происхождения Крючки, мы будем хранить конфигурацию в магазине параметра, а S3 — наше происхождение.
В Запрос на зритель Крюк мы проверим на специальное cookie, если файл cookie не установлен, мы внесем случайную версию. В Ответ происхождения Мы устанавливаем Set-cookie Заголовок для хранения версии, которую мы используем. Установив разные значения в магазине параметра, мы можем контролировать вес каждой версии, и мы также можем сбросить и иметь новую случайную версию.
Запрос на зритель
Начнем с функции Lambda, которая будет реагировать на событие запроса зрителя. Эта функция Lambda отвечает за проверку нашего cookie X-версия-имя Если значение установлено, функция обновит путь запроса на основе значения cookie. Если нет установленного значения, он будет катиться в Dice и получить случайную версию и обновить путь запроса. Эта функция также сопоставит значение в cookie X-версию-сброс к значению в магазине параметра, и если значение отличается, он будет игнорировать любое заданное значение в X-версия-имя Отказ Если нет значения в X-версия-имя Или если значение игнорируется, функция бросает кости и выбирает версию наугад. Вес для разных версий контролируется значением в магазине параметра. Наконец, функция пропускает cookie к следующему шагу в цепочке вызовов.
Код запроса зрителя
Полная версия доступна в [Github] [Github-link].
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']
headers = request['headers']
cookie_version_blue = 'X-Version-Name=Blue'
cookie_version_green = 'X-Version-Name=Green'
path_blue = '/Blue'
path_green = '/Green'
uri = ''
if request['uri'].endswith('/'):
request['uri'] = request['uri'] + 'index.html'
if 'cookie' not in request['headers']:
request['headers']['cookie'] = []
# Reset weights, ignore already set cookie
reset_weight, reset_cookie = do_weight_reset(headers)
if not reset_weight:
for cookie in headers.get('cookie', []):
if cookie_version_blue in cookie['value']:
uri = path_blue + request['uri']
break
elif cookie_version_green in cookie['value']:
uri = path_green + request['uri']
break
request['headers']['cookie'].append(
{'key': 'Cookie', 'value': reset_cookie})
if not uri:
weight = int(load_parameter('Weight'))
cookie_value = ''
if random.random() < float(weight / 100.0):
uri = path_blue + request['uri']
cookie_value = cookie_version_blue
else:
uri = path_green + request['uri']
cookie_value = cookie_version_green
request['headers']['cookie'].append(
{'key': 'Cookie', 'value': cookie_value})
request['uri'] = uri
return request
Ответ зрителя
Ответ зрителя Функция в основном имеет одну задачу, и это должен пройти Set-cookie заголовок к клиенту. Это необходимо, чтобы клиент устанавливал куки X-версия-имя и X-версия-сброс Таким образом, клиент отправляет их в следующий запрос. Это важно, чтобы клиент не прыгает между версиями. Функция имеет небольшую, но очень важное задание.
Код ответа зрителя
Полная версия доступна в [Github] [Github-link].
def lambda_handler(event, context):
response = event['Records'][0]['cf']['response']
request = event['Records'][0]['cf']['request']
# Persist cookie, set the set-cookie header
if 'set-cookie' not in response['headers']:
response['headers']['set-cookie'] = []
request_headers = request['headers']
cookie_version_blue = 'X-Version-Name=Blue'
cookie_version_green = 'X-Version-Name=Green'
cookie_reset = 'X-Version-Reset'
for cookie in request_headers.get('cookie', []):
if cookie_version_blue in cookie['value']:
response['headers']['set-cookie'].append(
{'key': 'set-cookie', 'value': cookie_version_blue})
elif cookie_version_green in cookie['value']:
response['headers']['set-cookie'].append(
{'key': 'set-cookie', 'value': cookie_version_green})
elif cookie_reset in cookie['value']:
response['headers']['set-cookie'].append(
{'key': 'set-cookie', 'value': cookie['value']})
return response
Развертывание функций
Функции лямбда должны быть развернуты в регионе США-Востока-1, поскольку именно этот край лямбда @ Мы также должны использовать фиксированную версию и не можем использовать Последние псевдоним. Как обычный AWS SAM используется для определения и развертывания функций лямбда.
Шаблон Сэма
Полная версия доступна в [Github] [Github-link].
ViewerRequestFunction:
Type: AWS::Serverless::Function
Properties:
AutoPublishAlias: "true"
Runtime: python3.7
MemorySize: 128
Timeout: 3
CodeUri: ./viewer-request
Handler: handler.lambda_handler
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- edgelambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- SSMParameterReadPolicy:
ParameterName: !Sub ${SsmConfigPath}/*
- Version: "2012-10-17"
Statement:
Action:
- lambda:GetFunction
Effect: Allow
Resource: "*"
ViewerResponseFunction:
Type: AWS::Serverless::Function
Properties:
AutoPublishAlias: "true"
Runtime: python3.7
MemorySize: 128
Timeout: 3
CodeUri: ./viewer-response
Handler: handler.lambda_handler
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- edgelambda.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- Version: "2012-10-17"
Statement:
Action:
- lambda:GetFunction
Effect: Allow
Resource: "*"
Настройка CloudFront.
Наконец, нам нужно создать распределение CloudFront и установить функции лямбда для запроса запроса зрителя и триггеры ответа. Обычно Cloudfront не будет использовать и передавать заголовки в кэш. Поскольку наша настройка в зависимости от двух файлов cookie, мы должны убедиться, что CloudFront пропустит их вместе. Это сделано путем добавления их в WhitelistedNames. раздел. Подстановочные знаки поддерживаются, поэтому мы просто добавляем X-версия- * к этому разделу.
Шаблон деформации облака
Полная версия доступна в [Github] [Github-link].
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: !Sub "Distribution for ${ProjectName}"
DefaultCacheBehavior:
AllowedMethods:
- "GET"
- "HEAD"
- "OPTIONS"
Compress: False
DefaultTTL: 0
MaxTTL: 0
MinTTL: 0
ForwardedValues:
QueryString: False
Cookies:
Forward: whitelist
WhitelistedNames:
- "X-Version-*"
LambdaFunctionAssociations:
- !If
- ViewerRequestLambdaArnSet
- EventType: viewer-request
LambdaFunctionARN: !Ref ViewerRequestLambdaArn
- !Ref AWS::NoValue
- !If
- ViewerResponseLambdaArnSet
- EventType: viewer-response
LambdaFunctionARN: !Ref ViewerResponseLambdaArn
- !Ref AWS::NoValue
TargetOriginId: !Sub ${ProjectName}-origin
ViewerProtocolPolicy: redirect-to-https
DefaultRootObject: !Ref DefaultRootObject
Enabled: True
Origins:
- DomainName: !Sub ${StorageBucket}.s3.amazonaws.com
Id: !Sub ${ProjectName}-origin
S3OriginConfig:
OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${OriginAccessIdentity}
PriceClass: PriceClass_100
Tags:
- Key: Name
Value: !Sub ${ProjectName}
Заключение
Несмотря на то, что Cloudfront не поддерживает эти методы развертывания из коробки Lambda, как много раз ранее, прийти к спасению. Универсальность AWS Lambda действительно чудо! Загрузите код и возьмите его для спина!
Счастливый взлом!
Оригинал: «https://dev.to/aws-builders/cloudfront-deployments-with-lambda-edge-gh5»