我使用 Terraform 通过 Fargate 部署容器。
我遇到了这个错误:
CannotPullContainerError: Error response from daemon: Get https://xxxxxxxxx.dkr.ecr.us-east-2.amazonaws.com/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
terraform 部署成功通过。
这个镜像只是 nginx (dockerfile):
FROM nginx:latest
WORKDIR /
COPY ./nginx.conf /etc/nginx/nginx.conf
nginx.conf:
user nginx;
worker_processes 4;
events { worker_connections 1024; }
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
server {
listen 80;
if ($host ~ ^(?!www\.)(?<domain>.+)$) {
return 301 $scheme://www.$domain$request_uri;
}
location / {
add_header Content-Type text/plain;
return 200 "<H1>Nginx works!</H1>";
}
}
}
我不明白为什么 aws 说它无法得到回应。网址没问题。我可以下载此镜像并在我的计算机上运行容器。
那为什么呢?问题出在哪里?
我的地形:
data "aws_iam_role" "ecs_task_execution_role" {
name = "ecsTaskExecutionRole"
}
resource "aws_ecs_cluster" "cluster" {
name = "${var.app}-ecs-cluster"
}
data "aws_iam_policy_document" "ecs_service_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "ecs_service_policy" {
statement {
effect = "Allow"
resources = ["*"]
actions = [
"elasticloadbalancing:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"ec2:Describe*",
"ec2:AuthorizeSecurityGroupIngress"
]
}
}
resource "aws_iam_role_policy" "ecs_service_role_policy" {
name = "ecs_service_role_policy"
policy = "${data.aws_iam_policy_document.ecs_service_policy.json}"
role = "${aws_iam_role.ecs_role.id}"
}
resource "aws_iam_role" "ecs_role" {
name = "ecs_role"
assume_role_policy = "${data.aws_iam_policy_document.ecs_service_role.json}"
}
resource "aws_ecs_task_definition" "nginx" {
family = "nginx-${var.app}"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
execution_role_arn = "${aws_iam_role.ecs_execution_role.arn}"
task_role_arn = "${aws_iam_role.ecs_execution_role.arn}"
container_definitions = <<DEFINITION
[
{
"image": "xxxxxx.dkr.ecr.us-east-2.amazonaws.com/org/prod/www-nginx:latest",
"memory": 300,
"name": "nginx-...-prod-www",
"networkMode": "awsvpc",
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/xx-ecs-...-prod/nginx",
"awslogs-region": "us-east-2",
"awslogs-stream-prefix": "web"
}
}
}
]
DEFINITION
}
resource "aws_cloudwatch_log_group" "nginx" {
name = "/ecs-${var.app}/nginx"
}
resource "aws_ecs_service" "web" {
name = "nginx-${var.app}"
task_definition = "${aws_ecs_task_definition.nginx.family}:${max("${aws_ecs_task_definition.nginx.revision}", "${aws_ecs_task_definition.nginx.revision}")}"
desired_count = 2
launch_type = "FARGATE"
cluster = "${aws_ecs_cluster.cluster.id}"
network_configuration {
subnets = [aws_subnet.demo-private-1.id, aws_subnet.demo-private-2.id, aws_subnet.demo-private-3.id]
security_groups = [aws_security_group.lb_sg.id]
}
load_balancer {
target_group_arn = aws_alb_target_group.nginx.id
container_name = "nginx-${var.app}"
container_port = "80"
}
depends_on = ["aws_alb_target_group.nginx", "aws_iam_role_policy.ecs_service_role_policy"]
}
resource "aws_alb_target_group" "nginx" {
name = "nginx-${var.app}"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.demo-tf.id
depends_on = [aws_alb.demo_eu_alb]
target_type = "ip"
stickiness {
type = "lb_cookie"
cookie_duration = 86400
}
health_check {
# path = "/health"
path = "/"
healthy_threshold = 2
unhealthy_threshold = 10 # 2 # 10
timeout = 60 # 5 # 60
interval = 300 # 8 # 300
matcher = "200,301,302"
}
}
resource "aws_alb" "demo_eu_alb" {
name = "eu-alb-${var.app}"
subnets = [aws_subnet.demo-private-1.id, aws_subnet.demo-private-2.id, aws_subnet.demo-private-3.id]
security_groups = [aws_security_group.lb_sg.id]
enable_http2 = "true"
idle_timeout = 600
}
output "alb_output" {
value = aws_alb.demo_eu_alb.dns_name
}
resource "aws_security_group" "lb_sg" {
description = "controls access to the application ELB"
vpc_id = aws_vpc.demo-tf.id
name = "ELB-${var.app}"
ingress {
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [
"0.0.0.0/0",
]
}
}
resource "aws_alb_listener" "front_end" {
load_balancer_arn = aws_alb.demo_eu_alb.id
port = "80"
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
resource "aws_alb_listener" "alb_front_https" {
load_balancer_arn = "${aws_alb.demo_eu_alb.arn}"
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
certificate_arn = "${aws_iam_server_certificate.lb_cert.arn}"
default_action {
target_group_arn = "${aws_alb_target_group.nginx.arn}"
type = "forward"
}
}
resource "aws_iam_server_certificate" "lb_cert" {
name = "lb_cert-${var.app}"
certificate_body = "${file("./www.____.com/cert.pem")}"
private_key = "${file("./www.____.com/privkey.pem")}"
certificate_chain = "${file("./www.____.com/chain.pem")}"
}
resource "aws_iam_role" "ecs_execution_role" {
name = "ecs_task_execution_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_policy" "ecs_permissions" {
name = "my_ecs_permissions"
description = "Permissions to enable CT"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"ecs:CreateCluster",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:Submit*",
"ecs:StartTask",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "ecs_attachment" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = aws_iam_policy.ecs_permissions.arn
}
### VPC
### Network
# Internet VPC
resource "aws_vpc" "demo-tf" {
cidr_block = "172.21.0.0/16"
instance_tenancy = "default"
enable_dns_support = "true"
enable_dns_hostnames = "true"
enable_classiclink = "false"
tags = {
Name = "vpc-${var.app}"
}
}
# Subnets
resource "aws_subnet" "demo-public-1" {
vpc_id = aws_vpc.demo-tf.id
cidr_block = "172.21.10.0/24"
map_public_ip_on_launch = "true"
availability_zone = "us-east-2a"
tags = {
Name = "public-1-${var.app}"
}
}
resource "aws_subnet" "demo-public-2" {
vpc_id = aws_vpc.demo-tf.id
cidr_block = "172.21.20.0/24"
map_public_ip_on_launch = "true"
availability_zone = "us-east-2b"
tags = {
Name = "public-2-${var.app}"
}
}
resource "aws_subnet" "demo-public-3" {
vpc_id = aws_vpc.demo-tf.id
cidr_block = "172.21.30.0/24"
map_public_ip_on_launch = "true"
availability_zone = "us-east-2c"
tags = {
Name = "public-3-${var.app}"
}
}
resource "aws_subnet" "demo-private-1" {
vpc_id = aws_vpc.demo-tf.id
cidr_block = "172.21.40.0/24"
map_public_ip_on_launch = "false"
availability_zone = "us-east-2a"
tags = {
Name = "private-1-${var.app}"
}
}
resource "aws_subnet" "demo-private-2" {
vpc_id = aws_vpc.demo-tf.id
cidr_block = "172.21.50.0/24"
map_public_ip_on_launch = "false"
availability_zone = "us-east-2b"
tags = {
Name = "private-2-${var.app}"
}
}
resource "aws_subnet" "demo-private-3" {
vpc_id = aws_vpc.demo-tf.id
cidr_block = "172.21.60.0/24"
map_public_ip_on_launch = "false"
availability_zone = "us-east-2c"
tags = {
Name = "private-3-${var.app}"
}
}
# Internet GW
resource "aws_internet_gateway" "demo-gw" {
vpc_id = aws_vpc.demo-tf.id
tags = {
Name = "IG-${var.app}"
}
}
# route tables
resource "aws_route_table" "demo-private" {
vpc_id = aws_vpc.demo-tf.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.demo-gw.id
}
tags = {
Name = "private-1-${var.app}"
}
}
# route tables
resource "aws_route_table" "demo-public" {
vpc_id = aws_vpc.demo-tf.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.demo-gw.id
}
tags = {
Name = "public-1-${var.app}"
}
}
# route associations public
resource "aws_route_table_association" "demo-public-1-a" {
subnet_id = aws_subnet.demo-public-1.id
route_table_id = aws_route_table.demo-public.id
}
resource "aws_route_table_association" "demo-public-2-a" {
subnet_id = aws_subnet.demo-public-2.id
route_table_id = aws_route_table.demo-public.id
}
resource "aws_route_table_association" "demo-public-3-a" {
subnet_id = aws_subnet.demo-public-3.id
route_table_id = aws_route_table.demo-public.id
}
# route associations private
resource "aws_route_table_association" "demo-private-1-a" {
subnet_id = aws_subnet.demo-private-1.id
route_table_id = aws_route_table.demo-private.id
}
resource "aws_route_table_association" "demo-private-2-a" {
subnet_id = aws_subnet.demo-private-2.id
route_table_id = aws_route_table.demo-private.id
}
resource "aws_route_table_association" "demo-private-3-a" {
subnet_id = aws_subnet.demo-private-3.id
route_table_id = aws_route_table.demo-private.id
}
最佳答案
可能的原因是无法访问互联网以执行您在 Fargate 中的任务。
具体来说,您在 aws_ecs_service
中使用:
network_configuration {
subnets = [aws_subnet.demo-private-1.id, aws_subnet.demo-private-2.id, aws_subnet.demo-private-3.id]
security_groups = [aws_security_group.lb_sg.id]
}
但是,它没有指定 assign_public_ip ,默认情况下为 false
。随后,您在 Fargate 上的任务没有公共(public) ip 并且无法访问 ECR 服务,导致观察到超时。
请注意,即使您添加了公共(public) ip,也可能有其他原因与您的 vpc 或其他设置相关,我尚未验证。
关于amazon-web-services - aws 地形错误 CannotPullContainerError : Error response from daemon - but the image url is valid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63087002/