Iac

Terraform | EKS 만들어 보기

no-easy-ray 2022. 1. 28. 16:58

테라폼을 이용하여 EKS를 생성하는 방법을 정리해 보려고 합니다.

EKS를 구성하고 있는 각각의 테라폼 리소스를 이용하여 만들 수 도 있지만 테라폼에서 제공하는 EKS모듈을 이용하면 보다 쉽게 만들 수 있습니다.

Terraform EKS Module

 

github의 example에 들어가 보시면 example이 존재합니다.

Terrarom EKS Module Example

 

예시로는 테라폼에서 제공하는 노드 그룹을 전부 이용하는 예제가 제공되고 있습니다.

간단하게 실습용으로 만들 것이기 때문에 제공하는 example보다는 간소화해서 만들어보도록 하겠습니다.

 

만들기 전에 기본적인 설정들을 정리하도록 하겠습니다.

EKS를 만들기 위해서 추가적으로 awscli2, kubectl, helm(CA(cluster-autoscaler 설치))이 필요합니다.

 

먼저 AWS Provider설정을 합니다.

# main.tf
provider "aws" {
  region = var.region

  default_tags {
    tags = {
      Terraform = "true"
      Project   = "${var.cluster_name}-project"
    }
  }
}

Region과 생성된 리소스들에 대해서 지정함 default tag를 작성합니다.

 

EKS등에서 사용될 variables를 생성합니다.

# variables.tf
variable "region" {
  default = "ap-northeast-2"
}

variable "azs" {
  description = "A list of availability zones names or ids in the region"
  type = list(string)
  default = ["ap-northeast-2a", "ap-northeast-2c"]
}

variable "cluster_name" {
  description = "Cluster Name"
  type = string
  default = null
}

variable "cluster_version" {
  description = "Cluster Version"
  type = string
  default = null
}

variable "vpc_cidr" {
  description = "VPC CIDR Range"
  type = string
  default = null
}

variable "vpc_name" {
  description = "VPC Name"
  type = string
  default = null
}

 

# terraform.auto.tfvars
vpc_name     = "ray-vpc"
vpc_cidr     = "192.168.0.0/16"

cluster_name     = "my-cluster"
cluster_version  = "1.21"

테라폼 실행 시 해당 파일에 작성한 변수명과 일치하는 variables에 맞게 사용됩니다.

위의 파일들이 준비가 되었으면 먼저 새로운 VPC를 생성할 수 있도록 작성합니다.

 

VPC 또한 테라폼에서 제공하는 모듈을 이용하면 손쉽게 만들 수 있습니다.

# vpc.tf
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = var.vpc_name
  azs  = var.azs
  cidr = var.vpc_cidr

  # NAT게이트웨이를 생성합니다.
  enable_nat_gateway = true
  # NAT게이트웨이를 1개만 생성합니다.
  single_nat_gateway = true

  public_subnets = [for index in range(2):
                      cidrsubnet(var.vpc_cidr, 4, index)]

  private_subnets = [for index in range(2):
                      cidrsubnet(var.vpc_cidr, 4, index + 2)]
}

cidrsubnet 서브넷 cidr을 나눠주기 위해 사용됩니다.

 

EKS를 생성합니다.

data "aws_caller_identity" "current" {}

locals {
  node_group_name        = "${var.cluster_name}-node-group"
  iam_role_policy_prefix = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:policy"
}

module "eks" {
  # 모듈 사용
  source = "terraform-aws-modules/eks/aws"

  cluster_name    = var.cluster_name
  cluster_version = var.cluster_version

  cluster_endpoint_private_access = true
  cluster_endpoint_public_access  = true

  vpc_id          = module.vpc.vpc_id
  subnet_ids      = module.vpc.private_subnets
  
  # 관리형 노드 그룹 사용 (기본 설정)
  eks_managed_node_group_defaults = {
    ami_type               = "AL2_x86_64" # 
    disk_size              = 10           # EBS 사이즈
    instance_types         = ["t2.small"]
    # vpc_security_group_ids = [aws_security_group.additional.id]
    vpc_security_group_ids = []
		
		# cluster-autoscaler에 사용 될 IAM 등록
    iam_role_additional_policies = ["${local.iam_role_policy_prefix}/${module.iam_policy_autoscaling.name}"]
  }

  # 관리형 노드 그룹 사용 (노드별 추가 설정)
  eks_managed_node_groups = {
    ("${var.cluster_name}-node-group") = {
      # node group 스케일링
      min_size     = 1 # 최소
      max_size     = 3 # 최대
      desired_size = 2 # 기본 유지

      # 생성된 node에 labels 추가 (kubectl get nodes --show-labels로 확인 가능)
      labels = {
        ondemand = "true"
      }

      # 생성되는 인스턴스에 tag추가
      tags = {
        "k8s.io/cluster-autoscaler/enabled" : "true"
        "k8s.io/cluster-autoscaler/${var.cluster_name}" : "true"
      }
    }
  }
}

테라폼 EKS모듈(현재 18.2.3 버전)에서는 3가지의 node group을 제공합니다.

AWS EKS에서 제공하는 Node Group은 여기에서 확일 할 수 있습니다.

 

Node Group에 사용될 IAM Policy를 생성합니다. (cluster-autoscaler를 사용하기 위함입니다.)

module "iam_policy_autoscaling" {
  source = "terraform-aws-modules/iam/aws//modules/iam-policy"

  name = "${var.cluster_name}-cluster-autoscaler"
  path = "/"
  description = "Autoscaling policy for cluster ${var.cluster_name}"

  policy      = data.aws_iam_policy_document.worker_autoscaling.json
}

data "aws_iam_policy_document" "worker_autoscaling" {
  statement {
    sid    = "eksWorkerAutoscalingAll"
    effect = "Allow"

    actions = [
      "autoscaling:DescribeAutoScalingGroups",
      "autoscaling:DescribeAutoScalingInstances",
      "autoscaling:DescribeLaunchConfigurations",
      "autoscaling:DescribeTags",
      "ec2:DescribeLaunchTemplateVersions",
    ]

    resources = ["*"]
  }

  statement {
    sid    = "eksWorkerAutoscalingOwn"
    effect = "Allow"

    actions = [
      "autoscaling:SetDesiredCapacity",
      "autoscaling:TerminateInstanceInAutoScalingGroup",
      "autoscaling:UpdateAutoScalingGroup",
    ]

    resources = ["*"]

    condition {
      test     = "StringEquals"
      variable = "autoscaling:ResourceTag/kubernetes.io/cluster/${var.cluster_name}"
      values   = ["owned"]
    }

    condition {
      test     = "StringEquals"
      variable = "autoscaling:ResourceTag/k8s.io/cluster-autoscaler/enabled"
      values   = ["true"]
    }
  }
}

Cluster Autoscaler가 IAM 역할을 사용하기 위해 필요한 권한입니다.

 

여기까지 작성 후 테라폼 명령을 이용하여 생성하도록 합니다.

terraform init

terraform plan

terraform apply

 

kubecofing설정

EKS를 생성하게 되면 생성한 IAM User에 대해서 system:master 권한을 갖게 됩니다.

따라서 초기 설정을 위해서 system:master로 클러스터에 접속하게 되는데 이때, 다음 명령을 통해 해당 User에 대해서

 

EKS 클러스터에 접속할 수 있는 토큰을 발급하여 사용하도록 하는 kubeconfig를 생성합니다.

# EKS생성에 사용된 IAM configure를 이용해야합니다. (~/.aws)
aws eks --region ap-northeast-2 update-kubeconfig --name my-cluster

 

생성된 kubeconfig 예시

# ~/.kube/kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ********==
    server: https://********.***.ap-northeast-2.eks.amazonaws.com
  name: arn:aws:eks:ap-northeast-2:********:cluster/my-cluster
contexts:
- context:
    cluster: arn:aws:eks:ap-northeast-2:********:cluster/my-cluster
    user: arn:aws:eks:ap-northeast-2:********:cluster/my-cluster
  name: arn:aws:eks:ap-northeast-2:********:cluster/my-cluster
current-context: arn:aws:eks:ap-northeast-2:********:cluster/my-cluster
kind: Config
preferences: {}
users:
- name: arn:aws:eks:ap-northeast-2:********:cluster/my-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-2
      - eks
      - get-token
      - --cluster-name
      - my-cluster
      command: aws
      env:
      - name: AWS_PROFILE
        value: my-aws-profile

kubeconfig가 생성되면 다음과 같은 config가 생성된 걸 확인할 수 있습니다.

 

kubectl을 이용하여 해당 EKS Api서버로 요청이 잘 가는지 확인합니다.

# 생성된 EKS의 Node 확인
kubectl get nodes

# 만약 연결이 되지 않는 경우 kubeconfig가 제대로 지정 되지 않았을 수 도 있습니다.
export KUBECONFIG="~/.kube/{해당 config파일}"

 

마지막으로 EKS 사용량에 따라 node group의 node들이 스케일링이 가능해지도록 CA(cluster-autoscaler)를 설치합니다.

 

먼저 CA(cluster-autoscaler)에 사용될 values.yaml을 생성합니다.

# values.yaml
autoDiscovery:
  clusterName: my-cluster # eks cluster name

awsRegion: ap-northeast-2 # eks region

extraArgs:
  logtostderr: true
  stderrthreshold: info
  v: 4
  expander: random
  scale-down-enabled: true # 사용량이 적을경우 scale-down허용

각각의 옵션은 여기서 확인할 수 있습니다.

 

마지막으로 Helm install을 통해 CA(cluster-autoscaler)를 설치합니다.

helm repo add autoscaler <https://kubernetes.github.io/autoscaler>

helm repo update

helm install cluster-autoscaler autoscaler/cluster-autoscaler --values=./valuse.yaml