2016-08-21 15 views
5

tôi đã nhận thấy terraform đó sẽ chỉ chạy "tập tin", "xa-exec" hoặc "địa phương-exec" trên nguồn lực một lần. Khi một tài nguyên được cung cấp nếu các lệnh trong một "remote-exec" được thay đổi hoặc một tập tin từ "file" cung cấp được thay đổi thì terraform sẽ không thực hiện bất kỳ thay đổi nào đối với cá thể đó. Vì vậy, làm thế nào để tôi có được terraform để chạy provisioner "tập tin", "từ xa-exec" hoặc "local-exec" mỗi khi tôi chạy một terraform áp dụng?Terraform: Làm thế nào để chạy từ xa-exec nhiều hơn một lần?

Để biết thêm chi tiết:

Thường thì tôi đã có một nguồn tài nguyên được cung cấp một phần do lỗi từ "xa-exec" gây terraform để stop (chủ yếu là do tôi nhập vào các lệnh sai trong khi tôi đang viết kịch bản của tôi). Chạy lại terraform sau khi điều này sẽ khiến tài nguyên được tạo trước đây bị hủy và buộc phải tạo một tài nguyên mới từ đầu. Đây cũng là cách duy nhất tôi có thể chạy "remote-exec" hai lần trên một tài nguyên ... bằng cách tạo nó từ đầu.

Đây thực sự là một nhược điểm để terraform như trái ngược với ansible, có thể thực hiện công việc chính xác giống như terraform ngoại trừ việc nó là hoàn toàn idempotent. Khi sử dụng Ansible với các tác vụ như "ec2", "shell" và "copy", tôi có thể thực hiện các tác vụ tương tự như terraform chỉ mỗi tác vụ đó sẽ là idempotent. Ansible sẽ tự động nhận ra khi nó không cần phải thực hiện thay đổi, nơi nó làm và vì điều này nó có thể nhận nơi một vở kịch không an toàn-play-off rời khỏi mà không phá hủy tất cả mọi thứ và bắt đầu từ đầu. Terraform thiếu tính năng này.

Để tham khảo ở đây là một khối tài nguyên terraform đơn giản cho một thể hiện EC2 sử dụng cả "xa-exec" và "tập tin" provisioners:

resource "aws_instance" "test" { 

count = ${var.amt} 
ami = "ami-2d39803a" 
instance_type = "t2.micro" 
key_name = "ansible_aws" 
tags { 
    name = "test${count.index}" 
} 

#creates ssh connection to consul servers 
connection { 
    user = "ubuntu" 
    private_key="${file("/home/ubuntu/.ssh/id_rsa")}" 
    agent = true 
    timeout = "3m" 
} 

provisioner "remote-exec" { 
    inline = [<<EOF 

    sudo apt-get update 
    sudo apt-get install curl unzip 
    echo hi 

    EOF 
    ] 
} 

#copying a file over 
provisioner "file" { 
    source = "scripts/test.txt" 
    destination = "/path/to/file/test.txt" 
} 

} 

Trả lời

5

Các Terraform docs on provisioning một cách rõ ràng rằng nó xem xét việc sử dụng các provisioners cho cơ bản bootstrapping như một công việc duy nhất một lần và nó không nên được sử dụng như là một thay thế cho một công cụ quản lý cấu hình thích hợp như Ansible:

Provisioners chỉ chạy khi một tài nguyên được tạo. Họ không phải là một sự thay thế cho quản lý cấu hình và thay đổi phần mềm của một máy chủ đã chạy, và thay vào đó chỉ có nghĩa như một cách để bootstrap một máy chủ. Để quản lý cấu hình, bạn nên sử dụng Cung cấp Terraform để gọi một giải pháp quản lý cấu hình thực sự .

Nếu một nguồn tài nguyên tạo thành công nhưng thất bại trong việc cung cấp, Terraform sẽ báo lỗi và đánh dấu các tài nguyên là "nhiễm độc". Một nguồn đó là nhiễm độc đã được thể chất tạo ra, nhưng không thể được coi an toàn để sử dụng kể từ khi trích lập dự phòng thất bại.

Khi bạn tạo kế hoạch thực hiện tiếp theo, Terraform sẽ xóa mọi tài nguyên bị nhiễm độc và tạo tài nguyên mới, cố gắng cung cấp lại . Nó không cố gắng khởi động lại cấp phép trên cùng một tài nguyên vì nó không được đảm bảo an toàn.

Terraform không tự động quay trở lại và phá hủy tài nguyên trong áp dụng khi sự thất bại xảy ra, bởi vì đó sẽ đi so với kế hoạch thực hiện: kế hoạch thực hiện sẽ đã cho biết một nguồn tài nguyên sẽ được tạo ra, nhưng không nói rằng nó sẽ bị xóa. Nhưng nếu bạn tạo một kế hoạch thực hiện với một nguồn tài nguyên bị nhiễm độc, kế hoạch sẽ nêu rõ rằng tài nguyên sẽ bị hủy vì đó là bị nhiễm độc.

Cấp phép rất quan trọng để có thể khởi động các bản sao. Với tư cách là một lời nhắc khác, đó không phải là sự thay thế cho cấu hình quản lý . Nó có nghĩa là chỉ đơn giản là bootstrap máy. Nếu bạn sử dụng quản lý cấu hình, bạn nên sử dụng cấp phép như một cách để khởi động tiện ích quản lý cấu hình.

Xem xét provisioners như giống như một kịch bản dữ liệu người dùng EC2 ở chỗ nó chỉ chạy một lần vào sáng tạo và nếu nó không thành công thì bạn cần phải tiêu diệt các ví dụ và thử lại.

Lợi ích của việc này là Terraform không cần biết bất kỳ kiến ​​thức nào về cách thay đổi idempotent trên hệ điều hành vì Terraform hoạt động ở mức cao hơn bản thân cá thể và nhiều hơn nữa.

Nếu bạn cần linh hoạt hơn, hãy xem xét sử dụng Terraform để gọi hệ thống quản lý cấu hình để cung cấp đúng trường hợp (và sau đó cho phép thử lại nếu nó thất bại, tách khỏi giai đoạn cung cấp Terraform) hoặc sử dụng dàn nhạc công cụ như Jenkins để bọc cả Terraform và một công cụ quản lý cấu hình thay thế như Ansible.

Một tùy chọn khác là đi dọc theo tuyến đường cơ sở hạ tầng không thay đổi và sử dụng Packer để tạo AMI bằng cách sử dụng Ansible hoặc một số công cụ khác và sau đó sử dụng Terraform để triển khai AMI như không cần.

1

Bạn có thể sử dụng lệnh taint để đánh dấu tài nguyên là bị nhiễm độc, buộc tài nguyên bị hủy và được tạo lại vào lần đăng ký tiếp theo.

12

Came qua thread này trong tìm kiếm của tôi và cuối cùng tìm ra giải pháp:

resource "null_resource" "ansible" { 

    triggers { 
    key = "${uuid()}" 
    } 

    provisioner "local-exec" { 
    command = "ansible-playbook -i /usr/local/bin/terraform-inventory -u ubuntu playbook.yml --private-key=/home/user/.ssh/aws_user.pem -u ubuntu" 
    } 
} 

Bạn có thể sử dụng uuid(), mà là duy nhất cho mỗi chạy terraform, để kích hoạt một tài nguyên vô giá trị hoặc Provisioner.

+0

ý tưởng thực sự tuyệt vời –

Các vấn đề liên quan