Terraform으로 EKS 구성해보기 -1
Terraform 스터디를 마무리하면서 간단한 프로젝트를 진행하려고 한다.
진행할 주제에 대해서 고민을 많이 했는데, 개인적으로 EKS를 공부해야할 일이 생겼다.
기존 가이드문서를 따라서 AWS Console로 하나하나 생성했던 EKS를
Terraform으로 간단하게 생성&삭제하는 실습을 해보고자 한다.
검색해보니 https://github.com/hashicorp/terraform-provider-aws 사이트에 굉장히 좋은 예시가 있어서
코드를 그대로 따라해서 EKS 생성을 실습해보고,
해당 구성을 토대로 내 입맞에 맞도록 하나씩 Terraform 코드를 변경해보고 수정해보고려고 한다.
해당 예시를 바탕으로 간단한 Application을 배포하는 블로그 글이 있길래 참고해서 진행하였다.
- http://dveamer.github.io/backend/TerrafromAwsEks.html
(다만 해당 블로그 글에서는 작업 환경이 Ubuntu인데 내 환경은 윈도우 PC이므로
기본 환경구성 세팅 및 명령어에 조금 차이가 있다.)
사전준비
윈도우 command 환경에서 필요한 명령어를 설치
(보통 bastion 서버를 설치하지만, 단순 실습을 위한 것이므로 윈도우 환경에 명령어를 설치함)
1. helm 설치 및 저장소 최신화
- https://github.com/helm/helm/releases
c:\terraform_study>curl -O https://get.helm.sh/helm-v3.10.2-windows-amd64.zip
c:\terraform_study>tar xvfz helm-v3.10.2-windows-amd64.zip
x windows-amd64/
x windows-amd64/helm.exe
x windows-amd64/LICENSE
x windows-amd64/README.md
c:\terraform_study>move windows-amd64\helm.exe c:\terraform_study
1개 파일을 이동했습니다.
c:\terraform_study>helm version
version.BuildInfo{Version:"v3.10.2", GitCommit:"50f003e5ee8704ec937a756c646870227d7c8b58", GitTreeState:"clean", GoVersion:"go1.18.8"}
c:\terraform_study>helm repo add stable https://charts.helm.sh/stable
"stable" has been added to your repositories
c:\terraform_study>helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
2. kubectl 설치
- https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/
c:\terraform_study>curl.exe -LO "https://dl.k8s.io/release/v1.26.0/bin/windows/amd64/kubectl.exe"
c:\terraform_study>kubectl version --client --output=yaml
clientVersion:
buildDate: "2022-12-08T19:58:30Z"
compiler: gc
gitCommit: b46a3f887ca979b1a5d14fd39cb1af43e7e5d12d
gitTreeState: clean
gitVersion: v1.26.0
goVersion: go1.19.4
major: "1"
minor: "26"
platform: windows/amd64
kustomizeVersion: v4.5.7
3. aws-iam-authenticator 설치
- https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/install-aws-iam-authenticator.html
c:\terraform_study>curl -Lo aws-iam-authenticator.exe https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v0.5.9/aws-iam-authenticator_0.5.9_windows_amd64.exe
c:\terraform_study>aws-iam-authenticator help
A tool to authenticate to Kubernetes using AWS IAM credentials
Usage:
aws-iam-authenticator [command]
EKS 구성 실습
1. EKS 구성 예시 코드 다운로드
git clone https://github.com/terraform-providers/terraform-provider-aws.git
cd terraform-provider-aws\examples\eks-getting-started
- variables.tf 파일에 작성되어있는 기본 Region은 us-west-2로 되어있어 한국 Region인 ap-northeast-2로 변경하였다.
- node group의 기본 ami type이 t3.medium으로 되어있길래 별도로 정의하는 코드를 추가하였다.
(https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group)
# variables.tf 파일 변경 내용
variable "aws_region" {
# 아래의 내용을 변경
default = "ap-northeast-2"
}
# eks-worker-nodes.tf 파일 변경내용
resource "aws_eks_node_group" "demo" {
cluster_name = aws_eks_cluster.demo.name
node_group_name = "demo"
node_role_arn = aws_iam_role.demo-node.arn
subnet_ids = aws_subnet.demo[*].id
# 아래의 내용을 추가
ami_type = "AL2_x86_64"
instance_types = ["t3.medium"]
capacity_type = "ON_DEMAND"
disk_size = 20
scaling_config {
...
...
2. Terraform init & plan & apply 수행
Terraform 코드 파일을 복사하여 임의의 폴더에 복사하고, Terraform init & plan & apply를 실행한다.
(git clone 폴더에서 수행해도 되지만, 기본 실습 후 코드를 수정하기 위해서 복사 수행)
c:\terraform_study\git_repository\terraform_eks_test\eks>dir
2022-12-11 오후 03:15 <DIR> .
2022-12-11 오후 03:15 <DIR> ..
2022-12-11 오후 02:33 2,124 eks-cluster.tf
2022-12-11 오후 02:33 1,638 eks-worker-nodes.tf
2022-12-11 오후 02:33 1,090 outputs.tf
2022-12-11 오후 02:33 412 providers.tf
2022-12-11 오후 02:41 144 variables.tf
2022-12-11 오후 02:33 1,212 vpc.tf
2022-12-11 오후 02:33 503 workstation-external-ip.tf
7개 파일 7,123 바이트
2개 디렉터리 40,474,451,968 바이트 남음
c:\terraform_study\git_repository\terraform_eks_test\eks>terraform init
Initializing the backend...
...
...
c:\terraform_study\git_repository\terraform_eks_test\eks>terraform plan
data.http.workstation-external-ip: Reading...
...
...
c:\terraform_study\git_repository\terraform_eks_test\eks>terraform apply
data.http.workstation-external-ip: Reading...
...
...
aws_eks_cluster.demo: Still creating... [8m42s elapsed]
aws_eks_cluster.demo: Creation complete after 8m52s [id=terraform-eks-demo]
aws_eks_node_group.demo: Creating...
aws_eks_node_group.demo: Still creating... [10s elapsed]
...
...
- "terraform-eks-demo"
EOT
c:\terraform_study\git_repository\terraform_eks_test\eks>
3. kubeconfig 설정
작업 중인 환경(여기선 윈도우PC)에서 kubectl을 통해 EKS에 접근하기위해 kubeconfig를 설정해줘야 한다.
kubeconfig 설정 파일을 지정하기 위해 환경변수를 사용하였다.
- KUBECONFIG 환경변수 : kubectl 명령어 실행시 필요한 kubernetes 환경설정 파일 위치에 대한 시스템 변수
c:\terraform_study\git_repository\terraform_eks_test\eks>terraform output kubeconfig
<<EOT
apiVersion: v1
clusters:
- cluster:
...
...
...
# kube.config 파일을 새로 생성해 출력된 내용(맨 처음과 끝의 EOF 줄은 제거)을 붙여넣기 해준다.
# config 내용에 token 정보 등이 존재하므로 외부에 유출되지 않도록 주의
c:\terraform_study>type kube.config
apiVersion: v1
clusters:
...
...
...
- "terraform-eks-demo"
c:\terraform_study>
# kube.config 파일을 config 파일로 등록하도록 환경변수 설정
c:\terraform_study>setx KUBECONFIG c:\terraform_study\kube.config
SUCCESS: Specified value was saved.
-> set 명령어는 임시 적용이며, 현재 명령을 수행한 cmd 창에서만 유효함
-> 영구 적용을 위해서 setx 명령어를 사용함
(환경변수가 덮어써지거나 길이가 길 경우 잘릴 수 있어서 권장하지 않는 방법)
# 환경변수 적용 후 cmd를 새로 실행
c:\terraform_study>kubectl get nodes -o wide
E1211 16:42:22.679296 13260 memcache.go:238] couldn't get current server API group list: Get "https://2284E515604912B07F587D7FAC929DC4.yl4.ap-northeast-2.eks.amazonaws.com/api?timeout=32s": getting credentials: exec: executable aws-iam-authenticator not found
-> 권한이 없어 조회가 되지 않는 것까지 확인
4. ConfigMap 설정
EKS Cluster가 Master 노드의 ConfigMap에 접근할 수 있도록 설정한다.
- EKS Cluster에 권한을 부여하려면 aws-auth ConfigMap에 사용자나 역할을 지정해야 한다.
c:\terraform_study\git_repository\terraform_eks_test\eks>terraform output config_map_aws_auth
<<EOT
apiVersion: v1
kind: ConfigMap
...
...
c:\terraform_study>kubectl apply -f configmap.yml
Warning: resource configmaps/aws-auth is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
configmap/aws-auth configured
c:\terraform_study>kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-0-1-72.ap-northeast-2.compute.internal Ready <none> 42m v1.23.13-eks-fb459a0 10.0.1.72 15.164.207.100 Amazon Linux 2 5.4.219-126.411.amzn2.x86_64 docker://20.10.17
설정 후 EKS의 ConfigMap
5. Worker Node 개수 변경 테스트
최초 1개만 배포되었던 Woker Node (EC2)를 2개로 변경 후 적용 테스트를 수행한다.
# eks-worker-nodes.tf 파일에 선언된 scaling_config 내용을 아래와 같이 변경
...
...
disk_size = 20
scaling_config {
desired_size = 2 # 1 -> 2로 변경, 희망하는 node 개수
max_size = 3 # 1 -> 3으로 변경, 최대 node 개수
min_size = 1 # 최소 node 개수
}
depends_on = [
...
...
위와 같이 수정 후 terraform apply 수행 및 결과 조회
c:\terraform_study\git_repository\terraform_eks_test\eks>kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-0-1-225.ap-northeast-2.compute.internal Ready <none> 95s v1.23.13-eks-fb459a0 10.0.1.225 3.34.180.220 Amazon Linux 2 5.4.219-126.411.amzn2.x86_64 docker://20.10.17
c:\terraform_study\git_repository\terraform_eks_test\eks>terraform apply
data.http.workstation-external-ip: Reading...
...
...
Terraform will perform the following actions:
# aws_eks_node_group.demo will be updated in-place
~ resource "aws_eks_node_group" "demo" {
id = "terraform-eks-demo:demo"
tags = {}
# (15 unchanged attributes hidden)
~ scaling_config {
~ desired_size = 1 -> 2
~ max_size = 1 -> 3
# (1 unchanged attribute hidden)
}
# (1 unchanged block hidden)
}
...
...
- "-i"
- "terraform-eks-demo"
EOT
c:\terraform_study\git_repository\terraform_eks_test\eks>
c:\terraform_study\git_repository\terraform_eks_test\eks>kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-0-0-27.ap-northeast-2.compute.internal NotReady <none> 3s v1.23.13-eks-fb459a0 10.0.0.27 43.200.2.213 Amazon Linux 2 5.4.219-126.411.amzn2.x86_64 docker://20.10.17
ip-10-0-1-225.ap-northeast-2.compute.internal Ready <none> 3m56s v1.23.13-eks-fb459a0 10.0.1.225 3.34.180.220 Amazon Linux 2 5.4.219-126.411.amzn2.x86_64 docker://20.10.17
c:\terraform_study\git_repository\terraform_eks_test\eks>
6. 테스트 Application 배포 및 접속 테스트
Node Port를 통해 접속하기위한 테스트 Application을 배포
# echo-deploy.yaml 파일 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-echo
spec:
replicas: 3
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: ndks-websrv
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
# svc-nodeport.yaml 파일 생성
apiVersion: v1
kind: Service
metadata:
name: svc-nodeport
spec:
ports:
- name: svc-webport
port: 9000
targetPort: 8080
selector:
app: deploy-websrv
type: NodePort
# 생성한 테스트 Application 배포
kubectl apply -f echo-deploy.yaml,svc-nodeport.yaml
# 배포된 Application POD 확인
c:\terraform_study>kubectl get pod
NAME READY STATUS RESTARTS AGE
deploy-echo-d4cc6b75d-59w8z 1/1 Running 0 56s
deploy-echo-d4cc6b75d-rg9rh 1/1 Running 0 56s
deploy-echo-d4cc6b75d-x82fn 1/1 Running 0 56s
접속 테스트
# NodePort 확인
c:\terraform_study>kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 12m
svc-nodeport NodePort 172.20.169.254 <none> 9000:31952/TCP 4m24s
# Node Public IP 확인
c:\terraform_study>kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-0-0-60.ap-northeast-2.compute.internal Ready <none> 7m33s v1.23.13-eks-fb459a0 10.0.0.60 3.39.228.222 Amazon Linux 2 5.4.219-126.411.amzn2.x86_64 docker://20.10.17
ip-10-0-1-152.ap-northeast-2.compute.internal Ready <none> 7m32s v1.23.13-eks-fb459a0 10.0.1.152 3.36.15.7 Amazon Linux 2 5.4.219-126.411.amzn2.x86_64 docker://20.10.17
# 접속 테스트
c:\terraform_study>curl -s 3.39.228.222:31952
Hostname: deploy-echo-d4cc6b75d-rg9rh
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.13.0 - lua: 10008
Request Information:
client_address=10.0.0.60
method=GET
real path=/
query=
request_version=1.1
request_uri=http://3.39.228.222:8080/
Request Headers:
accept=*/*
host=3.39.228.222:31952
user-agent=curl/7.83.1
Request Body:
-no body in request-
c:\terraform_study>
* 주의사항 : 기존 샘플 코드를 그대로 쓰는바람에 보안그룹으로 인해 통신이 되지 않았다. 참고한 링크들은 helm을 이용해 ingress를 사용해 유입 경로를 고정하였기 때문에 접속 테스트를 위해서는 보안그룹 수정이 필요하다.
지금까지 실습한 구성을 기본으로 아래 추가 사항을 고려해 Terraform 코드를 확장하려고 한다.
- 윈도우 PC환경이 아닌 bastion 서버를 별도로 생성해서 작업하도록 구성하기
- 변경이 가능한 입력값은 variable 변수로 분리하기
- 사용자가 원하는 Custom IP 대역으로 VPC, Subnet 을 생성해 해당 구역에 EKS 생성하기
- 가능한 한 Resource는 자동으로 생성되도록 하기
- 외부 트래픽 유입을 위한 ingress controler 구성하기
참고자료
- Terraform, Helm을 이용한 AWS EKS 구성 : http://dveamer.github.io/backend/TerrafromAwsEks.html
- From Zero to EKS with Terraform and Helm : https://aws.amazon.com/ko/blogs/startups/from-zero-to-eks-with-terraform-and-helm/
- Apache Tomcat packaged by Bitnami: https://github.com/bitnami/charts/tree/main/bitnami/tomcat