Geralmente me encontro criando quatro ambientes para cada projeto Serverless Framework que trabalho, eles são: dev
, staging
, prod
e local
. Obviamente, os três primeiros devem ser implantados na nuvem, mas o último, local
, deve executar e testar interações com recursos locais. Também é ótimo ter uma versão offline (como quando você está em um avião ✈ ou tem um wifi terrível em algum lugar). Além disso, o desenvolvimento é muito mais rápido, porque você não está esperando requisições de ida e volta ao servidor. 😉
Um recurso realmente excelente do Serverless Framework é a capacidade de configurar variáveis de AMBIENTE no arquivo serverless.yml
. Isso permite armazenar informações globais importantes, como nomes de bancos de dados, API de serviços e muito mais. Podemos até fazer referência a senhas com segurança usando o AWS Service Manager Parameter Store e decodificar senhas criptografadas na hora do deploy, mantendo elas protegidas contra desenvolvedores e repositórios git. 😬 Basta referenciar a variável ${ssm:/myapp/my-secure-value~true}
no seu arquivo de configuração.
Usando variáveis STAGES e de AMBIENTE juntos pode criar um fluxo de trabalho realmente poderoso para você e sua equipe de desenvolvimento
Eu acho que sls invoke local -f myFunction -p /path/to/event.json
é um dos comandos mais úteis na minha caixa de ferramentas. Não apenas você pode testar funções localmente simulando eventos, mas também manipular completamente o ambiente passando a opção -s
com o nome do stage desejado.
Por exemplo, se eu estivesse escrevendo um script que interaja com um banco de dados (talvez consultando dados para um relatório), provavelmente criaria um banco de dados local e apontaria meu MYSQL_HOST
para localhost (junto com outras configurações). Agora, a execução sls invoke local -f myDBFunction -p /path/to/event.json -s local
executaria minha consulta na versão local. No entanto, se eu mudar meu -s
para dev
desejo que meu código acesse a versão "dev" do meu banco de dados (que talvez esteja na nuvem). Isso é útil para testar alterações de consulta e compatibilidade.
Isso também é ótimo para permitir que você altere outros recursos com base em STAGE, como SQS, S3 buckets, tabelas Dynamo DB, etc.
Como configuramos nosso serverless.yml para fazer isso?
Outro ótimo recurso do Serverless Framework é "auto-referenciar" variáveis dentro do arquivo serverless.yml
. Isso nos permite usar valores estáticos (ou mesmo referenciados recursivamente) para definir outros valores. Tenho certeza que você usou isso ao nomear funções, por exemplo, name: ${opt:stage}-myFunction
, você também pode definir um valor padrão, caso a referência não exista, por exemplo stage: ${opt:stage,'dev'}
, o que é incrivelmente útil. 👍
No nosso caso, queremos fornecer uma lista de opções possíveis com base no STAGE fornecido. Isso pode ser realizado de várias maneiras. A documentação ainda oferece o exemplo de inclusão de um arquivo separado com base no nome STAGE, o que deixa tudo mais fácil. Tudo que você precisa fazer é criar um objeto dentro de custom:
que forneça um valor para cada stage:
# Custom Variables
custom:
mysqlHost:
local: localhost
dev: devdb.example.com
staging: ${ssm:/myapp/staging/mysql-host} # pegando do ssm
prod: ${ssm:/myapp/prod/mysql-host} # pegando do ssm
Agora basta auto-referenciar a chave correta do objeto na seção environment:
.
# Environment Variables
environment:
MYSQL_HOST: ${self:custom.mysqlHost.${self:provider.stage}}
E é isso! Agora, sempre que você usar a opção -s local
, o host do seu banco de dados será "localhost". Quando você altera o valor do stage, o valor do host também será alterado!
Abaixo um exemplo mais completo:
# Serverless Config
service: myapp
# Provider
provider:
name: aws
runtime: nodejs8.10
stage: ${opt:stage,'dev'}
...
# Environment Variables
environment:
MYSQL_HOST: ${self:custom.mysqlHost.${self:provider.stage}}
MYSQL_USER: ${self:custom.mysqlUser.${self:provider.stage}}
MYSQL_PASSWORD: ${self:custom.mysqlPassword.${self:provider.stage}}
MYSQL_DATABASE: ${self:custom.mysqlDatabase.${self:provider.stage}}
MYSQL_PORT: ${self:custom.mysqlPort.${self:provider.stage}}
# Custom Variables
custom:
stages:
- dev
- staging
- prod
mysqlHost:
local: localhost
dev: devdb.example.com
staging: ${ssm:/myapp/staging/mysql-host} #get from ssm
prod: ${ssm:/myapp/prod/mysql-host} #get from ssm
mysqlUser:
local: root
dev: myapp_devuser
staging: myapp_stag
prod: myapp
mysqlPassword:
local: root
dev: ${ssm:/myapp/dev/mysql-password~true} #get from ssm (secure)
staging: ${ssm:/myapp/staging/mysql-password~true} #get from ssm (secure)
prod: ${ssm:/myapp/prod/mysql-password~true} #get from ssm (secure)
mysqlDatabase:
local: myapp_testdb
dev: myapp_dev
staging: myapp_staging
prod: myapp_prod
mysqlPort:
local: '8889'
dev: '3306'
staging: '3306'
prod: '3306'
# Plugins
plugins:
- serverless-stage-manager
...
Para onde vamos daqui?
Essa técnica também funciona para sistemas de CI / CD. Se o seu ambiente de produção estiver em uma conta separada, o acesso a segredos compartilhados permanecerá seguro.
Se você deseja acessar serviços em nuvem que estão em uma VPC, sempre pode criar estágios adicionais, como dev_local
. Em seguida, você pode acessar recursos remotos por meio de uma VPN ou usar túneis SSH para acessar recursos atrás de uma VPC. Você pode usar o encaminhamento de porta, por exemplo, para direcionar o tráfego do MySQL para o host local através da sua instância do VPC RDS.
Se você quiser se salvar de digitar nomes errados de stages, confira o Serverless Stage Manager. Isso permite restringir os nomes de stages usados para implementar stacks completas e funções.
Espero que você tenha achado isso útil. Boa sorte e vá serverless! 🤘🏻
Créditos
- How To: Manage Serverless Environment Variables Per Stage, escrito originalmente por Jeremy Daly
Top comments (0)