如何通过API及Java SDK为EC2实例配置启停调度策略
Hey Leo, great questions! Let's walk through how to set up EC2 instance scheduling via API and implement it with the Java SDK step by step.
Under the hood, you'll use AWS EventBridge (the successor to CloudWatch Events) to create scheduled rules that trigger EC2 start/stop actions. Here's the step-by-step breakdown:
Step 1: Create an IAM Role for EventBridge
EventBridge needs permissions to call EC2 APIs on your behalf. Create a role with:- A trust policy that allows
events.amazonaws.comto assume the role. - A permission policy granting
ec2:StartInstancesandec2:StopInstancespermissions for your target EC2 instance(s).
- A trust policy that allows
Step 2: Create EventBridge Scheduled Rules
You'll need two separate rules (one for start, one for stop):- Start Rule: Define a cron expression matching your desired start time. By default, EventBridge uses UTC, so adjust for your timezone. For example, 7 AM Beijing time (UTC+8) translates to 11 PM UTC the previous day, so the cron expression is
cron(0 23 * * ? *). - Stop Rule: For 6 PM Beijing time, UTC is 10 AM, so use
cron(0 10 * * ? *).
- For each rule, add a target that invokes the EC2
StartInstancesorStopInstancesAPI, specifying your instance ID and the IAM role you created.
- Start Rule: Define a cron expression matching your desired start time. By default, EventBridge uses UTC, so adjust for your timezone. For example, 7 AM Beijing time (UTC+8) translates to 11 PM UTC the previous day, so the cron expression is
Optional: Use Local Timezone
If you don't want to convert to UTC, set thetimeZoneparameter when creating the rule (e.g.,Asia/Shanghai), then use your local time directly in the cron expression (e.g.,cron(0 7 * * ? *)for 7 AM Beijing time).
We'll use the AWS SDK for Java 2.x (the latest, maintained version) to automate this process. Here's a complete example:
Prerequisites
First, add these dependencies to your pom.xml (Maven):
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>eventbridge</artifactId> <version>2.25.0</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>iam</artifactId> <version>2.25.0</version> </dependency>
Step 1: Create the IAM Role (Optional, can also be done manually)
This code creates the role with the necessary trust and permission policies:
import software.amazon.awssdk.services.iam.IamClient; import software.amazon.awssdk.services.iam.model.*; public class CreateEventBridgeEC2Role { public static void main(String[] args) { String accountId = "YOUR_AWS_ACCOUNT_ID"; String region = "YOUR_AWS_REGION"; String instanceId = "YOUR_EC2_INSTANCE_ID"; try (IamClient iam = IamClient.create()) { // Trust policy: Allow EventBridge to assume this role String trustPolicy = """ { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } """; CreateRoleRequest roleRequest = CreateRoleRequest.builder() .roleName("EventBridge-EC2-Scheduler-Role") .assumeRolePolicyDocument(trustPolicy) .description("Grants EventBridge permission to start/stop EC2 instances") .build(); CreateRoleResponse roleResponse = iam.createRole(roleRequest); String roleArn = roleResponse.role().arn(); System.out.println("Created role ARN: " + roleArn); // Permission policy: Allow start/stop on target instance String permissionPolicy = String.format(""" { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ec2:StartInstances", "ec2:StopInstances"], "Resource": "arn:aws:ec2:%s:%s:instance/%s" } ] } """, region, accountId, instanceId); PutRolePolicyRequest policyRequest = PutRolePolicyRequest.builder() .roleName("EventBridge-EC2-Scheduler-Role") .policyName("EC2-Start-Stop-Permissions") .policyDocument(permissionPolicy) .build(); iam.putRolePolicy(policyRequest); System.out.println("Attached permission policy to role."); } catch (IamException e) { System.err.println("Error creating role: " + e.awsErrorDetails().errorMessage()); System.exit(1); } } }
Step 2: Create EventBridge Scheduler Rules
This code creates the start and stop rules with your desired schedule (using Beijing timezone directly):
import software.amazon.awssdk.services.eventbridge.EventBridgeClient; import software.amazon.awssdk.services.eventbridge.model.*; import java.util.List; public class EC2InstanceScheduler { public static void main(String[] args) { String instanceId = "YOUR_EC2_INSTANCE_ID"; String roleArn = "ARN_OF_THE_IAM_ROLE_YOU_CREATED"; String region = "YOUR_AWS_REGION"; try (EventBridgeClient eventBridge = EventBridgeClient.builder().region(region).build()) { // Create rule to start instance at 7 AM Beijing time createScheduledRule(eventBridge, "EC2-Start-At-7AM", "cron(0 7 * * ? *)", "Asia/Shanghai", "StartInstances", instanceId, roleArn); // Create rule to stop instance at 6 PM Beijing time createScheduledRule(eventBridge, "EC2-Stop-At-6PM", "cron(0 18 * * ? *)", "Asia/Shanghai", "StopInstances", instanceId, roleArn); System.out.println("Successfully created EC2 start/stop scheduler rules!"); } catch (EventBridgeException e) { System.err.println("Error creating EventBridge rules: " + e.awsErrorDetails().errorMessage()); System.exit(1); } } private static void createScheduledRule(EventBridgeClient eventBridge, String ruleName, String cronExpression, String timeZone, String ec2Action, String instanceId, String roleArn) { // Create the scheduled rule PutRuleRequest ruleRequest = PutRuleRequest.builder() .name(ruleName) .scheduleExpression(cronExpression) .timeZone(timeZone) .state(RuleState.ENABLED) .description("Automatically " + ec2Action.toLowerCase() + " EC2 instance " + instanceId) .build(); PutRuleResponse ruleResponse = eventBridge.putRule(ruleRequest); System.out.println("Created rule ARN: " + ruleResponse.ruleArn()); // Define the target: Invoke EC2 API action Target ec2Target = Target.builder() .id("EC2-" + ec2Action + "-Target") .arn("arn:aws:ec2:" + region + ":*:" + ec2Action.toLowerCase()) .roleArn(roleArn) .input("{\"InstanceIds\": [\"" + instanceId + "\"]}") .build(); PutTargetsRequest targetsRequest = PutTargetsRequest.builder() .rule(ruleName) .targets(List.of(ec2Target)) .build(); eventBridge.putTargets(targetsRequest); System.out.println("Added target to rule " + ruleName); } }
Key Notes
- Timezone Handling: In the example above, we use
timeZone("Asia/Shanghai")so we can directly use Beijing time in the cron expression. If you omit this, remember to convert your local time to UTC. - Permissions: Adjust the IAM policy's resource field if you need to apply the schedule to multiple instances (use
*for all instances, or list multiple instance IDs). - Testing: Manually trigger EventBridge rules via the AWS Console or API to verify they work, and check CloudWatch Logs for any errors.
内容的提问来源于stack exchange,提问作者Leo

