<0> EKS 구축 # EC2 로그인 cat <<'EOF' > eks-cluster.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-eks-cluster region: ap-northeast-2 managedNodeGroups: - name: standard-nodes instanceType: c7i-flex.large minSize: 1 maxSize: 3 EOF eksctl create cluster -f eks-cluster.yaml <1> 환경 설정 export CLUSTER_NAME="my-eks-cluster" export REGION="ap-northeast-2" export ACCOUNT_ID="588752323301" # 클러스터용 IAM OIDC 자격 증명 공급자 생성 eksctl utils associate-iam-oidc-provider \ --region ${REGION} \ --cluster ${CLUSTER_NAME} \ --approve # CLUSTER_NAME 확인법 aws eks list-clusters --region ap-northeast-2 # REGION 확인법 aws configure get region kubectl config current-context - # ACCOUNT_ID 확인 aws sts get-caller-identity --query Account --output text 2 # 1. IAM 정책 JSON 다운로드 (v2.7.2 기준) curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/docs/install/iam_policy.json # 2. IAM 정책 생성 aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json # 1. EKS 클러스터에 IAM OIDC 공급자 활성화 eksctl utils associate-iam-oidc-provider \ --region=ap-northeast-2 \ --cluster=my-eks-cluster \ --approve # 2. 서비스 어카운트 생성 다시 시도 eksctl create iamserviceaccount \ --cluster=my-eks-cluster \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --role-name AmazonEKSLoadBalancerControllerRole \ --attach-policy-arn=arn:aws:iam::588752323301:policy/AWSLoadBalancerControllerIAMPolicy \ --approve 3 # Helm 리포지토리 추가 및 업데이트 helm repo add eks https://aws.github.io/eks-charts helm repo update # ALB Controller 설치 helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=${CLUSTER_NAME} \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller k ns k ns kube-system 4 mkdir -p k8s-alb cat <<'EOF' > k8s-alb/app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-app spec: replicas: 2 selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: sample-app-svc spec: # ALB의 target-type이 'ip'일 경우 ClusterIP로 충분합니다. type: ClusterIP selector: app: sample-app ports: - port: 80 targetPort: 80 EOF kubectl apply -f k8s-alb/app.yaml 5 # 본인의 실제 ACM 인증서 ARN을 아래 따옴표 안에 넣어주세요. export MY_ACM_ARN="arn:aws:acm:ap-northeast-2:588752323301:certificate/aabf7b94-b987-44ad-bccb-7da40e3bbae0" cat < k8s-alb/ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: sample-app-ingress annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip # 80 포트(HTTP)로 접속 시 443 포트(HTTPS)로 자동 리다이렉트 alb.ingress.kubernetes.io/ssl-redirect: '443' # 트래픽을 수신할 포트 설정 alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' # 발급받은 ACM 인증서 ARN 연결 alb.ingress.kubernetes.io/certificate-arn: ${MY_ACM_ARN} spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: sample-app-svc port: number: 80 EOF kubectl apply -f k8s-alb/ingress.yaml watch -d kubectl get ing,svc,pods,no,deploy,rs NAME CLASS HOSTS ADDRESS PORTS AGE ingress.networking.k8s.io/sample-app-ingress alb * k8s-kubesyst-sampleap-435ab6a5b5-798317758.ap-northeast-2.elb.amazonaws.com 80 12m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE # alb 도메인 안 나올시 아래로 트라블 슈팅 # kubectl describe ingress sample-app-ingress 6 kubectl get ingress sample-app-ingress ---------------- <2> # AWS Route 53에서 호스팅 영역을 구성한 뒤, ACM 인증서를 발급 1 # 구입하신 실제 도메인 이름으로 변경해 주세요. (예: my-flask-app.com) export YOUR_DOMAIN="nct-seoul.ai.kr" export REGION="ap-northeast-2" 2 # 호스팅 영역 생성 aws route53 create-hosted-zone \ --name ${YOUR_DOMAIN} \ --caller-reference $(date +%s) # 생성된 네임서버(NS) 4개 주소 확인 aws route53 list-hosted-zones-by-name \ --dns-name ${YOUR_DOMAIN} \ --query "HostedZones[0].Id" --output text | \ xargs -I {} aws route53 get-hosted-zone --id {} \ --query "DelegationSet.NameServers" --output table 3 # 인증서 발급 요청 aws acm request-certificate \ --domain-name "*.${YOUR_DOMAIN}" \ --subject-alternative-names "${YOUR_DOMAIN}" \ --validation-method DNS \ --region ${REGION} # 방금 요청한 인증서의 ARN 확인 및 변수 저장 export ACM_ARN=$(aws acm list-certificates \ --region ${REGION} \ --query "CertificateSummaryList[?DomainName=='*.${YOUR_DOMAIN}'].CertificateArn" \ --output text) echo "발급된 ACM ARN: $ACM_ARN" 4 # 발급된 ACM ARN 확인 echo $ACM_ARN <3> 내 실제 도메인(example.com)으로 연결 생성된 EKS 로드밸런서의 긴 주소(k8s-sampleap...elb.amazonaws.com)를 내 실제 도메인(example.com)으로 연결해 주는 Route 53 A 레코드 (별칭, Alias) 세팅 방법 1 # 1. Ingress에서 로드밸런서 DNS 주소 가져오기 export ALB_HOSTNAME=$(kubectl get ingress sample-app-ingress -o jsonpath="{.status.loadBalancer.ingress[0].hostname}") echo "로드밸런서 주소: $ALB_HOSTNAME" # 2. 해당 로드밸런서의 Canonical Hosted Zone ID 가져오기 export ALB_ZONE_ID=$(aws elbv2 describe-load-balancers \ --query "LoadBalancers[?DNSName=='$ALB_HOSTNAME'].CanonicalHostedZoneId" \ --output text) echo "로드밸런서 Zone ID: $ALB_ZONE_ID" # 3. 내 도메인의 Route 53 Hosted Zone ID 가져오기 export DOMAIN_ZONE_ID=$(aws route53 list-hosted-zones-by-name \ --dns-name ${YOUR_DOMAIN} \ --query "HostedZones[0].Id" --output text | awk -F'/' '{print $3}') echo "내 도메인 Zone ID: $DOMAIN_ZONE_ID" 2 cat < route53-record.json { "Comment": "Create Alias record for EKS ALB", "Changes": [ { "Action": "UPSERT", "ResourceRecordSet": { "Name": "${YOUR_DOMAIN}", "Type": "A", "AliasTarget": { "HostedZoneId": "${ALB_ZONE_ID}", "DNSName": "dualstack.${ALB_HOSTNAME}", "EvaluateTargetHealth": true } } } ] } EOF 3 aws route53 change-resource-record-sets \ --hosted-zone-id ${DOMAIN_ZONE_ID} \ --change-batch file://route53-record.json 4 curl -I https://${YOUR_DOMAIN} echo @${YOUR_DOMAIN} https://nct-seoul.ai.kr/ <4> www3 으로 연결하기 1 echo "로드밸런서 주소: $ALB_HOSTNAME" ZONE_ID="Z04036953JFXQ3X89C70V" DOMAIN="www3.nct-seoul.ai.kr" TARGET="k8s-kubesyst-sampleap-435ab6a5b5-798317758.ap-northeast-2.elb.amazonaws.com" aws route53 change-resource-record-sets --hosted-zone-id $ZONE_ID --change-batch "{ \"Changes\": [ { \"Action\": \"UPSERT\", \"ResourceRecordSet\": { \"Name\": \"$DOMAIN.\", \"Type\": \"CNAME\", \"TTL\": 300, \"ResourceRecords\": [{\"Value\": \"$TARGET\"}] } } ] }" # 기존에 있는 www3 이면 에러 남. 없는것으로 하세요. 2 aws route53 list-hosted-zones-by-name \ --dns-name yourdomain.com \ --query "HostedZones[0].Id" \ --output text | sed 's/\/hostedzone\///' Z04036953JFXQ3X89C70V -------------- <5> 삭제 1 # 1. Ingress 삭제 (AWS ALB가 함께 삭제됨) kubectl delete -f k8s-alb/ingress.yaml # 2. 테스트용 Deployment 및 Service 삭제 kubectl delete -f k8s-alb/app.yaml 2 helm uninstall aws-load-balancer-controller -n kube-system 3 export CLUSTER_NAME="my-eks-cluster" export ACCOUNT_ID="588752323301" # 1. 서비스 어카운트 삭제 (연결된 IAM 역할도 함께 삭제됨) eksctl delete iamserviceaccount \ --cluster=${CLUSTER_NAME} \ --namespace=kube-system \ --name=aws-load-balancer-controller # 2. 다운로드했던 IAM 정책 삭제 aws iam delete-policy \ --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/AWSLoadBalancerControllerIAMPolicy 4 terraform destroy -auto-approve eksctl delete cluster --name my-eks-cluster