使用 Terraform 在 AWS 实现自动化创建VPC和EC2

本文最后更新于 320 天前, 如有失效请评论区留言.

需求

  • 新建vpc
  • Mysql所在节点不允许被公网访问,但是可以访问公网(NAT出去)
  • Web所在节点只允许80,443,22端口访问

准备工作

这里定义了 variables.tf 一些变量,主要是aws地域、vpc相关子网,以及EC2节点配置免密信任

variable "aws_region" {
  description = "aws region"
  default     = "us-east-1"
}

variable "vpc_cidr" {
  description = "CIDR block for the subnet"
  default     = "10.20.0.0/16"
}

variable "vpc_subnet_public_cidr" {
  default = "10.20.0.0/24"
}

variable "vpc_subnet_private_cidr" {
  default = "10.20.1.0/24"
}

variable "public_key_location" {
  description = "Location of the public key to be used for SSH access"
  default     = "/root/.ssh/id_rsa.pub"
}

创建vpc、子网、路由及网关

resource "aws_vpc" "ysicing" {
  cidr_block = var.vpc_cidr
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

resource "aws_subnet" "ysicing_public" {
  vpc_id            = aws_vpc.ysicing.id
  cidr_block        = var.vpc_subnet_public_cidr
  availability_zone = "us-east-1c"
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

resource "aws_subnet" "ysicing_private" {
  vpc_id            = aws_vpc.ysicing.id
  cidr_block        = var.vpc_subnet_private_cidr
  availability_zone = "us-east-1c"
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

// igw
resource "aws_internet_gateway" "ysicing" {
  vpc_id = aws_vpc.ysicing.id
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

resource "aws_eip" "ysicing" {
  domain = "vpc"
}

output "aws_eip_ip" {
  value = aws_eip.ysicing.public_ip
}

resource "aws_nat_gateway" "ysicing" {
  allocation_id = aws_eip.ysicing.id
  subnet_id     = aws_subnet.ysicing_public.id
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

resource "aws_route_table" "ysicing_private" {
  vpc_id = aws_vpc.ysicing.id
  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.ysicing.id
  }
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

resource "aws_route_table" "ysicing_public" {
  vpc_id = aws_vpc.ysicing.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.ysicing.id
  }
  tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

resource "aws_route_table_association" "ysicing_public" {
  subnet_id      = aws_subnet.ysicing_public.id
  route_table_id = aws_route_table.ysicing_public.id
}

resource "aws_route_table_association" "ysicing_private" {
  subnet_id      = aws_subnet.ysicing_private.id
  route_table_id = aws_route_table.ysicing_private.id
}

这里主要是定义vpc下有两个子网,其中公有子网和私有子网;新建了两个网关,一个IGW和一个NAT(绑定了弹性ip),IGW配置给了公有子网,NAT配置给了私有子网,同时也关联了相关路由表

创建ec2

resource "aws_key_pair" "ysicing-txhk-ssh-key" {
  key_name   = "ysicing-txhk-ssh-key"
  public_key = file(var.public_key_location)
}

resource "aws_security_group" "ysicing-k3s" {
  name        = "ysicing-k3s"
  description = "Security group for ysicing k3s EC2 instances"

  vpc_id = aws_vpc.ysicing.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.20.0.0/16", "1.1.1.1/32"]
  }

  ingress {
    from_port   = 6443
    to_port     = 6443
    protocol    = "tcp"
    cidr_blocks = ["10.20.0.0/16", "1.1.1.1/32"]
  }

  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   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["10.20.0.0/16"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "ysicing-db" {
  name        = "ysicing-db"
  description = "Security group for ysicing DB EC2 instances"

  vpc_id = aws_vpc.ysicing.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.20.0.0/16"]
  }

  ingress {
    from_port   = 3036
    to_port     = 3036
    protocol    = "tcp"
    cidr_blocks = ["10.20.0.0/16"]
  }

  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["10.20.0.0/16"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_eip" "k3s-ssh" {
  domain = "vpc"
}

output "k3s_ssh_eip_ip" {
  value = aws_eip.k3s-ssh.public_ip
}

resource "aws_eip_association" "k3s-ssh-eip-association" {
  instance_id   = aws_instance.ysicing-k3s[0].id
  allocation_id = aws_eip.k3s-ssh.id
}

resource "aws_instance" "ysicing-k3s" {
  count = 1
  ami = "ami-058bd2d568351da34"
  instance_type = "t2.medium"
  subnet_id = aws_subnet.ysicing_public.id
  vpc_security_group_ids = [aws_security_group.ysicing-k3s.id]
  key_name = aws_key_pair.ysicing-txhk-ssh-key.key_name
  # associate_public_ip_address = true
  root_block_device {
    volume_type           = "gp3"
    volume_size           = 30
    delete_on_termination = false
  }

  ebs_block_device {
    device_name           = "/dev/sdb"
    volume_type           = "gp3"
    volume_size           = 30
    delete_on_termination = false
  }
}

resource "aws_instance" "ysicing-db" {
  count = 1
  ami = "ami-058bd2d568351da34"
  instance_type = "t2.small"

  subnet_id = aws_subnet.ysicing_private.id

  vpc_security_group_ids = [aws_security_group.ysicing-db.id]

  key_name = aws_key_pair.ysicing-txhk-ssh-key.key_name
  root_block_device {
    volume_type           = "gp3"
    volume_size           = 30
    delete_on_termination = false
  }

  ebs_block_device {
    device_name           = "/dev/sdb"
    volume_type           = "gp3"
    volume_size           = 30
    delete_on_termination = false
  }

  volume_tags = {
    Name    = "ysicing"
    Project = "ysicing"
  }
}

核心main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.34.0"
    }
  }

  required_version = ">= 1.2.0"
}

provider "aws" {
  // 更改为你所需的 AWS 区域
  region  = var.aws_region
  # ~/.aws/config 和 .aws/credentials 配置要有东西
  profile = "default"
  default_tags {
    tags = {
      Name    = "ysicing"
      Project = "ysicing"
    }
  }
}

运行

terraform init
# 查看预期变更
terraform plan
# 生效变更
terraform apply

Chapters

Sponsor

Like this article? $1 reward

Comments