LocalStack, або Як налаштувати локальне AWS-середовище
Усі статті, обговорення, новини про DevOps — в одному місці. Підписуйтеся на DOU | DevOps!
Усім привіт, мене звати Богдан, я Intermediate Software Engineer у компанії VITech. З Amazon Web Services (AWS) я познайомився два роки тому, з того часу активно працюю з багатьма їхніми сервісами кожен день.
AWS надає дуже потужні інструменти, але є один нюанс — локальне середовище з використанням цих сервісів. Звісно, ми можемо використовувати щось на зразок відокремленого dev/sandbox середовища, але й тут не без проблем: швидкість отримання відгуку щодо нових змін, ціна, використання багатьма розробниками одночасно, обмежені можливості модифікації середовища.
Саме тут на допомогу приходить LocalStack. Що ж це таке та як його використовувати?
LocalStack — це локальний емулятор AWS, написаний на Python, який дає змогу працювати відокремлено та без підключення до інтернету.
Як використовувати
Є дві можливості запуску та використання:
- localstack cli
python3 -m pip install --upgrade localstack localstack start
- docker
docker run -d -p 4566:4566 localstack/localstack:2.2.0
Особисто я надаю перевагу docker-у, тому, що він незалежний щодо операційної системи та не вимагає встановлення додаткових речей, а ще можна зробити docker-compose та використовувати одну конфігурацію запуску на всьому проєкті. На відміну від docker-у, localstack cli використовує Python та вимагає попереднього встановлення.
Якщо ми вже згадали docker-compose, то розгляньмо приклад:
version: '3.9' services: localstack: container_name: localstack image: localstack/localstack:2.2.0 network_mode: bridge ports: - "4566:4566" environment: - LAMBDA_DOCKER_NETWORK=bridge - AWS_DEFAULT_REGION=us-east-2 - DEBUG=1 - DOCKER_HOST=unix:///var/run/docker.sock volumes: - ./init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh - /var/run/docker.sock:/var/run/docker.sock
З важливого:
- я використовую
network_mode: bridge
(можна й host), бо якщо ми будемо запускати lambda локально в docker, я хочу мати можливість туди підключатись (container-to-container); - init-aws.sh — це скрипт, який виконується після успішного запуску контейнера, тут ми можемо підготувати створення необхідних ресурсів за допомогою AWS CLI.
Приклади використання
AWS CLI
Тут дуже легко. Все, що потрібно, це додати --endpoint-url http://localhost:4566
aws s3 mb s3://local-bucket --endpoint-url http://localhost:4566 aws s3api list-buckets --query "Buckets[].Name" --endpoint-url http://localhost:4566
Дуже зручно використовувати alias - alias awslocal="aws --endpoint-url=http://localhost:4566”
. Після цього можна використовувати команду awslocal (або ж іншу, залежно від того, як ви назвете alias), яка ****автоматично буде додавати це поле.
awslocal s3 mb s3://local-bucket2 awslocal s3api list-buckets --query "Buckets[].Name"
AWS SDK (Java)
Для роботи з AWS нам необхідно підтягнути залежності, які містять імплементацію клієнтів для роботи з AWS-сервісами. Ми розглядаємо приклад на Gradle та Java, але всюди логіка однакова.
implementation platform('software.amazon.awssdk:bom:2.20.115') implementation 'software.amazon.awssdk:s3'
Створення S3 клієнта:
private static final S3Client S3 = S3Client.builder().build();
Отож, так само як і в попередньому прикладі, нам потрібно змінити ендпоінт, на який буде звертатись клієнт:
private static final S3Client S3 = S3Client.builder() .endpointOverride(URI.create("https://localhost:4566")) .build();
Spring
Варто почати з того, що всі налаштування, які підходять для Java, підходять і тут, але додатково ми отримуємо нові та спрощені можливості для налаштування. Перша така можливість — це анотація @Configuration, яка додається до класу, в якому описані створення необхідних bean-нів. Друга — @Profile, за допомогою цієї анотації дуже зручно розділити конфігураційні класи на ті, які працюють із AWS, і ті, які працюють із localStack.
Конфігурація:
@Configuration @Profile("localstack") public class Configurations { @Bean public S3Client s3Client() { return S3Client.builder() .endpointOverride(URI.create("https://s3.localhost.localstack.cloud:4566")) .build(); } }
Зверніть увагу, що тут використовується DNS https://s3.localhost.localstack.cloud:4566, це аналогічно до https://localhost:4566/
.
Spring Cloud
На цей час актуальна версія провайдера для AWS — v3. Тут нам стає ще зручніше працювати з клієнтами. Ми можемо задати ендпоінт через параметр.
spring: cloud: aws: region: static: us-east-2 s3: endpoint: http://s3.localhost.localstack.cloud:456
Необхідні залежності:
implementation platform('io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1') implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'
Testcontainers
Сьогодні всі активно використовують тестові контейнери для інтеграційних тестів, давайте й ми оглянемо такий приклад із Spring.
Необхідні залежності:
implementation platform('org.testcontainers:testcontainers-bom:1.18.3') testImplementation 'org.testcontainers:junit-jupiter' testImplementation 'org.testcontainers:localstack'
Тест:
@Testcontainers @SpringBootTest @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = ApplicationTests.TestConfig.class) class ApplicationTests { private static final DockerImageName LOCALSTACK_IMAGE = DockerImageName.parse("localstack/localstack:2.2.0"); @Container private static final LocalStackContainer LOCAL_STACK_CONTAINER = new LocalStackContainer(LOCALSTACK_IMAGE) .withEnv("AWS_DEFAULT_REGION", Region.US_EAST_2.toString()) @Autowired private S3Client s3Client; @Test void test() { // GIVEN // WHEN // THEN } @TestConfiguration public static class TestConfig { @Bean("s3ClientTest") @Primary public S3Client s3Client() { return S3Client.builder() .endpointOverride(LOCAL_STACK_CONTAINER.getEndpointOverride(LocalStackContainer.Service.S3)) .build(); } } }
Із важливого:
- анотація @Container запускає контейнер перед тестами;
- анотація @TestConfiguration описує налаштування клієнтів для тестів;
- анотація @ContextConfiguration(classes = ApplicationTests.TestConfig.class) дозволяє використати налаштування клієнтів, які ми змінили.
Terraform
Для використання Terraform та LocalStack, нам необхідно встановити спеціальний сервіс:
pip install terraform-local
Для роботи з AWS основна вимога — це provider:
provider "aws" { region = "us-east-2" }
Якщо раніше ми змінювали ендпоінт для клієнтів, то тепер нам необхідно змінити ендпоінт для провайдера:
provider "aws" { region = "us-east-2" endpoints { s3 = "https://s3.localhost.localstack.cloud:4566" sqs = "https://sqs.localhost.localstack.cloud:4566" } }
Наступними кроками нам потрібно виконувати tflocal init
та tflocal apply
(замість tf init
та tf apply
).
Підсумок
Це був швидкий огляд, з чого можна та варто почати впровадження LocalStack-у на вашому проєкті, але я можу з впевненістю сказати, що ця річ дійсно пришвидшує розробку.
Також ось репозиторій із готовою аплікацією та вище зазначеними сервісами.
15 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів