A/B -тестирование, синие/зеленые развертывания, канарейские релизы. Разные, но все же так много общего. Все они имеют разные цели, но используют в основном одно и то же техническое решение под капотом. Мы делаем такие испытания по нескольким причинам. Один — сделать тест A/B и определить, какую версию наших пользователей нравится лучшие. Уверен, что можно сделать A/B тестирование на клиентской стороне, но лично мне упростить на стороне сервера. Голубые/зеленые и канаречные развертывания сделаны, чтобы убедиться, что новая версия приложений работает так, как мы ожидаем и дам нам простой способ откатываться в предыдущую версию в случае проблемы. Все это важные практики в культуре DevOps.
Многие услуги от AWS предлагают это решение из коробки, одна услуга, которая не является Humentfront. К счастью, Cloudfront имеет возможность запустить лямбда @ kems, которую мы можем использовать для этого.
Весь исходный код для этой настройки найден на GitHub
Представляем Lambda @ Edge
Lambda может работать в четырех разных местах в потоке запросов.
Просмотр просмотра — работает, когда CloudFront получает запрос от зрителя. Происхождение запроса — бежит до того, как Cloudfront пересылает запрос к началу. Ответ происхождения — запускается, когда CloudFront получает ответ от начала координат. Ответ просмотра — запускается до того, как CloudFront возвращает ответ зрителям.
Есть несколько ограничений, когда дело доходит до лямбда@Edge, можно только создавать функции в Python и Node.js. Функции запроса просмотра и ответа могут выделять только 128 МБ памяти и работать только в течение 3 секунд. Вы не можете использовать переменные среды, вы не можете использовать Последние Версия псевдоним, поддерживаются только фиксированные версии. Журналы публикуются в области края, к которой вы получаете доступ, а не в US-EAST-1 регион, даже если функции должны быть развернуты в этом регионе. Обязательно прочитайте Документация Прежде чем начать работать с лямбда @ жрать.
Обзор решения
В этом решении мы собираемся использовать две разные функции Lambda для просмотр просмотра и Ответ происхождения Крюки, мы будем хранить конфигурацию в хранилище параметров, а S3 — наше происхождение.
В просмотр просмотра Крюк Мы проверим специальное cookie, если файл cookie не установлен, мы принесем случайную версию. В Ответ происхождения Мы устанавливаем Set-Cookie Заголовок для хранения версии, которую мы используем. Установив различные значения в хранилище параметров, мы можем управлять весом каждой версии, а также мы можем сбросить и заставить клиентов получать новую случайную версию.
Запрос на зритель
Начнем с функции Lambda, которая будет реагировать на событие запроса зрителя. Эта функция Lambda отвечает за проверку нашего cookie X-версия-имя Если значение установлено, функция обновит путь запроса на основе значения cookie. Если нет установленного значения, он будет катиться в Dice и получить случайную версию и обновить путь запроса. Эта функция также сопоставит значение в cookie X-версию-сброс к значению в магазине параметра, и если значение отличается, он будет игнорировать любое заданное значение в X-версия-имя Анкет Если нет значения в X-версия-имя Или если значение игнорируется, функция бросает кости и выбирает версию наугад. Вес для разных версий контролируется значением в магазине параметра. Наконец, функция передает файл cookie к следующему шагу в цепочке вызовов.
Код запроса просмотра
Полная версия доступна в GitHub Анкет
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 заголовок к клиенту. Это необходимо, чтобы клиент установил файлы cookie X-версия-имя и X-версия-сброс Таким образом, клиент отправляет их в следующий запрос. Это важно, чтобы клиент не прыгал между версиями. У этой функции есть небольшая, но очень важная работа.
Код ответа просмотра
Полная версия доступна в GitHub Анкет
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 используется для определения и развертывания функций Lambda.
Шаблон SAM
Полная версия доступна в GitHub Анкет
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-version-* к этому разделу.
Шаблон деформации облака
Полная версия доступна в GitHub Анкет
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 — это действительно чудо! Загрузите код и возьмите его для Spin!
Счастливый взлом!
Оригинал: «https://dev.to/jimmydqv/cloudfront-deployments-with-lambda-edge-4jmh»