이번에는 terraform으로 EKS 클러스터를 생성해 보고 (튜토리얼대로만)

terraform으로 kubernetes 리소스 관리까지 해 볼 것이다!

Provision an EKS Cluster (AWS)

참고 링크 ) Provision an EKS Cluster (AWS) - Terraform - HashiCorp Developer

hashicorp 사에서 제공하는 튜토리얼을 따라 EKS 클러스터를 구축해 보았다.

튜토리얼대로 따라하면 막힘없이 잘 구축할 수 있는데 필요에 따라 tf 파일을 수정해 주면 된다.

$ git clone https://github.com/hashicorp/learn-terraform-provision-eks-cluster
$ cd learn-terraform-provision-eks-cluster
$ ls -al
	total 61
	drwxr-xr-x 1 rkdls 197609     0 Dec  7 20:39 ./
	drwxr-xr-x 1 rkdls 197609     0 Dec  7 20:39 ../
	drwxr-xr-x 1 rkdls 197609     0 Dec  7 20:39 .git/
	-rw-r--r-- 1 rkdls 197609   674 Dec  7 20:39 .gitignore
	-rw-r--r-- 1 rkdls 197609  5772 Dec  7 20:39 .terraform.lock.hcl
	-rw-r--r-- 1 rkdls 197609 17136 Dec  7 20:39 LICENSE
	-rw-r--r-- 1 rkdls 197609   269 Dec  7 20:39 README.md
	-rw-r--r-- 1 rkdls 197609  1160 Dec  7 20:39 eks-cluster.tf
	-rw-r--r-- 1 rkdls 197609  1095 Dec  7 20:39 main.tf
	-rw-r--r-- 1 rkdls 197609   592 Dec  7 20:39 outputs.tf
	-rw-r--r-- 1 rkdls 197609   518 Dec  7 20:39 security-groups.tf
	-rw-r--r-- 1 rkdls 197609   527 Dec  7 20:39 terraform.tf
	-rw-r--r-- 1 rkdls 197609   107 Dec  7 20:39 variables.tf
	-rw-r--r-- 1 rkdls 197609   739 Dec  7 20:39 vpc.tf

eks-cluster.tf은 클러스터를 생성하고 노드 그룹을 구성할 수 있다.

main.tf에 지정해 둔 클러스터 이름을 사용하고 vpc.tfsecurity-groups.tf로 생성한 환경으로 사용한다

노드 그룹마다 인스턴스 타입을 지정할 수 있고 디폴트로 온디맨드 인스턴스가 생성된다.

min/max/desired size로 각 노드 그룹마다 원하는 노드 수를 지정할 수 있다

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

  cluster_name    = local.cluster_name     # main.tf
  cluster_version = "1.22"

  vpc_id     = module.vpc.vpc_id    # vpc.tf
  subnet_ids = module.vpc.private_subnets    # vpc.tf

  eks_managed_node_group_defaults = {
    ami_type = "AL2_x86_64"

    attach_cluster_primary_security_group = true

    # Disabling and using externally provided security groups
    create_security_group = false
  }

  eks_managed_node_groups = {
    one = {
      name = "node-group-1"

      instance_types = ["t3.small"]

      min_size     = 1
      max_size     = 3
      desired_size = 2

      pre_bootstrap_user_data = <<-EOT
      echo 'foo bar'
      EOT

      vpc_security_group_ids = [
        aws_security_group.node_group_one.id    # security-groups.tf
      ]
    }

    two = {
      name = "node-group-2"

      instance_types = ["t3.medium"]

      min_size     = 1
      max_size     = 2
      desired_size = 1

      pre_bootstrap_user_data = <<-EOT
      echo 'foo bar'
      EOT

      vpc_security_group_ids = [
        aws_security_group.node_group_two.id    # security-groups.tf
      ]
    }
  }
}

Untitled

마지막으로 variables.tf에서 region만 서울 리전으로 수정해 줬다.

이제 terraform 명령어를 실행해 주면 EKS 구축 성공이다!

$ terraform init
$ terraform apply -auto-approve

마지막으로 클러스터에 접속하기 위해 aws configure에 등록된 IAM 유저에 대해서 토큰을 발급하여 사용하도록 하는 kubeconfig를 생성하면 된당

$ aws eks --region $(terraform output -raw region) update-kubeconfig \
--name $(terraform output -raw cluster_name)
	Added new context arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos to /home/gain/.kube/config
$ cat /home/gain/.kube/config
	apiVersion: v1
	clusters:
	- cluster:
	    certificate-authority-data: [token]
	    server: https://[control-plane].gr7.ap-northeast-2.eks.amazonaws.com
	  name: arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos
	contexts:
	- context:
	    cluster: arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos
	    user: arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos
	  name: arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos
	current-context: arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos
	kind: Config
	preferences: {}
	users:
	- name: arn:aws:eks:ap-northeast-2:[account-id]:cluster/education-eks-woK1xAos
	  user:
	    exec:
	      apiVersion: client.authentication.k8s.io/v1beta1
	      args:
	      - --region
	      - ap-northeast-2
	      - eks
	      - get-token
	      - --cluster-name
	      - education-eks-woK1xAos
	      command: aws

이제 생성된 클러스터 정보와 node를 확인할 수 있다!

$ kubectl cluster-info
	Kubernetes control plane is running at https://[control-plane].gr7.ap-northeast-2.eks.amazonaws.com
	CoreDNS is running at https://[control-plane].gr7.ap-northeast-2.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
	
	To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
$ kubectl get nodes
	NAME                                           STATUS   ROLES    AGE    VERSION
	ip-10-0-2-41.ap-northeast-2.compute.internal   Ready    <none>   158m   v1.22.15-eks-fb459a0
	ip-10-0-2-7.ap-northeast-2.compute.internal    Ready    <none>   158m   v1.22.15-eks-fb459a0
	ip-10-0-3-12.ap-northeast-2.compute.internal   Ready    <none>   158m   v1.22.15-eks-fb459a0

Untitled 1

AWS EKS 생성 후,

EKS를 생성하고 나서 설치해야 하는 필수 리소스는 아래와 같은데 나는 deployment 하나만 생성하였다.

왜냐하면 EKS 생성하고 나서 어떻게 terraform으로 리소스 관리를 하는지가 이번 포스팅의 목적이기 때문에 나머지는 생략하였다! (쿠버네티스 사용이 아니라 테라폼 사용이 주 목적!!!!)

  • cluster-autoscaler
    cluster autoscaler는 pod 상태가 fail이거나 다른 노드로 rescheduled되는 경우에 클러스터의 노드 수를 autoscaling해 준다. 일반적으로 클러스터에 배포된다.
  • aws-node-termination-handler (NTH) (스팟 인스턴스 사용 시 필수인듯함)
    AWS에서는 미사용 EC2 용량을 활용하면서 비용 절감을 하기 위해 EC2 스팟 인스턴스를 사용하기도 한다는데, 스팟 인스턴스 종료 알람이 발생하고 나면 인스턴스는 2분 후에 회수된다. aws-node-termination-handler가 인터럽션을 체크하다가 node에 있는 pod를 drain하고, node가 회수되면 최대한 안전하게 다른 node에 pod를 binding하는 역할을 한다.
  • metrics-server
    클러스터 전체의 리소스 사용 데이터를 모니터링하는데, 노드나 컨테이너의 cpu 및 memory 같은 리소스 사용량 메트릭을 수집할 수 있다.
  • ingress controller
    외부 트래픽에 대한 규칙을 정의해 둔 ingress 리소스에 따라 L7 로드밸런서를 구성하는 컨트롤러이다.

참고 링크 ) k8s 필수 애플리케이션, 테라폼으로 한번에 설치하기

★ Manage Kubernetes Resources via Terraform

아래 링크를 참조하여 실습을 진행해 보았고 정말 간단하지만 내 GitHub Repo에 올려두었다ㅎㅎ

참고 링크 ) Manage Kubernetes Resources via Terraform - Terraform - HashiCorp Developer

1. Provider Kubernetes 설정

kubernetes.tf 파일에서 우선 provider를 지정해 준다.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 3.20.0"
    }

    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = ">= 2.0.1"
    }
  }
}

그리고 “learn-terraform-provision-eks-cluster”로 배포한 EKS 클러스터 정보는 tfstate 파일에 저장되어 있는 점을 활용하여 EKS 클러스터에 접근할 것이다.

data "terraform_remote_state" "eks" {
  backend = "local"

  config = {
    path = "../learn-terraform-provision-eks-cluster/terraform.tfstate"
  }
}

# Retrieve EKS cluster information
provider "aws" {
  region = data.terraform_remote_state.eks.outputs.region
}

data "aws_eks_cluster" "cluster" {
  name = data.terraform_remote_state.eks.outputs.cluster_id
}

그리고 kubernetes를 provider로 구성하려면 여러 가지 방법이 있지만 아래와 같이 하는 것이 좋다.

provider "kubernetes" {
  host                   = data.aws_eks_cluster.cluster.endpoint
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
  exec {
    api_version = "client.authentication.k8s.io/v1alpha1"
    command     = "aws"
    args = [
      "eks",
      "get-token",
      "--cluster-name",
      data.aws_eks_cluster.cluster.name
    ]
  }
}

왜냐하면 AWS EKS에서는 15분 후에 인증 토큰이 만료되기 때문에, EKS에서 제공하는 인증 플러그인(eks get-token)을 사용하여 토큰이 항상 최신인지 확인하는 것이 좋다!

다른 방법은 oauth2 token 사용, TLS 인증서 자격 증명 사용, HTTP 기본 인증 등이 있다고 한다.

궁금하다면 Terraform Registry에서 찾아 보자~

2. Deployment 리소스 생성

terraform으로 쿠버네티스 리소스를 생성할 때도 yaml 파일로 구성하는 것과 별반 다르지 않았다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-nginx
spec:
  selector:
    matchLabels:
      app: ScalableNginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: ScalableNginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.8
        ports:
        - containerPort: 80
				resources:
		      requests:
		        memory: "50Mi"
		        cpu: "250m"
		      limits:
		        memory: "512Mi"
		        cpu: "0.5"

기존 쿠버네티스에서 사용하는 yaml 구성파일인데 tf 파일로 아래와 같이 바꿀 수 있다.

resource "kubernetes_deployment" "nginx" {
  metadata {
    name = "deployment-nginx"
    labels = {
      App = "ScalableNginx"
    }
  }

  spec {
    replicas = 2
    selector {
      match_labels = {
        App = "ScalableNginx"
      }
    }
    template {
      metadata {
        labels = {
          App = "ScalableNginx"
        }
      }
      spec {
        container {
          image = "nginx:1.7.8"
          name  = "nginx"

          port {
            container_port = 80
          }

          resources {
            limits = {
              cpu    = "0.5"
              memory = "512Mi"
            }
            requests = {
              cpu    = "250m"
              memory = "50Mi"
            }
          }
        }
      }
    }
  }
}

아래와 같이 terraform apply를 해 주면 리소스 생성 완료다!

$ terraform apply -auto-approve
	data.terraform_remote_state.eks: Reading...
	data.terraform_remote_state.eks: Read complete after 0s
	data.aws_eks_cluster.cluster: Reading...
	data.aws_eks_cluster.cluster: Read complete after 0s [id=education-eks-woK1xAos]
	
	...(중략)...
	
	Plan: 1 to add, 0 to change, 0 to destroy.
	kubernetes_deployment.nginx: Creating...
	kubernetes_deployment.nginx: Creation complete after 5s [id=default/ingress-nginx]
	
	Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Untitled 2

헉 완전 신기…..

진짜 deployment-nginx가 생겼다!!!

삭제도 멀-끔한 Terraform 사용!

$ terraform destroy -auto-approve

이 명령어만 쳐주면 쿠버네티스 리소스도, EKS 클러스터도, 멀-끔하게 삭제 가능하다! 👏

Categories:

Updated:

Leave a comment