ECR 멀티 아키텍처 이미지를 활용하여 EKS Graviton 노드 그룹 관리하기
- -
이번 포스팅에서는 ECR 에서 제공하는 Multi Architecture Image 기능을 활용하여
EKS Cluster 의 Amazon Linux 노드 그룹과 Graviton 노드 그룹을 한 번에 관리하는 법에 대해 알아보겠습니다.
1. 개요
최근 서비스 개발에 EKS 를 도입하는 프로젝트가 눈에 띄게 많아졌습니다.
그 만큼 kubernetes 와 EKS 에 대한 관심과 이해도가 많이 증가한 것을 느낄 수 있습니다.
생각보다 EKS 를 서비스에 도입하고 활용하는 것에는 상당한 비용이 들기에 도입을 고려한 후 비용 때문에 도입을 철회하는 경우도 많이 있습니다.
하지만, 비교적 최근 AWS 에서 출시한 ARM 기반의 Graviton 인스턴스를 활용하면 기존 EC2 에 비해 가격을 20% 정도 절약할 수 있습니다.
그렇기 때문에, 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. 테스트 환경
테스트 환경을 위해 사용하는 리소스는 다음과 같습니다.
- EKS Cluster
- Amazon Linux Node Group + Graviton Node Group
- Private ECR Repo
- 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 를 통해 Layer 와 OS 등의 구성요소를 지정하게 됩니다.
자세한 내용은 아래 공식 문서를 참고 바랍니다.
앞서 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 를 활용해야 하는 보안 규정이 있을 경우 적합합니다.
'AWS > EKS' 카테고리의 다른 글
[EKS Study 7주차] EKS Automation - ACK (0) | 2023.06.10 |
---|---|
[AWS/EKS] IAM Group 을 통한 EKS 인증 관리 (0) | 2023.06.03 |
[AWS/EKS] EKS 인증/인가 파헤치기 (4) | 2023.06.02 |
[EKS Study 5주차] EKS AutoScaling - Karpenter (0) | 2023.05.28 |
[EKS Study 5주차] EKS AutoScaling - CA (0) | 2023.05.28 |