본문 바로가기

♻ Terraform(테라폼)/Terraform 활용

Terraform을 활용하여 EKS 클러스터 구축하기

# Terraform을 활용하여 EKS 클러스터를 구축하는 방법에 대해서 알아보자.

 

1. 일단 Terraform 설치는 아래의 링크로 이동하여 설치

2021.08.29 - [Terraform(테라폼)] - AWS CLI 및 Terraform 설치

 

AWS CLI 및 Terraform 설치

1. AWS CLI 설치 curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" 2. 다운받은 CLI 파일을 압축해제 unzip awscliv2.zip sudo ./aws/install 3. Terraform 설치 # 테라폼 다..

may9noy.tistory.com

2. 설치 후 Terraform의 폴더 구조는 아래와 같게 한다.

:~/environment/terraform $ ls -l
eks-cluster.tf
eks-worker-nodes.tf
providers.tf
variables.tf
vpc.tf
workstation-external-ip.tf

3. 이제 세부 구성에 대해서 알아보자.

- providers.tf

# providers.tf
provider "aws" {
  region = "ap-northeast-2"
}

provider "http" {}

프로바이더는 서비스 제공자라고 할수 있다. 테라폼은 멀티 플랫폼 서비스를 지원하므로 애저나 GCP, 네이버 클라우드등 다양한 프로바이더를 선택하여 인프라를 구축 할 수 있다.

- workstation-external-ip.tf

# workstation-external-ip.tf
data "http" "workstation-external-ip" {
  url = "http://ipv4.icanhazip.com"
}

locals {
  workstation-external-cidr = "${chomp(data.http.workstation-external-ip.body)}/32"
}

나의 공인ip 주소를 확인하고 입력한다고 보면 된다.

- vpc.tf

# create VPC
resource "aws_vpc" "terraform-eks-vpc" {
  cidr_block = "10.110.0.0/16"

  tags = {
    "Name" = "terraform-eks-node"
    "kubernetes.io/cluster/${var.cluster-name}" = "shared"
  }
}

...

# create subnet
resource "aws_subnet" "terraform-eks-public-subnet" {
  count = 2

  availability_zone       = data.aws_availability_zones.available.names[count.index]
  cidr_block              = "10.110.${count.index+1}.0/24"
  map_public_ip_on_launch = true
  vpc_id                  = aws_vpc.terraform-eks-vpc.id

  tags = {
    "Name" = "terraform-eks-public-${count.index+1 == 1 ? "a" : "c"}"
    "kubernetes.io/cluster/${var.cluster-name}" = "shared"
  }
}

...

# create route table
resource "aws_route_table" "terraform-eks-public-route" {
  vpc_id = aws_vpc.terraform-eks-vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.terraform-eks-igw.id
  }

  tags = {
    "Name" = "terraform-eks-public"
  }
}

...

# create route table association
# Subnet 과 Route table 을 연결
resource "aws_route_table_association" "terraform-eks-public-routing" {
  count = 2

  subnet_id      = aws_subnet.terraform-eks-public-subnet.*.id[count.index]
  route_table_id = aws_route_table.terraform-eks-public-route.id
}

생성시 주의할 점, aws_subnet.tags 중에 "kubernetes.io/cluster/${var.cluster-name}" = "shared"가  aws_vpc.tags 와 동일해야 한다. 이게 다를 경우 같은 클러스터인지 인식을 못해 정상적인 네트워크가 형성되지 않는다.

eks-cluster.tf

# IAM Role을 생성하고
resource "aws_iam_role" "terraform-eks-cluster" {
  name = "terraform-eks-cluster"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

# 위에서 생성한 IAM Role에 policy를 추가한다.
resource "aws_iam_role_policy_attachment" "terraform-eks-cluster-AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.terraform-eks-cluster.name
}

# 위에서 생성한 IAM Role에 policy를 추가한다.
resource "aws_iam_role_policy_attachment" "terraform-eks-cluster-AmazonEKSVPCResourceController" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
  role       = aws_iam_role.terraform-eks-cluster.name
}

# security group을 생성하고
resource "aws_security_group" "terraform-eks-cluster" {
  name        = "terraform-eks-cluster"
  description = "Cluster communication with worker nodes"
  vpc_id      = aws_vpc.terraform-eks-vpc.id

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "terraform-eks-cluster"
  }
}

# security group의 ingress 룰을 추가한다.
resource "aws_security_group_rule" "terraform-eks-cluster-ingress-workstation-https" {
  cidr_blocks       = [local.workstation-external-cidr]
  description       = "Allow workstation to communicate with the cluster API Server"
  from_port         = 443
  protocol          = "tcp"
  security_group_id = aws_security_group.terraform-eks-cluster.id
  to_port           = 443
  type              = "ingress"
}

# 마지막으로 cluster를 생성
resource "aws_eks_cluster" "terraform-eks-cluster" {
  name     = var.cluster-name
  role_arn = aws_iam_role.terraform-eks-cluster.arn
  version = "1.20"

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

  vpc_config {
    security_group_ids = [aws_security_group.terraform-eks-cluster.id]
    subnet_ids         = concat(aws_subnet.terraform-eks-public-subnet[*].id, aws_subnet.terraform-eks-private-subnet[*].id)
    endpoint_private_access = true
    endpoint_public_access = true
  }

  depends_on = [
    aws_iam_role_policy_attachment.terraform-eks-cluster-AmazonEKSClusterPolicy,
    aws_iam_role_policy_attachment.terraform-eks-cluster-AmazonEKSVPCResourceController,
  ]
}

이렇게 IAM Role, Policy, Security Group, Cluster를 생성한다.

eks-worker-nodes.tf

# 여기서는 EC2관련 IAM Role을 생성해주고
resource "aws_iam_role" "terraform-eks-node" {
  name = "terraform-eks-node"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

# 위에서 생성한 IAM Role에 Policy를 추가한다
resource "aws_iam_role_policy_attachment" "terraform-eks-node-AmazonEKSWorkerNodePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
  role       = aws_iam_role.terraform-eks-node.name
}

# 위에서 생성한 IAM Role에 Policy를 추가한다
resource "aws_iam_role_policy_attachment" "terraform-eks-node-AmazonEKS_CNI_Policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
  role       = aws_iam_role.terraform-eks-node.name
}

# 위에서 생성한 IAM Role에 Policy를 추가한다
resource "aws_iam_role_policy_attachment" "terraform-eks-node-AmazonEC2ContainerRegistryReadOnly" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.terraform-eks-node.name
}

# 마지막으로 Node Group을 생성한다.
resource "aws_eks_node_group" "terraform-eks-m5-large" {
  cluster_name    = aws_eks_cluster.terraform-eks-cluster.name
  node_group_name = "terraform-eks-m5-large"
  node_role_arn   = aws_iam_role.terraform-eks-node.arn
  subnet_ids      = aws_subnet.terraform-eks-private-subnet[*].id
  instance_types = ["m5.large"]
  disk_size = 50

  labels = {
    "role" = "terraform-eks-m5-large"
  }

  scaling_config {
    desired_size = 1
    min_size     = 1
    max_size     = 3
  }

  depends_on = [
    aws_iam_role_policy_attachment.terraform-eks-node-AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.terraform-eks-node-AmazonEKS_CNI_Policy,
    aws_iam_role_policy_attachment.terraform-eks-node-AmazonEC2ContainerRegistryReadOnly,
  ]

  tags = {
    "Name" = "${aws_eks_cluster.terraform-eks-cluster.name}-terraform-eks-m5-large-Node"
  }
}

위의 내용에서는 노드그룹을 생성하여 클러스터와 연결해 준다.

aws의 모듈 속성은 아래의 링크를 참조한다.

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

 

Terraform Registry

 

registry.terraform.io