EKS 환경에서 CloudWatch Observability 를 사용하여 특정 로그를 Cloudwatch 로 전송하고 있었다. 하지만 해당 기능은 비용으로 인해 사용하지 않고, 동일하게 가져가기 위해서 Flunet-Bit 만 구성하여 배포해야 했다.
하지만 DB 노드는 보안 정책으로 인터넷이 완전히 차단된 상태였고, 레지스트리(cr.fluentbit.io)에서 이미지를 가져오지 못하는 문제가 발생했다.
이로 인해 DB 노드에서만 Fluent Bit Pod가 ImagePullBackOff 상태에 빠지게 되었고,
로그 수집이 되지 않는 이슈가 발생하였다.
본 포스팅에서는 해당 문제를 해결하기 위해 AWS ECR의 Pull Through Cache 기능을 활용한 과정을 정리한다.
ECR Pull Through Cache는 Amazon Elastic Container Registry (ECR)의 기능 중 하나로, 외부 컨테이너 레지스트리의 이미지를 ECR을 통해 자동으로 가져와 캐싱(cache) 해주는 기능이다.
동작 방식
Pull Through Cache는 단순 복사가 아니라 요청 기반 캐싱 구조
사용자가 ECR 경로로 이미지 Pull 요청
ECR에 해당 이미지가 없으면 외부 레지스트리(예: Docker Hub, Quay 등)에서 가져옴
가져온 이미지를 ECR에 저장 (캐싱)후 요청부터는 외부가 아니라 ECR에서 바로 제공
인터넷 없는 환경 (가장 중요)
Private Subnet
DB 노드 (Outbound 차단)
보안 환경
속도 개선
매번 외부에서 Pull 안 함
ECR에서 빠르게 다운로드
안정성 확보
Docker Hub rate limit 영향 없음
외부 레지스트리 장애 영향 감소
보안 및 통제
외부 이미지 직접 접근 차단
ECR + IAM으로 접근 제어 가능
serviceAccount:
create: true
name: fluent-bit
# CHART 0.56.0
image:
repository: cr.fluentbit.io/fluent/fluent-bit
tag: 4.2.3
# fluent-bit 버전 확인
helm search repo fluent/fluent-bit
NAME CHART VERSION APP VERSION DESCRIPTION
fluent/fluent-bit 0.56.0 4.2.3 Fast and lightweight log processor and forwarde...
# 설치
helm upgrade --install fluent-bit fluent/fluent-bit -f values.yaml -n fluent-bit --create-namespace --version 0.56.0
위 yaml 로 모든 노드에 배포를 하게 된다면 DB 노드는 인터넷에 완전히 차단된 환경이라 해당 레지스트리에 접근하는 것이 불가하다.
아래와 같이 ErrImagePull 이란 상태가 되며 DB 노드에만 배포가 실패가 되는 것을 볼 수 있으며, describe 로 확인 시 Image 의 Pull 이 실패가 된 것을 볼 수 있다.
AP Node Group : 10.0.20.0/24, 10.0.30.0/24
DB Node Grouo : 10.0.40.0/24, 10.0.50.0/24

Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m7s default-scheduler Successfully assigned fluent-bit/fluent-bit-kscg2 to ip-10-0-40-27.ap-northeast-2.compute.internal
Warning Failed 2m37s kubelet Failed to pull image "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed to pull and unpack image "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed toresolve reference "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed to do request: Head "https://cr.fluentbit.io/v2/fluent/fluent-bit/manifests/4.2.3": dial tcp 54.179.124.27:443: i/o timeout
Warning Failed 111s kubelet Failed to pull image "cr.fluentbit.io/fluent/fluent-bit:4.2.3": rpc error: code = DeadlineExceeded desc = failed to pull and unpack image "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed to resolve reference "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed to do request: Head "https://cr.fluentbit.io/v2/fluent/fluent-bit/manifests/4.2.3": dial tcp 54.179.124.27:443: i/o timeout
Warning Failed 58s (x3 over 2m37s) kubelet Error: ErrImagePull
Warning Failed 58s kubelet Failed to pull image "cr.fluentbit.io/fluent/fluent-bit:4.2.3": rpc error: code = DeadlineExceeded desc = failed to pull and unpack image "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed to resolve reference "cr.fluentbit.io/fluent/fluent-bit:4.2.3": failed to do request: Head "https://cr.fluentbit.io/v2/fluent/fluent-bit/manifests/4.2.3": dial tcp 52.76.90.69:443: i/o timeout
Normal BackOff 20s (x5 over 2m36s) kubelet Back-off pulling image "cr.fluentbit.io/fluent/fluent-bit:4.2.3"
Warning Failed 20s (x5 over 2m36s) kubelet Error: ImagePullBackOff
Normal Pulling 6s (x4 over 3m7s) kubelet Pulling image "cr.fluentbit.io/fluent/fluent-bit:4.2.3"
작성자의 경우 ECR 은 공통으로 사용하는 계정에 위치하여 ECR 에서 생성한 레지스트리에 대한 권한을 추가해야한다.
IAM 같은 경우 외부 레지스트리에서 이미지를 한 번 가져와야 하여 Pull 권한이 있는 IAM Role 또는 IAM User 로 진행을 하였다.
참고 : 업스트림 레지스트리와 ECR 레지스트리를 동기화
작성자는 EC2 에서 아래의 권한을 부여했다.
# EC2 에서 필요한 Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchImportUpstreamImage"
],
"Resource": "arn:aws:ecr:ap-northeast-2:<ACCOUNT>:repository/docker-hub/*"
}
]
}
ECR 은 다른 계정에 있어 정책은 아래와 같이 추가한다.
# 생성한 ECR 의 Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPull",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<ACCOUN>:role/<YOUR_NODE_ROLE>",
"arn:aws:iam::<ACCOUN>:role/<YOUR_EC2_ROLE>",
]
},
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchImportUpstreamImage"
]
}
]
}
작성자 기준 fluent-bit 가 필요하여 아래와 같이 레지스트리를 생성 후 pull through cache 를 적용을 진행하였다.

보안 암호를 사용한 인증이 필요한 업스트림 레지스트리의 경우 보안 인증 정보를 AWS Secrets Manager 보안 암호에 필수로 저장해야 한다.

또한, 캐시 네임스페이스의 접두사는 docker-hub 로 두었으며, 업스트림 네임스페이스에선 특정 접두사를 통해 더 상세한 설정이 가능하다.
참고 : 풀스루 캐시 규칙 생성

설정이 끝났다면 아래와 같이 레지스트리에 대해 Docker 클라이언트를 인증을 진행하며, 이미지를 가져오기 위해서는 ECR 에 우선으로 이미지가 있어야 한다.
# 인증
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin <ACCOUNT>.dkr.ecr.ap-northeast-2.amazonaws.com
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
# 이미지 Pull
# 가져올 이미지를 1회 Pull 해줘야 노드에서도 ECR 에 올라간 Image 를 가져올 수 있다.
docker pull <ACCOUNT>.dkr.ecr.ap-northeast-2.amazonaws.com/docker-hub/fluent/fluent-bit:4.2.3
4.2.3: Pulling from docker-hub/fluent/fluent-bit
ce49d46500be: Pull complete
...중략...
a7bffe15054f: Pull complete
Digest: sha256:a5761fa961cb22dd0875883a4d446b1acd99d4935d77358aa9f50ee177e44fe2
Status: Downloaded newer image for <ACCOUNT>.dkr.ecr.ap-northeast-2.amazonaws.com/docker-hub/fluent/fluent-bit:4.2.3
<ACCOUNT>.dkr.ecr.ap-northeast-2.amazonaws.com/docker-hub/fluent/fluent-bit:4.2.3
아래와 같이 명시된 버전의 이미지를 가져올 수 있다.

# 기존 helm의 values.yaml 수정
# 기존
image:
# repository: cr.fluentbit.io/fluent/fluent-bit # 외부 레지스트리
tag: 4.2.3
# 변경
image:
repository: <ACCOUNT>.dkr.ecr.ap-northeast-2.amazonaws.com/docker-hub/fluent/fluent-bit # 사용자 AWS 계정의 ECR URI
tag: 4.2.3
# 재설치
helm uninstall fluent-bit -n fluent-bit
helm upgrade --install fluent-bit fluent/fluent-bit -f values.yaml -n fluent-bit --create-namespace --version 0.56.0
각 서브넷에 위치한 AP, DB 노드 모두 이미지를 가져온 후 배포를 완료할 수 있다.

인터넷이 차단된 환경에서는 외부 컨테이너 이미지를 사용하는 것이 어렵지만, ECR Pull Through Cache를 활용하면 이를 효과적으로 해결할 수 있다.
특히 EKS 환경에서 노드별 네트워크 제약이 있는 경우 해당 방식은 운영 안정성을 높이는 데 매우 유용하다.
향후에는 Private Registry 미러링 전략이나 이미지 사전 동기화 방식과도 비교해보면 좋을 것 같다.