目前从terraform创建ansible库存的最佳方式

时间:2017-08-03 16:12:20

标签: ansible terraform

我有很长的机器列表,所有这些机器在系统中的功能都有所不同。我想组织这些机器并自动添加到主机库存文件,以便我可以运行ansible并管理库存。那里有好的解决方案吗?

我认为ansible主机应该看起来像......

[webservers]
someip
someip
[integration]
someip
someip

等。

在提出问题之后,我目前正在研究输出变量并使用它们从文件中渲染模板。

6 个答案:

答案 0 :(得分:16)

我明白了。

data "template_file" "dev_hosts" {
  template = "${file("${path.module}/templates/dev_hosts.cfg")}"
  depends_on = [
    "aws_instance.dev-api-gateway",
    "aws_instance.dev-api-gateway-internal",
    ....
  ]
  vars {
    api_public = "${aws_instance.dev-api-gateway.private_ip}"
    api_internal = "${aws_instance.dev-api-gateway-internal.private_ip}"
  }
}

resource "null_resource" "dev-hosts" {
  triggers {
    template_rendered = "${data.template_file.dev_hosts.rendered}"
  }
  provisioner "local-exec" {
    command = "echo '${data.template_file.dev_hosts.rendered}' > dev_hosts"
  }
}

然后在前面引用的文件中创建一个模板

示例dev_hosts.cfg的内容

[public]
${api_public}


[private]
${api_internal}

答案 1 :(得分:6)

我们的方法略有不同。我们定义了一个Terraform模块(terraform-null-ansible),它可以在我们想要使用动态库存在主机上运行剧本时调用ansible。

https://github.com/cloudposse/terraform-null-ansible

这是一种非常以terraform为中心的方法,但可以实现非常干净的集成。另外,通过计算剧本的校验和,我们只在剧本发生变化时才调用ansible供应商。

使用非常简单:

module "web_provisioner" {
   source    = "git::https://github.com/cloudposse/terraform-null-ansible.git?ref=tags/0.3.8"

   arguments = ["--user=ubuntu"]
   envs      = ["host=${aws_instance.web.public_ip}"]
   playbook  = "../ansible/playbooks/test.yml"
   dry_run   = false
}

GitHub README.md

上有更多文档

答案 2 :(得分:6)

自Terraform 0.12+起,templatefile函数非常方便,尤其是在需要填充主机组的情况下:

# generate inventory file for Ansible
resource "local_file" "hosts_cfg" {
  content = templatefile("${path.module}/templates/hosts.tpl",
    {
      kafka_processors = aws_instance.kafka_processor.*.public_ip
      test_clients = aws_instance.test_client.*.public_ip
    }
  )
  filename = "../ansible/inventory/hosts.cfg"
}

hosts.tpl模板文件(未来的Ansible库存)可能如下所示:

[kafka_broker_hosts]
%{ for ip in kafka_processors ~}
${ip}
%{ endfor ~}

[test_client_hosts]
%{ for ip in test_clients ~}
${ip}
%{ endfor ~}

最终结果:

[kafka_broker_hosts]
18.224.140.239
18.224.140.234

[test_client_hosts]
3.21.134.83

答案 3 :(得分:0)

对于多服务器:

文件清单.tf

data  "template_file" "k8s" {
    template = "${file("./templates/k8s.tpl")}"
    vars {
        k8s_master_name = "${join("\n", azurerm_virtual_machine.k8s-master.*.name)}"
    }
}

resource "local_file" "k8s_file" {
  content  = "${data.template_file.k8s.rendered}"
  filename = "./inventory/k8s-host"
}

文件k8s.tpl

[kube-master]
${k8s_master_name}

最终结果

[kube-master]
k8s-master-01
k8s-master-02
k8s-master-03

答案 4 :(得分:0)

这对我有用:

data "template_file" "ansible_inventory" {
  template = "${file("${path.module}/hosts.tmpl")}"

  vars = {
    public_ips = "${join("\n", aws_instance.public_instance.*.public_ip)}"
  }
}

resource "local_file" "hosts" {
  filename = "${path.module}/hosts"

  content = data.template_file.ansible_inventory.rendered
}

答案 5 :(得分:0)

这在 aws ec2 上对我有用:

main.tf:

resource "aws_instance" "instance" {
  for_each      = toset(["ingress-01", "node-01", "node-02", "master-01" ])
  ami           = "ami-0c239ecd40dcc174c"
  instance_type = "t2.micro"

  tags = {
    Name = "${each.key}"
  }
}

resource "local_file" "inventory" {
  content = templatefile("inventory.tmpl", { content = tomap({
    for instance in aws_instance.instance:
      instance.tags.Name => instance.public_dns
    })
  })
  filename = format("%s/%s", abspath(path.root), "inventory.yaml")
}

模板(inventory.tmpl):

all:
  children:
    ingress:
      hosts:
%{ for content_key, content_value in content }
%{~ if length(regexall("ingress", content_key)) > 0 ~}
        ${content_key}:
          ansible_host: ${content_value}
%{ endif ~}
%{~ endfor ~}
    master:
      hosts:
%{ for content_key, content_value in content }
%{~ if length(regexall("master", content_key)) > 0 ~}
        ${content_key}:
          ansible_host: ${content_value}
%{ endif ~}
%{~ endfor ~}
    nodes:
      hosts:
%{ for content_key, content_value in content }
%{~ if length(regexall("node", content_key)) > 0 ~}
        ${content_key}:
          ansible_host: ${content_value}
%{ endif ~}
%{~ endfor ~}

猫清单.yaml

all:
  children:
    ingress:
      hosts:
        ingress-01:
          ansible_host: ec2-xx-xx-xx-xx.eu-central-1.compute.amazonaws.com
    master:
      hosts:
        master-01:
          ansible_host: ec2-xx-xx-xx-xx.eu-central-1.compute.amazonaws.com
    nodes:
      hosts:
        node-01:
           ansible_host: ec2-xx-xx-xx-xx.eu-central-1.compute.amazonaws.com
        node-02:
           ansible_host: ec2-xx-xx-xx-xx.eu-central-1.compute.amazonaws.com