Terraform 无法使用 Amazon EC2 导入密钥对

Terraform fails to import key pair with Amazon EC2

使用 Terraform 0.7.7.

我有一个简单的 Terraform 文件,其中包含以下内容:

provider "aws" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

resource "aws_instance" "personal" {
  ami           = "${lookup(var.amis, var.region)}"
  instance_type = "t2.micro"
}

resource "aws_eip" "ip" {
  instance = "${aws_instance.personal.id}"
}

resource "aws_key_pair" "personal" {
  key_name = "mschuchard-us-east"
  public_key = "${var.public_key}"
}

Terraform apply 产生以下错误:

aws_key_pair.personal: Creating...
  fingerprint: "" => "<computed>"
  key_name:    "" => "mschuchard-us-east"
  public_key:  "" => "ssh-rsa pubkey hash mschuchard-us-east"
aws_instance.personal: Creating...
  ami:                      "" => "ami-c481fad3"
  availability_zone:        "" => "<computed>"
  ebs_block_device.#:       "" => "<computed>"
  ephemeral_block_device.#: "" => "<computed>"
  instance_state:           "" => "<computed>"
  instance_type:            "" => "t2.micro"
  key_name:                 "" => "<computed>"
  network_interface_id:     "" => "<computed>"
  placement_group:          "" => "<computed>"
  private_dns:              "" => "<computed>"
  private_ip:               "" => "<computed>"
  public_dns:               "" => "<computed>"
  public_ip:                "" => "<computed>"
  root_block_device.#:      "" => "<computed>"
  security_groups.#:        "" => "<computed>"
  source_dest_check:        "" => "true"
  subnet_id:                "" => "<computed>"
  tenancy:                  "" => "<computed>"
  vpc_security_group_ids.#: "" => "<computed>"
aws_instance.personal: Creation complete
aws_eip.ip: Creating...
  allocation_id:     "" => "<computed>"
  association_id:    "" => "<computed>"
  domain:            "" => "<computed>"
  instance:          "" => "i-0ab94b58b0089697d"
  network_interface: "" => "<computed>"
  private_ip:        "" => "<computed>"
  public_ip:         "" => "<computed>"
  vpc:               "" => "<computed>"
aws_eip.ip: Creation complete
Error applying plan:

1 error(s) occurred:

* aws_key_pair.personal: Error import KeyPair: InvalidKeyPair.Duplicate: The keypair 'mschuchard-us-east' already exists.
status code: 400, request id: 51950b9a-55e8-4901-bf35-4d2be234abbf

我通过谷歌搜索找到的唯一帮助是删除了 *.tfstate 文件,我试过了但没有用。我可以使用带有此密钥对的 gui 启动 EC2 实例,并轻松地通过 ssh 进入它,但是当尝试使用相同的全功能密钥对时,Terraform 出错。

错误说密钥对已经存在于 AWS 中,但没有说明它是使用 Terraform 还是使用控制台创建的。

您应该在正确区域的 AWS 控制台 EC2 -> Key Pairs 中看到它。您应该先使用控制台删除它,然后再尝试使用 Terraform 导入它。

该错误告诉您该密钥对已存在于您的 AWS 帐户中,但 Terraform 在其状态文件中不知道它,因此每次都尝试创建它。

这里有两种选择。首先,您可以简单地将它从 AWS 帐户中删除并允许 Terraform 上传它,从而允许它由 Terraform 管理并保存在其状态文件中。

或者,您可以使用 Terraform import 命令将预先存在的资源导入您的状态文件:

terraform import aws_key_pair.personal mschuchard-us-east

使用 ${uuid()} 函数在生成时始终为密钥对获取随机 ID,selected/generated UUID 将其写入状态文件,因此您仍然可以删除,但是将无法更新。每次应用 terraform 文件时,都会生成一个新的密钥对...

虽然您确实无法使用 AWS 提供商从头开始生成密钥对,但您可以使用 TLS 提供商生成的 RSA 私钥在 AWS 中生成新的密钥对对象。

resource "aws_key_pair" "test" {
    key_name   = "${uuid()}"
    public_key = "${tls_private_key.t.public_key_openssh}"
}
provider "tls" {}
resource "tls_private_key" "t" {
    algorithm = "RSA"
}
provider "local" {}
resource "local_file" "key" {
    content  = "${tls_private_key.t.private_key_pem}"
    filename = "id_rsa"
    provisioner "local-exec" {
        command = "chmod 600 id_rsa"
    }
}

使用tls provider生成一个key,每次导入一个新对象。 然后导出私钥,以便稍后访问服务器。

值得注意的是,这打破了 Terraform 尝试使用的范例之一(基础架构即代码),但从实际开发的角度来看,这可能有点过于理想化了……Terraform 构建中途失败并且状态无效。更好的解决方案可能是,如果 AWS 插件收到它自动导入的 "already exists" 错误,或者如果这是可以设置的可选行为。