简体   繁体   English

Terraform 等到执行 user_data 然后制作图像以自动缩放?

[英]Terraform wait until execution of user_data then make an image to autoscale?

I am making a scalable service using AWS EC2, AutoScale Groups, SQS and CloudWatch Alarm using Terraform with user_data to set things up.我正在使用 AWS EC2、AutoScale Groups、SQS 和 CloudWatch Alarm 使用 Terraform 和user_data进行设置,从而提供 可扩展的服务 I am using a aws_launch_template and scaling using autoscale.我正在使用aws_launch_template并使用自动缩放进行缩放。

It works, but for every new instances it runs user_data again and that takes a lot of time.它可以工作,但是对于每个新实例,它都会再次运行 user_data 并且这会花费很多时间。 The only workaround to this is making machine image from my instance.唯一的解决方法是从我的实例制作machine image But terraform does not know if the user_data has executed or not.但是terraform不知道user_data有没有执行。

I am thinking of creating an instance, then making an image from it using terraform then use that as template to autoscale.我正在考虑创建一个实例,然后使用 terraform 从中制作图像,然后将其用作自动缩放的模板。 Found this post but not so clear.找到这篇文章但不太清楚。

I am trying this code -我正在尝试这段代码 -

resource "aws_ssm_document" "cloud_init_wait" {
  name = "cloud-init-wait"
  document_type = "Command"
  document_format = "YAML"
  content = <<-DOC
    schemaVersion: '2.2'
    description: Wait for cloud init to finish
    mainSteps:
    - action: aws:runShellScript
      name: StopOnLinux
      precondition:
        StringEquals:
        - platformType
        - Linux
      inputs:
        runCommand:
        - cloud-init status --wait
    DOC
}


resource "aws_instance" "example" {
  ami           = var.instance_ami
  instance_type = "t2.micro"
  key_name              = "${var.ssh_key}"

  provisioner "local-exec" {
    interpreter = ["/bin/bash", "-c"]

    command = <<-EOF
    set -Ee -o pipefail
    export AWS_DEFAULT_REGION=${var.aws_region}

    command_id=$(aws ssm send-command --document-name ${aws_ssm_document.cloud_init_wait.arn} --instance-ids ${self.id} --output text --query "Command.CommandId")
    if ! aws ssm wait command-executed --command-id $command_id --instance-id ${self.id}; then
      echo "Failed to start services on instance ${self.id}!";
      echo "stdout:";
      aws ssm get-command-invocation --command-id $command_id --instance-id ${self.id} --query StandardOutputContent;
      echo "stderr:";
      aws ssm get-command-invocation --command-id $command_id --instance-id ${self.id} --query StandardErrorContent;
      exit 1;
    fi;
    echo "Services started successfully on the new instance with id ${self.id}!"

    EOF
  }
}

I am having this error:我有这个错误:

 exit status 254. Output: 
│ An error occurred (InvalidInstanceId) when calling the SendCommand operation: Instances [[i-05b9f087e8d7dd7xx]] not in a
│ valid state for account 669201380121

Any idea on how we can make terraform wait until user data ran then make an image to autoscale?关于我们如何让 terraform 等到用户数据运行然后使图像自动缩放的任何想法?

Manual Image Creation (Old answer)手动创建图像(旧答案)

scroll down for automated solution with Packer使用 Packer 向下滚动以获取自动化解决方案

It might be possible but it seemed harder.这可能是可能的,但似乎更难。 So I first所以我先

  1. made an instance from the console从控制台创建一个实例
  2. then installed some dependencies然后安装一些依赖
  3. After that made an image之后做了一个图像
  4. used the image id to create an ec2 instance launch_template使用图像 ID 创建一个 ec2 实例 launch_template
  5. use user_data to provision source code to process (depending on your need).使用 user_data 提供要处理的源代码(取决于您的需要)。

Now whenever my autoscale group creates instances I have my dependencies installed.现在,每当我的自动缩放组创建实例时,我都会安装依赖项。 It's much faster now.现在快多了。

locals {
  provision_config= <<-END
    #cloud-config
    ${jsonencode({
      write_files = [
        {
          path        = "/root/src/main.py"
          permissions = "0644"
          encoding    = "b64"
          content     = filebase64("../src/main.py")
        },
      ]
    })}
  END
}

data "cloudinit_config" "config" {
  gzip                = false
  base64_encode       = true

  part {
    content_type      = "text/cloud-config"
    filename          = "cloud-config_provision.yaml"
    content           = local.provision_config
    }

  part {
    content_type      = "text/x-shellscript"
    filename          = "run_src.sh"
    content           = <<-EOF
      #!/bin/bash
      cd /root
      mkdir tmp
      mkdir tmp/origin
      mkdir tmp/converted
      mkdir tmp/packaged
      
      pip3 install boto3
      pip3 install ec2-metadata
      cd src

      python3 main.py

    EOF
  }
}

resource "aws_iam_instance_profile" "instance_profile" {
  name                  = "${local.resource_component}-profile"
  role                  = "${aws_iam_role.ec2_role.name}"
}

resource "aws_launch_template" "machine_template" {
  name                  = "${local.resource_component}-template" 
  image_id              = "${var.instance_ami}"
  instance_type         = "${var.instance_type}"
  key_name              = "${var.ssh_key}"
  user_data             = "${data.cloudinit_config.config.rendered}"

  iam_instance_profile {
    name                = "${aws_iam_instance_profile.instance_profile.name}"
  }

  tag_specifications {
    resource_type       = "instance"
    tags = {
      Name              = "${local.resource_component}-child"
      Source            = "Autoscaling"
    } 
  }

  monitoring {
    enabled             = true
  }

  instance_initiated_shutdown_behavior = "terminate"
}

Automated Image Creation with Packer by HCL (Edited Answer) HCL 使用 Packer自动创建图像(已编辑答案)

I am making AMI before terraform plan , and automated the system using a shell script, you can find my solution here .我在terraform plan之前制作 AMI,并使用 shell 脚本自动化系统,您可以在此处找到我的解决方案
I found this as the best of all the ways, with autoscale it's even faster since I don't have to provision things again and again.我发现这是所有方法中最好的,使用自动缩放它甚至更快,因为我不必一次又一次地提供东西。 There's also limitation for user_data which this solution solves easily.此解决方案很容易解决user_data的局限性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 terraform 中的 User_data 无法接收 pem 密钥的变量 - User_data in terraform unable to receive variable of pem key 我可以将变量传递给使用 terraform 和 user_data 创建的 AWS EC2 实例吗? 或者更新一个已经创建的资源 - Can i pass variables to AWS EC2 instances created with terraform and user_data? Or update an already created resource 让 CloudFormation 等待用户数据 - Having CloudFormation wait for the user data 如何使 spring controller json 响应等到 firebase 查询结束? - How to make spring controller json response wait until firebase query ends? 如何等到所有 Promise 都完成? - How to wait until all of Promise are fulfilled? 如何使用户数据对 firebabse 上的开发人员不可见 - How to make user data not visible for developer on firebabse Airflow `BeamRunPythonPipelineOperator` 确实尊重 `wait_until_finished = False` - Airflow `BeamRunPythonPipelineOperator` does respect `wait_until_finished = False` 我如何才能等到所有 FCM 订阅完成 - How can I wait until all FCM subscriptions are done 是否可以使用 terraform 创建 SSO 用户 - AWS - Is it possible to create an SSO user using terraform - AWS 使用 Terraform 为 AWS Cognito 用户池设置账户恢复首选项 - Set account recovery preference for AWS Cognito User Pool with Terraform
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM