Skip to content

fix: pass KeyPairName in RunInstances to enable cloud-init SSH key injection - #163

Open
codeloversa wants to merge 1 commit into
hashicorp:mainfrom
codeloversa:fix/ssh-keypair-cloud-init
Open

fix: pass KeyPairName in RunInstances to enable cloud-init SSH key injection#163
codeloversa wants to merge 1 commit into
hashicorp:mainfrom
codeloversa:fix/ssh-keypair-cloud-init

Conversation

@codeloversa

Copy link
Copy Markdown
Contributor

Problem

SSH connections to newly created ECS instances fail with timeout errors. The root cause is that the SSH keypair is not available in the instance's metadata service when cloud-init runs on first boot.

Previous Flow (Broken)

  1. stepConfigAlicloudKeyPair - creates keypair packer_xxx
  2. stepCreateAlicloudInstance - calls RunInstances API (instance starts immediately)
  3. Instance boots → cloud-init reads metadata → NO keypair available
  4. stepAttachKeyPair - attaches keypair via API (too late, cloud-init already finished)
  5. SSH fails because the key was never installed by cloud-init

Solution

Pass the KeyPairName parameter directly in the RunInstances API request. This ensures the SSH public key is available in the metadata service (http://100.100.100.200/latest/meta-data/public-keys/) before the instance boots, allowing cloud-init to install the SSH key on first boot.

Fixed Flow

  1. stepConfigAlicloudKeyPair - creates keypair packer_xxx
  2. stepCreateAlicloudInstance - calls RunInstances with KeyPairName
  3. Instance boots → cloud-init reads metadata → keypair IS available
  4. stepAttachKeyPair - skips (keypair already attached)
  5. SSH succeeds ✓

Changes

  • step_create_instance.go: Add KeyPairName to RunInstances request
  • step_attach_keypair.go: Skip AttachKeyPair if keypair is already attached (avoids redundant API calls)

Testing

Tested with Alibaba Cloud Linux 3 image. Build output shows:
`dchujun@MR6GY10QKW packer-plugin-alicloud % packer build ./packer-test/build.pkr.hcl
alicloud-ecs.test: output will be in this color.

==> alicloud-ecs.test: Prevalidating source region and copied regions...
==> alicloud-ecs.test: Prevalidating image name...
alicloud-ecs.test: Found image ID: m-j6c9minybp3mhnjqi9hi
==> alicloud-ecs.test: Creating temporary keypair: packer_699c7764-486a-f462-201e-20d8d8594401
==> alicloud-ecs.test: Creating instance...
==> alicloud-ecs.test: Stoping instance: i-j6cdmduz9l8rm02zr5tt
alicloud-ecs.test: Created instance: i-j6cdmduz9l8rm02zr5tt
==> alicloud-ecs.test: Allocating EIP...
alicloud-ecs.test: Allocated EIP: 47.86.84.150
alicloud-ecs.test: KeyPair packer_699c7764-486a-f462-201e-20d8d8594401 already attached to instance: i-j6cdmduz9l8rm02zr5tt
==> alicloud-ecs.test: Starting instance: i-j6cdmduz9l8rm02zr5tt
==> alicloud-ecs.test: Using SSH communicator to connect: 47.86.84.150
==> alicloud-ecs.test: Waiting for SSH to become available...
==> alicloud-ecs.test: Connected to SSH!
==> alicloud-ecs.test: Provisioning with shell script: /var/folders/t7/9kkt1b856l16r4274c32kg880000gn/T/packer-shell3665135465
==> alicloud-ecs.test: Error: This command has to be run with superuser privileges (under the root user on most systems).
==> alicloud-ecs.test: Provisioning step had errors: Running the cleanup provisioner, if present...
alicloud-ecs.test: Detach keypair packer_699c7764-486a-f462-201e-20d8d8594401 from instance: i-j6cdmduz9l8rm02zr5tt
==> alicloud-ecs.test: Deleting EIP association because of cancellation or error...
==> alicloud-ecs.test: Deleting EIP because of cancellation or error...
==> alicloud-ecs.test: Deleting instance because of cancellation or error...
==> alicloud-ecs.test: Deleting temporary keypair...
Build 'alicloud-ecs.test' errored after 1 minute 48 seconds: Script exited with non-zero exit status: 1. Allowed exit codes are: [0]

==> Wait completed after 1 minute 48 seconds

==> Some builds didn't complete successfully and had errors:
--> alicloud-ecs.test: Script exited with non-zero exit status: 1. Allowed exit codes are: [0]

==> Builds finished but no artifacts were created.`

Related

This is an alternative fix to PR #162. Compared to that PR:

  • Minimal change - only adds one parameter to existing API call
  • Preserves KMS support - keeps RunInstances which supports kms_key_id
  • Fewer API calls - no separate AttachKeyPair call needed
  • Root cause fix - addresses the actual missing parameter rather than switching APIs

…jection

Problem:
SSH connections to newly created instances were failing with timeout errors.
The root cause was that the SSH keypair was not available in the instance's
metadata service when cloud-init ran on first boot.

The previous flow was:
1. stepConfigAlicloudKeyPair - creates keypair
2. stepCreateAlicloudInstance - calls RunInstances (instance starts immediately)
3. Instance boots → cloud-init reads metadata → NO keypair available
4. stepAttachKeyPair - attaches keypair via API (too late, cloud-init already finished)
5. SSH fails because the key was never installed by cloud-init

Solution:
Pass the KeyPairName parameter directly in the RunInstances API request.
This ensures the SSH public key is available in the metadata service
(http://100.100.100.200/latest/meta-data/public-keys/) before the instance
boots, allowing cloud-init to install the SSH key on first boot.

Changes:
- step_create_instance.go: Add KeyPairName to RunInstances request
- step_attach_keypair.go: Skip AttachKeyPair if keypair is already attached
  (avoids redundant API calls and potential errors)

The fixed flow:
1. stepConfigAlicloudKeyPair - creates keypair
2. stepCreateAlicloudInstance - calls RunInstances WITH KeyPairName
3. Instance boots → cloud-init reads metadata → keypair IS available ✓
4. stepAttachKeyPair - skips (keypair already attached)
5. SSH succeeds ✓
@codeloversa
codeloversa requested a review from a team as a code owner February 24, 2026 03:01
@hashicorp-cla-app

Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes


chujun dong seems not to be a GitHub user.
You need a GitHub account to be able to sign the CLA.
If you have already a GitHub account, please add the email address used for this commit to your account.

Have you signed the CLA already but the status is still pending? Recheck it.

1 similar comment
@hashicorp-cla-app

Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes


chujun dong seems not to be a GitHub user.
You need a GitHub account to be able to sign the CLA.
If you have already a GitHub account, please add the email address used for this commit to your account.

Have you signed the CLA already but the status is still pending? Recheck it.

@hwhuangzsly

Copy link
Copy Markdown

Thanks for the detailed investigation. This appears to have been a valid fix for the RunInstances-based flow that existed when this PR was opened.
However, #162 has since changed the lifecycle on main to:

  1. CreateInstance and wait for Stopped
  2. AttachKeyPair
  3. StartInstance
  4. Establish the SSH connection
    The instance now receives its key pair before the first boot, so the cloud-init race addressed here should no longer exist. This patch also modifies RunInstancesRequest, which is no longer used on main.
    Maintainers may therefore want to close this PR as superseded by refactor: replace RunInstances API with CreateInstance API for ECS #162, rather than invalid. The original investigation was valid; the underlying lifecycle has simply changed.
    If the SSH timeout is still reproducible on the latest main, it would be helpful to capture the region, source image, cloud-init version, sanitized Packer logs, and whether a user-provided or temporary key pair
    was used. That could justify a new issue and a CreateInstance-specific fix. Passing KeyPairName during creation also remains an option if attach-before-start proves insufficient.
    The KMS compatibility concern should be tracked separately, as this patch does not implement KMS support and that issue relates to the API change introduced by refactor: replace RunInstances API with CreateInstance API for ECS #162.
    Flagging this for a maintainer with permission to review and close as appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants