如何使用Terraform格式化和挂载临时磁盘?

7
我正在编写Packer和Terraform代码,在aws上创建一个不可变的基础架构。然而,安装ext4到磁盘并将其挂载起来似乎并不是很简单。
步骤看起来很简单:
- 使用Packer在t2.micro上创建包含所有软件的ami,首先在测试中使用,然后在生产中使用。 - 从此ami启动一个r3.4xlarge实例,该实例具有300GB的临时磁盘。将该磁盘格式化为ext4,挂载它并将/var/lib/docker重定向到新文件系统以提高性能。 - 完成其余应用程序的启动。
首先:
最佳实践是使用与要使用的实例类型相同的实例类型创建ami,还是拥有一个“通用”映像并从其中启动多个实例类型?哪种理念最好?
- packer(软件版本)-> terraform(实例+挂载磁盘)-> 部署? - packer(软件版本)-> packer(实例特定挂载)-> terraform(实例)-> 部署? - packer(软件版本,实例特定挂载)-> terraform -> 部署?
后者看起来越来越好,但需要一个每个实例类型的AMI。
我已经尝试过的内容:
根据此答案,最好使用user_data的方式工作,而不是provisioners的方式。所以我走了这条路。 这个答案看起来很有前途,但太旧了,不能用了。我可以更新它,但可能有一种不同、更好的方法。 这个答案也看起来很有前途,但抱怨${DEVICE}。我想知道那个变量从哪里来,因为在template_file中没有指定任何变量。如果我将自己的DEVICE变量设置为xvdb,那么它就会运行,但不会产生结果,因为xvdb在lsblk中可见,但在blkid中不可见。

这是我的代码。format_disks.sh文件与上面提到的那个相同。非常感谢任何帮助。

# Create a new instance of the latest Ubuntu 16.04 on an
# t2.micro node with an AWS Tag naming it "test1"
provider "aws" {
  region = "us-east-1"
}

data "template_file" "format-disks" {
  template = "${file("format_disk.sh")}"

  vars {
    DEVICE = "xvdb"
  }
}

resource "aws_instance" "test1" {
  ami           = "ami-98181234"
  instance_type = "r3.4xlarge"
  key_name = "keypair-1"               # This needs to be changed so multiple users can use this
  subnet_id = "subnet-a0aeb123"            # maps to the vpc for the us production
  associate_public_ip_address = "true"
  vpc_security_group_ids = ["sg-f3e91234"] #backendservers
  user_data = "${data.template_file.format-disks.rendered}"
  tags {
    Name = "test1"
  }
  ephemeral_block_device {
    device_name = "xvdb"
    virtual_name = "ephemeral0"
  }
}

在这种情况下,我会将 format_disk.sh 脚本与一些配置一起集成到您的 AMI 中,使其在启动时运行,并完全脱离 Terraform 的控制。Terraform 只需安排附加磁盘,AMI 中的软件将负责在启动时格式化它。这样,您还可以更轻松地协调任何其他应用程序启动任务,以确保例如需要文件系统的应用程序在文件系统格式化和挂载之后才启动。 - Martin Atkins
确实可以有所帮助,谢谢 @MartinAtkins。目前我正在使用一种解决方法,在启动实例时将所有内容都安装/配置好,然后运行两个ansible角色来格式化/映射并移动需要在本地磁盘上运行的应用程序。不幸的是,这意味着Terraform无法对所有实例进行滚动更新。我会尝试看看能否使用您的建议。 - Evert
@Evert,您能否在这里分享一下Ansible角色,以便我可以重复使用?我有类似的需求。 - Santosh Garole
您好,@SantoshGarole。非常抱歉告诉您我已经不在同一家公司工作,无法向您发送这些职位了。那些职位相当基础,我相信您能够在其他地方找到类似的示例。祝您好运。 - Evert
1个回答

2

让我谈谈我的想法。

我认为cloud-init是AWS的关键,因为它可以动态创建所需的机器。 首先,尝试更改一些全局脚本,这些脚本将在启动您的机器时使用。然后,您应该将该脚本作为用户数据添加。我建议您同时使用ec2自动缩放,这样,如果您更改了cloud-init脚本,您可以终止实例,另一个实例将自动创建。

我的目录结构。

.
|____main.tf
|____templates
| |____cloud-init.tpl

main.tf

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

data "template_file" "cloud_init" {
  template = file("${path.module}/templates/cloud-init.tpl")
}

data "aws_ami" "linux_ami" {
  most_recent = "true"
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-2.0.????????.?-x86_64-gp2"]
  }
}

resource "aws_instance" "test1" {
  ami                         = data.aws_ami.linux_ami.image_id
  instance_type               = "r3.4xlarge"
  key_name                    = "keypair-1"       
  subnet_id                   = "subnet-xxxxxx"
  associate_public_ip_address = true
  vpc_security_group_ids      = ["sg-xxxxxxx"] 
  user_data                   = data.template_file.cloud_init.rendered
  root_block_device {
      delete_on_termination = true
      encrypted             = true
      volume_size           = 10
      volume_type           = "gp2"
  }

  ebs_block_device {
      device_name = "ebs-block-device-name"
      delete_on_termination = true
      encrypted             = true
      volume_size           = 10
      volume_type           = "gp2"
  }

  network_interface {
      device_index          = 0
      network_interface_id  = var.network_interface_id
      delete_on_termination = true
  }

  tags = {
    Name = "test1"
    costCenter = "xxxxx"
    owner = "xxxxx"
  }
}

templates/cloud-init.tpl

#!/bin/bash -x 

yum update -y
yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
systemctl enable amazon-ssm-agent
systemctl start amazon-ssm-agent

pip install aws-ssm-tunnel-agent

echo "[INFO] SSM agent has been installed!"
# More scripts here.

您想要挂载一个暂时的磁盘吗?您是否尝试添加一个root_block_device,并将delete_on_termination 设置为true?这样,在销毁 AWS EC2 实例资源后,该磁盘将被删除。这是在 AWS 上节省成本的好方法,但请注意,只有在存储在其中的数据不重要或已备份时才使用它。
如果需要在此实例上挂载外部 EBS 磁盘,可以使用 AWS API,请确保机器与可用区相同。
如果需要一些 Bash 脚本,请告诉我,这很容易做到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接