Nos últimos anos, a criação de uma infraestrutura serverless tornou-se mais acessível do que nunca. Com as plataformas AWS, Azure e Google Cloud, os desenvolvedores e engenheiros têm recursos quase ilimitados ao implantar sites e aplicativos. O Serverless Framework, uma estrutura popular para criar arquitetura serverless, tornou ainda mais fácil a utilização das maiores plataformas de computação em nuvem disponíveis. Eles fizeram isso abstraindo a configuração da arquitetura de nuvem para uma forma mais direta usando um arquivo YAML. Neste artigo, veremos o arquivo serverless.yml
em mais detalhes para ver como ele é usado para configurar uma arquitetura serverless.
O arquivo "serverless.yml"
O serverless.yml
é o coração de um aplicativo serverless. Este arquivo descreve toda a infraestrutura de aplicativos, desde a linguagem de programação até o acesso a recursos.
A seção principal deste arquivo YAML é o provider
. Na configuração do serverless.yml
, você tem a opção de usar o AWS, o Google Cloud ou o Microsoft Azure como seu provedor serverless. Você também pode especificar a linguagem de programação que deseja usar. No exemplo abaixo, eu especifico que vou usar o AWS com o Python 3.7.
Exemplo de um serverless.yml
:
service: my-first-serverless-app
provider:
name: aws
runtime: python3.7
O arquivo serverless.yml
acima é a base do que poderia ser um poder ilimitado de computação, centenas de funções serverless e uma infraestrutura de banco de dados que potencializa seu site ou aplicativo. Vamos nos aprofundar nessa configuração. Eu vou estar usando o AWS e python para o meu exemplo de base.
Variáveis de Ambiente
Configurar variáveis de ambiente para usar em seu aplicativo é realmente fácil com o arquivo serverless.yml
. Dentro da chave provider
, você adiciona uma seção de ambiente e uma lista de valores de chave/valor. Usando o nosso exemplo acima um passo adiante, vamos adicionar uma variável de ambiente que especifica um nome de tabela para uma tabela de usuários.
provider:
name: aws
runtime: python3.7
environment:
USER_TABLE: users_table
Agora, em qualquer função serverless que utilizamos, a variávei de ambiente USER_TABLE
estará disponível para uso. Também podemos usar essa variável em outras partes do nosso arquivo serverless.yml
para nomear recursos ou prefixar caminhos HTTP.
Para usar essa variável de ambiente no serverless.yml
mais tarde, use a seguinte sintaxe. Observe que é semelhante a percorrer um objeto em outras linguagens de programação.
${self:provider.environment.USER_TABLE}
Dividindo em múltiplos arquivos
Muitas vezes você precisa separar a configuração de seu aplicativo em múltiplos arquivos. O Serverless Framework possui uma sintaxe muito legal para incluir variáveis de outros arquivos. Digamos, por exemplo, que você queira que a tabela do usuário seja denominada dev_users_table
para um ambiente de desenvolvimento. Há muitas maneiras para isso, mas para ilustrar o fornecimento de outros arquivos, mostrarei uma maneira.
Você pode ter vários arquivos de configuração que são usados para ambientes específicos. Digamos que você tenha dois arquivos de configuração YAML na pasta raiz do seu projeto:
Exemplo dev.config.yml
:
table_name: 'dev_users_table'
Exemplo prod.config.yml
:
table_name: 'prod_users_table'
Seu aplicativo de produção usaria prod.config.yml
. Para obter esse arquivo em produção, você pode usar a seguinte sintaxe:
provider:
name: aws
runtime: python3.7
environment:
USER_TABLE: ${file(./prod.config.yml):table_name}
Mas espere, como você implementa este aplicativo em dev? Você tem que mudar o arquivo para especificar dev certo? Não, podemos atualizar essa configuração para utilizar a variável stage
. A variável stage
é uma variável especial na estrutura do arquivo yaml que pode ser usada para especificar qual ambiente você está usando. Por padrão, a variável stage é dev.
Variáveis stage
Vamos consertar nosso serverless.yml
para que possamos usar a configuração dev sem modificar o arquivo manualmente. Para fazer isso, usamos ${opt: stage, self: provider.stage}
.
Exemplo do serverless.yml com variável stage:
provider:
name: aws
runtime: python3.7
environment:
USER_TABLE: ${opt:stage, self:provider.stage}_users_table
Agora que estamos usando a variável stage. Nós não precisamos do arquivo prod.config.yml. Podemos facilmente prefixar todos os nossos serviços com a variável stage para que, quando implantarmos nosso aplicativo para testar um novo serviço ou recurso, não afetemos os serviços de produção.
Se nós quiséssemos usar arquivos de configuração separados, poderíamos usar nossa variável stage para separar a configuração em arquivos separados como este:
provider:
name: aws
runtime: python3.7
environment:
USER_TABLE: ${file(./${opt:stage, self:provider.stage}.config.yml):table_name}
Separar suas variáveis de ambiente em arquivos é uma ótima maneira de organizar aplicativos maiores que usam muitos recursos, como buckets do S3, tabelas de banco de dados, caminhos de versão da API etc.
Declarações de IAM Roles
Se você usou os serviços da AWS, provavelmente precisou criar um usuário do IAM ou Role. Com o serverless, você pode conceder permissões às suas aplicações para utilizar recursos através do arquivo serverless.yml. A configuração de permissão é basicamente o AWS Cloudformation escrito em YAML. As permissões vão sob a seção iamRoleStatements sob dentro de provider.
Dando acesso ao S3
Se você tiver um bucket S3 chamado awesome-bucket-name. O exemplo a seguir dará ao seu aplicativo acesso completo (Read, Write, List, etc) ao bloco especificado.
provider:
name: aws
runtime: python3.7
environment:
USER_TABLE: users_table
iamRoleStatements:
- Effect: "Allow"
Action:
- "s3:*"
Resource:
- arn:aws:s3:::awesome-bucket-name
Dando acesso ao SES
Se você tem um aplicativo que precisa enviar e-mails. Você pode dar acesso ao Amazon SES da seguinte forma: (Observação: você precisa configurar o SES com um domínio verificado separadamente.) O exemplo a seguir dá ao seu aplicativo acesso para usar todos os recursos do SES para enviar emails.
provider:
name: aws
runtime: python3.7
environment:
USER_TABLE: users_table
iamRoleStatements:
- Effect: "Allow"
Action:
- "ses:SendEmail"
Resource: "*"
Funções
Eu tenho escrito sobre esse misterioso "aplicativo", mas não expliquei o que ele é. Em seu arquivo serverless.yml, você configura as funções a serem criadas na plataforma serverless do provider. Para AWS, é possível dizer ao serverless para criar funções do Lambda que possam ser anexadas a um endpoint HTTP. Vamos dar uma olhada rápida em como definir um endpoint HTTP através do arquivo serverless.yml .
Sem funções, você não possui um aplicativo. Lembre-se da linguagem de programação que especificamos no provider? Isso diz ao nosso provider com qual linguagem de programação iremos criar nossas funções. (Nota: as linguagens de programação são determinadas pelo provider. Você não pode escolher qualquer idioma.)
Como exemplo, vamos criar um endpoint HTTP que retorne o hash md5 de um endereço de email, juntamente com a URL do Gravatar para esse email.
Para definir uma função, precisamos de duas coisas:
- Um arquivo com a função chamada getHash, chamaremos o arquivo de handler.py
- Uma definição de função em serverless.yml
Exemplo da definição no serverless.yml:
functions:
myCustomFunctionName:
handler: handler.getHash
Na primeira linha, temos functions. Esta é uma seção do arquivo YAML que vive na seção do provider. Na seção de funções, temos myCustomFunctionName. Esse nome será o nome da função Lambda no AWS Lambda, não o usado no código.
Em seguida, definimos o handler . O handler é o caminho para a função usando a notação de ponto. Essa notação de ponto é semelhante a como as importações funcionam no Python. handler é o nome do arquivo e getHash é o nome da função nesse arquivo.
Aqui está o nosso handler.py:
import hashlib
import json
CORS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': True,
}
def getHash(event, context):
string = event['pathParameters']['string']
h = hashlib.md5(string.encode('utf8'))
h = h.hexdigest()
return {
"statusCode": 200,
"headers": CORS,
"body": json.dumps({
"hash": h,
"avatar": "http://gravatar.com/avatar/{}".format(h)
})
}
Com o arquivo definido e a função chamada getHash dentro, nosso serverless.yml está pronto para criar nossa função no AWS Lambda. Antes de implantar isso, precisamos ativar o acesso a essa função via HTTP. Para tornar isso um endpoint HTTP, vamos adicionar uma seção de eventos.
Exemplo de funções com eventos:
functions:
myCustomFunctionName:
handler: handler.getHash
events:
- http:
path: md5/{email}
method: get
cors: true
A seção events vincula nossa função ao API Gateway fornecido pela AWS. Nesta seção, especificamos o caminho e o método do endpoint HTTP. Com esta configuração de evento, você poderá acessar sua função do Lambda através do caminho /md5/some@email.com. A resposta seria um objeto JSON com o hash md5 e um URL para a imagem gravatar.
Exemplo de saída com meu email:
{
"hash": "97fbef641c6e4669b6a1ad4ffb3342f5",
"avatar": "http://gravatar.com/avatar/97fbef641c6e4669b6a1ad4ffb3342f5"
}
Você pode ir ainda mais longe com isso, exigindo autenticação e limitação de taxa nesse endpoint. Mais na documentação.
Agora que temos nossos eventos, podemos enviar pedidos para essa função a partir de um aplicativo frontend e ela executará nossa função serverless.
Conclusão
Esta postagem arranha a superfície do arquivo serverless.yml. Espero que você entenda um pouco mais sobre serverless e mergulhe mais fundo nessa estrutura e tecnologia. O Serverless Framework, junto com as plataformas de nuvem disponíveis, permite que as pessoas criem produtos escaláveis a um baixo custo. Construir a infraestrutura para um aplicativo é muito mais fácil do que nunca e pode ser criado usando um arquivo de configuração simples como serverless.yml.
Obrigado pela leitura!
Créditos
- Anatomy of a Serverless YAML File, escrito originalmente por Richard Keller.
Top comments (0)