이 문서는 노드 그룹을 생성하고, ECR에 Nginx 도커 이미지를 업로드한 후 이를 EKS에 배포하는 방법을 설명합니다.
먼저 EKS 노드에 사용되는 역할 정책은 최소한으로 하여 IAM 역할을 생성합니다.
1단계 - 엔터티 유형 및 서비스 설정
엔터티 유형은 AWS 서비스를, 서비스는 EC2를 선택합니다.
2단계 - 권한 정책 설정
필요한 최소한의 권한 정책을 추가합니다.
AmazonEKSWorkerNodePolicy - EKS 워커 노드가 EKS 클러스터에 연결할 수 있도록 허용
AmazonEC2ContainerRegistryReadOnly - ECR 컨테이너 이미지 사용
AmazonEKS_CNI_Policy - VPC CNI 플러그인에 EKS 워커 노드의 IP 주소 구성을 수정할 때 사용
3단계 - 설정 정보 검토
역할의 이름을 입력하고 선택한 엔터티 유형과 권한 정책을 확인한 후 역할을 생성합니다.
시작 템플릿을 사용하여 노드를 생성하는 경우에는 먼저 EC2 콘솔 > Launch Templates 으로 이동하여 시작 템플릿을 생성합니다.
1단계 - 시작 템플릿 이름 및 설명
시작 템플릿 이름 및 설명을 입력하고 원본 템플릿이 있는 경우 원본 템플릿과 버전을 지정할 수 있습니다.
2단계 - 애플리케이션 및 OS 이미지(AMI)
Amazon EKS 사용자 가이드를 참고하여 Amazon EKS에 최적화된 AMI를 선택합니다.# Amazon EKS에 최적화된 Amazon Linux AMI ID 검색 aws ssm get-parameter --name /aws/service/eks/optimized-ami/<KUBERNETES_VERSION>/<AMI_TYPE>/recommended/image_id \ --region <REGION_CODE> --query "Parameter.Value" --output text
KEY VALUE KUBERNETES_VERSION 1.30 Amazon EKS 버전 AMI_TYPE amazon-linux-2 Amazon Linux 2 x86 기반 인스턴스 amazon-linux-2-arm64 Amazon Linux 2 ARM 기반 인스턴스 amazon-linux-2023/x86_64/standard Amazon Linux 2023 x86 기반 인스턴스
(AL2023부터 /etc/eks/bootstrap.sh 대신 nodeadm 사용)amazon-linux-2023/arm64/standard Amazon Linux 2023 ARM 기반 인스턴스
(AL2023부터 /etc/eks/bootstrap.sh 대신 nodeadm 사용)REGION_CODE ap-northeast-2 EKS 지원 AWS 리전 코드
3단계 - (옵션) 인스턴스 유형
원하는 요건에 맞는 인스턴스 유형을 선택합니다.
4단계 - (옵션) 키 페어
인스턴스 연결에 사용할 키 페어를 선택합니다.
5단계 - (옵션) 네트워크 설정
네트워크 인터페이스가 위치한 서브넷과 보안 그룹을 선택합니다.
6단계 - 스토리지(볼륨)
인스턴스에 대한 스토리지 옵션을 설정합니다.
7단계 - (옵션) 리소스 태그
시작 템플릿에 포함할 리소스 태그를 추가합니다.
8단계 - 사용자 데이터 설정
노드가 EKS 클러스터에 정상적으로 연결되고 필요한 설정이 적용되도록 고급 세부 정보의 사용자 데이터를 설정합니다.
Amazon Linux 2인 경우 (/etc/eks/bootstrap.sh)#!/bin/bash set -ex /etc/eks/bootstrap.sh <CLUSTER_NAME> --kubelet-extra-args "--node-labels=alpha.eksctl.io/cluster-name=<CLUSTER_NAME>,alpha.eksctl.io/nodegroup-name=<NODEGROUP_NAME>,eks.amazonaws.com/nodegroup=<NODEGROUP_NAME>,eks.amazonaws.com/nodegroup-image=<CUSTOM_AMI_ID>"Amazon Linux 2023인 경우 (nodeadm)
aws eks describe-cluster --name <CLUSTER_NAME> --region <REGION_CODE>EKS 콘솔에서 클러스터 세부 정보를 확인하거나 AWS CLI 명령어를 사용하여 클러스터 세부 정보를 확인할 수 있습니다.
확인한 정보를 사용하여 사용자 데이터를 구성합니다.MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOUNDARY" --BOUNDARY Content-Type: application/node.eks.aws --- apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: cluster: name: <CLUSTER_NAME> apiServerEndpoint: <API_SERVER_ENDPOINT> certificateAuthority: <CERTIFICATE_AUTHORITY> cidr: <K8S_NETWORK_CIDR> --BOUNDARY--
EKS 클러스터의 노드 그룹은 시작 템플릿과 사용자 지정 AMI를 사용하여 생성하는 방법과 시작 템플릿을 사용하지 않는 방법이 있습니다.
EKS 클러스터 콘솔 > 컴퓨팅 탭에서 노드 그룹을 추가를 선택합니다.

1단계 - 노드 그룹 구성
이름, 노드 IAM 역할 등을 입력합니다.
시작 템플릿을 사용하는 경우 더욱 다양하게 노드 그룹을 커스텀할 수 있습니다.
2단계 - 컴퓨팅 및 조정 구성 설정
AMI, 용량, 인스턴스 유형 등을 선택하고 노드 수를 지정합니다.
3단계 - 네트워크 지정
관리형 노드를 시작할 서브넷을 선택합니다.
노드에 원격으로 접속하는 경우 액세스 허용을 활성화하고 노드 인스턴스에 접속 시 사용할 키페어와 허용 대상을 선택합니다.
노드에 대한 액세스를 IP로 제한하는 경우, 아래 설정을 참고하여 보안 그룹을 생성하고 생성한 보안 그룹을 적용합니다.
유형 - SSH
프로토콜 - TCP
포트 - 22
소스 - 액세스할 소스
노드 그룹 설정 파일을 구성한 후 eksctl을 사용하여 생성하는 방법도 있습니다.
1단계 - 노드 그룹 설정 파일 구성
apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: <CLUSTER_NAME> # 클러스터 이름 (Cluster와 일치해야 함) region: <REGION_CODE> # AWS 리전 (Cluster와 일치해야 함) vpc: id: <VPC_ID> # 기존 VPC ID / 새로 생성도 가능 subnets: private: # Private 서브넷 환경에 맞게 AZ, 서브넷 ID 변경 ap-northeast-2a: { id: <SUBNET_ID> } ap-northeast-2c: { id: <SUBNET_ID> } securityGroup: <SG_ID> managedNodeGroups: - name: <NODEGROUP_NAME> # 클러스터의 노드 그룹명 instanceType: <INSTANCE_TYPE> # 클러스터 워커 노드의 인스턴스 타입 instanceName: <NODE_INSTANCE_NAME> desiredCapacity: 1 # 원하는 노드 수 minSize: 1 # 최소 노드 수 maxSize: 2 # 최대 노드 수 volumeSize: 20 # 클러스터 워커 노드의 EBS 용량 (단위: GiB) privateNetworking: true iam: withAddonPolicies: # 1. Addon 사용하는 경우 imageBuilder: true # Amazon ECR에 대한 권한 추가 albIngress: true # albIngress에 대한 권한 추가 cloudWatch: true # cloudWatch에 대한 권한 추가 autoScaler: true # auto scaling에 대한 권한 추가 instanceRoleARN: <ROLE_ARN> # 2. 자체 role 사용하는 경우2단계 - 노드 그룹 생성
설정 파일을 사용하여 노드 그룹을 생성합니다.
생성 과정은 AWS 콘솔의 CloudFormation에서 확인 가능합니다.eksctl create nodegroup --config-file <FILE_NAME>
클러스터 내에서 리소스를 그룹화하고 격리하여 쉽게 관리할 수 있도록 네임스페이스를 생성합니다.
kubectl create namespace <NAMESPACE_NAME>
Docker 이미지를 올리기 위해 Amazon ECR(Elastic Container Registry)를 생성합니다.
1단계 - 일반 설정
리포지토리 공개 여부, 이름, 태그 불변성 설정을 합니다.
태그 변경 불가능 설정은 리포지토리의 이미지 태그를 덮어쓸 수 있는지 여부를 결정합니다.
2단계 - 이미지 스캔 설정
리포지토리에 푸시할 때 이미지 자동 스캔 여부를 결정합니다.
3단계 - 암호화 설정
AWS KMS(Key Management Service)를 사용하여 저장된 이미지 암호화 여부를 결정합니다.
기본 명령어
aws ecr create-repository \ --repository-name <REPO_NAME> \ --region <AWS_REGION>기본 명령어에 아래 옵션들을 활용하여 ECR을 생성할 수 있습니다.
태그 불변성--image-tag-mutability IMMUTABLE이미지 스캔 여부
--image-scanning-configuration scanOnPush=true암호화 여부
--encryption-configuration encryptionType=KMS
nginx 기본 페이지를 띄우기 위해서 ECR에 Nginx 이미지를 업로드합니다.
1. ECR 로그인
ECR에 이미지를 푸시하기 위해 인증 토큰을 가져와 docker login 명령어를 실행합니다.aws ecr get-login-password --region <REGION_CODE> | docker login --username AWS --password-stdin <ACCOUNT_ID>.dkr.ecr.<REGION_CODE>.amazonaws.com2. Nginx 이미지 다운로드
docker pull nginx:latest3. 이미지 태그
docker tag nginx:latest <ACCOUNT_ID>.dkr.ecr.<REGION_CODE>.amazonaws.com/<REPOSITORY_NAME>:latest4. ECR에 이미지 푸시
docker push <ACCOUNT_ID>.dkr.ecr.<REGION_CODE>.amazonaws.com/<REPOSITORY_NAME>:latest(옵션) '/' 경로가 아닌 다른 경로로 접근하는 경우
Nginx에서 별도 경로(ex. /nginx)로 접근을 처리하려면 'default.conf'파일에 /nginx 경로에 대한 location 블록을 추가해야합니다.
Kubernetes 클러스터의 AWS Load Balancer Controller를 설치하기 위해선 Helm, 매니페스트 등 다양한 방법이 있지만 해당 문서에서는 매니페스트를 사용하여 기능을 설치해보도록 하겠습니다.
서브넷에 로드 밸런서를 배포하려는 경우 태그 설정이 필요합니다.
퍼블릭 서브넷
- Key - kubernetes.io/role/elb
- Value - 1
프라이빗 서브넷- Key - kubernetes.io/role/internal-elb
- Value - 1
이외에도 Kubernetes 버전에 따라 추가로 태그 설정이 필요한 경우가 있습니다.
Kubernetes 클러스터 버전이 1.14 이하인 경우
Amazon EKS에서 지정된 VPC에 다음 태그를 추가해야합니다.
- Key - kubernetes.io/cluster/<CLUSTER_NAME>
- Value - owned
Kubernetes 클러스터 버전이 1.18 이하인 경우
Amazon EKS에서 지정된 서브넷에 다음 태그를 추가해야합니다.- Key - kubernetes.io/cluster/<CLUSTER_NAME>
- Value - shared
IAM 콘솔에 AmazonEKSLoadBalancerControllerRole이 있는지 확인하고 있는 경우에는 2-3. IAM 역할 생성로 이동합니다.
2-1. IAM 정책 다운로드
사용자 대신 AWS API를 호출할 수 있는 AWS Load Balancer Controller의 IAM 정책을 다운로드합니다.curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/docs/install/iam_policy.json2-2. IAM 정책 생성
다운로드한 정책을 사용하여 IAM 정책을 생성합니다.aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json2-3. IAM 역할 생성
eksctl을 사용하여 IAM 역할을 생성합니다.eksctl create iamserviceaccount \ --cluster=<CLUSTER_NAME> \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --role-name AmazonEKSLoadBalancerControllerRole \ --attach-policy-arn=arn:aws:iam::<ACCOUNT_ID>:policy/AWSLoadBalancerControllerIAMPolicy \ --region=<REGION_CODE> \ --approve
인증서 구성을 웹훅에 삽입할 수 있도록 cert-manager를 설치합니다.
cert-manager는 쿠버네티스 클러스터 내에서 TLS인증서를 자동으로 프로비저닝 및 관리하는 오픈 소스입니다.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.5/cert-manager.yaml
4-1. 설정 파일 다운로드
컨트롤러 사양을 다운로드합니다.curl -Lo v2_7_2_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.7.2/v2_7_2_full.yaml4-2. 다운로드한 파일 수정
다음 명령을 실행하여 매니페스트에서 ServiceAccount 섹션을 제거합니다.sed -i.bak -e '612,620d' ./v2_7_2_full.yaml다른 버전의 파일을 다운받은 경우 해당 내용을 제거합니다.
apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: controller app.kubernetes.io/name: aws-load-balancer-controller name: aws-load-balancer-controller namespace: kube-system ---Deployment spec 섹션에 있는 my-cluster를 생성한 클러스터 이름으로 변경합니다.
sed -i.bak -e 's|your-cluster-name|<CLUSTER_NAME>|' ./v2_7_2_full.yaml4-3. AWS Load Balancer Controller 적용
kubectl apply -f v2_7_2_full.yaml4-4. IngressClass 다운로드
IngressClass 및 IngressClassParams 매니페스트를 클러스터에 다운로드합니다.curl -Lo v2_7_2_ingclass.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.7.2/v2_7_2_ingclass.yaml4-5. IngressClass 적용
IngressClass 매니페스트를 클러스터에 적용합니다.kubectl apply -f v2_7_2_ingclass.yaml4-6. Controller 설치 확인
kubectl get deployment -n kube-system aws-load-balancer-controller
1-1. Deployment YAML 파일 구성
apiVersion: apps/v1 kind: Deployment metadata: name: <DEPLOYMENT_NAME> namespace: <NAMESPACE_NAME> spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: <ECR_URI> ports: - containerPort: 801-2. Deployment 적용
kubectl apply -f deployment.yaml
2-1. Service YAML 파일 구성
apiVersion: v1 kind: Service metadata: name: <SERVICE_NAME> namespace: <NAMESPACE_NAME> spec: type: NodePort ports: - port: 80 targetPort: 80 selector: app: nginx2-2. Service 적용
kubectl apply -f service.yaml
3-1. Ingress YAML 파일 구성
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: <INGRESS_NAME> namespace: <NAMESPACE_NAME> annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/type: instance alb.ingress.kubernetes.io/load-balancer-name: <ALB_NAME> spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: <SERVICE_NAME> port: number: 803-2. Ingress 적용
kubectl apply -f ingress.yaml3-3. Ingress 확인
kubectl get ingress <INGRESS_NAME> -n <NAMESPACE_NAME>
Ingress 배포 후 생성된 로드밸런서는 AWS 콘솔 > EC2 > 로드밸런서에서 확인할 수 있습니다.
로드밸런서의 DNS 정보를 활용하여 접속하면 nginx 기본 페이지가 노출됩니다.
Ingress를 배포한 후에도 로드밸런서를 확인할 수 없다면 다음과 같은 명령어를 사용하여 원인을 파악할 수 있습니다.
로드밸런서 컨트롤러 로그
kubectl logs -f -n <NAME_SPACE> -l app.kubernetes.io/name=aws-load-balancer-controller