Study

[스터디] Terraform module을 이용한 여러 EKS 배포

mokpolar 2022. 12. 10. 21:01
반응형

CloudNet팀에서 진행하고 있던 Terraform study T101이 끝날 시간이 다가왔다.

CloudNet팀의 스터디는 중간과 기말과제로 과제물을 만들어야 한다. 

요즘 일이 많다보니 생각보다 시간이 부족해서.... 평범하게 현재 업무에 직접적으로 연관된, 

Terraform module을 이용해 여러 EKS 으로 쉽게 배포하는 내용을 최종과제로 작성하기로 했다. 

 

사용하고 있는 Terraform의 기능들

Module

테라폼에서 모듈을 사용하면 기능 별로 테라폼 코드를 작성하고 이들을 재사용할 수 있다. 

조금만 바꿔서 dev1, dev2, stage1, stage2 이런식으로 동일하게 여러 EKS를 배포할 수 있는 것이다. 

이렇게 되면 동일한 코드를 여럿 작성할 필요가 없고 테라폼의 재사용성을 제대로 느낄 수 있는 것 같다. 

그리고 사실 폴더내에 있는 테라폼 관련 파일들은 모두 모듈이다.

 

아래처럼 모듈 이름과 위치를 작성하여서 모듈을 사용할 수 있다. 

module "eks" {
  source = "../../modules/eks"
  ..
}

 

여러 EKS 환경에서 이런 모듈 코드를 사용해서 동일한 모듈을 참조해서 사용할 수 있는 것이다. 

만약에 모듈을 변경하거나 위치가 변경된다면 항상 

terraform init

커맨드를 실행해서 모듈을 다시 불러와야 한다. 

 

Variables

모듈에 사용할 variables를 사용하여 하드코딩을 피할 수 있다. 

variable "region" {
  type        = string
  description = "aws region"
}

이런식으로 variable을 선언해두고 모듈 내에서 ${var.region} 과 같은 방법으로 variable을 사용할 수 있다. 

그리고 입력 변수를 사용하는 것이다. 

 

 

Locals

locals를 읽어서 다른 모듈에 영향을 미치지 않으면서 모듈 외부에서 해당 값을 재정의할 수 있다. 

 

예컨대 위의 region에 대해 locals 를 사용해서 각 환경마다 다른 variables를 입력한다면 아래와 같이 작성할 수 있다. 

 

locals.tf

region          = "us-west-2"

 

main.tf

provider "aws" {
  region = local.region
}

module "eks" {
  source = "../../modules/eks"
  region = local.region
  ..
}

 

Workspace

테라폼의 Workspace를 사용하면 테라폼의 상태를 별도의 이름을 가진 작업 공간에 저장할 수 있다. 

테라폼은 default라는 기본 작업 공간에서 시작하고, 따로 지정하지 않으면 이걸 사용한다.

예를 들어, AWS의 S3 버킷을 현재 작업공간으로 아래와 같이 사용할 수 있다.

terraform {
  backend "s3" {
    region                  = "aws region"
    bucket                  = "my-terraform-backend-bucket"
    key                     = "example/terraform.tfstate"
  }
}

 

Terraform 을 이용한 VPC, EKS 구성

위에 사용한 개념들을 토대로 테라폼 코드들을 작성하였다.

파일 구조는 아래와 같다. 

modules에 eks와 vpc를 위한 재사용 가능한 모듈을 작성하고 

각 환경에서 필요한 입력 변수들을 작성하게 되어있다. 

https://github.com/mokpolar/t101-terraform/tree/main/final

.
├── modules
│   ├── eks
│   │   ├── eks.tf
│   │   ├── locals.tf
│   │   ├── outputs.tf
│   │   ├── security-groups.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   └── vpc
│       ├── locals.tf
│       ├── output.tf
│       ├── variables.tf
│       ├── versions.tf
│       └── vpc.tf
└── stage
    ├── eks
    │   ├── locals.tf
    │   ├── main.tf
    │   └── outputs.tf
    └── vpc
        ├── locals.tf
        ├── main.tf
        └── outputs.tf

 

AWS VPC

EKS를 생성하기 전에 VPC를 생성해서 네트워크 공간을 만들어줘야 한다.

만들고자 하는 VPC 형태는 아주 일반적은 아래와 같은 구조이다.

AWS 문서에서 자세하게 설명하고 있다.  

출처: https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/VPC_Scenario2.html

실행할 stage/vpc/main.tf 파일이다. 

provider와 상태파일을 어디에 저장할지, module에서 어떤 변수를 사용할지 local에서 어떤 변수를 갖고와야 할지들이 작성되어있다. 

그전에 먼저 tfstate를 저장할 AWS S3 bucket을 생성해주자. 

aws s3 mb s3://mokpolar-terraform-backend-bucket

 

https://github.com/mokpolar/t101-terraform/blob/main/final/stage/vpc/main.tf

provider "aws" {
  region = local.region
}

# Terraform workspace : S3 bucket에 tfstate를 저장
terraform {
  backend "s3" {
    region = "us-west-2" # S3 bucket region
    bucket = "mokpolar-terraform-backend-bucket" # S3 bucket 생성 후 해당 이름 입력
    key    = "my-eks-cluster/vpc.tfstate" # 하부 경로명
  }
}

module "vpc" {
  source          = "../../modules/vpc"
  region          = local.region
  environment     = local.environment
  vpc_name        = local.vpc_name
  vpc_cidr_block  = local.vpc_cidr_block
  azs             = local.azs
  private_subnets = local.private_subnets
  public_subnets  = local.public_subnets
}

 

그 다음이 locals.tf 이다.

dev나 stage나 prod 와 같이 환경별로 입력 변수를 달리하기 위해 필요하다.

 

AWS의 region이나 이름, tag에 들어갈 환경명이 있다. 

 

CIDR block 과 어떤 Availability Zone을 사용할지에 주의해야 한다. 

만약 GPU 노드들을 올려야 하는 EKS 라면 AZ에 특히 주의할 필요가 있다.

보통은 AWS 측에 문의해서 AZ 별로 가용한 g5 노드등의 숫자를 확인한 다음에 AZ 를 선정한다.

 

https://github.com/mokpolar/t101-terraform/blob/main/final/stage/vpc/locals.tf

locals { 
  region          = "us-west-2" # AWS region 선택
  vpc_name        = "my-vpc" # VPC 이름
  
  environment     = "prod" # tag에 집어넣을 환경명
  
  vpc_cidr_block  = "10.0.0.0/16" # VPC CIDR block
  azs             = ["us-west-2a", "us-west-2b"] # AWS Avaiability Zones
  private_subnets = ["10.0.128.0/20", "10.0.144.0/20"] # Private Subnets CIDR
  public_subnets  = ["10.0.0.0/20", "10.0.16.0/20",] # Public Subnets CIDR
}

 

참조할 module의 vpc 코드는 아래와 같다. 

아래 작성된 variable 들에는 위에서 local에서 입력 받아서 사용되는 형태이다. 

https://github.com/mokpolar/t101-terraform/blob/main/final/modules/vpc/vpc.tf

...
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.14.2"

  name                  = "${var.vpc_name}-vpc"
  cidr                  = var.vpc_cidr_block

  azs              = var.azs
  public_subnets   = var.public_subnets
  private_subnets  = var.private_subnets
  ...

코드가 준비되었으니 아래 커맨드로 실행해주자. 

terraform init
terraform plan
terraform apply

 

그러면 잠시의 시간이 지난 뒤, 작업이 끝나고 선언한 것과 같이 output이 출력되는 모습을 볼 수 있다. 

Outputs:

nat_public_ips = tolist([
  "XXXX/32",
  "XXXX/32",
])
private_route_table_ids = [
  "rtb-XXXX",
  "rtb-XXXX",
]
private_subnets = [
  "subnet-XXXX",
  "subnet-XXXX",
]
public_route_table_ids = [
  "rtb-XXXX",
]
public_subnets = [
  "subnet-XXXX",
  "subnet-XXXX",
]
vpc_cidr_block = "10.0.0.0/16"
vpc_id = "vpc-XXXX"

 

 

AWS EKS

이제 만들어진 VPC 위에서 EKS 를 생성할 수 있다.

코드 작성은 VPC와 마찬가지 방식으로 진행한다.

각 환경별로 달리할 입력 변수를 locals를 통해 갖고와서 main.tf에서 module에 입력할 수 있도록 작성해준다. 

 

VPC 와 달라진 것은 S3에 저장된 vpc.tfstate를 읽어들여와서 사용하기 때문에 그 위치를 작성해야 한다는 부분이다.

 

https://github.com/mokpolar/t101-terraform/blob/main/final/stage/eks/main.tf

provider "aws" {
  region = local.region
}

# Terraform workspace : S3 bucket에 tfstate를 저장
terraform {
  backend "s3" {
    region = "us-west-2" # S3 bucket region
    bucket = "mokpolar-terraform-backend-bucket" # S3 bucket 생성 후 해당 이름 입력
    key    = "my-eks-cluster/eks.tfstate" # 하부 경로명
  }
}

# EKS 생성에 필요한 VPC 정보는 VPC 생성 후 저장된 아래 Terraform workspace에서 읽어들임
data "terraform_remote_state" "vpc" {
  backend  = "s3"
  config = {
    region = "us-west-2"
    bucket = "mokpolar-terraform-backend-bucket"
    key    = "my-eks-cluster/vpc.tfstate"
  }
}

module "eks" {
  source                                   = "../../modules/eks"
  region                                   = local.region
  environment                              = local.environment
  cluster_name                             = local.cluster_name
  cluster_version                          = local.cluster_version
  cluster_endpoint_public_access_nat_cidrs = data.terraform_remote_state.vpc.outputs.nat_public_ips
  eks_managed_node_groups                  = local.eks_managed_node_groups
  eks_vpc_id                               = data.terraform_remote_state.vpc.outputs.vpc_id
  vpc_cidr_block                           = data.terraform_remote_state.vpc.outputs.vpc_cidr_block
  eks_subnet_ids                           = data.terraform_remote_state.vpc.outputs.private_subnets
  aws_auth_users_list                      = local.aws_auth_users_list
}

 

그리고 module을 참조한다면 이렇게 들어갈 local의 입력 변수들만을 수정해주는 것으로 여러 환경을 쉽게 배포할 수 있다. 

 

https://github.com/mokpolar/t101-terraform/blob/main/final/modules/eks/eks.tf

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "18.29.0"

  cluster_name    = var.cluster_name
  cluster_version = var.cluster_version

  cluster_enabled_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]

  vpc_id     = var.eks_vpc_id
  subnet_ids = var.eks_subnet_ids
  ...

 

마찬가지로 아래 커맨드로 실행해주자. 

몇 분의 시간이 지난 뒤 리소스가 생성된다.

terraform init
terraform plan
terraform apply

 

결과물들은 AWS Console에서 확인할 수 있다. 

remote backend로 사용한 S3 bucket 에는 아래와 같이 tfstate 파일이 들어있다. 

 

EKS 도 잘 생성되었다. 

 

생성한 리소스의 제거

테스트가 끝났으니 비용을 내고싶지 않다면 테라폼으로 생성한 모든 리소스들을 제거해주어야 한다.

각 main.tf 가 있는 디렉토리에서 아래 커맨드를 실행해주자. 

terraform destroy -auto-approve

Reference

 

반응형