1 cloudfomation으로 명령서버 1대 생성 2 mkdir 1 cd 1 vi vpc.tf module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" name = "eks-vpc" cidr = "10.0.0.0/16" # 가용 영역 설정 (서울 리전 기준) azs = ["ap-northeast-2a", "ap-northeast-2c"] # EKS Pod가 사용할 충분한 크기의 Private Subnet (/19) private_subnets = ["10.0.32.0/19", "10.0.64.0/19"] # 로드밸런서 등이 위치할 Public Subnet public_subnets = ["10.0.0.0/22", "10.0.4.0/22"] # NAT Gateway 설정 (Private Subnet의 Pod들이 외부 통신을 하기 위해 필수) enable_nat_gateway = true single_nat_gateway = true # 비용 절감을 위해 하나만 생성 (운영환경은 false 권장) # EKS 로드밸런서 자동 인식을 위한 필수 태그 public_subnet_tags = { "kubernetes.io/role/elb" = "1" } private_subnet_tags = { "kubernetes.io/role/internal-elb" = "1" "kubernetes.io/cluster/my-eks-cluster" = "owned" } } 3 vi eks.tf module "eks" { source = "terraform-aws-modules/eks/aws" version = "~> 20.0" cluster_name = "my-eks-cluster" cluster_version = "1.34" # 최신 안정화 버전 사용 # 앞서 생성한 VPC 모듈의 출력값 연결 vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets # 클러스터 엔드포인트 접근 설정 (보안상 Private 권장) cluster_endpoint_public_access = true # Managed Node Group 설정 eks_managed_node_groups = { general = { instance_types = ["m7i-flex.large"] # 테스트용으로 적당한 사양 min_size = 1 max_size = 3 desired_size = 2 # 위에서 언급한 Prefix Delegation 활성화를 위해 필요 # (기본값으로 두어도 소규모는 문제없음) } } # 액세스 권한 관리 (현재 테라폼 실행자에게 관리자 권한 부여) enable_cluster_creator_admin_permissions = true } terraform init terraform plan terraform apply yes (10분) 4 # eks 접속 방법 aws eks update-kubeconfig --region ap-northeast-2 --name my-eks-cluster k get nodes 5 # eks에 서비스 올리기 watch -d kubectl get ing,svc,deploy,pod vi my-app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-web-app spec: replicas: 3 # 3개의 파드를 띄움 selector: matchLabels: app: my-web-app template: metadata: labels: app: my-web-app spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-web-service spec: selector: app: my-web-app ports: - protocol: TCP port: 80 # 서비스가 노출할 포트 targetPort: 80 # 파드 내부의 포트 type: NodePort # ALB 연동을 위해 NodePort 혹은 IP 모드로 설정 # 배포 명령: kubectl apply -f my-app.yaml 6 AWS Load Balancer Controller 설치법 1단계: IAM 정책 생성 컨트롤러가 AWS 서비스(ALB, Target Group 등)를 생성하고 관리할 수 있도록 권한 정책을 생성합니다 # IAM 정책 파일 다운로드 curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json # AWS IAM 정책 생성 aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json 2단계: IAM Role 및 Service Account 생성 (IRSA) EKS 클러스터의 서비스 어카운트가 위에서 만든 정책을 사용할 수 있도록 연결합니다. (OIDC 설정 포함) # CLUSTER_NAME과 ACCOUNT_ID를 본인 환경에 맞게 수정하세요. eksctl create iamserviceaccount \ --cluster=my-eks-cluster \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --role-name "AmazonEKSLoadBalancerControllerRole" \ --attach-policy-arn=arn:aws:iam::<내-계정-ID>:policy/AWSLoadBalancerControllerIAMPolicy \ --approve 3단계: Helm을 이용한 컨트롤러 설치 이제 실제 컨트롤러 소프트웨어를 클러스터에 배포합니다. # Helm 레포지토리 추가 helm repo add eks https://aws.github.io/eks-charts helm repo update # 컨트롤러 설치 helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=my-eks-cluster \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller 설치 확인 및 결과 대기 설치가 완료되면 약 1분 후 watch 화면에서 변화를 확인할 수 있습니다. (3분 걸림) 컨트롤러 작동 확인: kubectl get deployment -n kube-system aws-load-balancer-controller 7 # ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-alb-ingress annotations: # 핵심! 이 주석이 있어야 ALB가 생성됩니다. kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing # 외부 접속 허용 alb.ingress.kubernetes.io/target-type: ip # Pod IP로 직접 전달 (성능 우수) spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: my-web-service # 위에서 만든 서비스 이름 port: number: 80 kubectl apply -f ingress.yaml 웹 브라우저로 접속 확인 8 # 파드와 노드증가를 시각화 하여 확인하는 Kubeops view 설치 1 git clone https://codeberg.org/hjacobs/kube-ops-view.git cd kube-ops-view/ kubectl apply -k deploy 2 # 외부에서 kube-ops-view를 접속하기 위해서 Service Type을 LoadBalancer 로 변경한다. kubectl edit svc kube-ops-view apiVersion: v1 kind: Service metadata: annotations: name: kube-ops-view spec: .... sessionAffinity: None type: LoadBalancer status: (3분 걸림) # type: ClusterIP => type: LoadBalancer 로 수정. 17 kubectl scale deployment.apps/mario --replicas=2 kubectl scale deployment.apps/mario --replicas=30 kubectl scale deployment.apps/mario --replicas=100 kubectl scale deployment.apps/mario --replicas=10 18 work node 수 늘리기 오토스케일링 그룹 이름을 알아야 한다/ 콘솔에서 확인 EC2 > Autoscaling Group에서 이름 확인 # eks-demo aws autoscaling describe-auto-scaling-groups --query "AutoScalingGroups[? Tags[? (Key=='eks:cluster-name') && Value=='eks-demo']].[AutoScalingGroupName, MinSize, MaxSize,DesiredCapacity]" --output table echo ${ASG_NAME} # 콘솔에서 확인 , EC2 > 오토스케일링 그룹 ASG_NAME=eks-node-group-02cde5e9-a1c8-96f0-8d35-21e2db10985c ASG_NAME=eks-node-group-82ce094a-4345-3771-a444-800d1575c737 echo ${ASG_NAME} # node를 5로 aws autoscaling update-auto-scaling-group --auto-scaling-group-name ${ASG_NAME} --min-size 2 --desired-capacity 5 --max-size 6 (i-0343e26104cfd2180@eks-demo:N/A) [root@kops-ec2 kube-ops-view]# k get no NAME STATUS ROLES AGE VERSION ip-192-168-20-86.ap-northeast-2.compute.internal Ready 43m v1.34.2-eks-ecaa3a6 ip-192-168-28-28.ap-northeast-2.compute.internal NotReady 5s v1.34.2-eks-ecaa3a6 ip-192-168-33-16.ap-northeast-2.compute.internal Ready 43m v1.34.2-eks-ecaa3a6 ip-192-168-92-134.ap-northeast-2.compute.internal Ready 43m v1.34.2-eks-ecaa3a6 ip-192-168-92-162.ap-northeast-2.compute.internal NotReady 5s v1.34.2-eks-ecaa3a6 (i-0343e26104cfd2180@eks-demo:N/A) [root@kops-ec2 kube-ops-view]# #node 1로 aws autoscaling update-auto-scaling-group --auto-scaling-group-name ${ASG_NAME} --min-size 1 --desired-capacity 1 --max-size 6 aws autoscaling update-auto-scaling-group --auto-scaling-group-name ${ASG_NAME} --min-size 1 --desired-capacity 3 --max-size 6 <5> 도메인(Route53> 연결 9 # ingress-https.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-alb-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip # --- HTTPS 설정 추가 --- alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:123456789012:certificate/xxxx-xxxx # 복사한 ARN 입력 alb.ingress.kubernetes.io/ssl-redirect: '443' # HTTP 접속 시 HTTPS로 자동 리다이렉트 spec: rules: - host: api.example.com # 본인의 도메인 입력 http: paths: - path: / pathType: Prefix backend: service: name: my-web-service port: number: 80 # ingress-https.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-alb-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip # --- HTTPS 설정 추가 --- alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]' alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:588752323301:certificate/d8afb231565a6 # 복사한 ARN 입력 alb.ingress.kubernetes.io/ssl-redirect: '443' # HTTP 접속 시 HTTPS로 자동 리다이렉트 spec: rules: - host: nct-api.seoul.ai.kr # 본인의 도메인 입력 http: paths: - path: / pathType: Prefix backend: service: name: my-web-service port: number: 80 kubectl apply -f ingress-https.yaml 10 ExternalDNS 설치 가이드 (Route 53 기준) 1단계: Route 53 호스팅 영역 ID 확인 먼저 도메인이 등록된 Route 53의 Hosted Zone ID를 알아야 합니다. aws route53 list-hosted-zones-by-name --dns-name "example.com" aws route53 list-hosted-zones-by-name --dns-name "nct-seoul.ai.kr" 2단계: IAM 정책 및 Role 생성 ExternalDNS가 Route 53 레코드를 수정할 수 있는 권한을 부여합니다. 1. 정책 파일 생성 (external-dns-policy.json) vi external-dns-policy.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["route53:ChangeResourceRecordSets"], "Resource": ["arn:aws:route53:::hostedzone/*"] }, { "Effect": "Allow", "Action": ["route53:ListHostedZones", "route53:ListResourceRecordSets"], "Resource": ["*"] } ] } 2. IAM 정책 생성 및 Service Account 연결 aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://external-dns-policy.json eksctl create iamserviceaccount \ --cluster=<내-클러스터-이름> \ --name=external-dns \ --namespace=default \ --attach-policy-arn=arn:aws:iam::<계정-ID>:policy/AllowExternalDNSUpdates \ --approve eksctl create iamserviceaccount \ --cluster=my-eks-cluster \ --name=external-dns \ --namespace=default \ --attach-policy-arn=arn:aws:iam::588752323301:policy/AllowExternalDNSUpdates \ --approve 3단계: Helm을 이용한 설치 가장 관리하기 쉬운 bitnami 차트를 사용합니다. helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update helm install external-dns bitnami/external-dns \ --set provider=aws \ --set aws.zoneType=public \ --set txtOwnerId=<호스팅-영역-ID> \ --set serviceAccount.create=false \ --set serviceAccount.name=external-dns helm install external-dns bitnami/external-dns \ --set provider=aws \ --set aws.zoneType=public \ --set txtOwnerId=Z04036953JFXQ3X89C70V \ --set serviceAccount.create=false \ --set serviceAccount.name=external-dns <호스팅-영역-ID> 는 Z로 시작 aws route53 list-hosted-zones --query "HostedZones[?Name=='nct-seoul.ai.kr.'].Id" --output text /hostedzone/Z04036953JFXQ3X89C70V Ingress에 도메인 적용하기 이제 기존에 작성하신 Ingress YAML에 host 필드를 추가하면 ExternalDNS가 이를 감지하고 Route 53에 A 레코드를 생성합니다. # 인그레스 파일 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-alb-ingress annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip spec: rules: - host: api.nct-seoul.ai.kr # <--- 여기에 사용할 실제 도메인을 적으세요! http: paths: - path: / pathType: Prefix backend: service: name: my-web-service port: number: 80 kubectl set image deployment/external-dns external-dns=registry.k8s.io/external-dns/external-dns:v0.14.2 정상 작동 확인 로그 확인: kubectl logs -f $(kubectl get po -l app.kubernetes.io/name=external-dns -o jsonpath='{.items[0].metadata.name}') 명령어를 통해 "All records are up to date" 메시지가 나오는지 확인하세요. Route 53 확인: AWS 콘솔의 Route 53 레코드 목록에 ALB 주소를 가리키는 새로운 레코드가 생겼는지 확인합니다.