새소식

AWS/EKS

ECR 멀티 아키텍처 이미지를 활용하여 EKS Graviton 노드 그룹 관리하기

  • -

이번 포스팅에서는 ECR 에서 제공하는 Multi Architecture Image 기능을 활용하여

EKS Cluster 의 Amazon Linux 노드 그룹과 Graviton 노드 그룹을 한 번에 관리하는 법에 대해 알아보겠습니다.

 

 

1. 개요

 

최근 서비스 개발에 EKS 를 도입하는 프로젝트가 눈에 띄게 많아졌습니다.
그 만큼 kubernetes 와 EKS 에 대한 관심과 이해도가 많이 증가한 것을 느낄 수 있습니다.

 

생각보다 EKS 를 서비스에 도입하고 활용하는 것에는 상당한 비용이 들기에 도입을 고려한 후 비용 때문에 도입을 철회하는 경우도 많이 있습니다.
하지만, 비교적 최근 AWS 에서 출시한 ARM 기반의 Graviton 인스턴스를 활용하면 기존 EC2 에 비해 가격을 20% 정도 절약할 수 있습니다.

 

ARM 프로세서 - 고성능 프로세서 - AWS EC2 Graviton - AWS

범용 M7g: 컴퓨팅, 메모리 및 네트워킹의 균형을 맞춘 범용 워크로드에 대한 최고의 가격 대비 성능 구동: AWS Graviton3 구축 대상: 애플리케이션 서버, 중간 규모의 데이터 스토어, 마이크로서비스

aws.amazon.com

 

 

그렇기 때문에, Graviton 을 이용한 EKS 활용도 흔히 볼 수 있는 Practice 가 되고 있습니다.

만약 이 글을 보고 있는 사람이 신규 EKS 구축을 Graviton 으로 하고자 할 때는 아마 크게 어려움이 없을 것입니다.


하지만 기존에 Amazon Linux 노드로 운영을 하고 있고 이를 비용 효율적인 Graviton 인스턴스로 Migration 하고 싶을 때,

Container Image 관리 측면에 어려움을 겪을 수 있습니다.

 

 

1.1. Multi Architecture

 

흔히, Container 는 프로세스가 격리되어 있기 때문에 어떠한 환경에서 띄운다 할 지라도 호환이 된다고 알고 있을 것입니다.
하지만, CPU Architecture 자체가 변경된 x86_64(amd) 와 ARM 환경의 Container 는 서로 호환이 되지 않습니다.
이러한 제약 때문에, 최근 업로드되는 Docker Hub 나 Public ECR 의 Container Image 는 Multi Architecture 를 지원하고 있습니다.

 

Multi Architecture Image 는 x86(amd), ARM 환경에서 동일하게 사용할 수 있는 Container Image 를 의미합니다.

 

실제 서비스에 활용되는 Container Image 는 보통 직접 빌드해서 사용하거나,

Private 한 환경에 보관된 Image 를 사용하기 때문에 어떻게 Multi Architecture Image 를 지원하는 환경을 구현할 것인지가 핵심 과제가 될 것입니다.

 

다행히도, 최근 ECR 에서 Multi Architecture Image 를 지원하는 기능을 발표했습니다.
이번 글에서는 이를 이용하여 Private ECR 을 이용하여

EKS 클러스터의 Amazon Linux Node 와 Graviton Node 이미지 배포를 관리하는 법에 대해 알아볼까 합니다.

 

 

1.2. 구성도

 

 

2. 테스트 환경

 

테스트 환경을 위해 사용하는 리소스는 다음과 같습니다.

  1. EKS Cluster
  2. Amazon Linux Node Group + Graviton Node Group
  3. Private ECR Repo
  4. EC2 2대 (amd + arm)



2.1. 사전 환경 검증

 

Private ECR 에 저장하기 위해서는 Public Image 를 내 환경에 다운 받은 후 ECR 로 다시 업로드 하는 과정을 거치게 됩니다.
이 때, amd와 arm 환경에서 각각 어떤 Image 를 다운받는 지 확인해볼 예정입니다.

 

각각의 Linux 환경에서 아래의 이미지를 가져옵니다. 해당 이미지는 fluent-bit 의 공식 이미지 주소입니다.

 

docker pull cr.fluentbit.io/fluent/fluent-bit

 

 

겉으로 보기에는 동일한 Image 로 보이지만, Image ID 를 보면 알 수 있듯이 전혀 다른 이미지입니다.
아래 명령어를 통해 무엇이 다른 지 명확하게 알 수 있습니다.

 

docker inspect cr.fluentbit.io/fluent/fluent-bit:latest | grep Architecture

 

 

보시다시피 amd 환경에서는 amd Image 를 다운받고, arm 환경에서는 arm Image 를 다운받습니다.
이것이 Multi Architecture Image 의 특징이라고 할 수 있습니다.

 

그렇다면, amd 환경에서 다운받은 Image 를 Private ECR 에 올리면 해당 Image 를 arm 환경에서 사용할 수 있을까요??

 

결론부터 말하자면 불가능합니다.

증명을 위해 Private ECR 을 생성 후 업로드 해보겠습니다.
Private ECR Repo 명은 multi-arch/fluent-bit 으로 진행했습니다.

 

  • AMD64 리눅스에서 실행
# ACCOUNT ID & Region 설정
ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

# ECR Repo 생성
aws ecr create-repository --repository-name multi-arch/fluent-bit

# ECR Login
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com

# Image Tag 변경
docker tag cr.fluentbit.io/fluent/fluent-bit:latest ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:amd64

# Image Push
docker push ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:amd64

 

ECR 콘솔에서 해당 이미지를 확인합니다.

 

 

arm 환경에서 해당 이미지를 다운합니다.

 

# ACCOUNT ID & Region 설정
ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

# ECR Login
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com

# Image Pull
docker pull ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:amd64

 

이후 해당 이미지의 아키텍처를 확인해보면 변경되지 amd 환경이 변경되지 않은 것을 확인할 수 있습니다.

docker inspect ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:amd64 | grep Architecture

 

 

그럼 이런 환경이 왜 문제가 되는 지, 실제 EKS 에 배포해보겠습니다.

 

 

2.2. Private ECR 을 통한 Pod 배포

 

Private ECR 에 있는 Image 를 Helm 을 통해서 배포해 보겠습니다.

 

ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

helm install fluent-bit fluent/fluent-bit \
    --set image.repository=${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit \
    --set image.tag=amd64

 

Pod 배포 결과 확인

 

kubectl get nodes -o wide
kubectl get pods -o wide

 

 

결과에서 보듯이, amd 환경에서 ECR 에 업로드 한 Image 는 Graviton 노드에서 활용할 수 없는 것을 확인할 수 있습니다.

그럼 반대로, arm 환경에서 올린 Image 는 어떨까요??

 

  • ARM 리눅스에서 실행
# ACCOUNT ID & Region 설정
ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

# ECR Login
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com

# Image Tag 변경
docker tag cr.fluentbit.io/fluent/fluent-bit:latest ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:arm64

# Image Push
docker push ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:arm64

 

Helm 의 Image 를 변경하여 다시 배포해봅니다.

ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

helm upgrade fluent-bit fluent/fluent-bit \
    --set image.repository=${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit \
    --set image.tag=arm64

 

 

이번엔 Amazon Linux 노드에서 사용할 수 없다는 것을 알 수 있습니다.

이런 환경은 저희가 원하는 것이 아닙니다.

 

amd 노드에서는 amd ECR Image 를, arm 노드에서는 arm ECR Image 를 다운받을 수 있게 하는 것을 원합니다.

 

 

3. ECR Multi Architecture Image 생성

 

이러한 문제점을 해결하기 위해 2개의 amd & arm 이미지를 1개로 묶어줘야 합니다.
ECR 에서는 이를 지원하고 있습니다.

 

3.1. Image Push

 

우선 ECR Repository 에 사용할 amd, arm 2개의 Image 를 업로드 해줍니다.

해당 이미지들을 통해 새로운 Multi Architecture Image 를 생성할 예정입니다.

 

3.2. Container Manifest 생성

 

Container 에는 Manifest 라고 하는 Container 구성 요소가 존재합니다.
Manifest 를 통해 LayerOS 등의 구성요소를 지정하게 됩니다.

 

자세한 내용은 아래 공식 문서를 참고 바랍니다.

 

docker manifest

 

docs.docker.com

 

 

앞서 ECR 에 업로드 했던 2개의 Image 를 사용하여 Multi Architecture 를 지원하는 Manifest 를 생성하겠습니다.

# 사용법
docker manifest create <PRIVATE_ECR_REPO>:<TAG> \
    <PRIVATE_ECR_REPO>:<ARM_TAG> \
    <PRIVATE_ECR_REPO>:<x86_TAG>

 

ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

# Manifest 생성
docker manifest create ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:multi-image \
    ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:amd64  \
    ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:arm64

# Manifest 생성 확인
docker manifest inspect ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:multi-image

 

 

3.3. Container Manifest 업로드

 

Manifest 만 생성했을 뿐, 아직 Image 로 사용하지는 못합니다.
ECR 에 업로드하여 사용할 수 있도록 변경해줍니다.

docker manifest push ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit:multi-image

 

이후 ECR 콘솔에서 확인해보면 실제 Image 가 올라가있는 것을 알 수 있습니다.

 

3.4. Multi Architecture Image 배포

 

그럼 실제 EKS 에 Image 를 배포하여 아키텍처 별로 잘 적용이 되는 지 확인해보겠습니다.

ACCOUNT_ID=$(aws sts get-caller-identity | jq .Account -r)
REGION=ap-northeast-2

helm upgrade fluent-bit fluent/fluent-bit \
    --set image.repository=${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/multi-arch/fluent-bit \
    --set image.tag=multi-image

 

kubectl get nodes -o wide
kubectl get pods -o wide

 

 

이제 ARM, AMD 환경 상관없이 이미지를 잘 가져오는 것을 확인할 수 있습니다.

 

가능한 구성 시나리오

해당 환경은 ARM, AMD 인스턴스를 혼합해서 사용하는 환경에 적합합니다.

Graviton 인스턴스로 Migration 과정에서 일시적으로 함께 사용할 때 적합합니다.

 

Public Image 외에 Private Image 를 활용해야 하는 보안 규정이 있을 경우 적합합니다.

 

 

Contents

포스팅 주소를 복사했습니다