简体   繁体   English

使用 terraform 创建 aws codedeploy ecs 基础设施

[英]use terraform to create an aws codedeploy ecs infrastructure

I tried to use terraform to setup aws codeploy ecs infrastructure, following aws documentation to understand aws deploy: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-blue-green.html , reading this post to have an example (it uses EC2 instance): https://hiveit.co.uk/techshop/terraform-aws-vpc-example/02-create-the-vpc/ and finally use reference into terraform documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codedeploy_deployment_group I tried to use terraform to setup aws codeploy ecs infrastructure, following aws documentation to understand aws deploy: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-blue-green.html , reading this post to有一个例子(它使用 EC2 实例): https://hiveit.co.uk/techshop/terraform-aws-vpc-example/02-create-the-vpc/最后使用参考 terraform 文档: Z5E0576C5050A18 registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codedeploy_deployment_group

The probleme is when I tried to make a deploy from aws codedeploy, the deployment is stuck in the install phase问题是当我尝试从 aws codedeploy 进行部署时,部署卡在安装阶段

在此处输入图像描述

Here is the terraform configuration I have done这是我做的terraform配置

# main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider "aws" {
  # defined in AWS_REGION env
  # defined in AWS_ACCESS_KEY_ID env
  # defined in AWS_SECRET_ACCESS_KEY env
}

# create repository to store docker image
resource "aws_ecr_repository" "repository" {
  name = "test-repository"
}
# network.tf
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "terraform-example-vpc"
  }
}

resource "aws_internet_gateway" "gateway" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "terraform-example-internet-gateway"
  }
}

resource "aws_route" "route" {
  route_table_id         = aws_vpc.vpc.main_route_table_id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.gateway.id
}

resource "aws_subnet" "main" {
  count                   = length(data.aws_availability_zones.available.names)
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.0.${count.index}.0/24"
  map_public_ip_on_launch = true
  availability_zone       = element(data.aws_availability_zones.available.names, count.index)

  tags = {
    Name = "public-subnet-${element(data.aws_availability_zones.available.names, count.index)}"
  }
}
# loadbalancer.tf
resource "aws_security_group" "lb_security_group" {
  name        = "terraform_lb_security_group"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

  tags = {
    Name = "terraform-example-lb-security-group"
  }
}

resource "aws_lb" "lb" {
  name            = "terraform-example-lb"
  security_groups = [aws_security_group.lb_security_group.id]
  subnets         = aws_subnet.main.*.id

  tags = {
    Name = "terraform-example-lb"
  }
}

resource "aws_lb_target_group" "group1" {
  name        = "terraform-example-lb-target1"
  port        = 80
  protocol    = "HTTP"
  vpc_id      = aws_vpc.vpc.id
  target_type = "ip"
}

resource "aws_lb_listener" "listener_http" {
  load_balancer_arn = aws_lb.lb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    target_group_arn = aws_lb_target_group.group1.arn
    type             = "forward"
  }
}
# cluster.tf
resource "aws_ecs_cluster" "cluster" {
  name = "terraform-example-cluster"

  tags = {
    Name = "terraform-example-cluster"
  }
}

resource "aws_iam_role" "ecsTaskExecutionRole" {
  name = "ecsTaskExecutionRole"

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

resource "aws_ecs_task_definition" "task_definition" {
  family                   = "deployment-app"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = 256
  memory                   = 512
  execution_role_arn       = aws_iam_role.ecsTaskExecutionRole.arn
  container_definitions = jsonencode([
    {
      "name" : "app",
      "image" : "httpd:2.4",
      "portMappings" : [
        {
          "containerPort" : 80,
          "hostPort" : 80,
          "protocol" : "tcp"
        }
      ],
      "essential" : true
    }
  ])
}

resource "aws_ecs_service" "service" {
  cluster             = aws_ecs_cluster.cluster.id
  name                = "terraform-example-service"
  task_definition     = "deployment-app"
  launch_type         = "FARGATE"
  scheduling_strategy = "REPLICA"
  platform_version    = "LATEST"
  desired_count       = 1

  load_balancer {
    target_group_arn = aws_lb_target_group.group1.arn
    container_name   = "app"
    container_port   = 80
  }

  deployment_controller {
    type = "CODE_DEPLOY"
  }

  network_configuration {
    assign_public_ip = true
    security_groups  = [aws_security_group.lb_security_group.id]
    subnets          = aws_subnet.main.*.id
  }

  lifecycle {
    ignore_changes = [desired_count, task_definition, platform_version]
  }
}
# codedeploy.tf
resource "aws_codedeploy_app" "codedeploy_app" {
  name             = "example-codedeploy-app"
  compute_platform = "ECS"
}

resource "aws_lb_target_group" "group2" {
  name        = "terraform-example-lb-target2"
  port        = 80
  protocol    = "HTTP"
  vpc_id      = aws_vpc.vpc.id
  target_type = "ip"
}

resource "aws_codedeploy_deployment_group" "codedeploy_group" {
  app_name               = aws_codedeploy_app.codedeploy_app.name
  deployment_group_name  = "deployment_group_name"
  service_role_arn       = "###"
  deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"

  auto_rollback_configuration {
    enabled = true
    events  = ["DEPLOYMENT_FAILURE"]
  }

  blue_green_deployment_config {
    deployment_ready_option {
      action_on_timeout    = "CONTINUE_DEPLOYMENT"
      wait_time_in_minutes = 0
    }

    terminate_blue_instances_on_deployment_success {
      action                           = "TERMINATE"
      termination_wait_time_in_minutes = 1
    }
  }

  deployment_style {
    deployment_option = "WITH_TRAFFIC_CONTROL"
    deployment_type   = "BLUE_GREEN"
  }

  load_balancer_info {
    target_group_pair_info {
      target_group {
        name = aws_lb_target_group.group1.name
      }

      target_group {
        name = aws_lb_target_group.group2.name
      }

      prod_traffic_route {
        listener_arns = [aws_lb_listener.listener_http.arn]
      }
    }
  }

  ecs_service {
    cluster_name = aws_ecs_cluster.cluster.name
    service_name = aws_ecs_service.service.name
  }
}
# datasource.tf
data "aws_availability_zones" "available" {}

note: replace ### with the arn of the role AWSCodeDeployRoleForECS : https://docs.aws.amazon.com/AmazonECS/latest/developerguide/codedeploy_IAM_role.html I don't add it into terraform yet note: replace ### with the arn of the role AWSCodeDeployRoleForECS : https://docs.aws.amazon.com/AmazonECS/latest/developerguide/codedeploy_IAM_role.html I don't add it into terraform yet

after using使用后

terraform plan
terraform apply

all the stack is set and i have access to the it works of httpd through the load balancer dns name所有堆栈都已设置,我可以通过负载平衡器 dns 名称访问 httpd 的it works

在此处输入图像描述

My probleme is when I push a new image to the repository, update the task definition and create a new deployment, this last one is stuck in the Step 1 without any error or whatever我的问题是当我将新图像推送到存储库,更新任务定义并创建新部署时,最后一个卡在步骤 1 中没有任何错误或任何错误

For the example, I tried to push an nginx image instead of httpd例如,我尝试推送 nginx 图像而不是 httpd

aws ecs register-task-definition \
        --family=deployment-app \
        --network-mode=awsvpc \
        --cpu=256 \
        --memory=512 \
        --execution-role-arn=arn:aws:iam::__AWS_ACCOUNT__:role/ecsTaskExecutionRole \
        --requires-compatibilities='["FARGATE"]' \
        --container-definitions='[{"name": "app","image": "nginx:latest","portMappings": [{"containerPort": 80,"hostPort": 80,"protocol": "tcp"}],"essential": true}]'

I am using aws console to create deployment, with yaml appspec:我正在使用 aws 控制台创建部署,使用 yaml appspec:

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "arn:aws:ecs:eu-west-3:__AWS_ACCOUNT__:task-definition/deployment-app:9"
        LoadBalancerInfo:
          ContainerName: "app"
          ContainerPort: 80
        PlatformVersion: "LATEST"

Can anyone help me to understand my mistake?谁能帮我理解我的错误? Thanks !谢谢 !

I didn't know where to find a log from codeploy to know what was the problem.我不知道在哪里可以找到来自 codeploy 的日志以了解问题所在。 Finally, I just needed to go to the service, and check the provisionning task, after that the task failed with error message.最后,我只需要 go 到服务,并检查配置任务,然后任务失败并显示错误消息。

The problem came from my ecsTaskExecutionRole because it didn't has enought ECR rights to pull the image I built问题来自我的ecsTaskExecutionRole ,因为它没有足够的 ECR 权限来提取我构建的图像

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM