App下載

對流層簡介:如何以編程方式創(chuàng)建 Cloudformation 模板

奶味起司 2021-08-24 12:01:04 瀏覽數(shù) (2552)
反饋

我們將首先安裝對流層庫:

$ pip install troposphere

安裝完成后,您可以創(chuàng)建一個名為 helloworld-cf-template.py 的新文件。

我們將通過從對流層模塊導入一些定義來開始我們的文件:


"""Generating CloudFormation template."""

from troposphere import (
  Base64,
  ec2,
  GetAtt,
  Join,
  Output,
  Parameter,
  Ref,
  Template,
)

從代碼的角度來看,我們要做的第一件事是初始化一個模板變量。在我們的腳本結束時,模板將包含我們基礎設施的完整描述,我們將能夠簡單地打印其輸出以獲取我們的 CloudFromation 模板:

t = Template()

在本書中,我們將同時創(chuàng)建和運行多個 CloudFormation 模板。為了幫助我們識別給定堆棧中的內(nèi)容,我們可以提供描述。創(chuàng)建模板后,添加如下描述:

t.add_description("Effective DevOps in AWS: HelloWorld web application")

當我們使用 Web 命令行界面啟動 EC2 實例時,我們選擇了使用哪個密鑰對以獲得對主機的 SSH 訪問。為了不失去這種能力,我們的模板首先要有一個參數(shù),它為 CloudFormation 用戶提供在啟動 EC2 實例時選擇要使用的密鑰對的能力。

為此,我們將創(chuàng)建一個 Parameter 對象,并通過提供標識符、描述、參數(shù)類型、描述和約束描述來初始化它,以幫助做出正確的決定

當我們啟動堆棧時。為了讓這個參數(shù)存在于我們的最終模板中,我們還將使用模板類中定義的 add_paramter() 函數(shù):

t.add_parameter(Parameter(
   "KeyPair",
   Description="Name of an existing EC2 KeyPair to SSH",
   Type="AWS::EC2::KeyPair::KeyName",
   ConstraintDescription="must be the name of an existing EC2 KeyPair.",
))

接下來我們要看的是安全組。我們將完全按照我們對 KeyPair 參數(shù)所做的那樣進行。


ApplicationPort = 3000 

t.add_resource(ec2.SecurityGroup(
   "SecurityGroup",
   GroupDescription="Allow SSH and TCP/{} access".format(ApplicationPort),
   SecurityGroupIngress=[
   ec2.SecurityGroupRule(
     IpProtocol="tcp",
     FromPort="22",
     ToPort="22",
     CidrIp="0.0.0.0/0",
   ),
   ec2.SecurityGroupRule(
     IpProtocol="tcp",
     FromPort=ApplicationPort,
     ToPort=ApplicationPort,
     CidrIp="0.0.0.0/0",
  ),
 ],
))

在下一節(jié)中,我們將不再需要登錄到我們的 EC2 實例并手動安裝 helloworld.js 文件及其初始化腳本。為此,我們將利用 EC2 提供的 UserData 功能。

創(chuàng)建 EC2 實例時,您可以通過 UserData 可選參數(shù)提供一組命令,以便在虛擬機啟動后運行。


user_data = Base64(Join('\n', [
 "#!/bin/bash",
 "sudo yum install --enablerepo=epel -y nodejs",
 "wget http://bit.ly/2vESNuc -O /home/ec2-user/helloworld.js",
 "wget http://bit.ly/2vVvT18 -O /etc/init/helloworld.conf",
 "start helloworld"
]))

我們現(xiàn)在將專注于我們模板的主要資源,我們的 EC2 實例。創(chuàng)建實例需要提供用于標識資源的名稱、映像 ID、實例類型、安全組、用于 SSH 訪問的密鑰對以及用戶數(shù)據(jù)。

為了簡單起見,我們將對 AMI ID ( ami-a4c7edb2 ) 和實例類型 ( t2.micro ) 進行硬編碼。

創(chuàng)建我們的 EC2 實例所需的其余信息是安全組信息和密鑰對名稱,我們之前通過定義參數(shù)和資源收集了這些信息。在 CloudFormation 中,您可以使用關鍵字 Ref 來引用模板的預先存在的小節(jié)。

在對流層中,這是通過調(diào)用 Ref() 函數(shù)來完成的。和以前一樣,我們將在 add_resource 函數(shù)的幫助下將結果輸出添加到我們的模板中:

t.add_resource(ec2.Instance(
  "instance",
  ImageId="ami-a4c7edb2",
  InstanceType="t2.micro",
  SecurityGroups=[Ref("SecurityGroup")],
  KeyName=Ref("KeyPair"),
  UserData=user_data,
))

在我們腳本的最后一部分,我們將專注于生成模板的輸出部分,當 CloudFormation 創(chuàng)建堆棧時,該部分會被填充。

此選擇允許您打印出在堆棧啟動期間計算的有用信息。在我們的例子中,有兩個有用的信息,訪問我們的 Web 應用程序的 URL 和實例的公共 IP 地址,以便我們可以根據(jù)需要通過 SSH 訪問它。

為了檢索此類信息,CloudFormation 使用函數(shù) Fn::GetAtt 。在對流層,這被轉(zhuǎn)換為使用 GetAttr() 函數(shù):


t.add_output(Output(
  "InstancePublicIp",
  Description="Public IP of our instance.",
  Value=GetAtt(instance, "PublicIp"),
))

t.add_output(Output(
  "WebUrl",
  Description="Application endpoint",
  Value=Join("", [
      "http://", GetAtt(instance, "PublicDnsName"), ":", ApplicationPort
  ]),
))

此時,我們可以讓我們的腳本輸出我們生成的模板的最終結果:

print t.to_json()


0 人點贊