14 votes

Délai de connexion à AWS Lambda RDS

J'essaie d'écrire une fonction Lambda utilisant Node.js qui se connecte à ma base de données RDS. La base de données fonctionne et est accessible depuis mon environnement Elastic Beanstalk. Lorsque j'exécute la fonction, elle renvoie une erreur de dépassement de délai.

J'ai essayé d'augmenter le délai d'attente jusqu'à 5 minutes avec exactement le même résultat.

Après quelques recherches, j'en suis arrivé à la conclusion qu'il s'agit probablement d'un problème de sécurité, mais je n'ai pas trouvé de solution dans la documentation d'Amazon ou dans le site Web de l'entreprise. ce (qui est la seule que j'ai pu trouver sur le sujet).

Voici les détails de la sécurité :

  • Le RDS et le Lambda sont tous deux dans le même groupe de sécurité.
  • Le RDS a des règles pour tout le trafic entrant et sortant.
  • Le Lambda a la politique AmazonVPCFullAccess dans son rôle.

Mon code est :

'use strict';
console.log("Loading getContacts function");

var AWS = require('aws-sdk');
var mysql = require('mysql');

exports.handler = (event, context, callback) => {

   var connection = mysql.createConnection({
        host     : '...',
        user     : '...',
        password : '...',
        port     : 3306,
        database: 'ebdb',
        debug    :  false
    });

    connection.connect(function(err) {
      if (err) callback(null, 'error ' +err);
      else callback(null, 'Success');
    });

};

Le résultat que j'obtiens est :

"errorMessage": "2017-03-05T05:57:46.851Z 9ae64c49-0168-11e7-b49a-a1e77ae6f56c Task timed out after 10.00 seconds"

21voto

ambaum2 Points 311

Si l'utilisation du contexte fonctionne, il suffit d'ajouter context.callbackWaitsForEmptyEventLoop = false; au gestionnaire et ensuite utiliser le callback normalement comme ceci :

exports.handler = (event, context) => {
  context.callbackWaitsForEmptyEventLoop = false; 
  var connection = mysql.createConnection({
    //connection info
  });
  connection.connect(function(err) {
    if (err) callback(err); 
    else callback(null, 'Success');
  });
};

La réponse se trouve ici dans la documentation (il m'a fallu quelques heures pour la trouver) : http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html

La section "Comparaison des méthodes de contexte et de rappel" contient une note "importante" qui explique les choses.

Au bas de la note, il est écrit :

Par conséquent, si vous souhaitez obtenir le même comportement que les méthodes contextuelles, vous devez définir la propriété de l'objet contextuel, callbackWaitsForEmptyEventLoop, sur false.

En fait, le rappel continue jusqu'à la fin de la boucle d'événement, contrairement au contexte qui met fin à la boucle d'événement. Ainsi, en définissant callbackWaitsForEmptyEventLoop, le callback fonctionne comme le contexte.

9voto

Sir Codesalot Points 1905

Je tiens à remercier tous ceux qui m'ont aidé, le problème s'est avéré être différent de ce que je pensais. Le site callback dans le code ne fonctionne pas pour une raison quelconque, même si c'est dans le propre échantillon par défaut d'AMAZON.

Le code de travail ressemble à ceci :

'use strict';
console.log("Loading getContacts function");

var AWS = require('aws-sdk');
var mysql = require('mysql');

exports.handler = (event, context) => {

   var connection = mysql.createConnection({
        host     : '...',
        user     : '...',
        password : '...',
        port     : 3306,
        database: 'ebdb',
        debug    :  false
    });

    connection.connect(function(err) {
      if (err) context.fail();
      else context.succeed('Success');
    });

};

3voto

Vor Points 3342

Le RDS et le Lambda sont tous deux dans le même groupe de sécurité.

C'est la clé. Par défaut, la communication au sein d'un même groupe de sécurité n'est pas autorisée. Vous devez donc l'autoriser explicitement (E.x sg-xxxxx ALL TCP ). Cela ne fonctionnera que si votre lambda essaie d'accéder à la base de données par une IP privée.

S'il tente d'y accéder par une IP publique, cela ne fonctionnera pas et vous devrez également percer les trous nécessaires à cet effet.

Il existe cependant une meilleure approche :

  1. Créez un groupe de sécurité séparé pour votre lambda
  2. Autoriser le trafic entrant sur le port 3306 dans RDS sg pour lambdas sg.

2voto

abdulbarik Points 3934

Je partage mon expérience en connectant RDS.

Vous devez activer VPC accès pour les Lambda function au cours de laquelle vous lui attribuerez un Groupe de sécurité .

Ensuite, au sein du groupe de sécurité attribué à l'instance RDS, vous activerez l'accès pour le groupe de sécurité attribué à la fonction Lambda.

Vous pouvez obtenir plus d'informations aquí

2voto

toonsend Points 119

Lors de la configuration initiale de la base de données, un groupe de sécurité est automatiquement créé, avec par défaut l'IP avec laquelle vous avez configuré la base de données. Lorsque vous exécutez depuis lambda, cette règle bloque le trafic. Vérifiez les journaux d'erreurs de votre base de données et vous pourrez confirmer qu'elle refuse la connexion.

***** could not be resolved: Name or service not known

Vous devez créer une règle dans le groupe de sécurité pour autoriser le trafic lambda. Allez dans la console de votre instance RDS et cliquez sur le groupe de sécurité, sélectionnez inbound. Vous y verrez les règles. Ensuite, faites l'appel pour vous ouvrir au monde, trouvez les IPs AWS lambda ou créez un VPC.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X