Back

Explore Courses Blog Tutorials Interview Questions
0 votes
3 views
in AWS by (5.6k points)

I'm getting this error :

PlatformTaskDefinitionIncompatibilityException: The specified platform does not satisfy the task definition’s required capabilities

Here is my script:

provider "aws" {

  region  = "us-east-1"

  profile = var.profile

}

### Network

# Fetch AZs in the current region

data "aws_availability_zones" "available" {}

resource "aws_vpc" "main" {

  cidr_block = "172.17.0.0/16"

}

# Create var.az_count private subnets, each in a different AZ

resource "aws_subnet" "private" {

  count             = "${var.az_count}"

  cidr_block        = "${cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)}"

  availability_zone = "${data.aws_availability_zones.available.names[count.index]}"

  vpc_id            = "${aws_vpc.main.id}"

}

# Create var.az_count public subnets, each in a different AZ

resource "aws_subnet" "public" {

  count                   = "${var.az_count}"

  cidr_block              = "${cidrsubnet(aws_vpc.main.cidr_block, 8, var.az_count + count.index)}"

  availability_zone       = "${data.aws_availability_zones.available.names[count.index]}"

  vpc_id                  = "${aws_vpc.main.id}"

  map_public_ip_on_launch = true

}

# IGW for the public subnet

resource "aws_internet_gateway" "gw" {

  vpc_id = "${aws_vpc.main.id}"

}

# Route the public subnet traffic through the IGW

resource "aws_route" "internet_access" {

  route_table_id         = "${aws_vpc.main.main_route_table_id}"

  destination_cidr_block = "0.0.0.0/0"

  gateway_id             = "${aws_internet_gateway.gw.id}"

}

# Create a NAT gateway with an EIP for each private subnet to get internet connectivity

resource "aws_eip" "gw" {

  count      = "${var.az_count}"

  vpc        = true

  depends_on = ["aws_internet_gateway.gw"]

}

resource "aws_nat_gateway" "gw" {

  count         = "${var.az_count}"

  subnet_id     = "${element(aws_subnet.public.*.id, count.index)}"

  allocation_id = "${element(aws_eip.gw.*.id, count.index)}"

}

# Create a new route table for the private subnets

# And make it route non-local traffic through the NAT gateway to the internet

resource "aws_route_table" "private" {

  count  = "${var.az_count}"

  vpc_id = "${aws_vpc.main.id}"

  route {

    cidr_block = "0.0.0.0/0"

    nat_gateway_id = "${element(aws_nat_gateway.gw.*.id, count.index)}"

  }

}

# Explicitely associate the newly created route tables to the private subnets (so they don't default to the main route table)

resource "aws_route_table_association" "private" {

  count          = "${var.az_count}"

  subnet_id      = "${element(aws_subnet.private.*.id, count.index)}"

  route_table_id = "${element(aws_route_table.private.*.id, count.index)}"

}

### Security

# ALB Security group

# This is the group you need to edit if you want to restrict access to your application

resource "aws_security_group" "lb" {

  name        = "tf-ecs-alb"

  description = "controls access to the ALB"

  vpc_id      = "${aws_vpc.main.id}"

  ingress {

    protocol    = "tcp"

    from_port   = 80

    to_port     = 80

    cidr_blocks = ["0.0.0.0/0"]

  }

  egress {

    from_port = 0

    to_port   = 0

    protocol  = "-1"

    cidr_blocks = ["0.0.0.0/0"]

  }

}

# Traffic to the ECS Cluster should only come from the ALB

resource "aws_security_group" "ecs_tasks" {

  name        = "tf-ecs-tasks"

  description = "allow inbound access from the ALB only"

  vpc_id      = "${aws_vpc.main.id}"

  ingress {

    protocol        = "tcp"

    from_port       = "${var.app_port}"

    to_port         = "${var.app_port}"

    security_groups = ["${aws_security_group.lb.id}"]

  }

  egress {

    protocol    = "-1"

    from_port   = 0

    to_port     = 0

    cidr_blocks = ["0.0.0.0/0"]

  }

}

### ALB

resource "aws_alb" "main" {

  name            = "tf-ecs-chat"

  subnets         = aws_subnet.public.*.id

  security_groups = ["${aws_security_group.lb.id}"]

}

resource "aws_alb_target_group" "app" {

  name        = "tf-ecs-chat"

  port        = 80

  protocol    = "HTTP"

  vpc_id      = "${aws_vpc.main.id}"

  target_type = "ip"

}

# Redirect all traffic from the ALB to the target group

resource "aws_alb_listener" "front_end" {

  load_balancer_arn = "${aws_alb.main.id}"

  port              = "80"

  protocol          = "HTTP"

  default_action {

    target_group_arn = "${aws_alb_target_group.app.id}"

    type             = "forward"

  }

}

### ECS

resource "aws_ecs_cluster" "main" {

  name = "tf-ecs-cluster"

}

resource "aws_ecs_task_definition" "app" {

  family                   = "app"

  network_mode             = "awsvpc"

  requires_compatibilities = ["FARGATE"]

  cpu                      = "${var.fargate_cpu}"

  memory                   = "${var.fargate_memory}"

  task_role_arn = "${aws_iam_role.ecs_task_role_role.arn}"

  execution_role_arn = "${aws_iam_role.ecs_task_role_role.arn}"

  container_definitions = <<DEFINITION

[

  {

    "cpu": ${var.fargate_cpu},

    "image": "${var.app_image}",

    "memory": ${var.fargate_memory},

    "name": "app",

    "networkMode": "awsvpc",

    "portMappings": [

      {

        "containerPort": ${var.app_port},

        "hostPort": ${var.app_port}

      }

    ]

  }

]

DEFINITION

  volume {

    name      = "efs-html"

    efs_volume_configuration {

      file_system_id = aws_efs_file_system.main.id

      root_directory = "/opt/data"

    }

  }

}

resource "aws_ecs_service" "main" {

  name            = "tf-ecs-service"

  cluster         = "${aws_ecs_cluster.main.id}"

  task_definition = "${aws_ecs_task_definition.app.arn}"

  desired_count   = "${var.app_count}"

  launch_type     = "FARGATE"

  network_configuration {

    security_groups = ["${aws_security_group.ecs_tasks.id}"]

    subnets         = aws_subnet.private.*.id

  }

  load_balancer {

    target_group_arn = "${aws_alb_target_group.app.id}"

    container_name   = "app"

    container_port   = "${var.app_port}"

  }

  depends_on = [

    "aws_alb_listener.front_end",

  ]

}

# ECS roles & policies

# Create the IAM task role for ECS Task definition

resource "aws_iam_role" "ecs_task_role_role" {

  name = "test-ecs-task-role"

  assume_role_policy = "${file("ecs-task-role.json")}"

  tags = {

    Terraform = "true"

  }

}

# Create the AmazonECSTaskExecutionRolePolicy managed role

resource "aws_iam_policy" "ecs_task_role_policy" {

  name = "test-ecs-AmazonECSTaskExecutionRolePolicy"

  description = "Provides access to other AWS service resources that are required to run Amazon ECS tasks"

  policy = "${file("ecs-task-policy.json")}"

}

# Assign the AmazonECSTaskExecutionRolePolicy managed role to ECS

resource "aws_iam_role_policy_attachment" "ecs_task_policy_attachment" {

  role = "${aws_iam_role.ecs_task_role_role.name}"

  policy_arn = "${aws_iam_policy.ecs_task_role_policy.arn}"

}

resource "aws_efs_file_system" "main" {

  tags = {

    Name = "ECS-EFS-FS"

  }

}

resource "aws_efs_mount_target" "main" {

  count = "${var.subnets-count}"

  file_system_id = "${aws_efs_file_system.main.id}"

  subnet_id      = "${element(var.subnets, count.index)}"

}

and variable.tf is here:

variable "az_count" {

  description = "Number of AZs to cover in a given AWS region"

  default     = "2"

}

variable "app_image" {

  description = "Docker image to run in the ECS cluster"

  default     = "xxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/test1:nginx"

}

variable "app_port" {

  description = "Port exposed by the docker image to redirect traffic to"

#  default     = 3000

  default     = 80

}

variable "app_count" {

  description = "Number of docker containers to run"

  default     = 2

}

variable "fargate_cpu" {

  description = "Fargate instance CPU units to provision (1 vCPU = 1024 CPU units)"

  default     = "256"

}

variable "fargate_memory" {

  description = "Fargate instance memory to provision (in MiB)"

  default     = "512"

}

################

variable "subnets" {

  type        = "list"

  description = "list of subnets to mount the fs to"

  default = ["subnet-xxxxxxx","subnet-xxxxxxx"]

}

variable "subnets-count" {

  type        = "string"

  description = "number of subnets to mount to"

  default = 2

}

Any suggestion would be appreciated!

1 Answer

0 votes
by (12.4k points)

Upgrade your ECS service to the latest , EFS feature is available only on latest version.

resource "aws_ecs_service" "service" {

  platform_version = "1.4.0"

  launch_type      = "FARGATE"

  ...

}

 So when you don't specify the "platform_version" it takes the Default which will not allow EFS volumes.

Do you want to learn more about AWS? Checkout AWS Training by Intellipaat!

Related questions

Want to get 50% Hike on your Salary?

Learn how we helped 50,000+ professionals like you !

0 votes
1 answer
0 votes
1 answer
asked Oct 5, 2020 in AWS by Justin (7k points)
0 votes
1 answer
asked Oct 5, 2020 in AWS by Justin (7k points)
0 votes
1 answer
asked Oct 5, 2020 in AWS by Justin (7k points)

Browse Categories

...