AWS EKS 클러스터 구축 및 Gitops 파이프라인 최종안
AWS EKS 클러스터 구축 및 Gitops 파이프라인 최종안 — #개발자의도구들 #AWSEKS #쿠버네티스 #AWS쿠버네티스 #gitops #깃옵스 #깃허브액션 #githubActi...
#개발자의도구들 #AWSEKS #쿠버네티스 #AWS쿠버네티스 #gitops #깃옵스 #깃허브액션 #githubActions
아키텍처
배포 파이프라인
- Dev Team이 Application Repository에 새로운 버전을 Push합니다.
- GitHub Actions가 트리거되어 빌드를 수행합니다. (자동/수동)
- 빌드된 이미지를 AWS ECR에 Push합니다.
- 빌드 완료 후 변경된 이미지 태그를 GitOps Repository에 업데이트합니다.
- ArgoCD가 GitOps Repository의 변경을 감지합니다.
-
- ArgoCD가 변경된 매니페스트를 클러스터에 Apply합니다.
6.Public Node는 IGW를 통해, Private Node는 VPC Endpoint를 통해 이미지를 새로운 이미지를 PULL하여 Pod를 배포합니다.
AWS EKS 클러스터 구축
사용자는 AWS EKS 내에 배포된 프론트 서버와 통신이 가능해야 합니다.
- 사용자는 프론트 서버에 데이터를 요청합니다.
- VPC 내의 모든 인터넷 통신은 Internet Gateway를 통합니다.
- VPC 내의 ALB는 사용자의 요청을 분석하여 Pod로 라우팅합니다.
-
- 현재 프론트 서버는 3개의 Pod로 밸런싱됩니다. (실습용)
- 프론트 서버는 내부 MSA 서버들과 통신합니다.
-
- 대부분의 서버는 Private Subnet에 배치되어 있습니다.
- 이미지 서버는 VPC Endpoint를 통해 AWS S3와 직접 통신합니다.
- Private Node Group의 Worker Node는 NAT Gateway → Internet Gateway를 통해 AWS EKS Control Plane과 통신합니다.
- VPC Endpoint를 직접 지원하지 않는 AWS 서비스(Cognito 등)는 NAT Gateway → Internet Gateway를 거쳐 VPC 외부 AWS 서비스와 통신합니다.
EKS 클러스터 구축 비용 분석
비용이 발생하는 구간
- Iternet GateWay
- 인바운드 트래픽은 무료
- 아웃바운드 트래픽은 유료: $0.09/GB
- ALB
- 시간당 요금: $0.0225/hour
- LCU(처리량)기반 요금
- VPC 내부 트래픽은 무료
- EKS
- 클러스터 시간당 요금: $0.10/hour
- 워커노드: EC2 인스턴스(Fargate) 비용
- ECR
-
- 이미지 저장 비용: $0.10/GB/월
- 같은 리전내 ECR → EC2는 전송비용 무료
5.NAT Gateway
-
- 시간당 요금: $0.045/hour
- 데이터 처리: $0.045/GB
- RDS
-
- 인스턴스 시간당 요금
- 스토리지 비용: $0.115/GB/월
- 데이터 번송비용: 같은 VPC내 무료
- S3
-
- 스토리지: $0.023/GB/월
- 요청 비용: PUT $0.005/1000건, GET $0.0004/1000건
무료리소스
- VPC, Subnet, Route Table, Security Group
- VPC Gateway Endpoint (S3, DynamoDB에 한정)
- ClusterIP Service (Pod 간 내부 통신)
실습
모든 실습은 AWS CLI 명령어로 진행합니다. 차례대로 구성한다면 AWS 네트워크 및 보안 원리를 이해하며 AWS EKS 클러스터 구축을 하실 수 있도록 설계하였습니다.
목차
- 네트워크 설정: VPC, Internet Gateway, Iptable, VPC Endpoint, NAT Gateway
- IAM Role 설정: Cluster Policy, Node Policy
\[AWS EKS\] 1. 네트워크 설정
VPC, Internet Gateway, Iptable, VPC Endpoint, NAT Gateway
실습에 사용할 Worker Node는 총 4개입니다. Public Subnet과 Private Subnet에 각각 2개씩 배포합니다.
- Public Subnet에는 Frontend 서버, ALB, NAT Gateway를 배치합니다.
- Private Subnet에는 RDS와 Backend MSA 서버들(Auth, Image, Profile)을 배치합니다.
1,1 VPC 생성 명령어 (CLI)
- Node를 배치할 VPC를 생성합니다.
# VPC 생성
aws ec2 create-vpc \
--cidr-block 172.31.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=marketing-vpc},{Key=Project,Value=marketing},{Key=Environment,Value=prod},{Key=ManagedBy,Value=terraform}]'
1.2 Internet Gateway 생성
- VPC가 외부와 통신하기 위해 Internet Gateway를 사용합니다.사용할 게이트웨이를 생성하고 VPC와 연결합니다.
# Internet Gateway 생성
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=marketing-igw},{Key=Project,Value=marketing},{Key=Environment,Value=prod}]
# VPC에 Internet Gateway 연결
aws ec2 attach-internet-gateway \
--internet-gateway-id <IGW_ID> \
--vpc-id <VPC_ID>
1.3 Public Subnet 구성 (2개)
- HA를 고려하여 Public Subnet을 두개 구성합니다.
- 이후 각 HA 영역에 하나씩 배포합니다.(ap-northeast-2a, ap-northeast-2c)
- Public Subnet은 Front Pod, ALB, NAT Gateway를 이후에 배치합니다.
# Public Subnet 1 (ap-northeast-2a)
aws ec2 create-subnet \
--vpc-id <VPC_ID> \
--cidr-block 172.31.0.0/20 \
--availability-zone ap-northeast-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=marketing-public-ap-northeast-2a},{Key=kubernetes.io/role/elb,Value=1},{Key=kubernetes.io/cluster/marketing-eks,Value=shared},{Key=Project,Value=marketing}]'
# Public Subnet 2 (ap-northeast-2c)
aws ec2 create-subnet \
--vpc-id <VPC_ID> \
--cidr-block 172.31.16.0/20 \
--availability-zone ap-northeast-2c \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=marketing-public-ap-northeast-2c},{Key=kubernetes.io/role/elb,Value=1},{Key=kubernetes.io/cluster/marketing-eks,Value=shared},{Key=Project,Value=marketing}]'
- 퍼블릭 자동 할당 활성
- Public Subnet에 배포되는 리소스(EC2, EKS 노드 등)가 인터넷과 직접 통신하려면 퍼블릭 IP가 필요합니다. 이를 AWS가 자동으로 부여해줍니다.
aws ec2 modify-subnet-attribute \
--subnet-id <PUBLIC_SUBNET_1_ID> \
--map-public-ip-on-launch
aws ec2 modify-subnet-attribute \
--subnet-id <PUBLIC_SUBNET_2_ID> \
--map-public-ip-on-launch
1.4 Private Subnet 생성 (2개)
- Public과 마찬가지로 HA를 고려하여 두 개의 Private Subnet을 구성합니다.
- 이후 각 HA 영역에 하나씩 배포합니다.(ap-northeast-2a, ap-northeast-2c)
- Private Subnet에 RDS 및 내부 MSA 서버들을 이후에 배치합니다.
# Private Subnet 1 (ap-northeast-2a)
aws ec2 create-subnet \
--vpc-id <VPC_ID> \
--cidr-block 172.31.32.0/20 \
--availability-zone ap-northeast-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=marketing-private-ap-northeast-2a},{Key=kubernetes.io/role/internal-elb,Value=1},{Key=kubernetes.io/cluster/marketing-eks,Value=shared},{Key=Project,Value=marketing}]'
# Private Subnet 2 (ap-northeast-2c)
aws ec2 create-subnet \
--vpc-id <VPC_ID> \
--cidr-block 172.31.48.0/20 \
--availability-zone ap-northeast-2c \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=marketing-private-ap-northeast-2c},{Key=kubernetes.io/role/internal-elb,Value=1},{Key=kubernetes.io/cluster/marketing-eks,Value=shared},{Key=Project,Value=marketing}]'
1.5 NAT Gateway
- Private Subnet의 리소스가 외부 인터넷과 통신하기 위해 필요합니다. 본 프로젝트에서는 Private Subnet의 Backend 서버가 AWS Cognito와 통신할 때 사용됩니다.
# Elastic IP 할당 (NAT Gateway용)
aws ec2 allocate-address \
--domain vpc \
--tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=marketing-nat-eip},{Key=Project,Value=marketing}]'
# NAT Gateway 생성 (Public Subnet 1에 배치)
aws ec2 create-nat-gateway \
--subnet-id <PUBLIC_SUBNET_1_ID> \
--allocation-id <EIP_ALLOCATION_ID> \
--tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=marketing-nat},{Key=Project,Value=marketing}]'
\* Elastic IP 할당 이유: NAT는 Pivate Subnet의 리소스들이 외부로 나갈 때 사용하는 고정된 출구 IP가 필요합니다.그래서 Elasitc IP를 사용하지 않으면 게이트웨이 생성이 불가능합니다.
1.6 Route Table 생성 및 연결
- 프로젝트 성격에 맞게 Route Table을 구성합니다.
- Public Route Table 생성 및 설정\]
- Public VPC는 인터넷과 통신하기 위해 IGW를 사용합니다.
- 이에 인터넷 라우트를 추가합니다.
# Public Route Table 생성
aws ec2 create-route-table \
--vpc-id <VPC_ID> \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=marketing-public-rt},{Key=Project,Value=marketing}]'
# Public Route Table에 인터넷 라우트(IGW) 추가
aws ec2 create-route \
--route-table-id <PUBLIC_RT_ID> \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id <IGW_ID>
# Public Subnet 1을 Public Route Table에 연결
aws ec2 associate-route-table \
--route-table-id <PUBLIC_RT_ID> \
--subnet-id <PUBLIC_SUBNET_1_ID>
# Public Subnet 2를 Public Route Table에 연결
aws ec2 associate-route-table \
--route-table-id <PUBLIC_RT_ID> \
--subnet-id <PUBLIC_SUBNET_2_ID>
- Private Route Table 생성 및 설정
- NAT Gateway에서 인터넷으로 Outbound 통신만 가능하도록 설계
# Private Route Table 생성
aws ec2 create-route-table \
--vpc-id <VPC_ID> \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=marketing-private-rt},{Key=Project,Value=marketing}]'
# Private Route Table에 NAT Gateway 라우트 추가
aws ec2 create-route \
--route-table-id <PRIVATE_RT_ID> \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id <NAT_GW_ID>
# Private Subnet 1을 Private Route Table에 연결
aws ec2 associate-route-table \
--route-table-id <PRIVATE_RT_ID> \
--subnet-id <PRIVATE_SUBNET_1_ID>
# Private Subnet 2를 Private Route Table에 연결
aws ec2 associate-route-table \
--route-table-id <PRIVATE_RT_ID> \
--subnet-id <PRIVATE_SUBNET_2_ID>
1.7 VPC Endpoint
Private Subnet에서 AWS 서비스에 직접 접근하기 위해 사용합니다. 본 프로젝트에서는 이미지 서버가 S3와 통신할 때 사용됩니다.
Security Group 생성
- Interface VPC 타입의 VPC Endpoint는 ENI(네트워크 인터페이스)를 생성하기 때문에 ,ENI에 대한 제어가 필요합니다.
# VPC Endpoints Security Group 생성
aws ec2 create-security-group \
--group-name marketing-vpc-endpoints-sg \
--description "Security group for VPC endpoints" \
--vpc-id <VPC_ID> \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=marketing-vpc-endpoints-sg},{Key=Project,Value=marketing}]'
# Ingress 규칙 추가 (HTTPS 443 from VPC CIDR)
aws ec2 authorize-security-group-ingress \
--group-id <VPC_ENDPOINTS_SG_ID> \
--protocol tcp \
--port 443 \
--cidr 172.31.0.0/16
1.8 VPC Endpoints 생성
- S3 Gateway Endpoint를 생성합니다.
# S3 Gateway Endpoint 생성
aws ec2 create-vpc-endpoint \
--vpc-id <VPC_ID> \
--service-name com.amazonaws.ap-northeast-2.s3 \
--vpc-endpoint-type Gateway \
--route-table-ids <PRIVATE_RT_ID> <PUBLIC_RT_ID> \
--tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=marketing-s3-endpoint},{Key=Project,Value=marketing}]'
- ECR Interface Endpoint를 생성합니다.
- AWS ECR에서 이미지를 Pull하는 과정이 여러 단계로 나뉘며,각 단계가 서로 다른 AWS 서비스를 호출합니다.
- 인증(STS): EKS Node가 ECR에 접근 권한이 있는지 확인(토큰 발급)
- ECR API: 이미지 메타데이터 조회
- ECR DKR: 실제 이미지 다운로드 (blob 파일들을 다운로드)
# STS Interface Endpoint 생성
aws ec2 create-vpc-endpoint \
--vpc-id <VPC_ID> \
--service-name com.amazonaws.ap-northeast-2.sts \
--vpc-endpoint-type Interface \
--subnet-ids <PRIVATE_SUBNET_1_ID> <PRIVATE_SUBNET_2_ID> \
--security-group-ids <VPC_ENDPOINTS_SG_ID> \
--private-dns-enabled \
--tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=marketing-sts-endpoint},{Key=Project,Value=marketing}]'
# ECR DKR Interface Endpoint 생성
aws ec2 create-vpc-endpoint \
--vpc-id <VPC_ID> \
--service-name com.amazonaws.ap-northeast-2.ecr.dkr \
--vpc-endpoint-type Interface \
--subnet-ids <PRIVATE_SUBNET_1_ID> <PRIVATE_SUBNET_2_ID> \
--security-group-ids <VPC_ENDPOINTS_SG_ID> \
--private-dns-enabled \
--tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=marketing-ecr-dkr-endpoint},{Key=Project,Value=marketing}]'
# ECR API Interface Endpoint 생성
aws ec2 create-vpc-endpoint \
--vpc-id <VPC_ID> \
--service-name com.amazonaws.ap-northeast-2.ecr.api \
--vpc-endpoint-type Interface \
--subnet-ids <PRIVATE_SUBNET_1_ID> <PRIVATE_SUBNET_2_ID> \
--security-group-ids <VPC_ENDPOINTS_SG_ID> \
--private-dns-enabled \
--tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=marketing-ecr-api-endpoint},{Key=Project,Value=marketing}]'
\[AWS EKS\] 2. IAM Role 설정
Cluster Policy, Node Policy
AWS EKS 및 AWS EKS에 등록된 워커 노드가 사용할 IAM Role을 생성해야합니다.
2.1 Cluster Policy: AWS EKS의 Control Plane이 사용할 IAM Role
# Trust Policy Json 파일 준비
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "eks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role \
--role-name marketing-eks-cluster-role \
--assume-role-policy-document file://eks-cluster-trust-policy.json \
--tags Key=Name,Value=marketing-eks-cluster-role Key=Project,Value=marketing
# AWS EKS Cluster Policy 연결 (Control Plane 용) = 클러스터 기본 권한
aws iam attach-role-policy \
--role-name marketing-eks-cluster-role \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
# VPC/ENI 관리
aws iam attach-role-policy \
--role-name marketing-eks-cluster-role \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSVPCResourceController
2.2 Node Policy: EKS Node Role 생성
# Trust Policy Json 파일 준비
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role \
--role-name marketing-eks-node-role \
--assume-role-policy-document file://eks-node-trust-policy.json \
--tags Key=Name,Value=marketing-eks-node-role Key=Project,Value=marketing
# AWS EKS용 Worker Node Policy 연결
aws iam attach-role-policy \
--role-name marketing-eks-node-role \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
# CNI Policy (Pod IP 할당)
aws iam attach-role-policy \
--role-name marketing-eks-node-role \
--policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
# ECR 읽기 권한
aws iam attach-role-policy \
--role-name marketing-eks-node-role \
--policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
\[AWS EKS\] 3. EKS 클러스터 생성 및 OIDC
이제 본격적으로 EKS 클러스터를 구축합니다.
3.1 AWS EKS 생성
# EKS Cluster Security Group 생성
aws ec2 create-security-group \
--group-name marketing-eks-cluster-sg \
--description "Security group for EKS cluster" \
--vpc-id <VPC_ID> \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=marketing-eks-cluster-sg},{Key=Project,Value=marketing}]'
# EKS 클러스터 생성 (10~15분 소요)
aws eks create-cluster \
--name marketing-eks \
--role-arn arn:aws:iam::<ACCOUNT_ID>:role/marketing-eks-cluster-role \
--resources-vpc-config subnetIds=<PUBLIC_SUBNET_1>,<PUBLIC_SUBNET_2>,<PRIVATE_SUBNET_1>,<PRIVATE_SUBNET_2>,securityGroupIds=<EKS_CLUSTER_SG>,endpointPublicAccess=true,endpointPrivateAccess=true \
--kubernetes-version 1.31 \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}' \
--tags Project=marketing,Environment=prod
# 클러스터 상태 확인
aws eks describe-cluster \
--name marketing-eks \
--query "cluster.status"
# ACTIVE 상태까지 대기
aws eks wait cluster-active \
--name marketing-eks
# 클러스터 정보 최종 확인
aws eks describe-cluster \
--name marketing-eks
3.2 OIDC Provider 설정 (IRSA)
특정 Pod가 AWS 서비스에 접근하려면 IAM 권한이 필요합니다.
IRSA(IAM Roles for Service Accounts)는 Pod 단위로 IAM 권한을 부여하는 방식입니다.
OIDC(OpenID Connect)는 신원 인증 프로토콜로 OAuth2.0 기반의 인증 프로토콜입니다. "이 사람이 누구인지 증명"해주는 표준 프로토콜입니다.
- Pod가 OIDC로 JWR 토큰을 보냅니다.
- OIDC는 JWT 토큰을 검증하고 이를 바탕으로 임시 자격증명을 발급해줍니다.
- Pod는 임시 자격증명을 통해 AWS 리소스에 접근할 수 있습니다.
왜 필요한가?
예전 방식은 Node에 모든 권한을 부여했습니다.
이 경우 해당 Node의 모든 Pod가 동일한 권한을 갖게 되어 보안에 취약합니다.
IRSA를 사용하면 필요한 Pod에만 필요한 권한을 부여할 수 있습니다.
# OIDC Provider URL 가져오기 (https 제거)
OIDC_PROVIDER=$(aws eks describe-cluster \
--name marketing-eks \
--query "cluster.identity.oidc.issuer" \
--output text | sed 's|https://||')
echo "OIDC_PROVIDER=${OIDC_PROVIDER}"
# 예: oidc.eks.ap-northeast-2.amazonaws.com/id/EXAMPLE1234567890
# AWS 계정 ID 가져오기
ACCOUNT_ID=$(aws sts get-caller-identity \
--query Account \
--output text)
echo "ACCOUNT_ID=${ACCOUNT_ID}"
# ALB Controller IAM Role Trust Policy 생성 (환경변수 치환)
cat <<EOF > alb-controller-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:aud": "sts.amazonaws.com",
"${OIDC_PROVIDER}:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
}
}
}
]
}
EOF
# IAM Role 생성 (AWS Load Balancer Controller용)
aws iam create-role \
--role-name AmazonEKSLoadBalancerControllerRole \
--assume-role-policy-document file://alb-controller-trust-policy.json \
--tags Key=Name,Value=AmazonEKSLoadBalancerControllerRole Key=Project,Value=marketing
# ALB Controller 정책 연결 (사전 생성된 커스텀 정책)
aws iam attach-role-policy \
--role-name AmazonEKSLoadBalancerControllerRole \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy
Kubernetes Service Account 생성
# .yaml 파일 준비
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws-load-balancer-controller
namespace: kube-system
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKSLoadBalancerControllerRole
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: aws-load-balancer-controller
# 적용
kubectl apply -f alb-controller-sa.yaml
\[AWS EKS\] 4. 노드 그룹 생성
노드 그룹은 노드가 배치되는 서브넷에 따라 나눠집니다. 퍼블릭 서브넷에 배치 퍼블릭 노드 그룹, 프라이빗 서브넷 배치 프라이빗 노드 그룹이라고 부릅니다.
4.1 Public Node Group 생성
# Public Node Group 생성
aws eks create-nodegroup \
--cluster-name marketing-eks \
--nodegroup-name marketing-public-nodes \
--node-role arn:aws:iam::<ACCOUNT_ID>:role/marketing-eks-node-role \
--subnets <PUBLIC_SUBNET_1> <PUBLIC_SUBNET_2> \
--instance-types t3.medium \
--capacity-type ON_DEMAND \
--scaling-config minSize=1,maxSize=4,desiredSize=2 \
--update-config maxUnavailable=1 \
--labels purpose=public \
--tags Project=marketing,Environment=prod
4.2 Private Node Group 생성
Private Node Group 생성에 유의점이 있습니다. BootStrap과정에서 온전히 노드가 등록되지 않고 무한 대기 상태로 빠질 수 있습니다.
BootStrap은 Worker Node가 EKS 클러스터에 등록되는 과정입니다. Node가 시작되면 bootstrap.sh 스크립트가 실행되어 kubelet을 설정하고, EKS Control Plane에 자신을 등록합니다.
Node가 정상적으로 등록되려면 다음 AWS 서비스들과 통신해야 합니다.
- EKS API Server: Node 등록 요청
- ECR: 컨테이너 이미지 Pull (kube-proxy, aws-node 등)
- S3: 이미지 레이어 다운로드
- STS: IAM 인증 토큰 발급
즉 VPC 외부와 소통이 가능해야 한다는 것입니다. Private Subnet과 VPC외부 통신을 하기 위해선 NAT Gateway가 필요합니다. 우리는 1장의 네트워크 설정에서 이미 다뤘기에 바로 생성이 가능합니다.
aws eks create-nodegroup \
--cluster-name marketing-eks \
--nodegroup-name marketing-private-nodes \
--node-role arn:aws:iam::<ACCOUNT_ID>:role/marketing-eks-node-role \
--subnets <PRIVATE_SUBNET_1> <PRIVATE_SUBNET_2> \
--instance-types t3.medium \
--capacity-type ON_DEMAND \
--scaling-config minSize=1,maxSize=4,desiredSize=2 \
--update-config maxUnavailable=1 \
--labels purpose=private \
--tags Project=marketing,Environment=prod
\[AWS EKS\] 5. ALB 설정
5.1. ALB Controller IAM Policy 생성 및 IRSA 적용
# AWS Load Balancer Controller IAM Policy 다운로드
curl -o alb-controller-policy.json \
https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.0/docs/install/iam_policy.json
# IAM Policy 생성
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://alb-controller-policy.json \
--tags Key=Name,Value=AWSLoadBalancerControllerIAMPolicy Key=Project,Value=marketing
# 변수 설정
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
OIDC_PROVIDER=$(aws eks describe-cluster \
--name marketing-eks \
--query "cluster.identity.oidc.issuer" \
--output text | sed 's|https://||')
echo "ACCOUNT_ID=${ACCOUNT_ID}"
echo "OIDC_PROVIDER=${OIDC_PROVIDER}"
# Trust Policy 생성 (IRSA)
cat <<EOF > alb-controller-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:aud": "sts.amazonaws.com",
"${OIDC_PROVIDER}:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
}
}
}
]
}
EOF
# IAM Role 생성 (AWS Load Balancer Controller용)
aws iam create-role \
--role-name AmazonEKSLoadBalancerControllerRole \
--assume-role-policy-document file://alb-controller-trust-policy.json \
--tags Key=Name,Value=AmazonEKSLoadBalancerControllerRole Key=Project,Value=marketing
# Policy 연결
aws iam attach-role-policy \
--role-name AmazonEKSLoadBalancerControllerRole \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy
5.2. ALB Controller 등록
ALB Controller는 워커노드 내 kube-system namespace에 Pod로 배포됩니다.
ALB Controller가 Ingress 리소스를 감지하면, AWS API를 호출하여 ALB(로드밸런서)를 VPC Public Subnet에 생성합니다.
# 변수 설정
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# ServiceAccount 생성 (IRSA)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws-load-balancer-controller
namespace: kube-system
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::${ACCOUNT_ID}:role/AmazonEKSLoadBalancerControllerRole
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: aws-load-balancer-controller
EOF
# Helm repo 추가 및 업데이트
helm repo add eks https://aws.github.io/eks-charts
helm repo update
# AWS Load Balancer Controller 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=marketing-eks \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set region=ap-northeast-2 \
--set vpcId=<VPC_ID>
Target Group 설정 시 직접 Pod IP를 사용하여 통신하거나, Pod를 띄운 Node IP를 설정합니다.
Node IP를 사용하는 경우, 내부 Pod와 통신하기 위해 NodePort를 등록합니다.
\[AWS EKS\] 6. Ingress 설정
6.1. Ingress예시
Ingress로 생성된 ALB는 AWS가 관리합니다. ALB에 Target Group을 설정하여 트래픽을 분배합니다.
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: marketing-ingress
namespace: default
annotations:
# ALB 생성 지정
kubernetes.io/ingress.class: alb
# 인터넷 facing (Public)
alb.ingress.kubernetes.io/scheme: internet-facing
# Public Subnet에 ALB 생성
alb.ingress.kubernetes.io/subnets: <PUBLIC_SUBNET_1>, <PUBLIC_SUBNET_2>
# Target Type (IP 모드 권장)
alb.ingress.kubernetes.io/target-type: ip
# Health Check 설정
alb.ingress.kubernetes.io/healthcheck-path: /health
alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
# 태그
alb.ingress.kubernetes.io/tags: Project=marketing,Environment=prod
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: marketing-service
port:
number: 80
\[GitOps\] 1. Github Actions
\[GitOps\] 2. AWS ECR
\[GitOps\] 3. Helm
\[GitOps\] 4. ArgoCD
