GNU/Linux >> Linux Esercitazione >  >> Panels >> Docker

Terraform – Distribuisci Python Lambda (immagine contenitore)

Alla fine del 2020, AWS ha annunciato il supporto delle immagini dei container per Lambda. Questa funzione ti consente di creare pacchetti e distribuire funzioni Lambda come immagini di container fino a 10 GB di dimensione. Questo articolo illustra come utilizzare Terraform per distribuire funzioni Lambda Python supportate dall'immagine del contenitore. In questo articolo, spieghiamo come utilizzare Terraform per distribuire funzioni Python Lambda supportate dall'immagine del contenitore.

Una delle attività comuni nel mondo del cloud è replicare i repository del codice sorgente da locale al cloud o tra ambienti cloud. Quindi, per illustrare l'approccio, abbiamo deciso di aggiungere il supporto Git e GitPython alla funzione Lambda.

Struttura del progetto

Ecco una struttura del progetto che utilizzeremo durante questa demo:

$ tree lambda_container
lambda_container
├── README.md
├── lambdas
│   └── git_client
│       ├── Dockerfile
│       └── index.py
└── main.tf

2 directories, 4 files
  • lambdas – la cartella in cui mettiamo il codice sorgente delle funzioni Lambda
  • main.tf – Codice demo Terraform, che creerà il container Docker per la funzione git_client Lambda e distribuirà la funzione in seguito

File Docker

Descriviamo un contenitore Docker che ospiterà tutte le dipendenze per le nostre funzioni lambda. Ecco il Dockerfile contenuto:

FROM public.ecr.aws/lambda/python:3.8

RUN yum update -y && \
  yum install -y git && \
  rm -Rf /var/cache/yum && \
  pip install git-remote-codecommit boto3 GitPython awscli

COPY index.py ${LAMBDA_TASK_ROOT}

CMD [ "index.handler" ]

Prendiamo come base l'immagine Docker pubblica di Python 3.8 da Amazon. Quindi installiamo Git, puliamo le cache yum per ridurre il contenitore e installiamo le dipendenze necessarie, che ci consentono di utilizzare Git con CodeCommit utilizzando IAM per l'autenticazione.

Successivamente, stiamo copiando il index.py file nella cartella in cui dovrebbe risiedere il codice della funzione Lambda. Consulta Utilizzo delle variabili di ambiente AWS Lambda per ulteriori informazioni.

Infine, stiamo specificando di eseguire il metodo del gestore dal file index.py all'avvio del contenitore.

Codice Lambda

Non appena la dichiarazione del contenitore Lambda è finalizzata, possiamo scrivere una funzione Lambda, che la utilizzerà. Ecco un esempio di codice, che mostrerà come clonare il repository Git. Sono sicuro che sarai in grado di adattare questo esempio alle tue esigenze personali:

import logging
import os
import git
 
TMP_DIR = "/tmp"
REPO_DIR = 'aws-config-rules'
REPO_URL = f'https://github.com/andreivmaksimov/{REPO_DIR}'
CLONE_PATH = os.path.join(TMP_DIR, REPO_DIR)
 
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
 
def clone(branch='master'):
   repo = git.Repo.clone_from(REPO_URL, CLONE_PATH, branch=branch)
 
   with repo.config_writer() as git_config:
       git_config.set_value('user', 'email', '[email protected]')
       git_config.set_value('user', 'name', 'Git Lambda')
  
def handler(event, context):
   LOGGER.info('Event: %s', event)
 
   LOGGER.info('Cloning repo: %s', REPO_URL)
   clone()

In questo codice, dichiariamo le librerie Python richieste, alcune costanti, la configurazione del logger e un paio di funzioni:

  • def clone(branch='master') – questa funzione mostra come clonare il repository Git
  • def handler(event, context) – questa funzione è il punto di ingresso principale della funzione Lambda, registra l'evento in arrivo e chiama clone funzione

Codice Terraform

Non appena abbiamo il codice Lambda e ne dichiariamo il contenitore, possiamo scrivere del codice Terraform per automatizzare la distribuzione. Eccolo:

variable region {
 default = "us-east-1"
}
 
provider aws {
 region = var.region
}
 
data aws_caller_identity current {}
 
locals {
 prefix = "git"
 account_id          = data.aws_caller_identity.current.account_id
 ecr_repository_name = "${local.prefix}-demo-lambda-container"
 ecr_image_tag       = "latest"
}
 
resource aws_ecr_repository repo {
 name = local.ecr_repository_name
}
 
resource null_resource ecr_image {
 triggers = {
   python_file = md5(file("${path.module}/lambdas/git_client/index.py"))
   docker_file = md5(file("${path.module}/lambdas/git_client/Dockerfile"))
 }
 
 provisioner "local-exec" {
   command = <<EOF
           aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${local.account_id}.dkr.ecr.${var.region}.amazonaws.com
           cd ${path.module}/lambdas/git_client
           docker build -t ${aws_ecr_repository.repo.repository_url}:${local.ecr_image_tag} .
           docker push ${aws_ecr_repository.repo.repository_url}:${local.ecr_image_tag}
       EOF
 }
}
 
data aws_ecr_image lambda_image {
 depends_on = [
   null_resource.ecr_image
 ]
 repository_name = local.ecr_repository_name
 image_tag       = local.ecr_image_tag
}
 
resource aws_iam_role lambda {
 name = "${local.prefix}-lambda-role"
 assume_role_policy = <<EOF
{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Action": "sts:AssumeRole",
           "Principal": {
               "Service": "lambda.amazonaws.com"
           },
           "Effect": "Allow"
       }
   ]
}
 EOF
}
 
data aws_iam_policy_document lambda {
   statement {
     actions = [
         "logs:CreateLogGroup",
         "logs:CreateLogStream",
         "logs:PutLogEvents"
     ]
     effect = "Allow"
     resources = [ "*" ]
     sid = "CreateCloudWatchLogs"
   }
 
   statement {
     actions = [
         "codecommit:GitPull",
         "codecommit:GitPush",
         "codecommit:GitBranch",
         "codecommit:ListBranches",
         "codecommit:CreateCommit",
         "codecommit:GetCommit",
         "codecommit:GetCommitHistory",
         "codecommit:GetDifferences",
         "codecommit:GetReferences",
         "codecommit:BatchGetCommits",
         "codecommit:GetTree",
         "codecommit:GetObjectIdentifier",
         "codecommit:GetMergeCommit"
     ]
     effect = "Allow"
     resources = [ "*" ]
     sid = "CodeCommit"
   }
}
 
resource aws_iam_policy lambda {
   name = "${local.prefix}-lambda-policy"
   path = "/"
   policy = data.aws_iam_policy_document.lambda.json
}
 
resource aws_lambda_function git {
 depends_on = [
   null_resource.ecr_image
 ]
 function_name = "${local.prefix}-lambda"
 role = aws_iam_role.lambda.arn
 timeout = 300
 image_uri = "${aws_ecr_repository.repo.repository_url}@${data.aws_ecr_image.lambda_image.id}"
 package_type = "Image"
}
 
output "lambda_name" {
 value = aws_lambda_function.git.id
}

Questo codice Terraform è stato testato utilizzando Terraform versione 0.14.8.

In questo esempio, utilizziamo le seguenti risorse di terraform:

  • aws_ecr_repository – crea un registro ECR in cui Terraform salverà l'immagine del contenitore Docker, che verrà successivamente utilizzata dalla nostra funzione Lambda
  • null_resource – viene utilizzato per creare un container Docker e inviarlo al registro ECR, attiva le modifiche dei controlli nel codice della funzione Lambda e nel Dockerfile e consente a Terraform di capire quando ricostruire l'immagine e aggiornare la funzione Lambda
  • aws_ecr_image – ci consente di richiedere informazioni sull'immagine Docker pubblicata
  • aws_iam_role , aws_iam_policy_document e aws_iam_policy – dichiara un'autorizzazione (invio log a CloudWatch, accesso CodeCommit) per la funzione Lambda
  • aws_lambda_function – Dichiarazione della funzione Lambda stessa

Distribuzione

Per testare la soluzione devi prima distribuire il codice Terraform:

terraform init
terraform apply -auto-approve

Quindi devi eseguire la funzione Lambda:

aws lambda invoke --function-name git-lambda out --log-type Tail --query 'LogResult' --output text |  base64 -d

Ecco un output previsto:

START RequestId: b8b742d6-5bd6-4098-90e3-5e30f5c6e816 Version: $LATEST
[INFO]  2021-03-16T02:10:28.064Z        b8b742d6-5bd6-4098-90e3-5e30f5c6e816    Event: {}
[INFO]  2021-03-16T02:10:28.064Z        b8b742d6-5bd6-4098-90e3-5e30f5c6e816    Cloning repo: https://github.com/andreivmaksimov/aws-config-rules
END RequestId: b8b742d6-5bd6-4098-90e3-5e30f5c6e816
REPORT RequestId: b8b742d6-5bd6-4098-90e3-5e30f5c6e816  Duration: 4069.15 ms    Billed Duration: 6131 ms        Memory Size: 128 MB     Max Memory Used: 83 MB  Init Duration: 2061.73 ms

Pulizia

Per ripulire tutto, esegui il seguente comando:

terraform destroy

Riepilogo

Questo articolo ha creato un container Docker per la funzione AWS Lambda e distribuito l'intera soluzione utilizzando Terraform. Ci auguriamo che tu abbia trovato utile questo articolo. Se è così, per favore, aiutaci a diffonderlo nel mondo. In caso di domande, non esitare a farle nella sezione chat qui sotto.


Docker
  1. Come costruire il contenitore Docker Anaconda Python Data Science

  2. Estrarre il file dall'immagine Docker?

  3. Come distribuire PostgreSQL come contenitore Docker

  4. Come creare un'immagine Docker da un contenitore e un file Docker

  5. Commit dati in un contenitore mysql

Come creare un'immagine Docker da un contenitore in esecuzione

Distribuire un'installazione di MariaDB di Production Docker

Come distribuire un container Docker in AWS Elastic Beanstalk

Come distribuire un'applicazione API Python Flask su Docker

Come distribuire e gestire un contenitore Docker MongoDB

Come utilizzare Docker Commit per modificare le immagini del contenitore