【问题标题】:remote-exec provisioner in terraform gives timeoutterraform 中的 remote-exec 供应商给出超时
【发布时间】:2022-02-10 01:03:36
【问题描述】:

我正在尝试使用 ubuntu 映像启动 EC2 实例。我想通过 terraform 提供对实例的 ssh 访问,安装和运行 apache 服务器,并打开端口 80。

我的 EC2 有以下 remote-exec 代码

provisioner "remote-exec" {
  inline = [
    "sudo apt update -y",
    "sudo apt upgrade -y",
    "sudo apt install apache2 -y",
    "sudo systemctl status apache2"
  ]
}

但是,在所有命令都成功执行后,即 systemctl 显示正确的响应,我的提示挂在 aws_instance.web_server_instance: Still creating...

我的完整代码

terraform {
  required_version = "~> 1.1.5"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "3.74.1"
    }

    local = {
      source  = "hashicorp/local"
      version = "2.1.0"
    }

    tls = {
      source  = "hashicorp/tls"
      version = "3.1.0"
    }
  }
}

provider "aws" {
  profile = "terraform"
  region  = "us-east-1"
}

locals {
  application_name = "web_server"
}



# ssh key

resource "tls_private_key" "web_server_key_pair_gen" {
  algorithm = "RSA"
}

resource "local_file" "web_server_private_key" {
  content  = tls_private_key.web_server_key_pair_gen.private_key_pem
  filename = "${local.application_name}_private_key.pem"
}

resource "aws_key_pair" "web_server_public_key" {
  key_name   = "${local.application_name}_public_key"
  public_key = tls_private_key.web_server_key_pair_gen.public_key_openssh
}



# security group

resource "aws_security_group" "web_server_security_group" {
  name = "${local.application_name}_security_group"

  dynamic "ingress" {
    for_each = [
      { port = 22, description = "ssh" },
      { port = 80, description = "http" },
    ]
    content {
      description      = ingress.value.description
      from_port        = ingress.value.port
      to_port          = ingress.value.port
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]
      ipv6_cidr_blocks = []
      prefix_list_ids  = []
      security_groups  = []
      self             = false
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "${local.application_name}_security_group"
  }
}



# ami lookup

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"]
}



# ec2 instance

resource "aws_instance" "web_server_instance" {
  ami                         = data.aws_ami.ubuntu.id
  instance_type               = "t2.micro"
  vpc_security_group_ids      = [aws_security_group.web_server_security_group.id]
  key_name                    = aws_key_pair.web_server_public_key.key_name
  associate_public_ip_address = true

  connection {
    user        = "ubuntu"
    private_key = tls_private_key.web_server_key_pair_gen.private_key_pem
    host        = self.public_ip
  }

  provisioner "local-exec" {
    command = "chmod 600 ${local_file.web_server_private_key.filename}"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt update -y",
      "sudo apt upgrade -y",
      "sudo apt install apache2 -y",
      "sudo systemctl status apache2"
    ]
  }

  tags = {
    Name = "${local.application_name}_instance"
  }
}

output "server_public_ip" {
  value = aws_instance.web_server_instance.public_ip
}

【问题讨论】:

  • 你为什么使用 remote-exec 而不是用户数据 cloud-init 脚本?
  • 嘿@MarkB,感谢您的回复。我今天早上开始学习 terraform,只是出于教育目的进行尝试。
  • 远程供应商通常被认为是 Terraform 中的“最后手段”。 AWS EC2 提供了一种通过用户数据脚本初始化服务器的方法,这将更加可靠。
  • 官方文档部分Provisioners are a Last Resort 中提供了有关供应商使用权衡的更多信息以及其他一些需要考虑的选项。具体而言,请参阅将数据传递到虚拟机和其他计算资源以了解此用例。

标签: amazon-web-services terraform terraform-provider-aws


【解决方案1】:

虽然您可能应该遵循 cmets 中给出的建议,但您的具体情况可能是由于 systemctl 输出通过寻呼机(更少)进行管道传输,因此它等待接收 q 退出。

https://man7.org/linux/man-pages/man1/systemctl.1.html:

   $SYSTEMD_PAGER
       Pager to use when --no-pager is not given; overrides $PAGER.
       If neither $SYSTEMD_PAGER nor $PAGER are set, a set of
       well-known pager implementations are tried in turn, including
       less(1) and more(1), until one is found. If no pager
       implementation is discovered no pager is invoked. Setting
       this environment variable to an empty string or the value
       "cat" is equivalent to passing --no-pager.

在这里使用--no-pager 选项应该会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-25
    • 2020-07-01
    • 2017-11-14
    • 2019-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多