- Le plus récent
- Le plus de votes
- La plupart des commentaires
Lambda runs in execution environments (micro VMs). Each such EE, runs a single request at a time. When the function returns we keep the EE live for a few minutes so that if another request is received for the same function, we can invoke it directly without going through the cold start again. This means that we absolutely encourage customers to cache values between invocations (when it makes sense) by saving them in global/instance variables. Everything you save in a global variable will be accessible in the following invocations.
As you can cache values (and database connections) between invocations, it is recommended that you initialize those variables in the initialization phase of your function. This means, outside the handler code. Look at this example and you will see that the S3 client is initialized in the main, and not in the handler. This means it will be called only once. (not an expert in Rust, so there may be other ways to achieve the same).
The recommendation with regards to secrets is to have environment variables with the secret name (in SSM/Secrets manager) and either use the extension or just read them at the function's initialization code. Save the credentials in the global variables and you can reuse them in all invocations. Same is true for database connections. Create the connection outside the handler, save it in a global variable, and use it in all invocations.
Last point is regarding RDS Proxy. If there is a chance that you function will scale very high, it is highly recommended that you use the proxy. Otherwise, you may overwhelm the database. Even if you do not anticipate high scale, the proxy can help with: 1. credentials (see above), and 2. better database failure handling.
Hi @Uri thanks for your answer.
I think we agree on the dots (1-) cache values 2-) read secrets securely) but I it's still not clear to me how to connect those dots especially when using Parameter and Secrets Lambda extension layer.
As I mentioned above, you can't access to Parameter and Secrets Lambda extension layer running on localhost outside of the handler function. This would mean that you can't cache code that depends on secrets, do you agree?
That being said, one could simply fetch secrets manually using SDK and cache the secrets in global variables as you suggested (that's what people are/were doing before Parameter and Secrets Lambda extension anyway).
To my understanding, one of the selling point of Parameter and Secrets Lambda extension is that you don't need to pollute your code with aws-sdk just because you want to cache secrets. However, that doesn't seem to be working in practice for cases where you want to have global variable that depends on secrets which you need to fetch from Parameter and Secrets Lambda extension layer.
To clarify, following is something you CANT do with Parameter and Secrets Lambda extension layer:
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { let http_client : reqwest::Client = reqwest::Client::new(); // Note that we are outside of the handler function. This request will result in "not ready to serve traffic, please wait" // which means you can't access to secrets outside of the handler function using Parameter and Secrets Lambda extension layer let secret_response = http_client.get("http://localhost:2773/secretsmanager/get?secretId=your-secret-id") .header("X-Aws-Parameters-Secrets-Token", env::var("AWS_SESSION_TOKEN").unwrap()) .send() .await? .text() .await?; // You CAN'T seem to do this! "http://localhost:2773/secretsmanager/get" doesn't work outside of the handler function. let global_variable_that_depends_on_some_secret = use_secret_to_generate_gloabl_variable(secret_response); lambda_http::run(service_fn(|event: Request| login(event, &http_client))).await?; Ok(()) }
^This made me confused because I expected this to work given the fact that Parameter and Secrets Lambda extension layer was trying to make the following pattern which is widely used easier:
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { let shared_config = aws_config::from_env().load().await; let client = Client::new(&shared_config); let secret_response = client.get_secret_value().secret_id(name).send().await?; // You CAN do this because at this point lambda already have everything it needs to access secret store etc. let global_variable_that_depends_on_some_secret = use_secret_to_generate_gloabl_variable(secret_response); lambda_http::run(service_fn(|event: Request| login(event, &http_client))).await?; Ok(()) }
Given the fact that you mentioned cache is for 5 minutes, this would mean that Attempt #3 - Use IAM authentication to access RDS
would also work because it's also using SDK to retrieve temporary token which can be done outside of the handler function.
To conclude, I was aware of the pattern where you would fetch secrets using SDK and cache them in global variable and given the fact that Parameter and Secrets Lambda extension layer introduced to make this process easier (https://aws.amazon.com/blogs/compute/using-the-aws-parameter-and-secrets-lambda-extension-to-cache-parameters-and-secrets/ see 2nd paragraph) I expected it to just work but it turns out that it's not exactly the same (for some cases) which lead to some confusion on my side. As a result, I won't be using Parameter and Secrets Lambda extension layer since it doesn't work for my use case :)
Contenus pertinents
- demandé il y a un an
- demandé il y a un an
- demandé il y a un an
- AWS OFFICIELA mis à jour il y a 2 ans
- AWS OFFICIELA mis à jour il y a 2 ans
- AWS OFFICIELA mis à jour il y a 2 ans
- AWS OFFICIELA mis à jour il y a 7 mois