May 13, 2018
|
Under node.js
(12)
, kubernetes
(4)
, coding
(15)
, open-source
(11)

Using Skaffold and LocalStack to Develop Cloud Applications Locally

You've just decided to start building on services hosted for you by your cloud provider. Great! However, you will soon realize, that building applications locally against these APIs can be challenging. Should each developer create a development environment for themselves in the cloud? Will you test against a staging environment? Will you mock them out all the time?

Sadly, each of these solutions has their drawbacks. Wouldn't it be great to run your version of the cloud services you need locally? LocalStack can do that for you.

Meet LocalStack

LocalStack provides an easy-to-use test/mocking framework for developing cloud applications - currently for AWS only.

  • Error injection: with LocalStack, you can inject errors that will occur in the real environment as well, like ProvisionedThroughputExceededException for DynamoDB,
  • HTTP services: all LocalStack AWS service implementations are exposed through a REST API; this also means, that you can use the AWS CLI with them,
  • Language agnostic: as LocalStack exposes HTTP services, you can use them with any languages.

Sounds exciting? Let's see how you can set it up for your machine!

Installing LocalStack

When it comes to running LocalStack, you have some options:

  • ~~installing all of its' dependencies, and run the Python application~~,
  • running a Docker image,
  • running a Kubernetes service with Skaffold.

As LocalStack has many dependencies (like pip, npm, java or mvn), I wouldn't recommend installing them locally.

Running a Docker image

To run the docker image, you will have to clone the LocalStack repository first, then spin up the service with docker-compose:

# cloning the repository
git clone git@github.com:localstack/localstack.git
# running docker compose
cd localstack
docker-compose up

Looks a lot cleaner than installing all the dependencies, right? However, if you use Kubernetes, and you'd like this to be the part of the local development workflow without starting it manually, or cloning it, you can take this to the next level with Skaffold. If you are not familiar with that, I'd recommend reading the Using Kubernetes for Local Development article before continue reading this article.

Running as a Kubernetes service with Skaffold

To run LocalStack with Skaffold, we have to create a Deployment and a Service Kubernetes object for it.

Let's start with the deployment first:

apiVersion: apps/v1
kind: Deployment
metadata:
name: localstack
spec:
# using the selector, we will expose the running deployments
# this is how Kubernetes knows, that a given service belongs to a deployment
selector:
matchLabels:
app: localstack
replicas: 1
template:
metadata:
labels:
app: localstack
spec:
containers:
- name: localstack
image: localstack/localstack:0.8.6
ports:
# exposing dynamodb
- containerPort: 31001
# exposing sqs
- containerPort: 31000
# expsosing the localstack ui
- containerPort: 32000
env:
# with the SERVICES environment variable, you can tell LocalStack
# what services to expose on what port
- name: SERVICES
value: "sqs:31000,dynamodb:31001"
- name: PORT_WEB_UI
value: "32000"

Once we have deployment, we have to expose them using a service:

apiVersion: v1
kind: Service
metadata:
name: localstack
spec:
# selector tells Kubernetes what Deployment this Service
# belongs to
selector:
app: localstack
ports:
- port: 32000
protocol: TCP
name: ui
nodePort: 32000
- port: 31001
protocol: TCP
name: dynamodb
nodePort: 31001
- port: 31000
protocol: TCP
name: sqs
nodePort: 31000
type: LoadBalancer

If you'd like, you can put these manifests into a single file, with the --- used as a separator. Once you have all these in place, the only thing you have to do is to update your skaffold.yml file so that Skaffold can pick up your new changes.

apiVersion: skaffold/v1alpha2
kind: Config
build:
artifacts:
- imageName: your-app
workspace: .
docker: {}
bazel: null
local:
skipPush: null
googleCloudBuild: null
kaniko: null
deploy:
helm: null
kubectl:
manifests:
- path-to-localstack-manifest.yml
- path-to-your-app-manifest.yml

Furher reading

Did you like this article? Subscribe to get notified about new ones on engineering management, open-source and the web!
No spam. Ever.