brikis98 / terraform-up-and-running-code

Code samples for the book "Terraform: Up & Running" by Yevgeniy Brikman
http://www.terraformupandrunning.com/
MIT License
2.87k stars 1.92k forks source link

Second example (source code) for web site with load balancer missing vars #22

Closed symgryph closed 4 years ago

symgryph commented 6 years ago

The source code is missing the web servers var. I added it and it fixed the code. Book is missing vars as well

brikis98 commented 6 years ago

Could you link to which example you mean? And which vars are missing?

rtjohn commented 5 years ago

I think @symgryph might be mentioning the same problem I'm seeing. I'm in Chapter 2 and applied my main.tf file. Everything builds and deploys but going to the elb_dns_name like so:

curl http://terraform-asg-example-1234567.us-east-1.elb.amazonaws.com

does nothing.

rtjohn commented 5 years ago

I think there is something missing in this part of the file:

resource "aws_launch_configuration" "example" {
  image_id = "ami-40d28157"
  instance_type = "t1.micro"
  security_groups = ["${aws_security_group.instance.id}"]

  user_data = <<-EOF
    #!/bin/bash
    echo "Hello, World" > index.html
    nohup busybox httpd -f -p "${var.server_port}" &
    EOF

  lifecycle {
    create_before_destroy = true
  }
}
tln8679 commented 5 years ago

I initially had the same issue. I changed this line in the ASG resource and now it works for me "load_balancers = ["${aws_elb.my_load_balancer.id}"]" (change name to id)

rtjohn commented 5 years ago

@tln8679

I initially had the same issue. I changed this line in the ASG resource and now it works for me "load_balancers = ["${aws_elb.my_load_balancer.id}"]" (change name to id)

Thanks for the advice. However, this did not fix my problem. I still get no response from

curl http://terraform-asg-example-1234567.us-east-1.elb.amazonaws.com

However, I did finally realize what @symgryph is referring to. @brikis98 He is referring to the fact that the code for this chapter is missing the following:

variable "server_port" {
  description = "The port the server will use for HTTP requests"
  default = 8080
}

You had us add that on page 47 of the book I have, but it is missing from the code example in the repo.

rtjohn commented 5 years ago

Upon closer examination, it appears @brikis98 writes the variables as separate tf files. Is this standard practice?

tln8679 commented 5 years ago

Upon closer examination, it appears @brikis98 writes the variables as separate tf files. Is this standard practice?

This is what hashicorp has to say: https://www.terraform.io/intro/getting-started/variables.html

You can create input variables via 1) command-line flags, 2) from a file (best for persistent values), 3) environment variables, 4) will ask you to input at runtime if you haven't specified a needed value or 4) Defaults

Seems like from a file promotes the idea of information hiding. From Wikipedia "In computer science, information hiding is the principle of segregation of the design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed."

brikis98 commented 5 years ago

Standard file naming convention for Terraform:

Makes it easy to see what parameters a module takes as input and what parameters it returns as outputs by looking in a single, obvious file.

davidATsains commented 4 years ago

I think @symgryph might be mentioning the same problem I'm seeing. I'm in Chapter 2 and applied my main.tf file. Everything builds and deploys but going to the elb_dns_name like so:

curl http://terraform-asg-example-1234567.us-east-1.elb.amazonaws.com

does nothing.

I have looked at the docs for launch_configuration but i do not see where i am suppose to enter the variable for server port https://www.terraform.io/docs/providers/aws/r/launch_configuration.html

i would like to know if you solved this problem and how as I am having the same problem as you.

davidATsains commented 4 years ago

when i curl the dns-name i get nothing. I noticed in AWS management console, the target group and the load balancer do not show up. Is this why I cannot curl the dns_name?

brikis98 commented 4 years ago

I'm not entirely following what you're struggling with. What example are you running? Could you link to it in this repo?

davidATsains commented 4 years ago

I'm not entirely following what you're struggling with. What example are you running? Could you link to it in this repo?

The part i am referring to is chapter 2 section: Deploying a load balancer you said that you can test alb the alb_dns_name output you copied earlier: $ curl http:// Hello, World

my code is below. the problem i have is that it does not display anything
Please tell me where am i going wrong?


provider "aws" {
  version = "~>2.0"
  region  = "eu-west-1"

}

resource "aws_launch_configuration" "example" {
  image_id        = "ami-02df9ea15c1778c9c"
  instance_type   = "t2.micro"
  security_groups = [aws_security_group.instance.id]
  user_data       = <<-EOF
              #!/bin/bash
              echo "Hello, David. How is work today" > index.html
              nohup busybox httpd -f -p 
  ${var.server_port} &
              EOF
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_group" "example" {
  launch_configuration = aws_launch_configuration.example.name
  vpc_zone_identifier  = data.aws_subnet_ids.default.ids
  target_group_arns    = [aws_lb_target_group.asg.arn]
  health_check_type    = "ELB"
  min_size             = 2
  max_size             = 10
  tag {
    key                 = "Name"
    value               = "terraform-asg-example"
    propagate_at_launch = true
  }
}

data "aws_vpc" "default" {
  default = true
}

data "aws_subnet_ids" "default" {
  vpc_id = data.aws_vpc.default.id
}

resource "aws_security_group" "instance" {
  name = var.security_group_name

  ingress {
    from_port   = var.server_port
    to_port     = var.server_port
    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"]
  }
}

variable "security_group_name" {
  description = "The name of the security group"
  default     = "terraform-example-instance"
}

variable "server_port" {
  description = "The port the server will use for HTTP requests"
  type        = number
  default     = 8080
}

resource "aws_lb" "example" {
  name               = "terraform-asg-example"
  load_balancer_type = "application"
  subnets            = data.aws_subnet_ids.default.ids
  security_groups    = [aws_security_group.instance.id]
}

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.example.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "404 : page not found"
      status_code  = 404
    }
  }
}

resource "aws_lb_target_group" "asg" {
  name     = "terrafor-asg-example"
  port     = var.server_port
  protocol = "HTTP"
  vpc_id   = data.aws_vpc.default.id

  tags = {
    name = "terraform-test"
  }

  health_check {
    path                = "/"
    protocol            = "HTTP"
    matcher             = "200"
    interval            = 15
    timeout             = 3
    healthy_threshold   = 2
    unhealthy_threshold = 2
  }
}

resource "aws_lb_listener_rule" "asg" {
  listener_arn = aws_lb_listener.http.arn
  priority     = 100

  condition {
    field  = "path-pattern"
    values = ["*"]
  }

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.asg.arn
  }
}

output "alb_dns_name" {
  value = aws_lb.example.dns_name
  description = "the name of the load balancer"
}
brikis98 commented 4 years ago

The general answer is to go through and systematically debug the network stack to see where the request is failing. I wrote up some sample, step-by-step instructions here.

However, as I can see your code, I think the issue is here:

resource "aws_lb" "example" {
  name               = "terraform-asg-example"
  load_balancer_type = "application"
  subnets            = data.aws_subnet_ids.default.ids
  security_groups    = [aws_security_group.instance.id]
}

It looks like you're using the same security group for your ELB as your instances. This is not quite right!

The security group for the instances allows inbound requests on var.server_port, which is port 8080:

resource "aws_security_group" "instance" {
  name = var.security_group_name

  ingress {
    from_port   = var.server_port
    to_port     = var.server_port
    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"]
  }
}

To be able to test your ELB at port 80, you need to open that port. That's why the book tells you to create a separate security group for the ELB that opens port 80.

davidATsains commented 4 years ago

The general answer is to go through and systematically debug the network stack to see where the request is failing. I wrote up some sample, step-by-step instructions here.

However, as I can see your code, I think the issue is here:

resource "aws_lb" "example" {
  name               = "terraform-asg-example"
  load_balancer_type = "application"
  subnets            = data.aws_subnet_ids.default.ids
  security_groups    = [aws_security_group.instance.id]
}

It looks like you're using the same security group for your ELB as your instances. This is not quite right!

The security group for the instances allows inbound requests on var.server_port, which is port 8080:

resource "aws_security_group" "instance" {
  name = var.security_group_name

  ingress {
    from_port   = var.server_port
    to_port     = var.server_port
    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"]
  }
}

To be able to test your ELB at port 80, you need to open that port. That's why the book tells you to create a separate security group for the ELB that opens port 80.

thank you i used your approach to systematically debug it. I managed to get it to work.

brikis98 commented 4 years ago

Looks like this issue was resolved, so closing.