2017-06-12 70 views
0

使用案例捕獲Terraform配置器輸出?

試圖提供一種(泊塢羣或領事)羣集,其中第一初始化羣集發生一個節點上,其產生一些令牌,然後需要通過加入集羣的其他節點可以使用上。關鍵的是節點1和節點2不應嘗試加入羣集,直到節點0生成連接密鑰。

例如,在節點0上,運行docker swarm init ...將返回一個加入令牌。然後在節點1和2上,您需要將該令牌傳遞給相同的命令,如docker swarm init ${JOIN_TOKEN} ${NODE_0_IP_ADDRESS}:{SOME_PORT}。和魔法,你已經有了一個整潔的小集羣...

嘗試到目前爲止

  • 嘗試初始化安裝了AWS SDK的所有節點和存儲節點從0 S3的連接鍵,然後在其他節點上獲取該連接密鑰。這是通過一個帶有'remote-exec'提供程序的null_resource完成的。由於Terraform並行執行事情的方式,存在活躍的類型條件,並且可預測的節點1和2經常試圖從S3中獲取尚未存在的密鑰(例如,節點0尚未完成其任務)。

  • 嘗試使用'local-exec'預置程序將SSH連接到節點0並捕獲其連接鍵輸出。這樣做效果不好,或者我喜歡這樣做。


我讀過的文檔。並且堆棧溢出。和Github的問題,如this really long outstanding one。徹底。如果這已在其他地方解決,鏈接表示讚賞!


PS - 這直接關係到,是this question一個較小的子集,但希望重新要求它以重點問題的範圍。

回答

1

當我問自己同樣的問題「我可以使用自動配置器的輸出來輸入另一個資源的變量嗎?」時,我找到了答案。

在這個時候,提供者的結果只是簡單地傳輸到terraform的標準輸出中,並且永遠不會被捕獲。

鑑於您正在兩個節點上運行遠程設置程序,並且您試圖訪問S3的值 - 我同意這種方法,我也會這樣做 - 您可能需要做的是處理比賽通過sleep命令或通過安排腳本稍後與atcron或類似的調度系統一起運行。

一般來說,Terraform想要預先訪問所有變量,或者作爲提供者的結果。提供者不一定被視爲Terraform中的頭等艙。我不在覈心團隊,所以我不能說爲什麼,但我的推測是,它會降低複雜性,忽略成功或失敗以外的預設結果,因爲提供者只是腳本,因此他們的結果通常是非結構化的。

如果您需要更多增強功能來設置您的實例,我建議一個專門的工具,如Ansible,Chef,Puppet等。Terraform的重點確實在於基礎設施,而不是軟件組件。

+0

達到了上面闡述的相同結論 - 我認爲terraform更適合於基礎設施組件(僅限於),而更好地將provisioning和bootstrapping-stuff-放在一起,以便更適合處理像Ansible這樣的工具。謝謝! – jiveTurkey

0

使用resource dependencies您可以確保資源是在另一個之前創建的。

下面是我如何創建我的領事集羣的一個不完整的例子,只是爲了給你一個想法。

resource "aws_instance" "consul_1" { 
    user_data = <<EOF 
    #cloud-config 
    runcmd: 
    - 'docker pull consul:0.7.5' 
    - 'docker run -d -v /etc/localtime:/etc/localtime:ro -v $(pwd)/consul-data:/consul/data --restart=unless-stopped --net=host consul:0.7.5 agent -server -advertise=${self.private_ip} -bootstrap-expect=2 -datacenter=wordpress -log-level=info -data-dir=/consul/data' 
    EOF 

} 

resource "aws_instance" "consul_2" { 

    depends_on = ["aws_instance.consul_1"] 

    user_data = <<EOF 
    #cloud-config 
    runcmd: 
    - 'docker pull consul:0.7.5' 
    - 'docker run -d -v /etc/localtime:/etc/localtime:ro -v $(pwd)/consul-data:/consul/data --restart=unless-stopped --net=host consul:0.7.5 agent -server -advertise=${self.private_ip} -retry-join=${aws_instance.consul_1.private_ip} -datacenter=wordpress -log-level=info -data-dir=/consul/data' 
    EOF 

} 

對於泊塢窗羣的設置,我認爲這是出Terraform範圍,我認爲這應該是因爲令牌是不是你正在創建的基礎設施的屬性。所以我同意nbering,你可以試着用Ansible或Chef這樣的工具來實現這個設置。

但無論如何,如果示例幫助您設置您的領事集羣,我認爲您只需將領事配置爲您的碼頭羣后端。

+0

感謝您發佈您如何處理領事設置。我對Docker Swarm設置可能超出了Terraform的範圍表示同意 - 但它與設置Consul集羣的方式相同,所以如果Bootstrap Consul是有意義的,那麼我會說Bootstrap Docker Swarm是有意義的以及。仍在考慮這一點...另外,不幸的是,使用最新的Docker Swarm(截至1.13),後端無法再配置Swarm自己的分佈式狀態存儲。反正 - 謝謝你的回覆。 – jiveTurkey

0

更簡單的解決方案是自己提供令牌。

創建ACL令牌時,只需傳入ID值,consul將使用該值,而不是隨機生成一個。

0

Sparrowform - 是基於Terraform基礎架構可以處理你的情況下,輕巧的供應者。這裏是aws ec2實例的例子。

假設我們有3個用於consul集羣的ec2實例:node0,node1和node2。第一個(node0)是我們從中獲取令牌並將其保存在S3存儲桶中的位置。另外兩個從S3開始加載令牌。

$ nano aws_instance.node0.sparrowfile 

#!/usr/bin/env perl6 

# have not checked this command, but that's the idea ... 
bash "docker swarm init | aws s3 cp - s3://alexey-bucket/stream.txt" 

$ nano aws_instance.node1.sparrowfile 

#!/usr/bin/env perl6 

my $i=0; 
my $token; 

try { 

    while True { 
    my $s3-token = run 'aws', 's3', 'cp', 's3://alexey-bucket/stream.txt', '-', :out; 
    $token = $s3-token.out.lines[0]; 
    $s3-token.out.close; 
    last if $i++ > 8 or $token; 
    say "retry num $i ..."; 
    sleep 2*$i; 
    } 

    CATCH { { .resume } } 

} 

die "we have not succeed in fetching token" unless $token; 

bash "docker swarm init $token"; 

$ nano aws_instance.node2.sparrowfile - the same setup as for node1 


$ terrafrom apply # bootstrap infrastructure 

$ sparrowform --ssh_private_key=~/.ssh/aws.pub --ssh_user=ec2-user # run provisioning on node0, node1, node2 

PS披露,我是工具的作者。