Dans l'ensemble, je suis assez confus en utilisant AWS Lambda dans un VPC. Le problème est que Lambda arrive à expiration en essayant d'accéder à un compartiment S3. La solution semble être un point de terminaison VPC.
J'ai ajouté la fonction Lambda à un VPC afin qu'il puisse accéder à une base de données hébergée RDS (non affichée dans le code ci-dessous, mais fonctionnelle). Cependant, maintenant je ne peux pas accéder à S3 et toute tentative de le faire expire.
J'ai essayé de créer un point final VPC S3, mais rien n'a changé.
Configuration VPC
J'utilise un VPC simple créé par défaut chaque fois que je crée une instance EC2 pour la première fois. Il a quatre sous-réseaux, tous créés par défaut.
Table de routage VPC
_Destination - Target - Status - Propagated_
172.31.0.0/16 - local - Active - No
pl-63a5400a (com.amazonaws.us-east-1.s3) - vpce-b44c8bdd - Active - No
0.0.0.0/0 - igw-325e6a56 - Active - No
Téléchargement simple S3 Lambda:
import boto3
import pymysql
from StringIO import StringIO
def lambda_handler(event, context):
s3Obj = StringIO()
return boto3.resource('s3').Bucket('marineharvester').download_fileobj('Holding - Midsummer/sample', s3Obj)
Avec boto3, les URL S3 sont virtuelles par défaut, ce qui nécessite alors que l'accès Internet soit résolu en URL spécifiques à la région. Cela provoque le blocage de la fonction Lambda jusqu'à l'expiration du délai.
Pour résoudre ce problème, vous devez utiliser un objet Config
lors de la création du client, qui indique à boto3 de créer chemin URL S3 basées sur le chemin:
import boto3 import botocore.config
client = boto3.client('s3', 'ap-southeast-2, config=botocore.config.Config(s3={'addressing_style':'path'}))
Notez que la région de l'appel doit être la région vers laquelle vous déployez le point de terminaison lambda et VPC.
Vous pourrez ensuite utiliser le pl-xxxxxx
liste de préfixes pour le point de terminaison VPC au sein du groupe de sécurité Lambda, et toujours accéder à S3.
Voici un fonctionnement script CloudFormation qui le démontre. Il crée un compartiment S3, un lambda (qui place les enregistrements dans le compartiment) associé à un VPC contenant uniquement des sous-réseaux privés et le point de terminaison VPC, et les rôles IAM nécessaires.
Il y a un autre problème concernant les sous-réseaux et les itinéraires qui n'est pas traité dans les autres réponses, donc je crée une réponse distincte à condition que toutes les réponses ci-dessus s'appliquent. Vous devez les obtenir correctement pour que la fonction lambda accède à S3.
Lorsque vous créez un nouveau compte AWS comme je l'ai fait l'automne dernier, aucune table de routage n'est automatiquement associée à votre VPC par défaut (voir Tables de routage -> Associations de sous-réseaux dans la console).
Donc, si vous suivez les instructions pour créer un point de terminaison et créer un itinéraire pour ce point de terminaison, aucun itinéraire n'est ajouté, car il n'y a pas de sous-réseau pour le mettre. Et comme d'habitude avec AWS, vous ne recevez pas de message d'erreur ...
Ce que vous devez faire est de créer un sous-réseau pour votre fonction lambda, associer ce sous-réseau à la table de routage et à la fonction lambda, puis réexécuter les instructions du point de terminaison et, en cas de succès, trouver une table de routage qui comporte trois entrées comme celle-ci:
Destination Target
10.0.0.0/16 Local
0.0.0.0/0 igw-1a2b3c4d
pl-1a2b3c4d vpce-11bb22cc
Si vous n'avez que deux entrées (aucune entrée "pl-xxxxx"), vous n'avez pas encore réussi.
En fin de compte, je suppose qu'il ne devrait pas être surprenant qu'une fonction lambda ait besoin d'un sous-réseau pour vivre, comme toute autre entité d'un réseau. Et il est probablement conseillé de ne pas vivre sur le même sous-réseau que vos instances EC2 car lambda peut avoir besoin de différentes routes ou autorisations de sécurité. Notez que l'interface graphique de lambda veut vraiment que vous ayez deux sous-réseaux dans deux AZ différents, ce qui est également une bonne idée.
La cause de mon problème n'était pas la configuration correcte des règles sortantes de mon groupe de sécurité. Plus précisément, j'ai dû ajouter une règle sortante de protocole personnalisé avec une destination pl-XXXXXXXX (le service S3. La valeur réelle a été fournie par la console AWS).
Il existe une autre solution liée aux points de terminaison VPC.
Sur AWS Console, choisissez le service VPC, puis les points de terminaison. Créez un nouveau point de terminaison, associez-le au service s3
sélection du point final VPC S
puis sélectionnez le VPC et la table de routage.
Sélectionnez ensuite le niveau d'accès (complet ou personnalisé) et cela fonctionnera.