본문 바로가기
스터디 이야기/25' AWS EKS

AWS ECR과 EKS 연동을 통한 컨테이너 이미지 배포하기

by lakescript 2025. 2. 9.
728x90

 

Overview

AWS ECR



ECR(Elastic Container Registry)이란?

AWS ECR(Amazon Elastic Container Registry)은 AWS에서 제공하는 완전 관리형 컨테이너 레지스트리 서비스로, Docker 및 OCI(Open Container Initiative) 기준에 맞춘 컨테이너 이미지와 artifact들을 안전하고 안정적으로 저장하며 관리할 수 있습니다.

 

주요 개념

Registry

Public Registry

public.ecr.aws/<registry_alias>/<repository_name>:<image_tag>

위와 같은 URL 형식을 가지며, 생성된 public 레지스트리는 Amazon ECR Public 갤러리에 공개되며, 공개적으로 접근할 수 있습니다. 

 

Private Registry

https://aws_account_id.dkr.ecr.region.amazonaws.com.


위와 같은 URL 형식을 같고, 계정 소유자는 레지스트리에 대한 read, write 권한을 가지지만 API 호출 및 image push/pull 작업을 수행하려면 추가적인 IAM 권한이 필요합니다.

 

Repository

Docker 이미지, Open Container Initiative(OCI) 이미지 등을 저장하고 관리하는 공간으로, 단일 Amazon ECR 레지스트리 내에서 여러 리포지토리를 사용하여 컨테이너 이미지를 구성할 수 있습니다.

 

네임스페이스 지원

네임스페이스를 지원하여 유사한 리포지토리를 그룹화할 수 있습니다. 예를 들어, frontend팀은 team-front, backend팀은 team-back 같이 네임스페이스를 사용하여 각 팀의 이미지를 구분할 수 있습니다.

 

이미지 복제

이미지는 동일한 Registry 내에서 리전 및 계정 간에 다른 리포지토리로 복제할 수 있습니다.

 

Registry와 Repository의 차이점
레지스트리(Registry)는 AWS 계정마다 하나의 ECR 레지스트리를 가지며, 레지스트리 ID는 AWS 계정 ID와 동일합니다. 반면, 레포지토리(Repository)는 ECR 레지스트리 내에서 Docker 이미지들을 그룹화하는 단위로 하나의 애플리케이션이나 서비스에 대한 여러 이미지 버전들을 저장합니다. 

즉, ECR에서는 레지스트리가 최상위 개념이고, 그 안에 여러 레포지토리들이 존재하는 구조입니다.

 

인증

Amazon Elastic Container Registry(Amazon ECR)에서 Private Registry에 접근하려면 인증이 필요합니다. 

 

AWS CLI를 통한 인증

 

aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com

 

 

aws ecr get-login-password 명령을 사용하여 인증 토큰을 생성하고, 이를 docker login 명령과 함께 사용하여 Docker 클라이언트를 Amazon ECR에 인증합니다.

 

Amazon ECR Docker 자격 증명 헬퍼 사용

 

 

GitHub - awslabs/amazon-ecr-credential-helper: Automatically gets credentials for Amazon ECR on docker push/docker pull

Automatically gets credentials for Amazon ECR on docker push/docker pull - awslabs/amazon-ecr-credential-helper

github.com

Docker 자격 증명 헬퍼를 제공하여 Docker 클라이언트가 Amazon ECR과 상호 작용할 때 자격 증명을 자동으로 관리할 수 있도록 지원합니다.

 

 

HTTP API를 통한 인증

TOKEN=$(aws ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken')
curl -i -H "Authorization: Basic $TOKEN" https://<aws_account_id>.dkr.ecr.<region>.amazonaws.com/v2/<repository_name>/tags/list

 

HTTP 요청 시 Authorization 헤더에 AWS CLI의 get-authorization-token 명령으로 얻은 토큰을 포함해야 합니다.

 

수명 주기 정책

https://docs.aws.amazon.com/ko_kr/AmazonECR/latest/userguide/LifecyclePolicies.html#lifecycle-policy-howitworks

 

오래되거나 사용되지 않는 이미지를 자동으로 정리하고 만료시키는 규칙을 정의하여 스토리지를 효율적으로 관리합니다. 이를 통해 오래되거나 사용되지 않는 이미지를 자동으로 정리하고 만료시킬 수 있습니다.

 

동작 방식
  1. 하나 이상의 테스트 규칙을 생성합니다.
  2. 테스트 규칙을 저장하고 미리 보기를 실행합니다.
  3. 수명 주기 정책 평가자는 모든 규칙을 살펴보고 각 규칙이 영향을 주는 이미지를 표시합니다.
  4. 그런 다음 수명 주기 정책 평가기는 규칙 우선순위에 따라 규칙을 적용하고 리포지토리에서 만료되도록 설정된 이미지를 표시합니다.
  5. 테스트 결과를 검토하여 만료될 것으로 표시된 이미지가 의도한 이미지인지 확인합니다.
  6. 리포지토리에 대한 수명 주기 정책으로 테스트 규칙을 적용합니다.
  7. 수명 주기 정책을 생성하면, 이미지가 만료 기준에 부합한 뒤 24시간 이내에 만료될 것으로 예상해야 합니다.

 

평가 규칙
- 모든 규칙이 동시에 평가되며, 평가가 끝나면 우선순위에 따라 규칙이 적용됩니다.
   이때, 하나의 이미지에 대해 정확히 한 개의 규칙만 적용되거나, 어떤 규칙에도 해당하지 않으면 아무 작업도 하지 않습니다.
- 태그 조건에 맞는 이미지는 우선순위가 낮은 규칙에 의해 만료되지 않습니다.
   즉, 높은 우선순위의 규칙이 이미지를 "선택"하면, 그 이미지는 다른 규칙으로는 처리되지 않습니다.
- 규칙들은 서로 다른 태그 접두사(예: prod-)를 기준으로 이미지를 선택해야 하며, 중복된 태그 접두사를 사용할 수 없습니다.
- 매니페스트 목록(이미지 그룹)을 참조하는 이미지가 있다면, 매니페스트 목록을 먼저 삭제해야 해당 이미지를 만료시킬 수 있습니다.
   또한, 만료 작업은 푸시된 시점 기준으로 항상 가장 오래된 이미지부터 처리됩니다.
- tagPatternList(패턴) 또는 tagPrefixList(접두사 목록) 중 하나만 사용할 수 있습니다. (둘을 동시에 사용할 수는 없습니다.)
   이때,  패턴(tagPatternList)을 사용할 때는 와일드카드를 써서 태그를 더 유연하게 매칭할 수 있습니다.
    (prod*는 prod, prod1, production-team1과 같은 태그와 일치)

 

이미지 스캔

컨테이너 이미지의 소프트웨어 취약성을 식별하는 통합 이미지 스캔 기능을 제공합니다. 이때, 기본 스캔과 고급 스캔으로 나눠지며 각 특징에 대해 알아보겠습니다.

 

기본 스캔

운영 체제(OS) 패키지의 취약성을 검사합니다. 스캔의 빈도를 설정할 수 있는데, 이미지를 repository에 푸시할 때마다 자동으로 스캔하는 푸시 시 스캔과 사용자가 필요에 따라 수동으로 스캔할 수 있는 수동 스캔이 있습니다.

 

고급 스캔

Amazon Inspector와 통합되어 운영 체제 및 프로그래밍 언어 패키지의 취약성을 모두 검사합니다. 고급 스캔에서도 기본 스캔과 마찬가지로 스캔 빈도를 설정할 수 있습니다. 하지만 이미지를 repository에 푸시할 때 자동으로 스캔하는 푸시 시 스캔은 동일하나 repository를 지속적으로 모니터링하여 새로운 취약성이 발견되면 자동으로 스캔 결과를 업데이트하고, Amazon EventBridge를 통해 알림을 전송할 수 있는 연송 스캔 기능이 추가됩니다.

 

암호화

AWS 공동 책임 모델에 기반히여, AWS는 클라우드 인프라의 보안을 담당하며, 사용자는 그 위에 구축된 콘텐츠와 서비스의 보안을 책임지는데,  AWS KMS를 사용하여 저장 중인 Docker 이미지의 서버 측 암호화를 지원합니다.

 

AWS ECR 실습

원활한 실습을 위해 AdministratorAccess 권한을 가진 IAM으로 진행했습니다. 

Docker Image 생성

index.html 파일 생성

<!DOCTYPE html>
<html>
<head>
    <title>AWS ECR Test</title>
</head>
<body>
    <h1>Hello from AWS ECR!</h1>
    <p>This is a test container image for Amazon ECR.</p>
</body>
</html>

Dockerfile 생성

# 기본 nginx 이미지 사용
FROM nginx:alpine

# HTML 파일 추가
COPY ./index.html /usr/share/nginx/html/index.html

# Nginx 기본 포트
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

 

Docker 이미지 빌드

docker build -t ecr-test-image .

 

local에서 container 테스트

docker run -d -p 8080:80 ecr-test-image

 

테스트를 위해 docker run 명령어를 통해 local에서 실행시켜 줍니다.

docker ps

 

그 후 docker ps 명령어를 통해 실행 중인지 확인해 보겠습니다.

 

local에 8080 포트로 매핑되어 container가 띄어진 상태인 것을 확인할 수 있습니다.

 

curl localhost:8080

 

curl 명령어로 8080 port를 호출해 보겠습니다.

 

간단한 웹 페이지가 떠있는 것을 확인하실 수 있습니다.

 

 

Docker Tag

docker tag ecr-test-image:latest $REPO_URL:latest

 

docker image는 tag로 식별하면서 푸시할 리포지토리 주소를 특정할 수 있기 때문에 태깅을 진행합니다.

 

 

그 후 docker image 목록을 보면 태깅된 이미지가 보입니다.

 

ECR 생성

생성한 Docker Image를 ECR에 업로드하기 위해 ECR을 먼저 생성해 보겠습니다.

 

AWSCLI를 통한 생성

aws ecr create-repository --repository-name ecr-test-image

 

위의 명령어를 통해 간단하게 AWS ECR Repository를 생성합니다. (이때 region 정보를 입력하지 않으면 IAM에 설정된 default region에 배포되니 주의해 주세요!)

 

 

생성 확인

 

위와 같이 AWS web Console로 접근하여 ECR 페이지에서 생성된 ECR Repository를 확인할 수 있습니다.

 

ECR Login

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${accountcode}.dkr.ecr.ap-northeast-2.amazonaws.com

 

ECR Repositogy가 생성이 되었으면 해당 ECR에 로그인해야 합니다.

 

 

ECR에 Push

docker push $REPO_URL:latest

 

docker push 명령어를 통해 tag 된 docker image를 ECR에 업로드합니다.

 

만약 auth 문제가 발생한다면?

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:PutImage"
      ],
      "Resource": "*"
    }
  ]
}

 

위의 IAM 권한을 한번 확인해 보세요!

 

ECR에서 Image 확인

 

위와 같이 정상적으로 업로드된 것을 확인하실 수 있습니다.

 

 

Pod에서 사용할 Image를 ECR에서 가져오기

EKS의 기본 동작 방식은 Pod에 IAM 권한이 없으므로, OIDC와 IAM 역할 및 ServiceAccount를 사용하여 Pod에 IAM 권한을 부여해야 합니다.  

 

기본적인 동작 흐름

OIDC 활성화

Kubernetes 클러스터가 AWS IAM 역할을 사용하도록 OIDC를 활성화합니다.

 

IAM 역할 생성

ECR 접근 권한이 포함된 IAM 역할을 생성하고, cluster의 OIDC를 허용합니다.

 

ServiceAccount 생성

ServiceAccount를 생성하고, IAM 역할을 연결합니다.

 

Pod에서 ServiceAccount 사용

Pod yaml에서 ServiceAccount를 참조하도록 설정합니다.

 

ECR에 등록된 Image를 Pod에서 사용하여 실행 

Pod가 ServiceAccount를 통해 ECR에 접근하여 Image를 가져올 수 있습니다.

 

OIDC 활성화

OIDC(OpenID Connect)를 통해 AWS와 Kubernetes 간의 신뢰 관계를 설정하여 Pod가 AWS 서비스에 접근할 수 있습니다. 즉,  AWS EKS에서 ECR에 올라가 있는 image를 사용하기 위해서는 OIDC(OpenID Connect)를 사용하여 IAM 역할 기반 인증을 통해 접근해야 합니다. 이를 통해 Pod가 실행 중인 ServiceAccount를 통해 IAM 권한을 상속받습니다.

 

eksctl utils associate-iam-oidc-provider --region <region> --cluster <cluster_name> --approve

 

 

위의 명령어로 활성화시켜줍니다.

 

 

 

그 후 IAM > 액세스 관리 > ID 제공업체에서 정상적으로 생성되었는지 확인합니다.

 

aws iam list-open-id-connect-providers

 

명령어로도 확인하실 수 있습니다.

 

 

 

IAM 역할 생성

EKS에서 특정 Pod가 ECR 이미지를 가져올 수 있도록 ServiceAccount와 IAM 역할을 연결합니다.

 

IAM 역할 생성

aws iam create-role --role-name EKS-ECR-Role --assume-role-policy-document file://<(cat <<EOF
{
  "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>:sub": "system:serviceaccount:<namespace>:<service-account-name>"
        }
      }
    }
  ]
}
EOF
)

 

위에서 생성한 OIDC에 접근할 수 있는 IAM을 생성합니다.

IAM 역할에 ECR 권한 부여

aws iam attach-role-policy \
    --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \
    --role-name EKS-ECR-Role

 

이제 해당 IAM에 ECR에 접근할 수 있는 권한을 넣어줍니다.

 

Service account 생성

Kubernetes의 ServiceAccount는 Pod가 실행 중에 사용하는 "사용자 계정"입니다. EKS에서는 ServiceAccount를 통해 Kubernetes와 AWS IAM 간의 연결을 설정합니다.

 

Pod → ServiceAccount → IAM 역할 연결에 대해 정리하면 아래와 같습니다.

  • Pod는 ServiceAccount를 사용합니다.
  • ServiceAccount는 IAM 역할과 연결됩니다.
  • IAM 역할에는 ECR 접근 권한이 정의됩니다.

이처럼 ServiceAccount를 통해 Pod는 AWS 리소스(ECR)에 안전하게 접근할 수 있습니다.

 

apiVersion: v1
kind: ServiceAccount
metadata:
  name: ecr-access-service-account
  namespace: default
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::{accountcode}:role/EKS-ECR-Role

 

해당 role을 매핑하기 위해 serviceaccount를 생성합니다.

kubectl get serviceaccount ecr-access-service-account --namespace default

 

위의 명령어의 결과가 아래와 같다면 정상적으로 생성된 것입니다!

 

 

Pod 및 Service 생성

yaml 파일

apiVersion: v1
kind: Service
metadata:
  name: ecr-test-service
  namespace: default
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: ecr-test-app
---
apiVersion: v1
kind: Pod
metadata:
  name: ecr-test-pod
  namespace: default
  labels:
    app: ecr-test-app
spec:
  serviceAccountName: ecr-access-service-account
  containers:
  - name: ecr-test-container
    image: {accountcode}.dkr.ecr.ap-northeast-2.amazonaws.com/ecr-test-image:latest
    ports:
    - containerPort: 80

 

ECR에 접근해서 Image를 가져오는 Pod와 외부에서 접근하기 위해 LoadBalancer type의 service를 작성합니다.

 

kubectl get po,svc

 

위의 명령어를 통해서 정상적으로 배포되었는지 확인해 보겠습니다.

 

 

pod와 service 모두 잘 배포된 것을 확인하실 수 있습니다. 이제 service의 EXTERNAL-IP를 통해 해당 Pod에 접근해 보겠습니다.

 

 

ECR에서 Image를 잘 받아와서 conainer를 생성한 것을 확인하실 수 있습니다!

 

 


참고

 

완전관리형 컨테이너 레지스트리 - Amazon Elastic Container Registry - Amazon Web Services

이미지에 보다 빠르게 액세스하고 배포하며, 다운로드 시간을 줄이고, 확장 가능하고 내구성이 뛰어난 아키텍처를 사용하여 가용성을 개선합니다.

aws.amazon.com

 

 

Amazon ECR의 개념 및 구성 요소 - Amazon ECR

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

 

 

728x90