Skip to content
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.

Related Articles

Moving at the Speed of Cryptocurrency with Infrastructure as Code

Read more

Automating API Information Storage with AWS - Introduction

Read more

AWS EKS Identity is Not Mapped Error

Read more

Contact Us

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

Contact Us