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

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

需求

  • 新建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

According to the relevant laws and regulations of the People's Republic of China, the comment function of the current website has been disabled. If you need to comment, please visit ysicing.me, but the comments still need to be reviewed by AI.