使用Terraform(Fargate)部署Nginx

首先

这是一个关于学习Terraform的备忘录。

请点击这里查看目录。

 

terraform配置

文件结构

.
├── Dockerfile
├── nginx
│   └── index.html
└── terraform
    ├── main.tf
    ├── modules
    │   ├── bash
    │   │   └── null_resource.tf
    │   ├── ecr
    │   │   └── ecr.tf
    │   ├── ecs
    │   │   ├── ecs.tf
    │   │   ├── ecs_service.tf
    │   │   └── ecs_task_definition.tf
    │   ├── iam
    │   │   ├── aws_iam_policy.tf
    │   │   ├── aws_iam_policy_attachment.tf
    │   │   ├── aws_iam_role.tf
    │   │   └── outputs.tf
    │   └── network
    │       ├── aws_vpc.tf
    │       ├── igw.tf
    │       ├── outputs.tf
    │       ├── route_table.tf
    │       ├── security_group.tf
    │       ├── security_group_rule.tf
    │       └── subnet.tf
    ├── terraform.tfstate
    ├── terraform.tfstate.backup
    └── variables.tf

网络配置

我们采用从本地推送到ECR的dockerimage,在fargate上拉取并部署的方法。

fargate.png

Dockerfile和HTML文件

我设定了一个简单的构成,以在画面上输出”Hello world!!!!!!!!!!!”。

FROM nginx:latest

COPY ./nginx /usr/share/nginx/html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>

<body>
    <div style="  line-height: 200px;height: 200px;text-align: center;">
        <p style="  line-height: 1.5;display: inline-block;vertical-align: middle;">
            Hello world!!!!!!!!!!!
        </p>
    </div>
</body>

</html>

主要的.tf文件

每个output.tf是为了通过main.tf将数据传输给其他模块而存在的,不过这里省略了解释。

provider "aws" {
  region      = var.region
}

# IAM
module "iam" {
  source = "./modules/iam"
}

# ECR
module "ecr" {
  source = "./modules/ecr"
  image_name = var.image_name
}

# Null Resource
module "after_ecr" {
  source = "./modules/bash"
  region = var.region
  image_name = var.image_name
}

# network
module "network" {
  source = "./modules/network"
  app_name = var.app_name
}

# ECS
module "ecs" {
  source = "./modules/ecs"
  app_name = var.app_name
  vpc_id       = module.network.security-group-id
  subnet_id    = module.network.subnet-public-1a-id
  aws_iam_role =  module.iam.aws_iam_role

}

我组成

resource "aws_iam_role" "newworld_role" {
  name = "newworld_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid: ""
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        }
      },
    ]
  })
}

“ecr:*”的描述使得Fargate能够进行拉取。
如果没有这个描述,将会出现400错误。

resource "aws_iam_policy" "newworld_policy" {
  name        = "test_policy"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ecr:*",
        ]
        Effect   = "Allow"
        Resource = "*"
      },
    ]
  })
}
resource "aws_iam_policy_attachment" "attach" {
  name       = "iam-attach"
  roles      = ["${aws_iam_role.newworld_role.name}"]
  policy_arn = "${aws_iam_policy.newworld_policy.arn}"
}

ECR建立

variable "image_name" {}

resource "aws_ecr_repository" "repository" {
  name                 = var.image_name
  image_tag_mutability = "IMMUTABLE"
  force_delete         = true

  image_scanning_configuration {
    scan_on_push = true
  }
}

空缺资源的构成

完成ECR构建后,将docker镜像自动推送至ECR。我们正在使用terraform执行以下描述的操作。

aws ecr get-login-password –region ap-northeast-1 | docker login –username AWS –password-stdin AWS的账号ID.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag hello-world-from-ecs:latest AWS的账号ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest
docker push AWS的账号ID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest

aws_caller_identity调用了AWS的账户ID。

data "aws_caller_identity" "self" { }
variable "image_name" {}
variable "region" {}

resource "null_resource" "default" {
  provisioner "local-exec" {
    command = "aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${data.aws_caller_identity.self.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com"
  }

  provisioner "local-exec" {
    command = "docker tag ${var.image_name}:latest ${data.aws_caller_identity.self.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/${var.image_name}:latest"
  }

  provisioner "local-exec" {
    command = "docker push ${data.aws_caller_identity.self.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/${var.image_name}:latest"
  }
}

网络构建

因为太长,我会简略地说。

云计算系统架构

variable "app_name" {}

resource "aws_ecs_cluster" "newworld-cluster" {
  name = "${var.app_name}-cluster"
}

resource "aws_ecs_cluster_capacity_providers" "newworld_capacity_providers" {
  cluster_name = "${var.app_name}-cluster"
  capacity_providers = ["FARGATE"]

  default_capacity_provider_strategy {
    base              = 1
    weight            = 100
    capacity_provider = "FARGATE"
  }
}
variable "vpc_id" {}
variable "subnet_id" {}

resource "aws_ecs_service" "newworld-service" {
  name            = "nginx-service"
  cluster         = aws_ecs_cluster.newworld-cluster.id
  task_definition = aws_ecs_task_definition.newworld-definition.arn
  desired_count   = 1

  network_configuration {
    security_groups  = [var.vpc_id]
    subnets          = ["${var.subnet_id}"]
    assign_public_ip = true
  }

  lifecycle {
    ignore_changes = [desired_count]
  }
}
variable "vpc_id" {}
variable "subnet_id" {}

resource "aws_ecs_service" "newworld-service" {
  name            = "nginx-service"
  cluster         = aws_ecs_cluster.newworld-cluster.id
  task_definition = aws_ecs_task_definition.newworld-definition.arn
  desired_count   = 1

  network_configuration {
    security_groups  = [var.vpc_id]
    subnets          = ["${var.subnet_id}"]
    assign_public_ip = true
  }

  lifecycle {
    ignore_changes = [desired_count]
  }
}

结果-

Screenshot 2023-02-25 at 20.44.16.png
广告
将在 10 秒后关闭
bannerAds