Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Terraform으로 AWS EKS에 Kubernetes 클러스터 프로비저닝 하기

Kubernetes를 사용하고 있지만 보통 클러스터를 설정해서 관리해 주는 사람이 따고 있고 그 위에서 사용만 하다 보니 간단한 컨셉은 이용하고 있지만 Kubernetes에 관해 깊이 알지는 못하고 있다. 사용하면서도 할 일이 많다는 핑계로 미루기도 했고 테스트용으로는 간단히 클러스터를 만들어서 썼지만, 체계적(?)으로 사용한 건 아니다 보니 계속해서 깊은 지식은 쌓지 못하고 있었다. 공부를 미룬 것도 있지만 꽤 복잡한 Kubernetes를 공부하려다 보면 볼 게 너무 많다보니 다 이해하고 정리하려다가 오히려 못하고 미루게 되었다.(계속할 때마다 클러스터를 지우고 새로 만들곤 했다.)

Kubernetes 공부를 해야지 하면서도 테스트하려면 돌려볼 수 있는 서비스가 필요하다는 생각에 괜히 쓸데없이 테스트용 서비스 만든다고 시간만 허비하다가 계속 못할 것 같아서 정리하면서 하나씩 설정하고 테스트 해보는게 낫겠다는 생각으로 바뀌었다. 모든 걸 한꺼번에 파악하기 어려우니 간단한 것부터 해봐야겠다 싶어서 Terraform을 이용해서 Kubernetes 클러스터를 AWS EKS에 세팅하고 하나씩 공부하면서 정리해보려고 한다. 전에는 kOps를 쓰기도 했지만 이제 AWS EKS(혹은 다른 클라우드 벤더의 매니지드 Kubernetes)도 좋아져서 그냥 EKS를 쓰는 게 더 좋아 보인다.

AWS EKS 클러스터

HashiCorp에서도 EKS 클러스터 프로비저닝 가이드를 제공하기 때문에 이 문서도 많이 참고 했다.

먼저 Terraform 프로바이더를 설정한다.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.23.0"
    }
  }
  required_version = ">= 1.0"

  backend "remote" {} // Terraform cloud 설정 생략
}

provider "aws" {
  region = "ap-northeast-2"
}

AWS를 사용해야 하니 hashicorp/aws 프로바이더를 설정한다. 테스트로는 Terraform v1.2.2를 사용했다.

terraform-aws-modules/eks/aws 모듈

Kuberentes는 설정이 꽤 복잡하지만 terraform-aws-modules/eks/aws 모듈이 있어서 비교적 간단히 AWS EKS에 클러스터를 프로비저닝할 수 있다. 물론 모듈도 복잡해서 원하는 구성으로 띄우려면 모듈 테스트도 많이 해봐야겠지만 예제에서 필요한 설정을 참고해 보는 것도 도움이 된다.

여기서는 간단한 기본 설정만 가지고 클러스터를 생성한다.

module "eks_playground" {
  source  = "terraform-aws-modules/eks/aws"
  version = "18.26.6"
}

테스트로 사용할 EKS 모듈을 설정했다.

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

  cluster_name    = "playground"
  cluster_version = "1.22"
  vpc_id          = data.terraform_remote_state.YOUR_VPC.outputs.playground_id
  subnet_ids      = data.terraform_remote_state.YOUR_VPC.outputs.playground_private_subnets

클러스터 이름을 지정하고 현재 EKS에서 지원하는 최신 버전인 1.22를 사용했다. Kubernete의 현재 최신 버전은 1.24이다. VPC와 서브넷은 이 글의 범위를 벗어나므로 미리 만들어 놓은 VPC와 서브넷 정보를 terraform_remote_state data로 끌어와서 지정해 주었다. 워커 노드도 외부 접속이 안 되도록 public이 아니라 private 서브넷을 지정했다.

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

  cluster_name    = local.name
  cluster_version = "1.22"
  vpc_id          = data.terraform_remote_state.apne2_vpc.outputs.playground_id
  subnet_ids      = data.terraform_remote_state.apne2_vpc.outputs.playground_private_subnets

  eks_managed_node_groups = {
    default_node_group = {
      min_size     = 2
      max_size     = 3
      desired_size = 2
      instance_types = ["m6i.large"]
    }
  }

  tags = {
    Environment = "dev"
  }
}

이제 eks_managed_node_groups를 통해 기본 노드 그룹을 지정했다. 테스트용이라 노드는 2대만 띄웠고 추가 노드 그룹은 이후에 공부하면서 이것저것 해보게 될 것 같아서(과연...) 일단 기본 노드 그룹만 지정했다.

terraform apply 결과

이 설정으로 terraform apply를 하면 꽤 많은 리소스라 생성되면서 적용이 완료된다.

사용자 삽입 이미지

AWS 콘솔에 들어가 보면 playground라는 이름으로 EKS 클러스터가 생성된 것을 확인할 수 있다.

kubectl로 클러스터 접근하기

kubectl로 접속을 확인해 보려면 kubeconfig를 구성해야 한다. AWS EKS에서는 aws CLI로 쉽게 업데이트를 할 수 있다.

$ aws eks --region ap-northeast-2 update-kubeconfig --name playground --kubeconfig ~/.kube/playground
Added new context arn:aws:eks:ap-northeast-2:252807701206:cluster/playground to /Users/outsider/.kube/playground

--region로 리전을 지정하고 --name은 클러스터의 이름을 지정하면 된다. 그냥 사용하면 ~/.kube/config가 생기지만 여러 클러스터를 관리하기 위해 --kubeconfig 플래그를 통해 ~/.kube/playground를 명시적으로 지정했고 export KUBECONFIG=$HOME/.kube/playground처럼 KUBECONFIG 환경변수를 지정해서 원하는 kubeconfig를 읽게 할 수 있다.

이제 클러스터에 잘 접근되는지 kubectl로 접근이 잘 되는지 확인해 보자.

$ kubectl get node
NAME                                             STATUS   ROLES    AGE   VERSION
ip-10-128-1-46.ap-northeast-2.compute.internal   Ready    <none>   46h   v1.22.9-eks-810597c
ip-10-128-3-97.ap-northeast-2.compute.internal   Ready    <none>   46h   v1.22.9-eks-810597c

위에서 지정한 2개의 노드가 잘 떠 있는 것을 알 수 있다.

여기서 추가 계정을 클러스터에 등록하지 않았으므로 kubectl을 이용하는 AWS 계정은 클러스터를 생성한 AWS 계정(여기서는 terraform apply를 실행한 계정)이어야 한다. 앞에서 aws eks 명령어로 생성한 kubeconfig를 열어보면 아래처럼 클러스터에 접근할 때 사용자 인증을 위해 명령어를 실행하는 부분이 있다.

users:
- name: arn:aws:eks:ap-northeast-2:252807701206:cluster/playground
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - --region
      - ap-northeast-2
      - eks
      - get-token
      - --cluster-name
      - playground
      command: aws
      env:
      - name: AWS_PROFILE
        value: YOUR_ACCOUNT

위를 보면 사용자 인증을 위해 aws --region ap-northeast-2 eks get-token --cluster-name playground 명령어를 실행하면서 AWS_PROFILE 환경변수로 로컬에 설정된 AWS 계정이 지정되어 있다. 이 계정이 클러스터를 만든 계정과 같아야 한다는 의미이다. 계정이 달라도 권한이 있으면 kubeconfig는 생성할 수 있을지라도 kubectl을 사용할 때는 error: You must be logged in to the server (Unauthorized) 오류가 발생하게 된다.

2022/07/29 02:22 2022/07/29 02:22