7주차 테라폼으로 AWS EKS 배포
1. 배경지식
1.1 EKS

AWS 환경에서 K8S 클러스터 패턴을 제공해줍니다.
Managed Service로 제공하는 서비스이며, Control Node에 대한 운영은 생각할 필요가 없습니다.
다른 AWS 서비스들과 빠른 호환성을 제공하며, AWS 환경 내의 K8S 운영을 도와줍니다.
컨테이너 이미지 저장소 ECR
로드 분산 ELB
인증 IAM
격리 VPC
1.2 Fargate

Fargate는 서버리스 컴퓨팅 엔진으로 서버나 클러스터를 직접 관리할 필요 없습니다.
다음과 같이 EKS + Fargate 를 사용하게되면 완전한 서버리스로 운용하고 서버 관리에 대한 복잡성을 줄일 수 있습니다.
autoscaling에 대한 부담도 자동확장이 되서 처리할 필요가 없어집니다.
1.3 Karpenter
ASG를 거치거나 Cluster Autoscaler를 거치지 않고 바로 EC2를 생성해주는 AWS 솔루션입니다.
23년 10월에 베타가 완료됨
2. AWS EKS Blueprints for Terraform
2.1 Karpenter EKS On Fargate Terraform으로 배포하기
AWS EKS Blueprints for terraform은 필요한 요구사항에 따른 terraform 예제 코드가 제공되어있어서 각각 알맞게 적용할 수 있습니다. (링크)
모듈로 구성되어 있진 않아서, 알맞게 모듈로 구성해서 사용하면 됩니다.
또한, blueprint addon들을 제공해줘서 helm 차트 기반으로 빠르게 요구사항을 충족시킬 수 있습니다.
terraform-aws-eks-blueprint-addons (여러 애드온을 한번에 프로비저닝 할 수 있는 모듈)
terraform-aws-eks-blueprints-teams (멀티 테넌시 리소스 구성을 위한 모듈)
2.2 주요 준비 사항
aws --version
terraform --version
kubectl version --client=true
helm -h
// 해당 툴들에 대한 준비를 해줍니다.
git clone https://github.com/aws-ia/terraform-aws-eks-blueprints
cd terraform-aws-eks-blueprints/patterns/karpenter
// repository를 받아옵니다.
terraform init
2.3 배포된 리소스들 확인
VPC 배포
// VPC 코드에는 다음과 같이 CIDR 이 있는데 해당 FUNCTION은 간편한 TERRAFORM FUNCTION이다.
```
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
```
// 현재 VPC 확인
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' --output yaml
Vpcs: []
terraform apply -target="module.vpc" -auto-approve
Apply complete! Resources: 23 added, 0 changed, 0 destroyed.

다음과 같이 vpc는 잘 구성이 되었다
eks 배포
terraform apply -target="module.eks" -auto-approve
// Apply complete! Resources: 24 added, 0 changed, 0 destroyed.
terraform state list // 정상적으로 배포된 것을 확인 할 수 있습니다.
// data.aws_availability_zones.available
module.eks.data.aws_caller_identity.current
module.eks.data.aws_iam_policy_document.assume_role_policy[0]
module.eks.data.aws_iam_session_context.current
module.eks.data.aws_partition.current
module.eks.data.tls_certificate.this[0]
module.eks.aws_cloudwatch_log_group.this[0]
module.eks.aws_ec2_tag.cluster_primary_security_group["Blueprint"]
module.eks.aws_ec2_tag.cluster_primary_security_group["GithubRepo"]
module.eks.aws_ec2_tag.cluster_primary_security_group["karpenter.sh/discovery"]
module.eks.aws_eks_access_entry.this["cluster_creator"]
module.eks.aws_eks_access_policy_association.this["cluster_creator_admin"]
module.eks.aws_eks_cluster.this[0]
module.eks.aws_iam_openid_connect_provider.oidc_provider[0]
module.eks.aws_iam_policy.cluster_encryption[0]
module.eks.aws_iam_role.this[0]
module.eks.aws_iam_role_policy_attachment.cluster_encryption[0]
module.eks.aws_iam_role_policy_attachment.this["AmazonEKSClusterPolicy"]
module.eks.aws_iam_role_policy_attachment.this["AmazonEKSVPCResourceController"]
module.eks.time_sleep.this[0]
module.vpc.aws_default_network_acl.this[0]
module.vpc.aws_default_route_table.default[0]
module.vpc.aws_default_security_group.this[0]
module.vpc.aws_eip.nat[0]
module.vpc.aws_internet_gateway.this[0]
module.vpc.aws_nat_gateway.this[0]
module.vpc.aws_route.private_nat_gateway[0]
module.vpc.aws_route.public_internet_gateway[0]
module.vpc.aws_route_table.private[0]
module.vpc.aws_route_table.public[0]
module.vpc.aws_route_table_association.private[0]
module.vpc.aws_route_table_association.private[1]
module.vpc.aws_route_table_association.private[2]
module.vpc.aws_route_table_association.public[0]
module.vpc.aws_route_table_association.public[1]
module.vpc.aws_route_table_association.public[2]
module.vpc.aws_subnet.private[0]
module.vpc.aws_subnet.private[1]
module.vpc.aws_subnet.private[2]
module.vpc.aws_subnet.public[0]
module.vpc.aws_subnet.public[1]
module.vpc.aws_subnet.public[2]
module.vpc.aws_vpc.this[0]
module.eks.module.fargate_profile["karpenter"].data.aws_caller_identity.current
module.eks.module.fargate_profile["karpenter"].data.aws_iam_policy_document.assume_role_policy[0]
module.eks.module.fargate_profile["karpenter"].data.aws_partition.current
module.eks.module.fargate_profile["karpenter"].data.aws_region.current
module.eks.module.fargate_profile["karpenter"].aws_eks_fargate_profile.this[0]
module.eks.module.fargate_profile["karpenter"].aws_iam_role.this[0]
module.eks.module.fargate_profile["karpenter"].aws_iam_role_policy_attachment.this["AmazonEKSFargatePodExecutionRolePolicy"]
module.eks.module.fargate_profile["karpenter"].aws_iam_role_policy_attachment.this["AmazonEKS_CNI_Policy"]
module.eks.module.fargate_profile["kube_system"].data.aws_caller_identity.current
module.eks.module.fargate_profile["kube_system"].data.aws_iam_policy_document.assume_role_policy[0]
module.eks.module.fargate_profile["kube_system"].data.aws_partition.current
module.eks.module.fargate_profile["kube_system"].data.aws_region.current
module.eks.module.fargate_profile["kube_system"].aws_eks_fargate_profile.this[0]
module.eks.module.fargate_profile["kube_system"].aws_iam_role.this[0]
module.eks.module.fargate_profile["kube_system"].aws_iam_role_policy_attachment.this["AmazonEKSFargatePodExecutionRolePolicy"]
module.eks.module.fargate_profile["kube_system"].aws_iam_role_policy_attachment.this["AmazonEKS_CNI_Policy"]
module.eks.module.kms.data.aws_caller_identity.current[0]
module.eks.module.kms.data.aws_iam_policy_document.this[0]
module.eks.module.kms.data.aws_partition.current[0]
module.eks.module.kms.aws_kms_alias.this["cluster"]
module.eks.module.kms.aws_kms_key.this[0]

# k8s 노드, 파드 정보 확인
kubectl cluster-info
kubectl get node
kubectl get pod -A

kube-ops-view 설치 : 노드의 파드 상태 정보를 웹 페이지에서 실시간으로 출력해 줍니다.
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
# 포트 포워딩
kubectl port-forward deployment/kube-ops-view -n kube-system 8080:8080
# 접속 주소 확인 : 각각 1배, 1.5배, 3배 크기
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080/#scale=3"

다음과 같이 local에서 바로 확인할 수 있습니다.
// karpenter 설치
helm install karpenter oci://public.ecr.aws/karpenter/karpenter --namespace "default"
// karpenter terraform 실행을 해주면
kubectl apply -f karpenter.yaml

// deployment 생성하고 3개로 스케일합니다.
kubectl apply -f example.yaml
kubectl scale deployment inflate --replicas=3
이렇게 provisioning이 되는 것을 확인할 수 있다.

terraform destroy -auto-approve
// 으로 vpc, eks, addon 등, 모두 삭제해주면 된다.
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' --output yaml
// kubeconfig 삭제 확인
rm -rf ~/.kube/config

3. EKS Workshop
3.1 EKS 배포
git clone https://github.com/aws-samples/eks-workshop-v2
terraform init
tree .terraform
cat .terraform/modules/modules.json | jq
tree .terraform/providers/registry.terraform.io/hashicorp -L 2
terraform apply -auto-approve
// 리소스 생성

terraform show
// 상세 정보 확인
# EKS 자격증명
## aws eks --region <REGION> update-kubeconfig --name <CLUSTER_NAME> --alias <CLUSTER_NAME>
aws eks --region ap-northeast-2 update-kubeconfig --name eks-workshop
cat ~/.kube/config
# 각자 자신의 IAM User 의 access entry 생성
ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
MYIAMUSER=<각자 자신의 IAM User>
MYIAMUSER=admin
echo $ACCOUNT_ID $MYIAMUSER
aws eks create-access-entry --cluster-name eks-workshop --principal-arn arn:aws:iam::${ACCOUNT_ID}:user/${MYIAMUSER}
aws eks list-access-entries --cluster-name eks-workshop
# 각자 자신의 IAM User에 AmazonEKSClusterAdminPolicy 연동
aws eks associate-access-policy --cluster-name eks-workshop --principal-arn arn:aws:iam::${ACCOUNT_ID}:user/${MYIAMUSER} \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster
aws eks list-associated-access-policies --cluster-name eks-workshop --principal-arn arn:aws:iam::${ACCOUNT_ID}:user/${MYIAMUSER} | jq
aws eks describe-access-entry --cluster-name eks-workshop --principal-arn arn:aws:iam::${ACCOUNT_ID}:user/${MYIAMUSER} | jq
# (참고) context name 변경
kubectl config rename-context "arn:aws:eks:ap-northeast-2:$(aws sts get-caller-identity --query 'Account' --output text):cluster/eks-workshop" "T101-Lab"

위와 같이 kube-ops-view를 설치해서 프로비져닝에 대한 모니터링이 바로 가능하다.
helm uninstall kube-ops-view -n kube-system
terraform destroy -auto-approve
# VPC 삭제 확인
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' --output yaml
# kubeconfig 삭제
rm -rf ~/.kube/config
Terraform을 이용한 aws eks 배포를 배웠고, 해당 워크숍에서 terraform으로 빠르고 쉽게 배포할 수 있습니다.
Last updated