如何安装Terraform和Provision AWS EC2云实例

时间:2020-03-05 15:25:12  来源:igfitidea点击:

用于将基础设施定义为代码(IAAC)的Terraform的基元。
我们可以使用相同的工具在AWS,数字海洋,谷歌云,Heroku,Microsoft Azure等中构建,更改和版本基础架构。
使用Terraform描述单个应用程序或者整个数据中心的组件。
在本教程中,我们将使用Terraform和Provision EC2实例创建基础架构。

1.安装Terraform.

根据系统下载Terraform。

安装非常简单。
下载Terraform zip存档并将其解压缩在合适的位置。
一旦我们解开了Terraform,更新路径环境变量指向Terraform。
由于文件夹/usr/local/bin已设置为path环境变量,因此我们不需要再次设置它。
如果我们使用的是任何其他位置,请在路径环境变量中指定它。
bash_profile或者/etc/complet。

[thegeek@mysandbox ~]$cd /usr/local/src
[root@mysandbox src]# wget https://releases.hashicorp.com/terraform/0.8.5/terraform_0.8.5_linux_386.zip
[root@mysandbox src]# unzip terraform_0.8.5_linux_386.zip
[root@mysandbox src]# mv terraform /usr/local/bin/

现在添加以下行以在路径位置添加Terraform。

export PATH=$PATH:/terraform-path/

使用以下命令验证TerraForm的安装

[root@mysandbox src]# terraform
Usage: terraform [--version] [--help] <command> [args]
The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.
Common commands:
apply               Builds or changes infrastructure
console            Interactive console for Terraform interpolations
destroy            Destroy Terraform-managed infrastructure
fmt                  Rewrites config files to canonical format
get                  Download and install modules for the configuration
graph              Create a visual graph of Terraform resources
import             Import existing infrastructure into Terraform
init                  Initializes Terraform configuration from a module
output             Read an output from a state file
plan                Generate and show an execution plan
push               Upload this Terraform module to Atlas to run
refresh            Update local state file against real resources
remote            Configure remote state storage
show               Inspect Terraform state or plan
taint                Manually mark a resource for recreation
untaint             Manually unmark a resource as tainted
validate           Validates the Terraform files
version            Prints the Terraform version
All other commands:
debug              Debug output management (experimental)
state                Advanced state management

2.创建EC2用户

当我们第一次在AWS中创建帐户时,我们将提供root登录,用于访问AWS中的所有服务/功能。
对于AWS最佳安全性实践,使用root帐户,创建具有有限访问AWS服务的用户帐户。
由于我们将使用Terraform的API在AWS中创建一个基础架构,因此它将与EC2服务交互,因此我们将仅创建一个用户访问所有EC2服务的用户。

使用root帐户登录AWS控制台。

选择服务 - > A-Z-> IAM

单击IAM仪表板的用户。

单击"添加用户"

提供用户名,然后单击"编程访问"。
我们向用户名提供为"Terraformuser"。
单击"下一步:权限"

接下来单击"创建组"。
提供组名和策略类型,通过Amazonec2过滤。
选择第一行,它为Amazon EC2完全访问。

点击"下一步:注释"

单击"创建用户"

通过单击"下载CSV"下载新创建的用户访问密钥ID和密钥。
这些凭据需要通过Terraform连接到Amazon EC2服务

3. Terraform文件

正如我们已经知道的那样,Terraform是一个命令行工具,用于在云中创建,更新和版本控制基础架构,然后我们想知道它是如何做到的?
Terraform使用称为Hashicorp配置语言(HCL)的语言来描述文件中的文件中的基础架构。
TF它是一种描述云中基础架构的声明性语言。
当我们使用HCL编写我们的基础架构时。
TF文件,Terraform生成一个执行计划,该执行计划描述它将达到所需状态的结果。
执行计划已准备就绪后,TerraForm执行计划并由名称Terraform生成状态文件。
默认情况下TFState。
此文件将资源元数据映射到实际资源ID,并让Terraform知道它在云中管理的内容。

4. Terraform和Provision AWS

通过Terraform部署EC2实例,创建具有扩展名的文件。
TF此文件包含两个部分。
第一个部分声明提供者(在我们的情况下它是AWS)。
在提供程序部分中,我们将指定在创建EC2用户之前之前下载的CSV文件中写入的访问密钥和密钥。
还选择我们选择的地区。
资源块定义我们要创建的资源。
由于我们要创建EC2实例,因此我们使用"aws_instance"指定了"aws_instance"和它中的实例属性,如ami,instance_type和标记。
找到EC2图像浏览Ubuntu云图像。

[root@mysandbox src]# cd
[root@mysandbox ~]# mkdir terraform
[root@mysandbox ~]# cd terraform/
[root@mysandbox terraform]# vi aws.tf
provider "aws" {
access_key = "ZKIAITH7YUGAZZIYYSZA"
secret_key = "UlNapYqUCg2m4MDPT9Tlq+64BWnITspR93fMNc0Y"
region = "ap-southeast-1"
}
resource "aws_instance" "example" {
ami = "ami-83a713e0"
instance_type = "t2.micro"
tags {
Name = "your-instance"
}
}

首先应用Terraform计划,了解Terraform将是什么。
在实际应用之前,Terraform计划将让我们知道将在基础架构中完成哪些更改,添加和删除。
将创建"+"符号的资源,将删除" - "符号的资源,并将修改"~"符号的资源。

[root@mysandbox terraform]# terraform plan

现在要创建实例,请执行执行Terraform

[root@mysandbox terraform]# terraform apply
aws_instance.example: Creating...
ami:                                                   "" => "ami-83a713e0"
associate_public_ip_address:             "" => "<computed>"
availability_zone:                                "" => "<computed>"
ebs_block_device.#:                          "" => "<computed>"
ephemeral_block_device.#:                "" => "<computed>"
instance_state:                                    "" => "<computed>"
instance_type:                                     "" => "t2.micro"
key_name:                                          "" => "<computed>"
network_interface_id:                         "" => "<computed>"
placement_group:                               "" => "<computed>"
private_dns:                                        "" => "<computed>"
private_ip:                                          "" => "<computed>"
public_dns:                                         "" => "<computed>"
public_ip:                                           "" => "<computed>"
root_block_device.#:                          "" => "<computed>"
security_groups.#:                              "" => "<computed>"
source_dest_check:                           "" => "true"
subnet_id:                                          "" => "<computed>"
tags.%:                                              "" => "1"
tags.Name:                                        "" => "your-instance"
tenancy:                                             "" => "<computed>"
vpc_security_group_ids.#:                 "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Still creating... (20s elapsed)
aws_instance.example: Creation complete
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

接下来,我们将前往EC2仪表板,我们会发现新实例正在初始化。

5.更复杂的Terraform示例

现在,我们理解了如何使用Terraform创建EC2实例,让我们使用Terraform创建更高的基础架构。
我们的基础设施旨在包括 -

→使用CIDR 10创建VPC 10. 0. 0. 0/16

→VPC内的公共子网,CIDR 10. 0. 1. 0/24

→VPC内的私有子网,CIDR 10. 0. 2. 2. 0/24

→公共和私有实例的安全组

→三个EC2 InstancesWeb服务器,数据库服务器和NAT实例

首先,我们通过名称onItoad-deployer创建密钥对。
通过AWS控制台PEM。
为此,单击EC2仪表板的"键对",然后单击"创建密钥对",然后将其保存在我们在步骤4中创建的Terraform文件夹中的新创建目录中。

[root@mysandbox ]# cd ~/terraform
[root@mysandbox ]# mkdir ssh

下载并复制oniToad-Deployer。
在~/terraform/ssh目录中的pem。

现在,我们从VPC开始一个接一个地创建资源。
我们也将配置分为几个。
TF文件基于他们所做的。
e。
g用于创建VPC资源,我们将由名称VPC创建一个文件。
TF使我们可以跟踪每个文件的内容。
在创建资源之前,让我们在变量中声明所有变量。
TF文件。

variables.tf.

variable "access_key" {
description = "AWS access key"
default = "ZKIAITH7YUGAZZIYYSZA"
}
variable "secret_key" {
description = "AWS secret key"
default = "UlNapYqUCg2m4MDPT9Tlq+64BWnITspR93fMNc0Y"
}
variable "region" {
description = "AWS region for hosting our your network"
default = "ap-southeast-1"
}
variable "key_path" {
description = "Key path for SSHing into EC2"
default  = "./ssh/theitroad-deployer.pem"
}
variable "key_name" {
description = "Key name for SSHing into EC2"
default = "theitroad-deployer"
}
variable "vpc_cidr" {
description = "CIDR for VPC"
default     = "10.0.0.0/16"
}
variable "public_subnet_cidr" {
description = "CIDR for public subnet"
default     = "10.0.1.0/24"
}
variable "private_subnet_cidr" {
description = "CIDR for private subnet"
default     = "10.0.2.0/24"
}
variable "amis" {
description = "Base AMI to launch the instances"
default = {
ap-southeast-1 = "ami-83a713e0"
ap-southeast-2 = "ami-83a713e0"
}
}

让我们定义VPC,CIDR块为10. 0. 0. 0/16

VPC.TF.

resource "aws_vpc" "default" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "terraform-aws-vpc"
}
}

定义网关

Gateway.tf.

resource "aws_internet_gateway" "default" {
vpc_id = "${aws_vpc.default.id}"                                                                                                                                       tags {
Name = "theitroad gw"
}
}

使用CIDR 10定义公共子网10. 0. 1. 0/24

public.tf.

resource "aws_subnet" "public-subnet-in-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "${var.public_subnet_cidr}"
availability_zone = "ap-southeast-1a"
tags {
Name = "theitroad Public Subnet"
}
}

使用CIDR 10定义私有子网。
0. 2. 0/24

private.tf.

resource "aws_subnet" "private-subnet-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"
cidr_block = "${var.private_subnet_cidr}"
availability_zone = "ap-southeast-1a"
tags {
Name = "theitroad Private Subnet"
}
}

公共/私有子网的路由表

Route.tf.

resource "aws_route_table" "public-subnet-in-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.default.id}"
}
tags {
Name = "theitroad Public Subnet"
}
}
resource "aws_route_table_association" "public-subnet-in-ap-southeast-1-association" {
subnet_id = "${aws_subnet.public-subnet-in-ap-southeast-1.id}"
route_table_id = "${aws_route_table.public-subnet-in-ap-southeast-1.id}"
}
resource "aws_route_table" "private-subnet-in-ap-southeast-1" {
vpc_id = "${aws_vpc.default.id}"
route {
cidr_block = "0.0.0.0/0"
instance_id = "${aws_instance.nat.id}"
}
tags {
Name = "theitroad Private Subnet"
}
}
resource "aws_route_table_association" "private-subnet-in-ap-southeast-1-association" {
subnet_id = "${aws_subnet.private-subnet-in-ap-southeast-1.id}"
route_table_id = "${aws_route_table.private-subnet-in-ap-southeast-1.id}"
}

定义NAT安全组

natsg.tf.

resource "aws_security_group" "nat" {
name = "vpc_nat"
description = "NAT security group"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["${var.private_subnet_cidr}"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["${var.private_subnet_cidr}"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${var.vpc_cidr}"]
}
egress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "NATSG"
}
}

为Web定义安全组

websg.tf.

resource "aws_security_group" "web" {
name = "vpc_web"
description = "Accept incoming connections."
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["${var.private_subnet_cidr}"]
}
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "WebServerSG"
}
}

在私有子网中定义数据库的安全组

dbsg.tf.

resource "aws_security_group" "db" {
name = "vpc_db"
description = "Accept incoming database connections."
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = ["${aws_security_group.web.id}"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["${var.vpc_cidr}"]
}
ingress {
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["${var.vpc_cidr}"]
}
egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "DBServerSG"
}
}

定义Web服务器实例

webserver.tf.

resource "aws_instance" "web-1" {
ami = "${lookup(var.amis, var.region)}"
availability_zone = "ap-southeast-1a"
instance_type = "t2.micro"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${aws_security_group.web.id}"]
subnet_id = "${aws_subnet.public-subnet-in-ap-southeast-1.id}"
associate_public_ip_address = true
source_dest_check = false
tags {
Name = "Web Server LAMP"
}
}

定义数据库实例

dbinstance.tf.

resource "aws_instance" "db-1" {
ami = "${lookup(var.amis, var.region)}"
availability_zone = "ap-southeast-1a"
instance_type = "t2.micro"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${aws_security_group.db.id}"]
subnet_id = "${aws_subnet.private-subnet-in-ap-southeast-1.id}"
source_dest_check = false
tags {
Name = "Database Server"
}
}

定义NAT实例

natinstance.tf.

resource "aws_instance" "nat" {
ami = "ami-1a9dac48" # this is a special ami preconfigured to do NAT
availability_zone = "ap-southeast-1a"
instance_type = "t2.micro"
key_name = "${var.key_name}"
vpc_security_group_ids = ["${aws_security_group.nat.id}"]
subnet_id = "${aws_subnet.public-subnet-in-ap-southeast-1.id}"
associate_public_ip_address = true
source_dest_check = false
tags {
Name = "NAT instance"
}
}

为NAT和Web实例分配EIP

EIP.TF.

resource "aws_eip" "nat" {
instance = "${aws_instance.nat.id}"
vpc = true
}
resource "aws_eip" "web-1" {
instance = "${aws_instance.web-1.id}"
vpc = true
}

首先执行Terraform计划,了解Terraform将要做什么。
在执行Terraform时,我们还可以最终重新检查基础架构

[root@mysandbox terraform]# terraform plan
---------------------------
---------------------------
Plan: 16 to add, 0 to change, 0 to destroy.

有16个计划增加,没有什么可以改变或者摧毁

现在执行Terraform适用

[root@mysandbox terraform]# terraform apply

一旦执行上述命令完成,我们的基础架构将与一个VPC,两个子网,网关,路由表,安全组,EIP关联,所有三个EC2实例等一起。
我们将拥有所有16个资源。
我们可以使用以下命令创建基础架构图。

[root@mysandbox terraform]# terraform graph | dot -Tpng > infrastructure_graph.png

现在从本地工作站连接到NAT实例,我们将在NAT实例中。
分配给我们的基础架构中的NAT实例的私有IP为10. 0. 1. 220.访问私有子网中的实例,例如:通过NAT实例以及"Web Server Lamp"实例中的DB实例。
分配给DB和Web服务器实例的私有IP为10. 0. 2. 220和10. 0.1.
分别为207.
浏览EC2仪表板以查找分配给我们实例的私有IP。

[root@mysandbox terraform]# ssh -i "./ssh/theitroad-deployer.pem" [email protected]

从nat ping db实例

[ec2-user@ip-10-0-1-220 ~]$ping 10.0.2.220
PING 10.0.2.220 (10.0.2.220) 56(84) bytes of data.
64 bytes from 10.0.2.220: icmp_seq=1 ttl=64 time=0.321 ms
64 bytes from 10.0.2.220: icmp_seq=2 ttl=64 time=0.452 ms
64 bytes from 10.0.2.220: icmp_seq=3 ttl=64 time=0.393 ms

从nat ping web服务器实例

[ec2-user@ip-10-0-1-220 ~]$ping 10.0.1.207
PING 10.0.1.207 (10.0.1.207) 56(84) bytes of data.
64 bytes from 10.0.1.207: icmp_seq=1 ttl=64 time=0.747 ms
64 bytes from 10.0.1.207: icmp_seq=2 ttl=64 time=0.517 ms

我们已安装Terraform和Provision AWS。
我们现在可以使用该代码轻松更新基础架构,甚至在另一个具有次要修改的区域中部署它。