terraform копировать / загружать файлы в aws экземпляр ec2 - PullRequest
0 голосов
/ 30 мая 2020

У нас есть cronjob и сценарий оболочки, который мы хотим скопировать или загрузить в экземпляр aws ec2 при создании экземпляра с использованием terraform.

мы пробовали

  1. инициализатор файлов: но он не работает, и эта опция чтения не работает со всеми версиями terraform
      provisioner "file" {
        source      = "abc.sh"
        destination = "/home/ec2-user/basic2.sh"
      }
попробовал вариант файла шаблона данных
    data "template_file" "userdata_line" {
      template = <<EOF
    #!/bin/bash
    mkdir /home/ec2-user/files2
    cd /home/ec2-user/files2
    sudo touch basic2.sh
    sudo chmod 777 basic2.sh
    base64 basic.sh |base64 -d >basic2.sh
    EOF
    }

попробовал все варианты, но ни один из них не работал.
не могли бы вы помочь или посоветовать.
Я новичок в terraform, так что борюсь это с давних времен.

Ответы [ 4 ]

3 голосов
/ 30 мая 2020

При запуске из AMI, в котором установлен cloud-init (что часто встречается во многих официальных Linux дистрибутивах), мы можем использовать модуль write_files cloud-init * для помещать в файловую систему произвольные файлы, если они достаточно малы, чтобы соответствовать ограничениям аргумента user_data вместе со всеми другими cloud-init данными.

Как и все модули cloud-init, мы настраиваем write_files с использованием формата конфигурации cloud-init на основе YAML , который начинается со специальной строки маркера #cloud-config в отдельной строке, за которой следует структура данных YAML. Поскольку JSON является подмножеством YAML, мы можем использовать Terraform jsonencode для получения допустимого значения [1] .

locals {
  cloud_config_config = <<-END
    #cloud-config
    ${jsonencode({
      write_files = [
        {
          path        = "/etc/example.txt"
          permissions = "0644"
          owner       = "root:root"
          encoding    = "b64"
          content     = filebase64("${path.module}/example.txt")
        },
      ]
    })}
  END
}

write_files модуль может принимать данные в формате base64, когда мы устанавливаем encoding = "b64", поэтому мы используем это вместе с функцией Terraform filebase64 для включения содержимого внешнего файла. Здесь возможны другие подходы, такие как динамическое создание строки с использованием шаблонов Terraform и использование base64encode для ее кодирования в качестве содержимого файла.

Если вы можете express все, что хотите, облако -init для выполнения в одном файле конфигурации, как указано выше, тогда вы можете назначить local.cloud_config_config непосредственно как свой экземпляр user_data, и облачная конфигурация должна распознать и обработать его при загрузке системы:

  user_data = local.cloud_config_config

Если вместо этого вам нужно совместить создание файла с некоторыми другими действиями, такими как запуск сценария оболочки, вы можете использовать формат multipart archive cloud-init для кодирования нескольких «файлов» для обработки cloud-init. Terraform имеет поставщика cloudinit, который содержит источник данных для простого создания многостраничного архива для cloud-init:

data "cloudinit_config" "example" {
  gzip          = false
  base64_encode = false

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

  part {
    content_type = "text/x-shellscript"
    filename     = "example.sh"
    content  = <<-EOF
      #!/bin/bash
      echo "Hello World"
    EOT
  }
}

Этот источник данных будет генерировать единственную строку в cloudinit_config.example.rendered, которая является подходящим составным архивом. для использования в качестве user_data для cloud-init:

  user_data = cloudinit_config.example.rendered

EC2 устанавливает максимальный размер пользовательских данных 64 килобайт, поэтому все закодированные данные вместе должны соответствовать этому пределу . Если вам нужно разместить большой файл, который приближается к этому пределу или превышает его, вероятно, было бы лучше использовать другую промежуточную систему для передачи этого файла, например, чтобы Terraform записал файл в корзину Amazon S3 и поместил программное обеспечение в ваш экземпляр получает эти данные, используя профиль экземпляра учетные данные. Однако в этом не должно быть необходимости для небольших файлов данных, используемых для конфигурации системы.

Важно отметить, что с точки зрения Terraform и EC2 содержимое user_data - это просто произвольная строка. Любые проблемы при обработке строки должны быть отлажены в самой целевой операционной системе путем чтения журналов cloud-init, чтобы увидеть, как она интерпретировала конфигурацию и что произошло, когда она попыталась предпринять эти действия.


[1] : Мы также потенциально могли бы использовать yamlencode, но в то время, когда я пишу это, эта функция имеет предупреждение о том, что ее точное форматирование может измениться в будущих версиях Terraform, и это нежелательно для user_data, потому что это приведет к замене экземпляра. Если вы читаете это в будущем и этого предупреждения больше нет в документах yamldecode, рассмотрите возможность использования вместо него yamlencode.

3 голосов
/ 30 мая 2020

Я использовал provisioner "file" только для этого, без проблем ... но вам необходимо предоставить соединение:

resource "aws_instance" "foo" {
...
  provisioner "file" {
    source      = "~/foobar"
    destination = "~/foobar"

    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key = "${file("~/Downloads/AWS_keys/test.pem")}"
      host        = "${self.public_dns}"
    }
  }
...
}

вот несколько примеров кода: https://github.com/heldersepu/hs-scripts/blob/master/TerraForm/ec2_ubuntu.tf#L21

0 голосов
/ 26 июня 2020

как-то в корпоративном домене ни один из вариантов не работал. но, наконец, мы смогли скопировать / загрузить файлы с помощью ведра s3.

создать s3.tf для загрузки этих файлов basic2. sh

resource "aws_s3_bucket" "demo-s3" {

  bucket = "acom-demo-s3i-<bucketID>-us-east-1"
  acl    = "private"


  tags {
    Name = "acom-demo-s3i-<bucketID>-us-east-1"
    StackId = "demo-s3"
  }
}

resource "aws_s3_bucket_policy" "s3_policy" {

  bucket = "${aws_s3_bucket.demo-s3.id}"

  policy = <<EOF
{
    "Version": "2009-10-17",
    "Statement": [
            {
            "Sid": "Only allow specific role",
            "Effect": "allow",
            "Principal":{ "AWS": ["arn:aws:iam::<bucketID>:role/demo-s3i"]},
            "Action":  "s3:*",
            "Resource": [
          "arn:aws:s3:::acom-demo-s3i-<bucketID>-us-east-1",
          "arn:aws:s3:::acom-demo-s3i-<bucketID>-us-east-1/*"
            ]

        }
    ]
}
EOF
}


resource "aws_s3_bucket_object" "object" {
  bucket = "acom-demo-s3i-<bucketID>-us-east-1"
  key    = "scripts/basic2.sh"
  source = "scripts/basic2.sh"
  etag = "${filemd5("scripts/basic2.sh")}"
}

, а затем объявить часть загрузки файла в другом tpl файл.

 aws s3 cp s3://acom-demo-s3i-<bucketID>-us-east-1/scripts/basic2.sh /home/ec2-user/basic2.sh
0 голосов
/ 30 мая 2020

Вы должны использовать средство подготовки файлов с данными подключения к экземпляру ec2. Пример конфигурации будет выглядеть так:

provisioner "file" {
  source      = "${path.module}/files/script.sh"
  destination = "/tmp/script.sh"

  connection {
    type     = "ssh"
    user     = "root"
    password = "${var.root_password}"
    host     = "${var.host}"
  }
}

Вы можете использовать имя пользователя / пароль, закрытый ключ или даже хост-бастион для подключения. Подробнее https://www.terraform.io/docs/provisioners/connection.html

...