Более миллиона компаний по всему миру создают приложения на облаке AWS. Одна из проблем при работе с облаком — это огромное количество сервисов в распоряжении, а также число подвижных частей. Например, сборка на базе бессерверной архитектуры AWS — обещается простота работы с ней, но при этом она поставляется с энным количеством подвижных частей. Если вы создаете простую лямбда-функцию, придется задействовать смесь сервисов, таких как CloudWatch, S3, IAM, Kinesis, Step Functions и так далее.

C AWS сделать среду разработки, как при продакшне, сложно, особенно с организационными ограничениями, которые касаются безопасности или затрат. Тестирование только усложняет жизнь (большинство сервисов — черные ящики).

Что такое LocalStack?

LocalStack — проект с открытым исходным кодом от Atlassian, который предоставляет простой способ разработки облачных приложений AWS непосредственно с локального хоста. На нем он запускает тестовую среду, которая обеспечивает почти те же функциии API, что и реальная облачная среда AWS, но без масштабирования и с меньшей надежностью.

источник https://localstack.cloud/

Но и эти недостатки можно компенсировать с помощью инструментов имитации (мокинга)/тестирования: kinesalite/dynalite и moto. LocalStack написан на Python, но поскольку все сервисы доступны через HTTP, можно писать на любом языке, например, на том же, что и с AWS.

LocalStack не имеет полного паритета функций с AWS, но локальная среда и не должна быть один в один, нужно просто покрывать все варианты применения.

Отношения с посредниками AWS

В зависимости от характера среды сервисы AWS могут быть ограничены и предоставлены лишь для нескольких посредников.

Я работал в AWS над основным стеком, а SQS был единственной точкой входа в наше приложение. Сначала мы создавали конвейеры SQS для разработчиков, но это привело к экспоненциальному увеличению очередей, поскольку каждый из них должен был получить X количество очередей, чтобы предотвратить конфликты передачи сообщений.

AWS для локальной разработки может стать дорогостоящим, если службы всегда находятся в состоянии простоя, что обычно происходит постоянно. Некоторые из сред не нуждаются в постоянной работе службы. Бессерверностьпомогает с этим, но затрудняет тестирование. Поэтому есть смысл запускать определенные сервисы только по мере необходимости, например на время тестирования.

LocalStack решил некоторые из этих проблем, поскольку с его помощью можно создать собственное end-to-end AWS приложение без необходимости интеграции в реальный аккаунт.

Необходимые условия

1. Установите Docker.

2. Установите платформу Serverless.

3. Установите CLI AWS для взаимодействия с LocalStack.

4. awscli-local, тонкая оболочка интерфейса командной строки для использования с LocalStack (необязательно).

Установка

LocalStack можно установить двумя способами: как в примере или с помощью Docker. Если вы устанавдиваете через pip install, убедитесь, что pip запускается в новой виртуальной среде или среде conda.

$ pip install localstack

Чтобы запустить LocalStack с Python, выполните:

$ localstack start

Мы будем работать с Docker для унификации рабочей среды, поэтому необходимы базовые знания Docker.

Точка старта: файл compose

Создайте новый docker-compose.yml или добавьте следующее в существующий compose-file:

version: "3.7"
services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME-localstack}"
    image: localstack/localstack
    hostname: localstack
    networks:
      - localstack-net
    ports:
      - "4566-4599:4566-4599"
      - "${PORT_WEB_UI-8080}:${PORT_WEB_UI-8080}"
    environment:
      - SERVICES=s3,sqs,lambda,cloudformation,sts,iam,cloudwatch,apigateway,events
      - DEBUG=1
      - DATA_DIR=/tmp/localstack/data
      - PORT_WEB_UI=8080
      - LAMBDA_EXECUTOR=docker-reuse
      - LAMBDA_REMOTE_DOCKER=false
      - LAMBDA_REMOVE_CONTAINERS=true
      - KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- }
      - DOCKER_HOST=unix:///var/run/docker.sock
      - HOST_TMP_FOLDER=${TMPDIR}
    volumes:
      - ./data:/tmp/localstack
      - "/var/run/docker.sock:/var/run/docker.sock"
      - ./bin:/docker-entrypoint-initaws.d
networks:
  localstack-net:
    external: false
    driver: bridge
    name: localstack-net

Создайте каталог с именем data на том же корневом уровне, что и файл compose. Мы будем использовать его для подключения к каталогу tmp/localstack. tmp будет применяться стеком для постоянных данных, таких как Kinesis, DynamoDB, Elasticsearch, S3, Secrets Manager, SSM, SQS и SNS.

Включение этого каталога гарантирует, что сохраненные данные не будут потеряны.

./bin:/docker-entrypoint-initaws.d

Создайте папку bin и файл bash на том же уровне, что и docker-compose.yml: /bin/localstack-entrypoint.sh. UI в бесплатной версии нет, поэтому файл localstack-entrypoint.sh скрипта bash будет отвечать за создание служб и ресурсов в LocalStack, таких как файлы S3, таблицы баз данных и других, при его загрузке.

Если вы не знакомы с bash, то можете выполнять скрипты Python непосредственно из localstack-entrypoint.sh, если они помещены в одну папку или используются в AWS CLI. Можно запустить специальные команды в среде LocalStack вот так:

#!/usr/bin/env bash
printf "Configuring localstack components..."

readonly LOCALSTACK_S3_URL=http://localstack:4572
readonly LOCALSTACK_SQS_URL=http://localstack:4576

sleep 5;

set -x

aws configure set aws_access_key_id foo
aws configure set aws_secret_access_key bar
echo "[default]" > ~/.aws/config
echo "region = us-east-1" >> ~/.aws/config
echo "output = json" >> ~/.aws/config

aws --endpoint $LOCALSTACK_SQS_URL sqs create-queue --queue-name blockchain-local-engine-cancel
aws --endpoint $LOCALSTACK_SQS_URL sqs create-queue --queue-name blockchain-local-engine-input.fifo --attributes FifoQueue=true,MessageGroupId=blockchain
aws --endpoint $LOCALSTACK_SQS_URL sqs create-queue --queue-name blockchain-local-engine-output.fifo --attributes FifoQueue=true,MessageGroupId=blockchain
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket blockchain-s3-local-bitcoin
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket blockchain-s3-local-ziliqa
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket blockchain-s3-local-xrp
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket blockchain-s3-local-ada
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket blockchain-s3-local-eth
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket nyc-tlc

printf "Sample data begin..."
# Создание каталога tmp для размещения образцов данных после разбиения на блоки
mkdir -p /tmp/localstack/data
# aws s3 cp --debug "s3://nyc-tlc/trip data/yellow_tripdata_2018-04.csv" /tmp/localstack --no-sign-request --region us-east-1
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket nyc-tlc
# Создание корзины для развертки лямбды в простом примере конечной точки http
aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket simple-http-endpoint-local-deploy
# Разрешение на публичное чтение корзины
aws --endpoint-url=$LOCALSTACK_S3_URL s3api put-bucket-acl --bucket nyc-tlc --acl public-read
aws --endpoint-url=$LOCALSTACK_S3_URL s3api put-bucket-acl --bucket simple-http-endpoint-local-deploy --acl public-read
# Создание папки внутри корзины
aws --endpoint-url=$LOCALSTACK_S3_URL s3api put-object --bucket nyc-tlc --key "trip data/"
aws --endpoint-url=$LOCALSTACK_S3_URL s3 sync /tmp/localstack "s3://nyc-tlc/trip data" --cli-connect-timeout 0
# Отображение содержимого корзины
aws --endpoint-url=$LOCALSTACK_S3_URL s3 ls "s3://nyc-tlc/trip data"

set +x

# Это панель управления localstack, она бесполезна, знайте, как использовать AWS Cli, хорошо!
printf "Localstack dashboard : http://localhost:8080/#!/infra"

LocalStack требует установки учетных данных, но пока реальной аутентификации нет: он будет принимать их без проверки. Не вставляйте свои настоящие ключи AWS в систему управления версиями.

Порты LocalStack 4563–4599:4563–4599 и 8080

Когда контейнер Docker запускается, LocalStack открывает порты, определенные в docker-compose.yml, где левый номер связывает порт на хосте с портом контейнера справа. В большинстве случаев они одинаковы, например 8080:8080. Если порт справа занят, нужно будет изменить значение по умолчанию, например 8086:8080. Открытие браузера на http://localhost:8086 переведет на 8080 контейнера.

Строка ‘4566–4599:4566–4599’ делает то же самое, но связывает целый ряд портов. Эти номера задействованы в LocalStack в качестве конечных точек для различных API, таких как S3, RDS, шлюза-API и так далее.

Вышеупомянутые порты могут быть открыты внешнему миру, если нет сетевого брандмауэра. Можно выбрать привязку только к хост-машине 127.0.0.1:8080:8080.

Переменные среды LocalStack

Они передаются в контейнер LocalStack при загрузке.

  • SERVICES=s3: можно определить разделенный запятыми список сервисов AWS для эмуляции. Каждая служба может запустить другой контейнер docker для обслуживания запросов.
  • DATA_DIR=/tmp/localstack/data: это каталог, в котором LocalStack будет сохранять данные. Подробнее в следующих разделах.

Томы

‘./data: / tmp / localstack’

Контейнеры Docker не хранят состояние, и единственный способ сделать это — через томы, которые обращаются к части жесткого диска. ./data относится к файлу docker-compose.yml. Путь можно определить любой.

Приведенной выше конфигурации compose сейчас будет достаточно. Для запуска среды LocalStack с помощью Docker, compose выполняет команду в том же месте, где находится файл docker-compose.yml. В конце можно добавить аргумент -d, чтобы запустить LocalStack как демон в фоновом режиме.

Пока запущен docker-compose up, на консоли можно увидеть, что LocalStack создал файл ../data/data/recorded_api_calls.json

Устойчивость каталога tmp, в котором хранятся файлы, достигается за счет автоматического создания recorded_api_calls.json, который облегчает воспроизведение ранее выполненных вызовов службы AWS. Когда контейнер перезапустится, он повторно применит эти вызовы. 

Именно так можно хранить данные между перезапусками. Загрузки будут записываться в файл как байтовые необработанные данные. Этот файл можно включить в свой репозиторий, если хотите поделиться состоянием контейнера с другими — но в зависимости от того, сколько вы загрузили, он может стать огромным. 

Можно сделать резервную копию корзины. Когда будете готовы к восстановлению, просто удалите обновленный файл, замените его резервной копией и перезагрузите контейнер.

Доступ к LocalStack за пределами Docker

После работы c AWS становится ясно, что именованные профили для обеспечения безопасности и управления ключами, когда у вас есть доступ к нескольким учетным записям AWS или более одного доступа и секретного ключа — хорошая практика.

Определим новый именованный профиль localstack для выполнения командыкоманды AWS CLI в среде LocalStack, где ~ ссылается на директорию $HOME.

~/.aws/credentials

[localstack]
aws_access_key_id = foo
aws_secret_access_key = bar

~/.aws/config

[profile localstack]
region = us-east-1
output = json

Если LocalStack запущен, каждая из команд AWS CLI будет состоять из параметра endpoint-url, который гарантирует, что команды выполняются на LocalStack вместе с именованным профилем, созданным для поддельной аутентификации.

$ aws — endpoint-url=http://localhost:4572 s3 ls “s3://nyc-tlc/trip data/” — profile localstack 

LocalStack и SQS

Приведенный пример иллюстрирует, как подключаться к LocalStack с помощью boto3 SQS. Те же принципы применимы и к другим языкам программирования.

import os
import json
import uuid
import boto3

# Внутри Docker используйте DNS-имя докера localstack 
# os.environ['LOCALSTACK_SQS_ENDPOINT_URL'] = 'http://localstack:4576'

# Если вы подключаетесь к localstack вне docker, используйте хост ДНС.
# Каждый сервис aws имеет свой собственный url-адрес конечной точки, 
# гарантирующий, что клиент boto3 настроен соответствующим образом.
# Вы можете изменить endpoint_url, чтобы он указывал на любой 
# локальный стек aws, например на локальный экземпляр dynamodb aws
os.environ['LOCALSTACK_SQS_ENDPOINT_URL'] = 'http://localhost:4576'
os.environ['AWS_ACCESS_KEY_ID'] = 'foo'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'bar'
os.environ['AWS_DEFAULT_REGION'] = 'us-east-1'


if os.environ.get('LOCALSTACK_SQS_ENDPOINT_URL'):
    sqs = boto3.client("sqs", endpoint_url = os.environ.get('LOCALSTACK_SQS_ENDPOINT_URL'))
else:
    sqs = boto3.client("sqs")


body = {
  "time": {
    "updated": "Jul 4, 2020 14:12:00 UTC",
    "updatedISO": "2020-07-04T14:12:00+00:00",
    "updateduk": "Jul 4, 2020 at 15:12 BST"
  },
  "disclaimer": "Эти данные были получены из индекса цен биткойнов CoinDesk (USD). Данные о валюте, не являющейся долларом США, конвертируются с использованием почасового курса из openexchangerates.org",
  "bpi": {
    "USD": {
      "code": "USD",
      "rate": "9,083.8632",
      "descriptio n": "United States Dollar",
      "rate_float": 9083.8632
    },
    "BTC": {
      "code": "BTC",
      "rate": "1.0000",
      "description": "Bitcoin",
      "rate_float": 1
    }
  }
}

# Ниже - типичная отправка и получение сообщений с длительным опросом
response = sqs.send_message(
    QueueUrl='http://localhost:4576/000000000000/blockchain-local-engine-input.fifo',
    MessageBody=json.dumps(body),
    DelaySeconds=3,
    MessageDeduplicationId=str(uuid.uuid4()),
    MessageGroupId='blockchain',
    MessageAttributes={
        "contentType": {
            "StringValue": "application/json", "DataType": "String"}
    }
)

# WaitTimeSeconds=20 позволяет дольше опрашивать, то есть будет меньше циклов чтения для SQS, что снизит затраты при запуске в продакшн
messages = sqs.receive_message(QueueUrl='http://localhost:4576/000000000000/blockchain-local-engine-input.fifo',
    AttributeNames=['All'], MaxNumberOfMessages=10, WaitTimeSeconds=20, VisibilityTimeout=30)


messages = messages.get("Messages", [])
    
print('Total messages = {}'.format(len(messages)))

for message in messages:

    message_body = json.loads(message.get('Body'))

    print(message_body)

    sqs.delete_message(
            QueueUrl='http://localhost:4576/000000000000/blockchain-local-engine-input.fifo',
            ReceiptHandle=message.get("ReceiptHandle"))

    messages = sqs.receive_message(QueueUrl='http://localhost:4576/000000000000/blockchain-local-engine-input.fifo',
                                   AttributeNames=['All'], MaxNumberOfMessages=10, WaitTimeSeconds=20,
                                   VisibilityTimeout=30)

    messages = messages.get("Messages", [])

    print('Total messages remaining ={}'.format(len(messages)))

Эквивалент Node.js:

var AWS = require('aws-sdk');
// Создание сервисного объекта SQS через конечную точку localstack 
var config = {
  endpoint: new AWS.Endpoint('http://localhost:4576'),
  accessKeyId: 'foo',
  secretAccessKey: 'bar',
  region: 'us-east-1'
}
var sqs = new AWS.SQS(config);

И Java:

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.net.URI;
public class Sqs {
    private SqsClient client;
    public Sqs(URI endpoint) {
        client = SqsClient.builder()
                .region(Region.US_EAST_1)
                .endpointOverride(endpoint)
                .build();
    }
}

LocalStack и Dask

Dask — это обязательный инструмент при обработке средних и больших данных. Код пишется единожды, и Dask решает, как распределить работу на несколько процессоров или узлов, управляя вычислениями большего размера, чем память. Тестирование Dask на LocalStack тривиально, если понимать, что нужно изменить:

import os
import math
import dask.dataframe as dd
import numpy as np
import pandas as pd

from dask.distributed import Client


client = Client('tcp://scheduler:8786')
# То, на что указывает boto3, переключает localstack
if os.environ.get('LOCALSTACK_S3_ENDPOINT_URL'):
    taxi_data = dd.read_csv( 's3://nyc-tlc/trip data/yellow_tripdata_2018-04.csv',
        storage_options={
            'anon': True,
            'use_ssl': False,
            'key': 'foo',
            'secret': 'bar',
            "client_kwargs": {
                "endpoint_url": os.environ.get('LOCALSTACK_S3_ENDPOINT_URL'),
                "region_name": "us-east-1"
            }
        }
    )
else:
    # Это предполагает использование именованных профилей в aws cli с профилем по умолчанию для доступа к корзине s3, экземпляру EC2, либо роли задачи ECS
    taxi_data = dd.read_csv('s3://nyc-tlc/trip data/yellow_tripdata_2018-04.csv')

taxi_data.head()

Нужно убедиться, что вы явно определяете storage_options и endpoint-url, чтобы boto3 понимал, где находится LocalStack.

os.environ['LOCALSTACK_S3_ENDPOINT_URL'] = 'http://localstack:4572'

Обратите внимание, как LOCALSTACK_S3_ENDPOINT_URL указывает на LocalStack, который является DNS-сервером по умолчанию, заданным экземпляру LocalStack Docker. Dask обеспечивает большую сохраняемость локального файлового хранилища, поэтому важно, чтобы код выполнялся в той же сети, что и контейнер. Чтобы лучше понять, как все устроено, можете перейти по ссылке на GitHub в конце статьи.

Создание лямбда-функции в LocalStack

Если не нравится писать файлы CloudFormation YAML, то serverless — это альтернативный вариант, который упрощает развертывание лямбда-функций.

Приведенный конфигурационный файл serverless.yml дает представление о том, что требуется для развертывания шлюза API с функцией HTTP. Раздел custom -> localstack определяет все конфигурации, необходимые для развертывания локальной лямбда-функции в LocalStack.

service: simple-http-endpoint

frameworkVersion: ">=1.2.0 <2.0.0"

plugins:
  - serverless-localstack
  # - serverless-python-requirements

provider:
  name: aws
  runtime: python3.7
  stage: ${opt:stage, 'local'}
  memorySize: 10  24
  timeout: 20
  logRetentionInDays: 14
  region: us-east-1
  deploymentPrefix: aws-lambda
  deploymentBucket: # при применении localstack важно чтобы перед развертыванием лямбды ваша корзина s3 уже существовала, чтобы вы могли сделать это автоматически, добавьте в aws cli команды create bucket в скрипт localstack-entrypoint.sh 
    name: ${self:service}-${opt:stage}-deploy

package:
  exclude:
    - node_modules/**
    - venv/**
    - .pytest_cache/**
    - tests/*

functions:
  currentTime:
    handler: handler.endpoint
    events:
      - http:
          path: ping
          method: get
# Развертка serverless --stage=local.
# Локальные конфигурации этапа будут применены только на этапе развертывания local.
# Атрибут stage позволяет легко переключаться между средами.
# Вам необходимо убедиться, что службы localstack запускаются со следующими параметрами s3,lambda,cloudformation,sts,iam,cloudwatch, apigateway (если ваша лямбда-функция использует http, websockets).
custom:
  pythonRequirements:
    dockerizePip: false
  localstack:
    debug: true # включение режима дебага
    stages:
      # список stage, для которых должен быть включен плагин
      - local
    host: http://localhost  # опционально - хост LocalStack для соединения
    autostart: true  # опционально - запуск LocalStack в Docker для развертки на Serverless
    endpoints:
      # Этот раздел необязателен - может использоваться для настройки целевых конечных точек
      S3: http://localhost:4572
      DynamoDB: http://localhost:4569
      CloudFormation: http://localhost:4581
      Elasticsearch: http://localhost:4571
      ES: http://localhost:4578
      SNS: http://localhost:4575
      SQS: http://localhost:4576
      Lambda: http://localhost:4574
      Kinesis: http://localhost:4568
    lambda:
      # Включите этот флаг для повышения производительности
      mountCode: True
    docker:
      # Включите этот флаг для запуска команд "docker ..." как sudo
      sudo: True

Лямбда-функция возвращает “Hello World” с текущей меткой времени.

def endpoint(event, context):
    current_time = datetime.datetime.now().time()
    body = {
        "message": "Hello, world",
        "eventTime": str(current_time)
    }
    response = {
        "statusCode": 200,
        "body": json.dumps(body)
    }
    return response

serverless.yml выполнит всю тяжелую работу: создаст пакет lambda, загрузит его в LocalStack, подготовит любые дополнительные необходимые ресурсы, например API-шлюз. Но он не создаст корзину S3. Важно обновить свой localstack-entrypoint.sh с помощью команды создания или выполнить ее один раз вручную, как только стек будет запущен.

# Создание корзины для развертки лямбды в простом примере конечной точки http 
$ aws --endpoint-url=$LOCALSTACK_S3_URL s3api create-bucket --bucket simple-http-endpoint-local-deploy

В файле serverless.yml, пропишите ${self:service}-${opt:stage}-deploy , а не встроенное имя корзины. Переменные serverless позволяют пользователям динамически заменять значения конфигурации в файле настроек serverless.yml . Они особенно полезны, когда нужно предоставить секреты для служб serverless или когда мы хотим развернуть их в нескольких средах, например непрерывной интеграции, разработки, QA и продакшна, с помощью аргумента stage.

Если LocalStack работает в фоновом режиме нужно выполнить команду, которая вызовет развертывание на LocalStack, так как параметр stage указывает на local.

$ serverless deploy --stage local  --profile localstack

Чтобы выполнить лямбда-функцию через serverless в LocalStack:

$ serverless invoke --function currentTime --log --profile localstack --stage local

Результат:

Чтобы вызвать лямбда-функцию через браузер, обслуживаемый шлюзом API, можно выполнить URL, где шаблон для выполнения LocalStack такой:

http://localhost:4566/restapis/<apiId>/<stage>/_user_request_/<methodPath>

Если опустим аргумент profile и изменим stage на профиль разработки (dev), предположив, что именованный профиль AWS по умолчанию указывает на действительную учетную запись AWS, то обычная последовательность фактической развертки будет инициирована на ней.

Проверка работоспособности LocalStack

После запуска LocalStack можно проверить его работоспособность, введя этот URL:

http://localhost:4566/health{
  "services": {
    "cloudformation": "running",
    "cloudwatch": "running",
    "iam": "running",
    "sts": "running",
    "lambda": "running",
    "logs": "running",
    "s3": "running",
    "sqs": "running",
    "events": "running",
    "apigateway": "running"
  }
}

Первый запуск вызовов REST API может занять некоторое время. Конечная точка отобразит количество запущенных служб и их статус. Место, в котором работает служба, будет зависеть от того, где объявили переменную среды LocalStack.

SERVICES=s3,sqs,lambda,cloudformation,sts,iam,cloudwatch,apigateway,events

Переход на локальный уровень с помощью Awscli-local

До сих пор мы работали через AWS CLI. Но есть альтернатива: пакет awscli-local. Это аккуратная маленькая оболочка AWS CLI, которая гарантирует, что все, что вы запускаете, запускается на LocalStack по умолчанию.

Как создать корзину S3

Она будет называться “my-test-bucket” и будет создана с помощью команды ниже. Если хотите перечислить её содержимое, надо предоставить ACL открытый доступ для чтения.

$ awslocal s3 mb s3://my-test-bucket

В терминале вы увидете make_bucket: my-test-bucket — значит создание прошло успешно.

$ awslocal s3 ls

Подводные камни LocalStack

  • Параметры LocalStack, которые не будут хорошо работать вместе, сохранение корзин в точках монтирования и попытка развернуть лямбду, сжимая и копируя её в корзину LocalStack, вызовут ошибку.
2020-07-22T12:12:51:DEBUG:localstack.services.cloudformation.cloudformation_listener: Error response for CloudFormation action "CreateStack" (400) POST /: b'Unknown error: Please note that Lambda mounts (bucket name "__local__") cannot be used with LAMBDA_REMOTE_DOCKER=1 Traceback (most recent call last):\n  File "/opt/code/localstack/localstack/services/awslambda/lambda_api.py", line 954, in create_function\n    result = set_function_code(func_details.code, lambda_name)\n  File "/opt/code/localstack/localstack/services/awslambda/lambda_api.py", line 721, in set_function_code\n    lambda_cwd = lambda_cwd or set_archive_code(code_passed, lambda_name)\n  File "/opt/code/localstack/localstack/services/awslambda/lambda_api.py", line 676, in set_archive_code\n    raise Exception(msg % BUCKET_MARKER_LOCAL)\nException: Please note that Lambda mounts (bucket name "__local__") cannot be used with LAMBDA_REMOTE_DOCKER=1\n'
localstac
  • Лучше удалять /data/data/recorded_api_calls.json, если вы внесли изменения в настройки среды LocalStack docker-compose. Иногда он выходит из строя при воспроизведении выполненных вызовов API.
  • Хорошая идея — указать внутри docker-compose.yml точную версию образа LocalStack, с которой хотите работать, вместо извлечения последней. Последний тег затрудняет отслеживание запущенной версии образа, и иногда новые функции могут содержать изменения, ломающие работоспособность.
  • LocalStack далек от AWS — зато он бесплатный.
  • Основные бесплатные функции должны охватывать большинство вариантов применения.


Дополнительные сведения по устранению неполадок Localstack см. в файле README.

Альтернативы LocalStack

Можно выбрать имитации SDK, особенно если вы разрабатываете свои классы с учетом расширения.

В качестве альтернативы корзины S3 существует MinIO как замена облачного хранилища объектов.

Для написания портативных функций Node.js, которые можно запустить на локальном компьютере для других облачных сервисов, например Google, есть такие варианты, как эмуляторы Google Cloud и фреймворк FaaS с открытым исходным кодом от Google .

Заключение

При создании приложений на AWS необходимо взять под контроль экономическую модель своей архитектуры: в противном случае можно потерять много денег. Любые альтернативы работают только отчасти.

LocalStack предоставляет разработчикам платформу для экспериментов и тестирования нового кода. Переход к LocalStack — это прагматичный подход к хэшированию кода, который будет работать на AWS.

Можете попробовать создать оболочку boto3 или AWS SDK с наиболее часто используемыми сервисами и функцией переключения LocalStack с помощью переменной среды либо с помощью файлов свойств. Конечные точки LocalStack можно настроить в файле YAML:

endpoints:
  S3: http://localhost:4572
  DynamoDB: http://localhost:4569
  CloudFormation: http://localhost:4581
  Elasticsearch: http://localhost:4571
  ES: http://localhost:4578
  SNS: http://localhost:4575
  SQS: http://localhost:4576
  Lambda: http://localhost:4574
  Kinesis: http://localhost:4568

В репозитории вы найдете больше примеров:

timothymugayi/localstack_python_examples

Спасибо за чтение!

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Timothy Mugayi: Don’t Be Intimidated — Learn How to Run AWS on Your Local Machine With LocalStack

Предыдущая статьяСоздайте собственный AdBlocker за 10 минут
Следующая статья5 секретов наилучшего использования кортежей в Python