我尝试为我的lambda函数启用snapstart,该函数仅使用简单的java AWS SDK连接到仅将消息放入队列。没有snapstart代码工作正常,但是当它启用时,我得到这个错误
提交异常消息时出错:无法从链中的任何提供者加载AWS凭据
我已经附上了SQS的完整访问策略,它在没有snapstart的情况下工作得很好。
final Map<String, MessageAttributeValue> messageAttributes = new HashMap<>();
messageAttributes.put("testID", new MessageAttributeValue().withStringValue("id123").withDataType("String"));
final AmazonSQS sqs = AmazonSQSClientBuilder.standard().withRegion(Regions.EU_WEST_1).build();
final SendMessageRequest sendMessageStandardQueue = new SendMessageRequest().withQueueUrl("https://sqs.eu-west-1.amazonaws.com/111111/my-queue")
.withMessageBody("Test message from lambda")
.withMessageAttributes(messageAttributes);
sqs.sendMessage(sendMessageStandardQueue);
这段代码没有在lambda函数上启用snapstart也可以正常工作。启用snapstart后,我在代码中添加了以下代码:
@Override
public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
System.out.println("Before Checkpoint");
}
@Override
public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception {
System.out.println("After Restore");
}
你能帮我理解为什么它无法加载凭据吗?
?如果您依赖于AWS SDK的环境凭证提供程序,则重新水合的SnapStart Lambda函数将无法找到AWS凭证。根据使用SnapStart与AWS sdk:
当SnapStart被激活时,Java运行时自动使用容器凭证(AWS_CONTAINER_CREDENTIALS_FULL_URI和AWS_CONTAINER_AUTHORIZATION_TOKEN)而不是访问键环境变量。这可以防止在恢复功能之前凭据过期。
所以,我认为这意味着:
- 始终通过IAM角色向Lambda函数提供IAM凭据
- 确保您的代码使用默认凭证提供程序链
如果这不是问题,那么尝试确定Lambda函数是否依赖于对快照和恢复操作不具有弹性的状态。考虑使用AWS Lambda SnapStart漏洞扫描器进行进一步调查。
特别是,兼容性考虑包括:临时数据有些函数在初始化阶段下载或初始化临时数据,例如临时凭据或缓存的时间戳。在使用函数处理程序之前刷新它中的临时数据,即使不使用SnapStart。
此外,在发布时根据博客文章有一些限制:
- 它目前只支持Java,特别是Corretto (java11)运行时
- 不能将Lambda SnapStart用于较大的临时存储、弹性文件系统、预置并发性或gravon2
- 缓存的快照在14天后被删除
如何放置?
使用AWS SDK v2:SqsClient sqs = SqsClient.builder()
.credentialsProvider(SdkSystemSetting.AWS_CONTAINER_CREDENTIALS_FULL_URI
.getStringValue()
.isPresent()
? ContainerCredentialsProvider.builder().build()
: EnvironmentVariableCredentialsProvider.create())
.region(Region.of(SdkSystemSetting.AWS_REGION.getStringValueOrThrow()))
.build();
对于Snapstart环境,我们将使用SDK的容器凭据;对于普通的Lambda环境,我们可以为SDK使用环境凭据。确定我们所处环境的一种方法是检查容器URI:
public AwsCredentialsProvider provideAwsCredentials()
return System.getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI") == null ?
EnvironmentVariableCredentialsProvider.create() : ContainerCredentialsProvider.builder().build();