Рубрики
Uncategorized

» Развертывание CloudFront с Lambda @ Edge «

Тестирование A / B, синие / зеленые развертывания, канареечные релизы. Разные, но все же столько общего. Они… Помечено с AWS, DevOps, лямбда.

Тестирование 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»