T101 3기(=Terraform 101 Study)는 Terraform 실무 실습 스터디입니다.
CloudNet@ 유형욱, 윤서율님이 진행하시며, 책 "테라폼으로 시작하는 IaC"을 기반으로 진행하고 있습니다.
지난 포스트 글에서는 테라폼 클라우드를 통해 EKS를 프로비저닝하였습니다. 프로비저닝은 EKS 모듈을 통해 진행하였는데요. 이번 글에서는 EKS 모듈에 대해 자세히 다뤄볼 예정입니다. 테라폼 레파지토리를 확인하면 EKS 모듈 사용 예제를 비롯하여 ALB 컨트롤러, External DNS와 같은 addon를 확인할 수 있습니다. 이번 글에서는 모듈 예제를 학습하고 EKS와 기본 addon을 프로비저닝하겠습니다. 구성 예제는 필자의 깃허브에서 확인이 가능합니다.
1. 테라폼 EKS 모듈
EKS 모듈 예제를 확인하면 EKS에서 프로비저닝할 수 있는 모든 워크 노드 타입이 제공되는 것을 확인할 수 있습니다. 각 워크 노드 타입의 특징은 다음과 같이 요약할 수 있습니다.
eks_managed_nodegroup (EKS Managed Node Groups) : EKS 관리형 노드 그룹입니다. AWS가 노드 그룹의 라이프사이클을 자동으로 관리해주는 타입입니다. 작동 상태를 모니터링하고 필요에 따라 패치 적용 및 업데이트를 자동으로 수행합니다.
Fargate : 노드 타입을 서버리스로 설정해주는 옵션입니다. 노드(ec2)가 아니라 별도로 관리할 필요가 없으며 컨테이너가 fargate로 할당됩니다. 쿠버네티스의 복잡한 관리 작업 없이 서비스를 실행할 수 있습니다.
Karpenter : karpenter는 오픈소스 자동 스케일러로 karpenter 수행되는 서버 타입(EC2 Fleet)로 할당하여 노드 그룹을 구성합니다. karpenter 를 적용하면 빠르게 서버를 스케일러할 수 있게 됩니다.
self_managed_nodegroup (Self-Managed Node Groups) : 비관리형 노드 그룹입니다. 사용자가 노드의 모든 측면을 관리해야 합니다. Custom AMI를 통해 노드를 구성할 수 있으며 보안 목적이나 노드의 추가 설정 필요시 사용합니다.
Outposts : 로컬 EKS 노드 그룹 옵션입니다. 온프레미스 또는 다른 원격 위치에서 노드 그룹을 프로비저닝하여 EKS 클러스터를 운영할 수 있습니다.
위 예제 옵션 중 다루지 않은 complete는 모든 노드 그룹의 유형을 사용하는 예제이며, user_data는 노드의 부트스트랩 스크립트 및 구성하는 예제입니다. 예제 중 가장 기본이 되는 self-managed-node-group 예제를 통해 모듈 사용 예를 확인해보겠습니다. 모듈 구성은 다음과 같습니다.
디렉토리 modules 에 사용하는 커스컴 모듈을 모두 정의합니다. self_managed_node_group 폴더에 모듈에 따른 값을 정의합니다. self_managed_node_group main.tf 을 확인하면 eks 클러스터 구성, 노드 그룹 구성, vpc 구성을 확인할 수 있습니다.
module "eks"{source="../modules/eks"# 클러스터 정보 입력 cluster_name= local.name
cluster_version= local.cluster_version
cluster_endpoint_public_access=true# addon 구성 cluster_addons={coredns={most_recent=true} kube-proxy ={most_recent=true} vpc-cni ={most_recent=true}}# vpc 설정 vpc_id= module.vpc.vpc_id
subnet_ids= module.vpc.private_subnets
control_plane_subnet_ids= module.vpc.intra_subnets
# Self-managed node groups에 대한 AWS auth ConfigMap 자동 생성 설정create_aws_auth_configmap=truemanage_aws_auth_configmap=true# Self-managed node groups에 대한 기본 설정self_managed_node_group_defaults={# Cluster-autoscaler를 위한 자동 스케일링 그룹 태그 활성화autoscaling_group_tags={"k8s.io/cluster-autoscaler/enabled" : true,
"k8s.io/cluster-autoscaler/${local.name}" : "owned",
}}# 노드 그룹 설정self_managed_node_groups={ ..
}# aws-auth 설정 aws_auth_users=[ ..
]# 태그 설정tags= local.tags
}
1.1 노드 그룹
eks 모듈 내부의 self_managed_node_groups dict 을 통해 노드 그룹을 구성할 수 있습니다.. 구성 예제에서는 5가지의 노드 그룹으로 확인이 가능합니다. 노드 그룹별 키워드만 정리하면 다음과 같이 구성할 수 있습니다.
self_managed_node_groups={# 1. default_node_group 초기 설정 노드 그룹 구성default_node_group={}# 2. 컨테이너 운영의 특화된 bottlerocket AMI 사용하여 노드 그룹 구성 bottlerocket={platform="bottlerocket"ami_id= data.aws_ami.eks_default_bottlerocket.id
..
}# 3. 혼합 인스턴스 노드 그룹 구성 mixed={# 혼합 인스턴스 사용use_mixed_instances_policy=true# 혼합 인스턴스 정책 설정 mixed_instances_policy={instances_distribution={on_demand_base_capacity=0# 온디맨드 인스턴스 초기 0개로 설정on_demand_percentage_above_base_capacity=20# 온디맨드 인스턴스 비중을 20프로로 설정spot_allocation_strategy="capacity-optimized"# spot 인스턴스 할당받을 때 용량 최적화 전략으로 설정}# 가중치 설정override=[{instance_type="m5.large"weighted_capacity="1"},
{instance_type="m6i.large"weighted_capacity="1"},
]}}# 4. 고성능 컴퓨팅(HPC) 및 기계 학습 애플리케이션의 속도를 높일 수 있는 네트워크 디바이스 사용 인스턴스 efa={# 주의 인스턴스 타입이 고비용에서만 제공됩니다. # aws ec2 describe-instance-types --region eu-west-1 --filters Name=network-info.efa-supported,Values=true --query "InstanceTypes[*].[InstanceType]" --output text | sortinstance_type="c5n.9xlarge"network_interfaces=[{description="EFA interface example"delete_on_termination=truedevice_index=0associate_public_ip_address=falseinterface_type="efa"}] ..
}# 5. 완전 사용자 정의 노드 그룹 설정이나 프로비저닝시, 버그로 넘어갑니다. complete={ ..
}}
구성시 efa 노드 그룹 구성을 주의해주세요. efa 기능 지원 인스턴스가 고비용의 인스턴스(9x.large) 이상으로만 설정이 가능합니다. 필자는 제외했습니다.
complete 노드 그룹은 사용자 정의 노드 그룹으로 디바이스, 모니터링, 메타데이터 옵션을 통해서 노드 그룹을 구성하지만, eks 에 붙지 않습니다. arg를 통해 노드 그룹으로 연결해야 하는지는 확인이 필요합니다.
EKS 구성시 노드 그룹 정보는 EKS 탭에서 확인이 가능합니다. 자세한 노드 그룹은 정보는 EC2 텝의 오토스케일링 그룹 정보를 확인해주세요.
1.2 보안 구성
EKS 모듈을 통해 보안 구성을 크게 3가지로 분류하여 설정할 수 있습니다.
1.2.1 EKS Auth
AWS IAM 과 kubernetes RBAC 를 통해 EKS 클러스터에 대한 신원 정보를 확인하는 방법입니다. eks 모듈에서 aws_auth_users 에서 iam 정보를 입력합시다. 입력된 정보는 aws-auth configmap에 등록됩니다.
AWS auth에서 IAM 사용자 정보를 입력하지 않을 경우 EKS 콘솔에서 다음의 메세지가 확인되며 노드 그룹의 리소스를 확인할 수 없습니다.
‘This may be due to the current user or role not having Kubernetes RBAC permissions to describe cluster resources or not having an entry in the cluster’s auth config map’
1.2.2 Security Group
보안 그룹(Security Groups, SG)은 인스턴스에 대한 인바운드 및 아웃바운드 트래픽을 제어하는 가상 방화벽 역할을 합니다. main.tf에서는 별도로 설정하지 않았습니다. eks 모듈과 node_group 모듈에서 자동으로 설정됩니다.
초기 sg의 경우 클러스터 sg은 인그래스 포트로 443만 허용되며, 노드 그룹의 경우 다음과 같이 설정됩니다.
1.2.3 AWS IAM
EKS에서는 IAM 역할을 사용하여 노드 그룹이 AWS 리소스와 통신할 수 있는 권한을 부여합니다. main에서는 할당하지 않지만, 모듈에서 기본 IAM 정책을 할당합니다. 클러스터 할당 정책은 모듈에서 확인이 가능합니다. 관리형 정책 AmazonEKSClusterPolicy, AmazonEKSVPCResourceController 할당받으며, kms 사용 정책을 고객 관리형 정책으로 사용합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Policies attached ref https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.htmlresource "aws_iam_role_policy_attachment""this"{for_each={for k, v in {AmazonEKSClusterPolicy= local.create_outposts_local_cluster ? "${local.iam_role_policy_prefix}/AmazonEKSLocalOutpostClusterPolicy" : "${local.iam_role_policy_prefix}/AmazonEKSClusterPolicy",
AmazonEKSVPCResourceController="${local.iam_role_policy_prefix}/AmazonEKSVPCResourceController",
} : k=> v if local.create_iam_role }policy_arn= each.value
role= aws_iam_role.this[0].name
}resource "aws_iam_role_policy_attachment""additional"{for_each={for k, v in var.iam_role_additional_policies : k=> v if local.create_iam_role }policy_arn= each.value
role= aws_iam_role.this[0].name
}
# /terraform-t101-eks/self_managed_node_group➜ terraform init
..
➜ terraform plan
..
➜ terraform apply -auto-approve
# 20분 소요... ➜ eksctl get cluster
NAME REGION EKSCTL CREATED
t1013-eks ap-northeast-2 False
➜ eksctl utils write-kubeconfig --cluster t1013-eks --region ap-northeast-2
2023-09-15 18:16:45 [✔] saved kubeconfig as "/Users/mzc02-hseungho/.kube/config-f08"➜ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-node-d7sd4 2/2 Running 0 24m
kube-system aws-node-gx7lk 2/2 Running 0 24m
kube-system aws-node-xlnsx 2/2 Running 0 24m
kube-system coredns-754fbc56c6-fmcqr 1/1 Running 0 24m
kube-system coredns-754fbc56c6-qwkdk 1/1 Running 0 24m
kube-system kube-proxy-6mg4q 1/1 Running 0 24m
kube-system kube-proxy-7hlv8 1/1 Running 0 24m
kube-system kube-proxy-fqbls 1/1 Running 0 24m
2. 테라폼 EKS addon 모듈
EKS (Elastic Kubernetes Service)의 애드온(add-ons)은 EKS 클러스터의 기능성과 운영을 강화하는 소프트웨어 컴포넌트입니다. 이러한 애드온은 주로 네트워킹, 로깅, 모니터링, 보안 등 다양한 목적으로 사용됩니다. EKS는 몇 애드온에 대해 AWS 서비스를 연동하여 제공하기도 합니다.
addons 이름
연동 AWS 서비스
설명
VPC CNI
VPC
AWS VPC (Virtual Private Cloud) 내 통신을 위한 네트워크 인터페이스(CNI)
CoreDNS
VPC
서비스 디스커버리와 DNS를 위한 애드온
kube-proxy
VPC
Kubernetes 네트워크 프록시 관리
external-dns
Route53
쿠버네티스 서비스와 인그레스에 대한 DNS 레코드 관리
ALB Controller
ALB
ALB를 쿠버네티스 인그레스 리소스로 관리
EBS CSI Controller
EBS
EBS 볼륨을 쿠버네티스 퍼시스턴트 볼륨으로 관리
EKS addon 도 테라폼 모듈을 통해 설치가 가능합니다. 테라폼 레파지토리 fully-loaded-eks-cluster 에 모듈화된 addon 서비스를 확인할 수 있습니다.
위에 소개한 모듈을 통해 addon 구성은 모듈 변수의 flag를 통해 손 쉽게 구성이 가능합니다. 다만, 개인적으로 내부 동작 이해가 어려워 확장성을 원하는 분들이나 추후 모듈을 구성하려는 분들에게 해당 모듈 사용을 추천드리지 않습니다.
공식적으로 제공하는 모듈외에도 사용자 모듈이 많습니다. 이번 포스트 글에서는 자주 다뤘던 ALB controller,external dns addon에 대해 직관적인 테라폼 모듈을 찾아 구성해보겠습니다.
2.1 ALB Controller
개인적으로 ALB controller 직관적인 모듈로 깃허브 campaand 님의 모듈을 추천드립니다. 모듈 내 main.tf을 확인하면 내부 동작을 확인할 수 있습니다. 먼저, alb 을 관리하기 위한 IAM 정책 선언 후 role에 연결합니다. 그 다음 helm 프로바이더를 통해 aws-load-balancer-controller 차트를 구성합니다.
모듈 문서를 참고하면, 헬름 차트의 추가 매개변수가 필요할 때는 다음 예제와 같이 구성할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module "alb_controller"{source="campaand/alb-controller/aws"version="~> 2.0"cluster_name= var.cluster_name
# 차트 버전 helm_chart_version="1.6.0"# 매개변수 선언 settings={key1= value1,
key2= value2,
key3= value3,
key4= value4
}}
테라폼을 통해 addon을 구성하는 방법은 많습니다. 이번 포스트 글에서는 모듈을 통해 구성하였지만, 모듈 버전호환과 필요 매개 변수 등으로 구성 시간을 많이 소비하였습니다. 개인적으로는 모듈로 addon을 구성하는 것은 참고 예제가 많아지면 시도하는 것을 추천드립니다. 그 전까지는 스크립트나 CD를 통해 구성하는 것이 추천드립니다.