EKS AI Langchain - Part 1 Setting Up the Landing Zone for EKS

EKS AI Langchain - Part 1 Setting Up the Landing Zone for EKS

Before deploying our super cool infrastructure, setting up a landing zone is essential. A landing zone is a foundational infrastructure setup that includes networking, security, and essential services required for a secure and scalable environment. In this article, I'll guide you through setting up a landing zone for your EKS cluster using Terraform.

Clone the repo here.

Prerequisites

Ensure you have the following tools installed and configured:

  • Terraform installed.
  • AWS CLI installed and configured with necessary permissions (BlueSentry cross-account role).

Step 1: Define Variables

First, create a terraform.tfvars file with the necessary variables:

company = ""

domain = ""

openvpn_instance_type = ""

region = ""        

Step 2: Create VPC Configuration

Create a vpc.tf file to define the Virtual Private Cloud (VPC), subnets, and related networking components:

data "aws_availability_zones" "main" {}

locals {
  availability_zones = [
    data.aws_availability_zones.main.names[0],
    data.aws_availability_zones.main.names[1],
    data.aws_availability_zones.main.names[2],
  ]

  public_subnets = [
    cidrsubnet(var.vpc_cidr, 6, 0),
    cidrsubnet(var.vpc_cidr, 6, 1),
    cidrsubnet(var.vpc_cidr, 6, 2),
  ]

  private_subnets = [
    cidrsubnet(var.vpc_cidr, 6, 4),
    cidrsubnet(var.vpc_cidr, 6, 5),
    cidrsubnet(var.vpc_cidr, 6, 6),
  ]

  database_subnets = [
    cidrsubnet(var.vpc_cidr, 6, 7),
    cidrsubnet(var.vpc_cidr, 6, 8),
    cidrsubnet(var.vpc_cidr, 6, 9),
  ]

  vpc_route_tables = flatten([
    module.vpc.private_route_table_ids,
    module.vpc.public_route_table_ids,
  ])

}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.8.1"

  azs                                             = local.availability_zones
  cidr                                            = var.vpc_cidr
  create_database_subnet_group                    = true
  create_flow_log_cloudwatch_iam_role             = true
  create_flow_log_cloudwatch_log_group            = true
  database_subnets                                = local.database_subnets
  enable_dhcp_options                             = true
  enable_dns_hostnames                            = true
  enable_dns_support                              = true
  enable_flow_log                                 = true
  enable_nat_gateway                              = true
  flow_log_cloudwatch_log_group_retention_in_days = 7
  flow_log_max_aggregation_interval               = 60
  name                                            = var.environment
  one_nat_gateway_per_az                          = var.vpc_redundancy ? true : false
  private_subnet_suffix                           = "private"
  private_subnets                                 = local.private_subnets
  public_subnets                                  = local.public_subnets

  public_subnet_tags = {
    "kubernetes.io/cluster/${module.eks.cluster_name}" = "shared"
    "kubernetes.io/role/elb"                           = 1
  }

  single_nat_gateway = var.vpc_redundancy ? false : true
  tags               = local.tags
}

module "vpc_endpoints" {
  source  = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints"
  version = "~> 5.8.1"

  vpc_id = module.vpc.vpc_id
  tags   = local.tags

  endpoints = {
    s3 = {
      route_table_ids = local.vpc_route_tables
      service         = "s3"
      service_type    = "Gateway"
      tags            = { Name = "s3-vpc-endpoint" }
    }
  }
}        

Step 3: OpenVPN

Create a openvpn.tf file for security groups and roles and EC2:

data "aws_ami" "openvpnas" {
  most_recent = true

  filter {
    name = "name"

    values = [
      "OpenVPN Access Server Community Image-fe8020db-5343-4c43-9e65-5ed4a825c931*"
    ]
  }

  owners = [
    "679593333241",
  ]

  include_deprecated = true
}

data "aws_iam_policy_document" "ec2_role" {
  statement {
    effect = "Allow"
    principals {
      identifiers = ["ec2.amazonaws.com"]
      type        = "Service"
    }
    actions = ["sts:AssumeRole"]
  }
}

data "aws_iam_policy" "AmazonSSMManagedInstanceCore" {
  name = "AmazonSSMManagedInstanceCore"
}

data "aws_route53_zone" "this" {
  name = var.domain
}

locals {
  openvpn_name = "openvpn"
}

resource "aws_eip" "vpn" {
  tags = merge(var.tags, { Name = "openvpn" })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_eip_association" "eip_vpn" {
  instance_id   = aws_instance.openvpn.id
  allocation_id = aws_eip.vpn.id
}

resource "aws_iam_instance_profile" "this" {
  name = "${var.company}_ec2_role"
  role = aws_iam_role.ec2_role.name

  tags = var.tags
}

resource "aws_iam_role" "ec2_role" {
  name = "${var.company}_ec2_role"

  assume_role_policy = data.aws_iam_policy_document.ec2_role.json

  tags = var.tags
}

resource "aws_iam_role_policy_attachment" "AmazonSSMManagedInstanceCore" {
  role       = aws_iam_role.ec2_role.name
  policy_arn = data.aws_iam_policy.AmazonSSMManagedInstanceCore.arn
}

resource "aws_instance" "openvpn" {
  ami = data.aws_ami.openvpnas.id

  disable_api_termination = true
  ebs_optimized           = true
  iam_instance_profile    = aws_iam_instance_profile.this.name
  instance_type           = var.openvpn_instance_type
  key_name                = module.dev.ssh_keypair
  monitoring              = true
  subnet_id               = module.dev.public_subnets[0]
  vpc_security_group_ids  = [aws_security_group.openvpn.id]

  metadata_options {
    http_endpoint               = "enabled"
    http_put_response_hop_limit = 3
    http_tokens                 = "required"
  }

  tags = merge(var.tags, {
    "Name"        = local.openvpn_name
    "Patch Group" = "A"
    "backup"      = "true"
  })

  volume_tags = merge(var.tags, {
    "Name"   = "${local.openvpn_name}_vol"
    "backup" = "true"
  })

  root_block_device {
    encrypted   = true
    volume_type = "gp3"
  }

  lifecycle {
    ignore_changes = [user_data, ami]
  }
}

resource "aws_route53_record" "vpn" {
  zone_id = data.aws_route53_zone.this.zone_id
  name    = "vpn"
  type    = "A"
  ttl     = "300"
  records = [aws_eip.vpn.public_ip]
}

resource "aws_security_group" "openvpn" {
  name        = local.openvpn_name
  vpc_id      = module.dev.vpc_id
  description = "OpenVPN security group"
  tags        = merge(var.tags, { Name = "${local.openvpn_name}-sg" })
}

resource "aws_security_group_rule" "egress_all" {
  type        = "egress"
  protocol    = -1
  from_port   = 0
  to_port     = 0
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = aws_security_group.openvpn.id
}

resource "aws_security_group_rule" "ingress_tcp443" {
  type        = "ingress"
  protocol    = "tcp"
  from_port   = 443
  to_port     = 443
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = aws_security_group.openvpn.id
}

resource "aws_security_group_rule" "ingress_tcp80" {
  type        = "ingress"
  protocol    = "tcp"
  from_port   = 80
  to_port     = 80
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = aws_security_group.openvpn.id
}

resource "aws_security_group_rule" "ingress_udp1194" {
  type        = "ingress"
  protocol    = "udp"
  from_port   = 1194
  to_port     = 1194
  cidr_blocks = ["0.0.0.0/0"]

  security_group_id = aws_security_group.openvpn.id
}        

Step 4: S3 Buckets for State Management

Create a backend file to define S3 buckets for storing Terraform state files:

terraform {
  backend "s3" {
    bucket = <BUCKET_NAME>
    key    = "infra/terraform.tfstate"
    region = "us-east-1"
  }
}        

Step 5: Initialize and Apply Terraform

Initialize Terraform and apply the configuration:

terraform init
terraform validate
terraform plan -out=plan.out
terraform apply plan.out        

You've successfully set up a landing zone for your EKS cluster. This foundational setup includes networking components, security configurations, and essential services, providing a secure and scalable environment for deploying your EKS cluster.

Visit my website here.

要查看或添加评论,请登录

Todd Bernson的更多文章

社区洞察

其他会员也浏览了