У меня следующая ситуация:
- Выделенный арендатор
m4.large
Экземпляр EC2 под управлением RHEL6
- Запуск вручную с помощью консоли AWS работает нормально
- Лямбда-функция (написанная на Java), которая пытается ее запустить, завершается сбоем, потому что состояние экземпляра переходит: остановлено -> ожидание -> остановка -> остановлено
У меня есть лямбда-функция, которая регистрирует все изменения состояния EC2 через VPC следующим образом:
'use strict';
exports.handler = (event, context, callback) => {
console.log('LogEC2InstanceStateChange');
console.log('Received event:', JSON.stringify(event, null, 2));
callback(null, 'Finished');
}
И еще одна лямбда-функция, которая пытается запускать экземпляры EC2 на основе расписания, написанного на Java, которое состоит из большого количества кода, но его ядро выглядит примерно так:
public void handleRequest(Object input, Context context) {
final List<String> instancesToStart = getInstancesToStart(); //implementation not shown
try {
StartInstancesRequest startRequest = new StartInstancesRequest().withInstanceIds((String[]) instancesToStart.toArray());
context.logger.log("StartInstancesRequest: " + startRequest.toString());
StartInstancesResult res = ec2.startInstances(startRequest);
context.logger.log("StartInstancesResult: " + res.toString());
}
catch(Exception e) {
logException(e); //calls context.logger.log on the stack trace string
}
}
Массив instancesToStart
заполняется идентификаторами экземпляров, такими как i-0abcdef1234567890
.
Я создаю функции Lambda и все необходимые роли IAM и т. Д. С помощью CloudFormation. Вот бит, описывающий роль / разрешения для лямбда-функции на основе Java, которая выполняет эту работу:
Resources:
EC2SchedulerRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
EC2SchedulerPolicy:
DependsOn:
- EC2SchedulerRole
Type: 'AWS::IAM::Policy'
Properties:
PolicyName: ec2-scheduler-role
Roles:
- !Ref EC2SchedulerRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'logs:*'
Resource:
- 'arn:aws:logs:*:*:*'
- Effect: Allow
Action:
- 'ec2:DescribeInstanceAttribute'
- 'ec2:DescribeInstanceStatus'
- 'ec2:DescribeInstances'
- 'ec2:StartInstances'
- 'ec2:StopInstances'
- 'ec2:DeleteTags'
Resource:
- '*'
В конечном итоге, согласно журналам CloudWatch от первой функции (сценарий, который регистрирует изменения состояния экземпляра), мы получаем:
Received event:
{
"version": "0",
"id": "<guid>",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "12345678",
"time": "2019-06-20T19:01:35Z",
"region": "us-east-1",
"resources": [
"arn:aws:ec2:us-east-1:12345678:instance/i-0abcdef12345678"
],
"detail": {
"instance-id": "i-0abcdef12345678",
"state": "pending"
}
}
Received event:
{
"version": "0",
"id": "<guid>",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "12345678",
"time": "2019-06-20T19:01:37Z",
"region": "us-east-1",
"resources": [
"arn:aws:ec2:us-east-1:12345678:instance/i-0abcdef12345678"
],
"detail": {
"instance-id": "i-0abcdef12345678",
"state": "stopping"
}
}
Received event:
{
"version": "0",
"id": "<guid>",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "12345678",
"time": "2019-06-20T19:01:37Z",
"region": "us-east-1",
"resources": [
"arn:aws:ec2:us-east-1:12345678:instance/i-0abcdef12345678"
],
"detail": {
"instance-id": "i-0abcdef12345678",
"state": "stopped"
}
}
И согласно журналам CloudWatch от функции «worker» (функция, которая фактически пытается запустить экземпляры), мы получаем:
StartInstancesRequest: {InstanceIds: [i-0abcdef12345678],}
StartInstancesResult: {StartingInstances: [{CurrentState: {Code: 0,Name: pending},InstanceId: i-0abcdef12345678,PreviousState: {Code: 80,Name: stopped}}]}
Таким образом, с точки зрения лямбды на основе Java, которая делает эту работу, она делает все, что ей нужно, чтобы дать команду для запуска экземпляра EC2; но затем, когда экземпляр EC2 пытается фактически запуститься, он переходит от «ожидающего» к «остановке» к «остановленному». Если бы у него не было разрешения, оно бы даже не зашло так далеко, верно?
Если бы это была проблема с самим экземпляром (например, с аппаратным обеспечением), я ожидал бы, что ручной запуск его с помощью консоли AWS завершится с ошибкой . Но это не подводит. Это успешно при запуске вручную!
Так что происходит? Как мне диагностировать это дальше? Это разрешения или экземпляр испорчен?
Я на 99% уверен, что не из-за недостатка доступной емкости в АЗ, потому что всякий раз, когда я пытаюсь запустить экземпляр вручную, он всегда работает. Это не эфемерная проблема или что-то, что происходило только недавно. Это продолжается в течение нескольких месяцев, как это, где ручной запуск работает 100% времени, а запуск на основе сценариев работает 0% времени.