Merge branch 'feature/alpha-cluster-sample'

This commit is contained in:
shockrah 2023-01-09 17:05:56 -08:00
commit d71c4780d9
13 changed files with 366 additions and 77 deletions

View File

@ -2,19 +2,16 @@
# Essentially it is a cluster with services that we
# choose to expose to the internet in one form or another
# Logging Configuration for services inside the cluster
#######################################################
resource "aws_cloudwatch_log_group" "alpha" {
name = "alpha-log"
}
# Alpha cluster definition
###########################
resource "aws_ecs_cluster" "alpha" {
name = "alpha"
name = "${var.athens_prefix}-athens-alpha"
configuration {
execute_command_configuration {
logging = "OVERRIDE"
log_configuration {
cloud_watch_log_group_name = aws_cloudwatch_log_group.alpha.name
}
@ -23,38 +20,70 @@ resource "aws_ecs_cluster" "alpha" {
}
# Lewdlad Service Definition
############################
resource "aws_ecs_task_definition" "lewdlad" {
family = "lewdlad-task-definition"
# Lewdlad Task Definition
# This is what the service will launch to actually provide the lewdlad service
##############################################################################
resource "aws_ecs_task_definition" "sample" {
family = "${var.athens_prefix}-sample"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
execution_role_arn = aws_iam_role.alpha_iam_role.arn
cpu = 256
memory = 512
container_definitions = jsonencode([
{
name = "lewdlad-container"
image = "registry.gitlab.com/shockrah/left-coast-server-bot:latest"
# Literally the smallest amount that fargate will allow
name = "${var.athens_prefix}-sample-container"
image = "nginx"
cpu = 256
memory = 512
essential = true
environment = [
{ name: DISCORD_ID, value: var.DISCORD_ID },
{ name: DISCORD_TOKEN, value: var.DISCORD_TOKEN },
{ name: AWS_API_ID, value: var.AWS_API_ID },
{ name: AWS_API_STAGE, value: var.AWS_API_STAGE },
{ name: AWS_API_REGION, value: var.AWS_API_REGION },
{ name: AWS_API_KEY, value: var.AWS_API_KEY },
{ name: DEV_GUILD_ID, value: var.DEV_GUILD_ID },
{ name: BEEHIVE_ID, value: var.BEEHIVE_ID },
portMappings = [
{
containerPort = 80
hostPort = 80
}
]
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.alpha.name
awslogs-region = "us-west-1"
awslogs-stream-prefix = "sample-container"
}
}
}
])
tags = {
Name = "${var.athens_prefix}-sample-task-def-container"
}
}
resource "aws_ecs_service" "lewdlad" {
name = "lewdlad"
cluster = aws_ecs_cluster.alpha.arn
task_definition = aws_ecs_task_definition.lewdlad.arn
# Service level definition
##########################
resource "aws_ecs_service" "sample" {
name = "${var.athens_prefix}-sample-service"
cluster = aws_ecs_cluster.alpha.id
task_definition = aws_ecs_task_definition.sample.arn
desired_count = 1
launch_type = "FARGATE"
load_balancer {
target_group_arn = aws_lb_target_group.alpha_cluster.arn
container_name = "${var.athens_prefix}-sample-container"
container_port = 80
}
network_configuration {
assign_public_ip = true
subnets = [
aws_subnet.delphi.id,
aws_subnet.crete_subnet.id
]
security_groups = [
aws_security_group.ecs_web_ingress.id,
aws_security_group.base_ecs.id
]
}
}

View File

@ -1,3 +1,6 @@
# NOTE: this will no longer be used and is getting removed once we seutp the
# new alpha cluster correctly
# This is the continuation of the old alpha host but with much cleaner code
# and less manual infra setup involved. Key differences are that block storage
# is now completely kept in this module instead of yolo'd out like before.
@ -29,38 +32,3 @@ resource "aws_ebs_volume" "clips-shockrah-xyz" {
Description = "Used for the clippable instance"
}
}
######################### ATTACHMENT FOR files.leftcoast.space #################
resource "aws_volume_attachment" "files-leftcoast-space" {
device_name = "/dev/sdf"
volume_id = aws_ebs_volume.files-leftcoast-space.id
instance_id = aws_instance.atlas.id
}
######################### ATTACHMENT FOR clips.shockrah.xyz ####################
resource "aws_volume_attachment" "clips-shockrah-xyz" {
device_name = "/dev/sdg"
volume_id = aws_ebs_volume.clips-shockrah-xyz.id
instance_id = aws_instance.atlas.id
}
######################### INSTANCE CONFIGURATION ###############################
resource "aws_instance" "atlas" {
ami = var.atlas_ami_id
instance_type = var.atlas_instance_type
key_name = var.atlas_ssh_key_name
private_ip = "10.0.1.20"
vpc_security_group_ids = [
aws_security_group.general_web_req.id,
aws_security_group.remote_ssh_rec.id
]
subnet_id = aws_subnet.crete_subnet.id
tags = {
Name = "Atlas Host"
Description = "Simple Docker host for some personal stuff"
}
}

15
infra/cert.tf Normal file
View File

@ -0,0 +1,15 @@
# Here is the TLS cert that we create for the alpha cluster
resource "aws_acm_certificate" "sample" {
domain_name = "*.project-athens.xyz"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
resource "aws_acm_certificate_validation" "sample" {
certificate_arn = aws_acm_certificate.sample.arn
validation_record_fqdns = [ aws_route53_record.project-athens-record["2"].fqdn ]
}

28
infra/cluster-logging.tf Normal file
View File

@ -0,0 +1,28 @@
# Logging Configuration for services inside the cluster
#######################################################
# Alpha Cloudwatch logging configuration
########################################
resource "aws_cloudwatch_log_group" "alpha" {
name = "${var.athens_prefix}-alpha-log"
retention_in_days = 7
}
# Alpha logging role
#####################
resource "aws_iam_role" "alpha_iam_role" {
name = "${var.athens_prefix}-alpha-iam-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Principal = {
Service = [ "ecs-tasks.amazonaws.com" ]
}
Effect = "Allow"
}
]
})
}

View File

@ -1,12 +1,3 @@
resource "aws_eip" "alpha_eip" {
instance = aws_instance.alpha.id
vpc = true
tags = {
Name = "Alpha EIP"
}
}
resource "aws_eip" "beta_eip" {
vpc = true
instance = aws_instance.beta.id

View File

@ -103,3 +103,11 @@ variable "athens_cidr" {
description = "VPC Subnet CIDR block"
type = string
}
######################### Alpha Cluster variables
variable "athens_prefix" {
description = "Prefix for all things in alpha cluster"
type = string
default = "athens"
}

43
infra/load-balancer.tf Normal file
View File

@ -0,0 +1,43 @@
# Here is the application load balancer that we use for services hosted on ECS
##############################################################################
# The LB that we'll use to move traffic into our services
#########################################################
resource "aws_lb" "alpha" {
name = "alpha-lb"
internal = false
load_balancer_type = "application"
subnets = [ aws_subnet.delphi.id, aws_subnet.crete_subnet.id ]
security_groups = [
aws_security_group.ecs_web_ingress.id,
aws_security_group.load_balancer_health_check.id
]
# TODO: change this to true later
enable_deletion_protection = false
}
## ECS services manage themselves when it comes to registering to the
## target group so we only need to provide the pool
#####################################################################
resource "aws_lb_target_group" "alpha_cluster" {
name = "${var.athens_prefix}-alpha-cluster"
port = 80
protocol = "HTTP"
target_type = "ip"
vpc_id = aws_vpc.athens_vpc.id
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.alpha.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = aws_acm_certificate_validation.sample.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.alpha_cluster.arn
}
}

24
infra/roles.tf Normal file
View File

@ -0,0 +1,24 @@
resource "aws_iam_policy" "alpha_iam_policy" {
name = "${var.athens_prefix}-alpha-iam-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
]
"Resource" = "*"
}
]
})
}
resource "aws_iam_role_policy_attachment" "alpha_logs" {
role = aws_iam_role.alpha_iam_role.name
policy_arn = aws_iam_policy.alpha_iam_policy.arn
}

View File

@ -10,7 +10,14 @@ resource "aws_route_table" "crete_route_table" {
Name = "Crete IGW Route Table"
}
}
resource "aws_route_table_association" "crete_gateway_association" {
subnet_id = aws_subnet.crete_subnet.id
route_table_id = aws_route_table.crete_route_table.id
}
resource "aws_route_table_association" "delphi_gateway_association" {
subnet_id = aws_subnet.delphi.id
route_table_id = aws_route_table.crete_route_table.id
}

View File

@ -0,0 +1,59 @@
#############################
# project-athens.xyz DNS ZONE
#############################
# This entry is just for the sample service that is just plain nginx
# No TLS will be placed on this just yet as we need to make sure this
# and the load balancer are setup to receive things properly
resource "aws_route53_zone" "project-athens" {
name = "project-athens.xyz"
comment = "Project Athens domain zone"
}
locals {
project-athens-records = [
{
name = "project-athens.xyz"
type = "NS"
ttl = 172800
records = [
"ns-806.awsdns-36.net.",
"ns-1881.awsdns-43.co.uk.",
"ns-1109.awsdns-10.org.",
"ns-11.awsdns-01.com.",
]
},
{
name = "project-athens.xyz"
type = "SOA"
ttl = 900
records = [
"ns-806.awsdns-36.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"
]
},
{
name = tolist(aws_acm_certificate.sample.domain_validation_options)[0].resource_record_name
type = tolist(aws_acm_certificate.sample.domain_validation_options)[0].resource_record_type
records = [ tolist(aws_acm_certificate.sample.domain_validation_options)[0].resource_record_value ]
},
{
name = "sample.project-athens.xyz"
type = "CNAME"
records = [ aws_lb.alpha.dns_name ]
}
]
}
resource "aws_route53_record" "project-athens-record" {
for_each = {
for index, record in local.project-athens-records:
index => record
}
zone_id = aws_route53_zone.project-athens.id
name = each.value.name
type = lookup(each.value, "type", "A")
ttl = lookup(each.value, "ttl", 300)
records = each.value.records
}

View File

@ -0,0 +1,56 @@
#############################
# shockrah.xyz DNS ZONE
#############################
resource "aws_route53_zone" "shockrah-xyz" {
name = "shockrah.xyz"
comment = "Main shockrah.xyz zone - for personal stuff"
}
locals {
records = [
{
name = "shockrah.xyz"
type = "NS"
ttl = 172800
records = [
"ns-612.awsdns-12.net.",
"ns-285.awsdns-35.com.",
"ns-1702.awsdns-20.co.uk.",
"ns-1360.awsdns-42.org.",
]
},
{
name = "shockrah.xyz"
type = "SOA"
ttl = 900
records = [
"ns-612.awsdns-12.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"
]
},
{
name = "shockrah.xyz"
type = "TXT"
ttl = 300
records = [ "v=spf1 include:_mailcust.gandi.net ?all" ]
},
{ name = "shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] },
{ name = "freechat.shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] },
{ name = "resume.shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] },
{ name = "www.shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] },
]
}
resource "aws_route53_record" "shockrah-xyz-record" {
for_each = {
for index, record in local.records:
index => record
}
zone_id = aws_route53_zone.shockrah-xyz.id
name = each.value.name
type = lookup(each.value, "type", "A")
ttl = lookup(each.value, "ttl", 300)
records = each.value.records
}

View File

@ -1,5 +1,56 @@
# Here are general definitions for security rulesets
resource "aws_security_group" "ecs_web_ingress" {
name = "Alpha-Web-Ingress"
description = "Allow web traffic into the host"
vpc_id = aws_vpc.athens_vpc.id
ingress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
protocol = "tcp"
}
ingress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
protocol = "tcp"
}
}
resource "aws_security_group" "base_ecs" {
vpc_id = aws_vpc.athens_vpc.id
egress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
to_port = 80
protocol = "tcp"
}
egress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 443
to_port = 443
protocol = "tcp"
}
egress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 2049
to_port = 2049
protocol = "tcp"
}
}
resource "aws_security_group" "load_balancer_health_check" {
name = "Load Balancer Health check"
vpc_id = aws_vpc.athens_vpc.id
egress {
cidr_blocks = ["10.0.0.0/8"]
from_port = 80
to_port = 80
protocol = "tcp"
}
}
resource "aws_security_group" "general_web_req" {
name = "Athens General web server ruleset"
description = "Allowing strictly web traffic"

View File

@ -1,6 +1,5 @@
# This script represents the subnet structure for Crete(primary subnet)
# Crete will serve as the private subnet with internal services
resource "aws_subnet" "crete_subnet" {
vpc_id = aws_vpc.athens_vpc.id
# 10.0.1.0/24
@ -8,6 +7,17 @@ resource "aws_subnet" "crete_subnet" {
availability_zone = var.athens_availability_zone
tags = {
Name = "Crete Subnet - Internal"
Name = "Crete Subnet"
Description = "Main subnet for EC2 and Alpha-LB"
}
}
resource "aws_subnet" "delphi" {
vpc_id = aws_vpc.athens_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-west-1c"
tags = {
Name = "Delphi Subnet"
Description = "Secondary subnet for the Alpha-LB mostly"
}
}