问题
I have an API running on ECS Fargate
that accepts GET
method requests. I put an API Gateway
endpoint in front of it with a VPC_LINK
integration with an NLB
in a private subnet. When I send a GET
request using the invoke url, I get a 404 page not found
error. I am confused why I am getting this. I set up every component - the NLB listener, the target group, and my host and container ports in my task definition - on 8000/tcp
. So, I am not sure why this error is happening. My Fargate
task is also running successfully and passing all health checks. When I test the container locally doing curl -X GET localhost/nmapscan:8000
it works fine. Below are my configurations in Terraform
as well as screenshots from the console.
Terraform:
resource "aws_lb" "myapis" {
name = "my-apis"
internal = true
load_balancer_type = "network"
subnets = ["${module.vpc.private_subnets}"]
enable_deletion_protection = false
tags = {
Environment = "dev"
}
}
resource "aws_security_group" "ecs_tasks" {
name = "ecs-tasks"
description = "allow inbound access from the NLB only"
vpc_id = "${module.vpc.vpc_id}"
ingress {
protocol = "tcp"
from_port = 8000
to_port = 8000
cidr_blocks = ["10.10.11.0/24", "10.10.12.0/24", "10.10.13.0/24"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_lb_target_group" "test" {
name = "test-api"
port = 8000
protocol = "TCP"
target_type = "ip"
vpc_id = "${module.vpc.vpc_id}"
stickiness{
enabled = false
type = "lb_cookie"
}
health_check{
interval = 30
port = 8000
protocol = "tcp"
healthy_threshold = 2
unhealthy_threshold = 2
}
}
resource "aws_lb_listener" "test" {
load_balancer_arn = "${aws_lb.myapis.id}"
port = "8000"
protocol = "TCP"
default_action {
target_group_arn = "${aws_lb_target_group.test.id}"
type = "forward"
}
}
resource "aws_api_gateway_vpc_link" "myapi" {
name = "my_api_link"
description = "VPC link for API NLB"
target_arns = ["${aws_lb.myapis.arn}"]
}
resource "aws_api_gateway_rest_api" "GOAPI" {
name = "GO"
description = "REST API for GO APIs"
}
resource "aws_api_gateway_resource" "test" {
rest_api_id = "${aws_api_gateway_rest_api.GOAPI.id}"
parent_id = "${aws_api_gateway_rest_api.GOAPI.root_resource_id}"
path_part = "nmapscan"
}
resource "aws_api_gateway_method" "testmethod" {
rest_api_id = "${aws_api_gateway_rest_api.GOAPI.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "GET"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "integrationtest" {
connection_type = "VPC_LINK"
connection_id = "${aws_api_gateway_vpc_link.myapi.id}"
type = "HTTP"
integration_http_method = "GET"
rest_api_id = "${aws_api_gateway_rest_api.GOAPI.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "${aws_api_gateway_method.testmethod.http_method}"
uri = "${format("https://%s:8000/", aws_lb.myapis.dns_name)}"
}
resource "aws_api_gateway_method_response" "test-200" {
rest_api_id = "${aws_api_gateway_rest_api.GOAPI.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "${aws_api_gateway_method.testmethod.http_method}"
status_code = "200"
response_models = {
"application/json" = "Empty"
}
}
resource "aws_api_gateway_integration_response" "testintegrationresponse" {
rest_api_id = "${aws_api_gateway_rest_api.GOAPI.id}"
resource_id = "${aws_api_gateway_resource.test.id}"
http_method = "${aws_api_gateway_method.testmethod.http_method}"
status_code = "${aws_api_gateway_method_response.test-200.status_code}"
response_templates = {
"application/json" = ""
}
}
resource "aws_api_gateway_deployment" "testdeploy" {
depends_on = ["aws_api_gateway_integration.integrationtest"]
rest_api_id = "${aws_api_gateway_rest_api.GOAPI.id}"
stage_name = "v1"
}
resource "aws_ecs_cluster" "goapi" {
name = "goapis"
}
data "aws_iam_role" "ecs_task_execution_role" {
name = "ecsTaskExecutionRole"
}
resource "aws_ecs_task_definition" "test" {
family = "test"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = 256
memory = 512
execution_role_arn = "${data.aws_iam_role.ecs_task_execution_role.arn}"
container_definitions = "${file("test-service.json")}"
}
resource "aws_ecs_service" "test" {
name = "test-service"
cluster = "${aws_ecs_cluster.goapi.id}"
task_definition = "${aws_ecs_task_definition.test.arn}"
launch_type = "FARGATE"
desired_count = 1
network_configuration {
subnets = ["${module.vpc.private_subnets}"]
security_groups = ["${aws_security_group.ecs_tasks.id}"]
}
load_balancer {
target_group_arn = "${aws_lb_target_group.test.id}"
container_name = "test-service"
container_port = 8000
}
depends_on = [
"aws_lb_listener.test",
]
}
Task Definiton:
[
{
"name": "test-service",
"image": "12345678910.dkr.ecr.us-east-1.amazonaws.com/myimages:latest",
"cpu": 256,
"memory": 512,
"essential": true,
"portMappings": [
{
"containerPort": 8000,
"hostPort": 8000
}
]
}
]
Screenshots:
回答1:
EDIT Looks like the answer came about here, might be worth deprecating this post.
Unless you are successfully SIGV4 Signing your requests with IAM auth on your Method Request or have mapped custom Gateway Responses in case of auth failures, API Gateway will not return a 404, and neither will the NLB thus this response has to be coming from beyond the NLB in this stack. You should be able to confirm this by looking in your API Gateway CloudWatch logs (enable full request/response data on the stage).
NOTE: You should match the request id in your CloudWatch logs to the API GW response header "x-amzn-requestid", for example:
x-amzn-requestid: 7cc765bb-4086-45f4-9450-1a2a3c4e67d5
In the logs, you should see it say something like "Sending request to..." or a line about the response it gets back from that request. That is an indication that API Gateway received the request, sent it to the backend integration and received a 404 in return.
I'd say the next steps are to implement debug logging on your integration to log the requests coming in, and the properties of those requests so you can determine where the breakdown is. Seems like the request is to a URI your application isn't configured to respond to.
来源:https://stackoverflow.com/questions/58089140/aws-api-gateway-404-page-not-found-error-when-invoking-endpoint-url