스타트업에서 초기 환경을 구축하기 위해서 시도하는 과정이라 대규모 시스템을 구축하는 것과는 괴리가 있습니다.
0
에서 점진적으로 증가할 것을 가정하고 구축합니다. 추가적
으로 분리합니다. local
- AWS와 관련없는 환경이지만 k8s 로 추상화되어 유사하게 구현 dev
- 로컬 개발환경도 있긴하지만, EKS 환경하에서 개발 및 테스트를 위한 환경이 필요합니다. stage
- 실서버와 동일한 환경하에서의 배포전 검증등을 진행하는 환경 다만, 초반에는 optional
로 생각하고 생략할 예정prod
- 실서비스 환경 궁극적으로 고립되어 간섭이 없는 환경이어야 합니다. 운영자의 실수가 영향이 되지 않도록 권한까지 분리하면 더욱 더 좋습니다. (바램)위는 단일 서비스에서의 기본적인 고려사항입니다.
여기에 추가적으로 환경은 아니지만 infra를 관리하기 위한 영역이 필요합니다.
이 환경을 어떻게 isolation 할것인가?를 고민해봤는데, 현실적인 비용을 고려하면서 생각하다보니 생각의 흐름이 이런식이 되었습니다.
비용
시간
시간을 앞당길 수 있나
도 알아봤지만 Scale up을 할 수 있는 옵션은 없어서 시간 단축은 AWS가 힘써주지 않는한 없다고 봐야합니다. aws_nat_gateway.kts-eks-nat-gateway: Creation complete after 1m38s [id=nat-017806cdee17537ef]
위 두가지를 고려했을때 단일 EKS Cluster로 진행하고자 합니다.
그럼 환경은 어떻게 처리할 것일지 고민했습니다.
k8s의 namespace
를 기반으로 하기로 정리하였습니다.
거기에 추가적인 infra(eg. CI/CD 등)를 관리하기 위한 것도 모두 namespace 기반으로 분리할 예정입니다.
terraform {
required_version = ">= 0.12"
backend "s3" {
profile = "terraform"
bucket = "{{s3-bucket}}"
key = "base/terraform.tfstate"
region = "ap-northeast-2"
}
}
provider "aws" {
profile = var.profile
region = var.aws-region-seoul
}
data "aws_availability_zones" "available" {
all_availability_zones = true
}
region
: ap-northeast-2 seoul
availability zone
(az) : seoul
리전은 4개의 az를 가지고 있음S3
를 사용하기로 결정
terraform cloud
와S3
를 고민했으나, 또다른 risk point를 추가하는것은 지양하자고 생각해서S3
로 결정
EKS는 단일 VPC로 구성을 해야 해서 private IP 대역대에서 10.10.0.0/16
을 우선 사용하기로 정의하였습니다.
10.10.0.0
~10.10.255.255
즉,65,536
개의 IP를 사용할 수 있다.
# create VPC
resource "aws_vpc" "kts-eks-vpc" {
cidr_block = "10.10.0.0/16"
tags = {
"Name" = "kts-eks-node"
"kubernetes.io/cluster/${var.eks-cluster-name}" = "shared"
}
}
resource "aws_subnet" "kts-eks-public-subnet" {
count = length(data.aws_availability_zones.available.names)
availability_zone = element(data.aws_availability_zones.available.names, count.index)
cidr_block = "10.10.${var.subnet-cidr.public-index + (count.index * var.subnet-cidr.public-subnet-step)}.0/${var.subnet-size[var.subnet-cidr.public-subnet-step]}"
map_public_ip_on_launch = true
vpc_id = aws_vpc.kts-eks-vpc.id
tags = {
"Name" = "kts-eks-public-${count.index}"
"kubernetes.io/cluster/${var.eks-cluster-name}" = "shared"
}
}
# private subnet
resource "aws_subnet" "kts-eks-private-subnet" {
count = length(data.aws_availability_zones.available.names)
availability_zone = element(data.aws_availability_zones.available.names, count.index)
cidr_block = "10.10.${var.subnet-cidr.private-index + (count.index * var.subnet-cidr["private-subnet-step"])}.0/${var.subnet-size[var.subnet-cidr["private-subnet-step"]]}"
vpc_id = aws_vpc.kts-eks-vpc.id
tags = {
"Name" = "kts-eks-private-${count.index}"
"kubernetes.io/cluster/${var.eks-cluster-name}" = "shared"
}
}
# db subnet
resource "aws_subnet" "kts-eks-db-subnet" {
count = length(data.aws_availability_zones.available.names)
availability_zone = element(data.aws_availability_zones.available.names, count.index)
cidr_block = "10.10.${var.subnet-cidr.db-index + (count.index * var.subnet-cidr["db-subnet-step"])}.0/${var.subnet-size[var.subnet-cidr["db-subnet-step"]]}"
vpc_id = aws_vpc.kts-eks-vpc.id
tags = {
"Name" = "kts-eks-db-${count.index}"
"kubernetes.io/cluster/${var.eks-cluster-name}" = "shared"
}
}
variable "subnet-size" {
type = map
default = {
1 = "24"
2 = "23"
4 = "22"
8 = "21"
}
}
variable "subnet-cidr" {
type = map
default = {
# 0 부터 시작해서 1단위로 총 4개 - 0 + (1 * 4) = 4
"public-index" = 0
"public-subnet-step" = 1
# 4부터 시작해서 4단위로 총 4개 - 4 + (4 * 4) = 20
"private-index" = 4
"private-subnet-step" = 4
# 20부터 시작해서 1단위로 총 4개 - 20 + (1 * 4) = 24
"db-index" = 20
"db-subnet-step" = 1
}
}
exclude_names = ["ap-northeast-2b", "ap-northeast-2d"]
)을 이용해서 public/private 각 2개씩 az으로 나누려 했으나, 단일 EKS Cluster로 구성을 진행할 예정이라 4개의 az을 다 활용하는 구성으로 진행하는게 좋겠다고 생각했습니다. data "aws_availability_zones" "available" {
}
all_availability_zones = true
라는 설정도 있지만 이렇게 진행한다면 4개의 az 가 있음에도 0 ~ 4까지의 총 5개의 subnet을 생성하도록 시도하며 우리가 본적이 없는 0번때문에 실패합니다. "ap-northeast-2-wl1-cjj-wlz-1"
와 같은 zone을 설정하려 합니다.
EKS의 worker node의 경우 private subnet만을 사용하지만, EKS 클러스터는 public 및 private 을 둘다 사용하도록 설정을 해두어야 public ELB를 통해 내부망 통신으로 내부 worker node 들과 통신하는 형태를 구성할 수 있습니다.
db subnet은 RDS를 사용할 것이라 EKS subnet으로 지정하지는 않습니다.
resource "aws_internet_gateway" "kts-eks-igw" {
vpc_id = aws_vpc.kts-eks-vpc.id
tags = {
"Name" = "kts-eks-igw"
}
}
# create public route table
resource "aws_route_table" "kts-eks-public-route" {
vpc_id = aws_vpc.kts-eks-vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.kts-eks-igw.id
}
tags = {
"Name" = "kts-eks-public"
}
}
# create route table association
# subnet 과 route table을 연결
resource "aws_route_table_association" "kts-eks-public-routing" {
count = length(aws_subnet.kts-eks-public-subnet.*.id)
subnet_id = aws_subnet.kts-eks-public-subnet.*.id[count.index]
route_table_id = aws_route_table.kts-eks-public-route.id
}
# EIP 정의
resource "aws_eip" "kts-eks-eip" {
vpc = true
tags = {
"Name" = "kts-eks-public-nat-gw"
}
}
# NAT Gateway
resource "aws_nat_gateway" "kts-eks-nat-gateway" {
allocation_id = aws_eip.kts-eks-eip.id
subnet_id = data.terraform_remote_state.base.outputs.kts-eks-main-public-subnet-id
tags = {
"Name" = "kts-eks-nat-gw"
}
}
data "terraform_remote_state" "base" {
backend = "s3"
config = {
bucket = "{{s3-bucket}}"
key = "base/terraform.tfstate"
region = "ap-northeast-2"
}
}
output "kts-eks-main-public-subnet-id" {
value = aws_subnet.kts-eks-public-subnet[0].id
}
분리된 폴더에서 생성된 자원의 정보를 참조하기 위해선 S3 backend 같은 설정이 필요하고, output.tf 에서 어떤 설정을 어떤 변수이름으로 접근할지에 대해서 선언해주어야 하며, 이렇게 되어 있다면 data.terraform_remote_state.base.outputs.kts-eks-main-public-subnet-id
와 같이 설정을 통해서 접근이 가능하게 됩니다.
추가적으로 private, db의 route table 및 association (route table과 subnet을 연결해주는 설정)을 설정합니다.
이상으로 VPC 기본적인 네트워크 설정을 마쳤습니다.
다음에는 EKS 클러스터 및 Worker Node 설정을 진행해보겠습니다.