Skip to content
EKS AI Langchain - Part 1 Setting Up the Landing Zone for EKS
todd-bernson-leadership

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.

Related Articles

Inter-Region WireGuard VPN in AWS

Read more

Making PDFs Searchable Using AWS Textract and CloudSearch

Read more

Slack AI Bot with AWS Bedrock Part 2

Read more

Contact Us

Achieve a competitive advantage through BSC data analytics and cloud solutions.

Contact Us